Skip to content

Commit

Permalink
Delete orphaned field layouts during garbage collection
Browse files Browse the repository at this point in the history
Resolves #16032
  • Loading branch information
brandonkelly committed Nov 8, 2024
1 parent 09e238f commit 1e1f01f
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG-WIP.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
- Added `craft\services\Addresses::EVENT_DEFINE_ADDRESS_COUNTRIES`. ([#15711](https://github.com/craftcms/cms/pull/15711))
- Added `craft\services\Addresses::getCountryList()`. ([#15711](https://github.com/craftcms/cms/pull/15711))
- Added `craft\services\Fields::EVENT_BEFORE_APPLY_FIELD_SAVE`. ([#15872](https://github.com/craftcms/cms/discussions/15872))
- Added `craft\services\Gc::deleteOrphanedFieldLayouts()`.
- Added `craft\web\View::registerCpTwigExtension()`.
- Added `craft\web\View::registerSiteTwigExtension()`.
- Improved support for creating log targets for third party logging services. ([#14974](https://github.com/craftcms/cms/pull/14974))
Expand All @@ -43,3 +44,4 @@

### System
- `Location` headers added via `craft\web\Response::redirect()` are now set to encoded URLs. ([#15838](https://github.com/craftcms/cms/issues/15838))
- Fixed a bug where orphaned field layouts weren’t getting garbage collected. ([#16032](https://github.com/craftcms/cms/issues/16032))
35 changes: 35 additions & 0 deletions src/services/Gc.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,13 @@ public function run(bool $force = false): void
$this->deletePartialElements(Tag::class, Table::CONTENT, 'elementId');
$this->deletePartialElements(User::class, Table::CONTENT, 'elementId');

$this->deleteOrphanedFieldLayouts(Asset::class, Table::VOLUMES);
$this->deleteOrphanedFieldLayouts(Category::class, Table::CATEGORYGROUPS);
$this->deleteOrphanedFieldLayouts(Entry::class, Table::ENTRYTYPES);
$this->deleteOrphanedFieldLayouts(GlobalSet::class, Table::GLOBALSETS);
$this->deleteOrphanedFieldLayouts(MatrixBlock::class, Table::MATRIXBLOCKTYPES);
$this->deleteOrphanedFieldLayouts(Tag::class, Table::TAGGROUPS);

$this->_deleteUnsupportedSiteEntries();

// Fire a 'run' event
Expand Down Expand Up @@ -520,6 +527,34 @@ private function _deleteOrphanedStructureElements(): void
$this->_stdout("done\n", Console::FG_GREEN);
}

/**
* Deletes field layouts that are no longer used.
*
* @param string $elementType The element type
* @phpstan-param class-string<ElementInterface> $elementType
* @param string $table The table name that contains a foreign key to `fieldlayouts.id`
* @param string $fk The column name that contains the foreign key to `fieldlayouts.id`
* @since 4.13.0
*/
public function deleteOrphanedFieldLayouts(string $elementType, string $table, string $fk = 'fieldLayoutId'): void
{
/** @var string|ElementInterface $elementType */
$this->_stdout(sprintf(' > deleting orphaned %s field layouts ... ', $elementType::lowerDisplayName()));

$ids = (new Query())
->select('fl.id')
->from(['fl' => Table::FIELDLAYOUTS])
->leftJoin(['t' => $table], "[[t.$fk]] = [[fl.id]]")
->where(['fl.type' => $elementType, "t.$fk" => null])
->column();

if (!empty($ids)) {
Db::delete(Table::FIELDLAYOUTS, ['id' => $ids]);
}

$this->_stdout("done\n", Console::FG_GREEN);
}

/**
* Hard delete structures data
* Any soft-deleted structure elements which have revisions will be skipped, as their revisions may still be needed by the owner element.
Expand Down

0 comments on commit 1e1f01f

Please sign in to comment.