vangrg/profanity-bundle
vangrg/profanity-bundle adds configurable profanity filtering to PHP applications, detecting and masking offensive words in user input and text. A lightweight way to clean comments, usernames, and messages before storage or display.
Architecture fit: This is a Symfony bundle (vangrg/profanity-bundle), not a Laravel package. The name “Bundle” and the repository origin point to Symfony’s DependencyInjection extension + compiler-pass model, whereas Laravel expects a ServiceProvider with package auto-discovery. There is no architectural overlap; a Laravel integration would be a wrapper or a fork, not a drop-in. The only genuinely reusable asset is the profanity-matching logic and dictionary, not the package scaffolding.
Integration feasibility: Low-to-moderate via extraction. Composer install is possible, but service wiring, configuration trees, and event hooks will not resolve inside Laravel’s container without manual binding. The pragmatic path is to vendor the checker class and word lists, then re-expose them through a thin Laravel service provider and facade. Even then, the package’s PHP/Symfony version constraints (circa 2018–2019) are likely to conflict with modern Laravel stacks (PHP 8.1+, Symfony 6/7 components pulled in by Laravel itself).
Technical risk: High, concentrated in four areas: (1) unmaintained since February 2019 — no PHP 8.x or security updates; (2) zero dependents and 4 stars means no community validation, no regression safety net; (3) profanity dictionaries age quickly — new slurs, slang, and evasions (leetspeak, Unicode homoglyphs) will not be covered; (4) the underlying matching strategy is unknown — a naive regex over a large word list risks catastrophic backtracking and Unicode bugs (accents, CJK, zero-width characters). The 0.43 score is consistent with a stale, low-adoption artifact.
Key questions: What PHP and Symfony versions does composer.json pin? Is the word list a static resource, a database table, or remote? Does the checker do whole-word, substring, or regex matching — and is it Unicode-safe? Is there any test coverage we could inherit? Which Symfony container features (tags, compiler passes, config trees) are actually load-bearing versus incidental? Is the dictionary licensed for our use and redistribution? Can we lift just the lexicon and matcher without the bundle? Finally, since opportunity score (5.73) outpaces package quality (0.43), is the real requirement “profanity detection” rather than “this package,” making a better-maintained alternative (e.g., a standalone PHP matcher or a fork) the rational buy?
Stack fit: Poor as-is for Laravel, workable only as a source of logic. Treat the package as a reference implementation, not a dependency. If the team is on Symfony instead, fit is better but still constrained by the 2019 vintage and version gaps.
Migration path: Two viable routes. (a) Fork: strip the Symfony bundle layer, keep the matcher and word list, publish as an internal acme/profanity Laravel package with a service provider, config file, and facade. (b) Adopt: evaluate a maintained alternative, and port the dictionary from this repo (subject to license) if its coverage is useful. Forking is the lower-risk path only if the core logic is small and clean; otherwise adopt.
Compatibility: Audit composer.json first — PHP constraint, symfony/framework-bundle requirement, and autoload map. Expect to bump PHP to 8.1+/8.2 and drop Symfony coupling entirely. Check that the matcher avoids PCRE features removed in PHP 8 and that the dictionary file is UTF-8. Confirm the package does not depend on Symfony’s EventDispatcher or translation components at runtime.
Sequencing:
ProfanityServiceProvider, config publishing, facade, and a check()/filter() API.Maintenance: The upstream is effectively abandoned — last release February 2019, no activity signal, no dependents to absorb bugs. Whoever integrates this owns it permanently. Budget for a fork-and-maintain decision up front, including a named code owner and a dictionary-refresh cadence (quarterly minimum) as new terms enter circulation.
Support: No vendor support, no community forum, no issue triage. Internal on-call must absorb failures. Escalation path is the internal team that forked it. This is acceptable for a low-stakes filter, not for user-facing safety-critical content moderation.
Scaling: Profanity matching is CPU-light per request, so throughput is unlikely to be the bottleneck — unless the implementation compiles a large regex per call or loads the dictionary from disk each time. Ensure the word list is loaded once (cached/singleton) and, if large, indexed (trie or hash set) rather than linear-scanned. For high-volume write paths, consider running checks asynchronously or in a middleware with a bounded time budget. Memory footprint should be tens of KB to low MB depending on dictionary size.
Failure modes: False positives on legitimate words (the “Scunthorpe problem”) and names; false negatives from leetspeak, spacing, Unicode homoglyphs, and zero-width joiners; encoding corruption on non-Latin input; regex backtracking on adversarial long strings (DoS vector if user input is unbounded); silent pass-through if the dictionary fails to load; and version drift where the app upgrades PHP and the unmaintained matcher breaks without a clear error. Each needs a defined behavior — fail-open vs. fail-closed — decided by product, not left to chance.
Ramp-up: Low to consume (one check() call), medium to fork — a competent PHP engineer can lift and re-wrap the logic in a few days, but hardening Unicode handling, building an evasion corpus, and setting up dictionary maintenance is a multi-week effort with ongoing cost. The opportunity score suggests demand for the capability; the package score suggests this artifact is not the vehicle. Recommend a short spike (1–2 days) to audit the source, then decide fork vs. adopt before committing engineering time.
How can I help you explore Laravel packages today?