zikula/pagelock-module
A Zikula module that locks pages while they are being edited, preventing concurrent modifications and edit conflicts. It integrates with Zikula's permission system to manage who can lock and unlock content, helping teams collaborate safely on shared pages.
Architecture fit — poor, effectively zero. zikula/pagelock-module is a Zikula module, and Zikula is a Symfony-based CMS with its own module bootstrap, ModUtil/ModUtil::getVar configuration layer, Doctrine ORM entities, Zikula-specific Twig extensions, and hook/event wiring. None of that maps onto Laravel. There is no Illuminate component, no service provider, no Blade view, no Eloquent model, and no Composer package boundary that can be consumed standalone — Zikula modules are only loadable by the Zikula kernel. A Laravel application cannot composer require this and get working behavior.
What is actually reusable is the concept, not the code. Page locking is a well-understood concurrency-control pattern: a lock row keyed by (record type, record id), an acquiring user, an acquisition timestamp, a TTL/heartbeat, a unique constraint to make acquisition atomic, and a sweep for expired locks. That design survives a stack change. The ~implementation does not.
Integration feasibility — low. A viable path requires either (a) forking and rewriting the module's locking logic as a Laravel package (migration + trait/policy + lock service), or (b) reimplementing from the observable behavior. Either way, the deliverable is a new internal package with this repository serving as a design reference only. Budget roughly 3–5 engineer-days for a scoped reimplementation with tests, versus an unbounded and likely unsuccessful port.
Technical risk — high and compounding. The repository is archived, last released 2021-12-14, with 0 stars and 0 dependents. That combination means: no maintainer, no security response path, no compatibility work for PHP 8.2/8.3 or Symfony 6/7, and no evidence of production usage to validate the locking semantics against real edge cases (browser crash, tab duplication, multi-node deployments). A dependency with zero dependents is a signal, not a coincidence.
Key questions to resolve before any commitment:
version or updated_at check on save); the latter needs a lock lease.Cache::lock() with block() gives atomic lease acquisition and TTL for free, and this package becomes redundant.Stack fit — none. Target stack is Laravel 10/11 on PHP 8.1+, using Eloquent, service providers, Blade, and a queue worker. The package targets Zikula 3.x on PHP 7.4/8.0-era Symfony with Doctrine. There is no shared abstraction layer, no shared HTTP kernel, and no shared persistence layer. Treat this as a greenfield build informed by an archived reference implementation.
Recommended migration path (concept extraction):
Cache::lock("page:{id}", $ttl) backed by Redis or the database lock driver for atomicity and automatic TTL — this removes the need for a hand-rolled lock table and expiry sweeper. Fall back to a page_locks table with a unique index on (lockable_type, lockable_id) and an expires_at column only if Redis is unavailable.LocksPages trait or a PageLockService injected into controllers/policies; a EnsurePageIsNotLocked middleware for write routes; a Blade partial for the "locked by X, expires in Y" banner; release on save, cancel, and via a finally block so exceptions don't leak locks.Compatibility and sequencing. Nothing installs into the Laravel app, so there is no version-matrix problem to manage — but there is also no upstream to track. The internal package must own its own semver and changelog from day one. Sequence: spike → design doc → build with tests covering concurrent acquisition, expiry, and crash-release → flag-gated rollout → removal of the flag. Do not sequence this behind any Zikula decommissioning work; the two are independent.
Maintenance — this is a build, so you own it. Adopting the repository as a dependency would mean owning a fork with no upstream; that is strictly worse than owning a small internal package. Either way, budget ongoing ownership for the lock service, its tests, and its failure-mode runbook. The archived status also means no CVE feed — if the code were ever embedded, vulnerability scanning would return nothing and give false assurance.
Support — none. No maintainer, no issue triage, no release cadence since December 2021. Any defect found in the locking logic is ours to diagnose with no upstream to consult.
Scaling — the real operational concern, independent of this package. Locks must be enforced from a shared store. In-process locks break the moment a second app server exists. Redis-backed Cache::lock() scales cleanly; a MySQL lock table concentrates contention on one table and needs an index and a sweep job. Expect lock churn proportional to concurrent editors, not to total pages.
Failure modes to design for explicitly:
beforeunload fires. The TTL is the only real safety net — keep it short (2–5 min) with a heartbeat refresh, and show a "force unlock" affordance for admins.try/finally leaves the page locked for the full TTL after a 500.SET NX, or a unique index insert), not a read-then-write check.Ramp-up — low for the build, moderate for the reading. The domain is small enough that a mid-level engineer can implement it in days. The non-obvious cost is comprehension: understanding the archived module requires learning Zikula's module conventions, which has no residual value for the team. Keep the spike timeboxed and extract a written spec rather than letting engineers reverse-engineer the Zikula code path-by-path.
Bottom line. Reject as a dependency. The score of 0, archived status, zero dependents, and framework mismatch are all consistent. Use it as a one-hour design reference for lock state transitions, then build a small Redis-backed lock service on Laravel primitives. The opportunity here is not integration — it is recognizing that the underlying requirement is a ~100-line internal capability, not a package adoption.
How can I help you explore Laravel packages today?