[Grid config & Saved search] Set owner to NULL on user delete instead of cascading#1940
Conversation
… of cascading Deleting a user cascaded to their grid configurations and saved searches, removing them even when they were shared with or made global for other users. Switch the owner foreign key from ON DELETE CASCADE to ON DELETE SET NULL on both bundle_studio_grid_configurations and bundle_studio_saved_search_configurations, make the owner column nullable, and surface a NULL owner through the Entity Ownership management as owner id 0 (ownerDeleted = true). Resolves #1918 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Up to standards ✅🟢 Issues
|
| Category | Results |
|---|---|
| BestPractice | 1 minor |
| CodeStyle | 11 minor |
🟢 Metrics 18 complexity
Metric Results Complexity 18
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
There was a problem hiding this comment.
Pull request overview
This pull request resolves #1918 by preventing shared/grid and saved-search configurations from being deleted when their owning user is deleted. Instead of cascading deletions, the schema now preserves configurations and represents “deleted owner” consistently (DB owner NULL, surfaced as owner id 0 + ownerDeleted = true in ownership management; API owner id nullable).
Changes:
- Database schema update: switch
ownerFK fromON DELETE CASCADEtoON DELETE SET NULLfor grid + saved-search configuration tables (and make saved-searchownernullable). - Domain/API alignment:
ownerbecomes?intin entities +ShareableConfigurationInterface, and saved-searchDetailedConfiguration::ownerIdbecomes nullable. - Ownership management mapping: providers translate
NULLowner toownerId = 0andownerName = null, which results inownerDeleted = true.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Unit/OwnershipManagement/Provider/GridConfigurationProviderTest.php | Adds regression coverage for surfacing deleted owners as owner id 0. |
| src/Search/Schema/DetailedConfiguration.php | Makes saved-search ownerId nullable in the OpenAPI schema + PHP type. |
| src/OwnershipManagement/Provider/SavedSearchConfigurationProvider.php | Maps NULL owner to ownership-management “deleted owner” representation. |
| src/OwnershipManagement/Provider/GridConfigurationProvider.php | Same “deleted owner” mapping for grid configurations. |
| src/Migrations/Version20260703120000.php | New migration to switch owner FK behavior to SET NULL and ensure nullable owner column. |
| src/Installer.php | Updates fresh-install schema for both tables to use SET NULL and nullable owner (saved search). |
| src/Entity/Search/SavedSearchConfiguration.php | Makes owner nullable (?int) to support SET NULL hydration. |
| src/Entity/Grid/GridConfiguration.php | Fixes owner type to ?int to match nullable column and avoid hydration issues. |
| src/Configuration/Share/ShareableConfigurationInterface.php | Updates getOwner() return type to ?int to support nullable owners. |
| $ownerId ?? 0, | ||
| $ownerId === null ? null : ($ownerNames[$ownerId] ?? null), |
| // SET NULL requires a nullable column; CASCADE keeps it nullable as well (harmless superset). | ||
| $table->getColumn('owner')->setNotnull(false); |



Changes in this pull request
Resolves #1918
Deleting a user cascaded to their grid configurations and saved searches, removing them even when they were shared with or made global for other users. Those users silently lost the shared configurations.
This switches the
ownerforeign key fromON DELETE CASCADEtoON DELETE SET NULLon both configuration tables so the configurations survive owner deletion, and surfaces an orphaned configuration through the Entity Ownership management as owner id0(ownerDeleted = true), as requested in the issue.Details
Installer.php+ new migrationVersion20260703120000): owner FKCASCADE→SET NULLonbundle_studio_grid_configurationsandbundle_studio_saved_search_configurations; the saved-searchownercolumn is made nullable (grid's already was). Matches theSET NULLpattern already used by other bundles' owner FKs (job run, bookmark list, copilot).ownerbecomes?inton both entities andShareableConfigurationInterface::getOwner()(a NULL owner would otherwise fatal on Doctrine hydration). Owner-based permission checks remain correct (null === userId→ false).GridConfigurationProvider/SavedSearchConfigurationProvidermap a NULL owner toownerId: 0/ownerName: null⇒ownerDeleted: true.Search\Schema\DetailedConfiguration::ownerIdis now nullable, mirroringGrid\Schema\DetailedConfiguration(a shared config's owner can now be null). Minor, backward-tolerant OpenAPI change — worth a heads-up to the frontend.CASCADE(a share pointing at a deleted user is meaningless).Additional info
php -l+ PHPStan clean on changed dirs; full Unit suite (417 tests) passes plus 2 new regression tests inGridConfigurationProviderTest; migration applied to a dev DB and confirmed (SET NULL+ nullableowner).2026.1/2026.xper the branching workflow.