|
| 1 | +<?php |
| 2 | + |
| 3 | +namespace happycog\craftmcp\tools; |
| 4 | + |
| 5 | +use Craft; |
| 6 | +use craft\elements\Entry; |
| 7 | +use happycog\craftmcp\exceptions\ModelSaveException; |
| 8 | + |
| 9 | +class DeleteSite |
| 10 | +{ |
| 11 | + /** |
| 12 | + * Delete a site from Craft CMS. This will remove the site and potentially affect related data. |
| 13 | + * |
| 14 | + * **WARNING**: Deleting a site that has existing entries will cause data loss. The tool will |
| 15 | + * provide usage statistics and require confirmation for sites with existing content. |
| 16 | + * |
| 17 | + * You _must_ get the user's approval to use the force parameter to delete sites that have existing |
| 18 | + * entries. This action cannot be undone. |
| 19 | + * |
| 20 | + * **IMPORTANT**: You cannot delete the primary site. If you need to delete it, first set another |
| 21 | + * site as primary using the UpdateSite tool. |
| 22 | + * |
| 23 | + * @return array<string, mixed> |
| 24 | + */ |
| 25 | + public function delete( |
| 26 | + /** The ID of the site to delete */ |
| 27 | + int $siteId, |
| 28 | + |
| 29 | + /** Force deletion even if entries exist (default: false) */ |
| 30 | + bool $force = false |
| 31 | + ): array |
| 32 | + { |
| 33 | + $sitesService = Craft::$app->getSites(); |
| 34 | + |
| 35 | + // Get the site |
| 36 | + $site = $sitesService->getSiteById($siteId); |
| 37 | + throw_unless($site, "Site with ID {$siteId} not found"); |
| 38 | + |
| 39 | + // Prevent deletion of primary site |
| 40 | + throw_if($site->primary, "Cannot delete the primary site. Set another site as primary first."); |
| 41 | + |
| 42 | + // Analyze impact before deletion |
| 43 | + $impact = $this->analyzeImpact($site); |
| 44 | + |
| 45 | + // Check if force is required |
| 46 | + if ($impact['hasContent'] && !$force) { |
| 47 | + // Type-safe access to impact data for string interpolation |
| 48 | + assert(is_int($impact['entryCount']) || is_string($impact['entryCount'])); |
| 49 | + assert(is_int($impact['draftCount']) || is_string($impact['draftCount'])); |
| 50 | + assert(is_int($impact['revisionCount']) || is_string($impact['revisionCount'])); |
| 51 | + |
| 52 | + $entryCount = (string)$impact['entryCount']; |
| 53 | + $draftCount = (string)$impact['draftCount']; |
| 54 | + $revisionCount = (string)$impact['revisionCount']; |
| 55 | + |
| 56 | + throw new \RuntimeException( |
| 57 | + "Site '{$site->name}' contains data and cannot be deleted without force=true.\n\n" . |
| 58 | + "Impact Assessment:\n" . |
| 59 | + "- Entries: {$entryCount}\n" . |
| 60 | + "- Drafts: {$draftCount}\n" . |
| 61 | + "- Revisions: {$revisionCount}\n\n" . |
| 62 | + "Set force=true to proceed with deletion. This action cannot be undone." |
| 63 | + ); |
| 64 | + } |
| 65 | + |
| 66 | + // Store site info for response |
| 67 | + $siteInfo = [ |
| 68 | + 'id' => $site->id, |
| 69 | + 'name' => $site->name, |
| 70 | + 'handle' => $site->handle, |
| 71 | + 'language' => $site->language, |
| 72 | + 'baseUrl' => $site->getBaseUrl(), |
| 73 | + 'impact' => $impact |
| 74 | + ]; |
| 75 | + |
| 76 | + // Delete the site |
| 77 | + throw_unless($sitesService->deleteSite($site), ModelSaveException::class, $site); |
| 78 | + |
| 79 | + return $siteInfo; |
| 80 | + } |
| 81 | + |
| 82 | + /** |
| 83 | + * @return array<string, mixed> |
| 84 | + */ |
| 85 | + private function analyzeImpact(\craft\models\Site $site): array |
| 86 | + { |
| 87 | + // Count entries for this site |
| 88 | + $entryCount = Entry::find() |
| 89 | + ->siteId($site->id) |
| 90 | + ->count(); |
| 91 | + |
| 92 | + // Count drafts for this site |
| 93 | + $draftCount = Entry::find() |
| 94 | + ->siteId($site->id) |
| 95 | + ->drafts() |
| 96 | + ->count(); |
| 97 | + |
| 98 | + // Count revisions for this site |
| 99 | + $revisionCount = Entry::find() |
| 100 | + ->siteId($site->id) |
| 101 | + ->revisions() |
| 102 | + ->count(); |
| 103 | + |
| 104 | + // Check if there's any content |
| 105 | + $hasContent = $entryCount > 0 || $draftCount > 0 || $revisionCount > 0; |
| 106 | + |
| 107 | + return [ |
| 108 | + 'hasContent' => $hasContent, |
| 109 | + 'entryCount' => $entryCount, |
| 110 | + 'draftCount' => $draftCount, |
| 111 | + 'revisionCount' => $revisionCount, |
| 112 | + ]; |
| 113 | + } |
| 114 | +} |
0 commit comments