Skip to content

Instantly share code, notes, and snippets.

@duncanmcclean
Last active March 5, 2024 15:32
Show Gist options
  • Save duncanmcclean/8124d22cd4685d76d37aeb0cc0871db8 to your computer and use it in GitHub Desktop.
Save duncanmcclean/8124d22cd4685d76d37aeb0cc0871db8 to your computer and use it in GitHub Desktop.
Identify & fix Duplicate IDs in Statamic 3.

Duplicate ID Identifier & Fixer for Statamic 3

Instructions:

  • Copy the contents of this gist's console.php into routes/console.php
  • Run php artisan identify-duplicates

At the start of the script, it will ask you if you want to replace any identied duplicate IDs. If you choose to do so, new Stache IDs will be generated and the Laravel cache will be cleared.

<?php // copy everything after this line
Artisan::command('identify-duplicates', function () {
$duplicates = [];
$shouldFixDuplicates = $this->confirm('Should Duplicate IDs be replaced with fresh IDs?');
$items = collect(\Illuminate\Support\Facades\File::allFiles(__DIR__.'/../content'))
->filter(function ($file) {
return $file->isFile();
})
->map(function (SplFileInfo $file) {
$data = \Statamic\Facades\YAML::parse(file_get_contents($file->getRealPath()));
return [
'path' => $file->getRealPath(),
'stache_id' => isset($data['id']) ? $data['id'] : null,
];
})
->reject(function ($item) {
return is_null($item['stache_id']);
});
$items->each(function ($item) use (&$duplicates, $items) {
$itemsWithCurrentId = $items->where('stache_id', $item['stache_id']);
if ($itemsWithCurrentId->count() > 1) {
if (array_key_exists($item['stache_id'], $duplicates)) {
$duplicates[$item['stache_id']] = array_merge($duplicates[$item['stache_id']], [
$item['path'],
]);
} else {
$duplicates[$item['stache_id']] = [
$item['path'],
];
}
}
});
foreach ($duplicates as $id => $items) {
$this->error("Duplicate ID Found: {$id}");
foreach ($items as $item) {
$this->line($item);
if ($shouldFixDuplicates) {
$contents = file_get_contents($item);
$contents = str_replace($id, \Statamic\Facades\Stache::generateId(), $contents);
file_put_contents($item, $contents);
}
}
$this->line('');
}
if ($shouldFixDuplicates) {
Artisan::call('cache:clear');
$this->info('Duplicate IDs have been replaced and your Cache has been cleared. Have a good day!');
}
});
@jmartsch
Copy link

The success message should only be triggered if there were duplicate IDs.
I also think it is better to tell the user if there are duplicate IDs and ask him then if he wants to replace them.

@duncanmcclean
Copy link
Author

The success message should only be triggered if there were duplicate IDs.
I also think it is better to tell the user if there are duplicate IDs and ask him then if he wants to replace them.

Yeah, I might need to refactor the way that's done.

@sheldonkotyk
Copy link

sheldonkotyk commented Jan 22, 2021

I don't think this is working anymore. Here's my pages.yaml

revisions: false
route: '{parent_uri}/{slug}'
structure:
  root: true
  tree:
    optimaliving:
      -
        entry: home
      -
        entry: 4cb7317c-2d05-4ec3-8ba4-acca5da67b9d
        children:
          -
            entry: 3e165f06-ad6a-4d6d-8ffa-56463683e135
            children:
              -
                entry: 9afebbdd-8ce3-41aa-9e15-6ce0c12c9e58
              -
                entry: 2cf6fc2a-ec6c-41b5-8b26-fc5be8a14420
          -
            entry: ae092d2b-24ce-4bfc-8ab9-30b441a1034a
            children:
              -
                entry: de922ec7-a0ec-4154-8d4b-8281f3199f4d
              -
                entry: bb164485-093c-452b-96de-586874f96316
              -
                entry: d70303a2-28b8-46b0-8b35-fff0b802b634
              -
                entry: f094fb0d-1ac6-4fe4-96b9-a1d85858af8e
              -
                entry: 0f04564b-3dc6-4ee9-be23-7c9d3608bf0e
              -
                entry: 2b019110-38a1-4ae0-9ee3-ce9a66102a8a
              -
                entry: 870c6c1c-e2c0-4233-aac2-cdf0db9f661a
      -
        entry: 06d67bc8-b7c5-46ba-8afa-6f5dd0548f98
        children:
          -
            entry: 972d56a8-541c-4ee9-a73d-c95f620ee9b4
          -
            entry: b12a8053-768a-4ac1-b99b-8e0a588184d2
          -
            entry: 2062cc8c-150a-4927-8008-ac9d0c114387
      -
        entry: bc4acf1f-eb62-4f87-b43f-f6bef9892fdb
      -
        entry: ad28eb16-cf0a-4ef5-bf4e-24239c542580
        children:
          -
            entry: 5fffa1f8-4549-45d7-9182-0b756522d7a1
          -
            entry: 5bcb8044-46d8-463a-a6a8-725689842d94
          -
            entry: 3134b6dd-bd44-4432-be27-5539d4cae113
      -
        entry: da84ec8d-9945-4436-81a1-5923f13171bb
      -
        entry: e02afce5-3158-4028-893d-3351e3f1d5b9
        children:
          -
            entry: 8bd0b9be-525c-455e-9e03-43684d10e14a
          -
            entry: 1c881f3c-1d1e-4d61-9bc9-a2907ae771eb
          -
            entry: dfe33ce6-3dab-40ca-9f03-b0db77db6911
          -
            entry: d5fbb07d-4e7e-4a09-ac2b-6ecd98f43da4
          -
            entry: bb021c4d-dce2-4c6a-9e09-2165649ea99a
      -
        entry: de14bb7b-8709-4dff-919c-5cd5f81ece99
      -
        entry: 22feafe8-0d50-45b9-b751-0a1b4cb09644
      -
        entry: 52f0ade1-0ae3-4613-8e62-16f6da5390f0
      -
        entry: 1643df7d-c2ae-4c8f-8c99-78401aa69417
      -
        entry: a7bbb52d-d9a9-4e48-8916-5dcffa417fa9
      -
        entry: 552b8329-7eb0-46f8-a741-1e9280aed326
      -
        entry: 1c79d3e3-d974-452f-85ec-75d908807233
      -
        entry: 1a28bce5-6d3b-40a4-99bf-552356b9b097
      -
        entry: a06f9015-34df-4b48-b0c3-2698475a9338
      -
        entry: d96429d4-a5e5-4465-a58c-86e9401b4300
    wisteriaplace:
      -
        entry: 67c5c119-e1bd-4042-a2fb-61641f542417
      -
        entry: ca99526d-cbe7-40b3-8d81-2df7bff7b013
      -
        entry: f380572d-d441-4fb9-8b7b-8c3e86e05466
        children:
          -
            entry: dffb83dd-6aff-4ee0-80bc-59a967e7a664
          -
            entry: b164b4a6-3641-4e3a-a638-6b7f4f44ca03
          -
            entry: 0713f379-5178-49e6-8fcb-d0572e7c0b2c
          -
            entry: e19003ed-c7fa-42ae-a882-9173b34498d6
          -
            entry: 461766b0-1a96-4c38-b582-5e6fb1621061
      -
        entry: df384d7c-6f99-476e-bc31-d7e1eca7a23c
        children:
          -
            entry: 4a2d2347-d108-4f1c-9fcc-231704674f4f
          -
            entry: 19e46cbd-4a74-4521-9333-9fa85ca72de9
      -
        entry: 22fca943-57af-415e-a1f0-22035b8afbd8
      -
        entry: 20a40160-81be-4d50-8148-5250b3c6d499
      -
        entry: c0e4250b-da18-4f82-8114-ce82b05c5350
      -
        entry: c27d813c-7a0c-4dd5-a15b-c6be0e667bf4
      -
        entry: 706fc927-9508-4456-bf8e-0a895fb9cf1b
      -
        entry: f1a7a394-8d20-408c-867e-f544552b5b7a
      -
        entry: 7fda5012-2253-4221-be18-cf82126febc8
      -
        entry: 14102812-07bb-472c-a0a6-985bfca33810
      -
        entry: 7782ee2b-aa96-4191-9089-c809745790a9
      -
        entry: bb0980e2-d00e-4d40-9e84-f1133035ce35
    wildrose:
      -
        entry: b418f0a4-20c3-4091-9636-9ead96012399
      -
        entry: 644b2f46-b16c-42bb-8ae3-7c947c8189c4
      -
        entry: 745e40b9-3ac7-410e-9ec2-90c6e0da5eb3
      -
        entry: ebe0c482-da67-471c-a6f9-30d4e87e4ad0
      -
        entry: cef3a8ae-ce62-4880-b0ce-b1f0ca9a5280
      -
        entry: f0de3150-9e27-499b-b482-d3b211bd223e
      -
        entry: 0d97bdb1-9248-4a35-8e7a-4d35d37e2530
      -
        entry: a7d1b85b-af87-4c11-820c-56aabedfa2ce
      -
        entry: fa47dcf8-0111-4d40-b06d-648ac9523133
      -
        entry: f8c466ee-8d79-48ae-a1d3-5a4774f0eca8
      -
        entry: a7bd2d1f-aa35-4792-b2e8-8abdd15a4b88
        children:
          -
            entry: 80a36bbe-e912-4392-86e4-9a8817f3eca1
          -
            entry: 4bccbcc9-d10a-4fe8-a247-1dbe49d40a08
          -
            entry: f27b2f93-4e4e-4e97-889b-50abd80ab928
          -
            entry: d081ec23-4bb2-4b43-bd05-55732799c19b
    centurypark:
      -
        entry: 29f9ed95-7794-4cb0-ad02-ed288457cca5
      -
        entry: 62c4080b-3b02-4405-906f-ce5a66e557bb
    cottonwoodvillage:
      -
        entry: dc98758f-78d9-4063-9e18-56ad95ccc62c
      -
        entry: bcc3567d-8457-4b5f-8856-460c4ec45528
      -
        entry: 5596a0a4-7e6a-44b2-befb-568092da01f2
      -
        entry: 065978b6-10d4-4502-8cf1-aba43c716a26
      -
        entry: 7b54ce61-8ee4-448a-a75e-1c9076b629d8
      -
        entry: 96d8f1f2-f19f-4cce-ada3-ac956a3403c7
        children:
          -
            entry: fa7cb1ae-5da0-4df7-befd-2b3837c8aaef
          -
            entry: 97fb1ca1-7ab0-4b7f-a227-61c212c26d04
          -
            entry: e8e179d5-1a26-418c-ad36-549e0816413e
      -
        entry: 6fb67903-7588-49c8-a4b4-24d528901ad9
      -
        entry: 1ca99bcd-51e8-4048-9853-634ea062984a
      -
        entry: a8c53058-1a7a-446f-bacc-d14481898637
      -
        entry: abcd89f1-db45-49f1-b177-58450661892c
      -
        entry: a517a025-9698-4f71-966f-16a2cc886278
        children:
          -
            entry: f27577ab-933d-42a5-a213-9799cc82fa1f
          -
            entry: 13bd5554-c582-4b4b-9b80-88086abd2655
          -
            entry: cd620594-7329-47f8-9c0e-860ce38cb759
          -
            entry: 1dcbab6f-23f4-4d53-8f5e-07d9ff4ce416
      -
        entry: 242fbcc2-f36e-4791-9a86-dd54a073a6c6
      -
        entry: 8573cbbb-be56-41c1-968a-04b630dc239b
      -
        entry: 8897a859-dc00-494d-b436-2abc332b50b4
    chilliwacklifestyles:
      -
        entry: 3b7c2f94-5763-4f1a-bc60-143614b09542
      -
        entry: 2d0b4087-d83c-4825-8bf3-56421afa77d7
      -
        entry: 1a5d98d3-84c2-42c8-a878-ae632fb2adc3
      -
        entry: 777183d7-5897-43d3-9ef7-272f28727e17
      -
        entry: 6c9a1f15-2715-41cb-8441-471a4bbf9fa7
      -
        entry: fa74af47-5e93-40ab-9f93-6a7d5e9977e7
        children:
          -
            entry: 98f3402f-d9db-40f7-bfcd-fa3daccacb5c
      -
        entry: 1b268784-5738-48ba-a912-d79cae0d1a0e
      -
        entry: 557b0fd7-06b7-4317-ae86-10313ed02b9e
      -
        entry: e49eb575-689e-4ab8-be39-b8b8a66b0417
      -
        entry: 04288241-bbbe-4374-a067-48de4b3bb5d8
      -
        entry: b34561fe-92c8-4c3c-83fd-fa99cbc710ff
        children:
          -
            entry: 93d6d44d-1c42-49d0-a452-cee82283ed0c
          -
            entry: 3568c146-b834-4e00-92bf-2195b595ed70
          -
            entry: c506a089-776c-466a-8c5c-062fbc933af2
          -
            entry: ce61f4d0-fd9b-42dd-a15f-a1454fd3288a
      -
        entry: 5dfbaf04-27bf-49e1-94b5-1766fd044209
      -
        entry: bc45c6e7-f9e9-46b6-a0d4-9d961ef0d1d3
      -
        entry: fcb9f36f-78a7-4222-9ba7-fd19192e621e
    normanmanor:
      -
        entry: 618a74ba-3b6a-4bea-8612-9ff62369e009
      -
        entry: f030f490-4b8d-42fa-8ce0-cc15ad7787a9
        children:
          -
            entry: 666cde74-c330-4885-8e8d-a3421724713e
      -
        entry: 08e2cc1b-ac13-411f-b633-3e8263141dc3
      -
        entry: 19733744-6b48-47ef-a3aa-0eafdab01825
      -
        entry: 7ecd3092-e6a3-4ea0-8668-f2fc4b92c807
      -
        entry: fa32a7df-e971-47aa-96e7-14570ab25939
      -
        entry: 661fac1e-e67e-4647-a851-84962fe73bac
      -
        entry: 67dc004a-ca1f-495f-a24b-9f06444b1a34
      -
        entry: cd8f6bcd-27d7-48f8-b5a9-434ccae9f290
      -
        entry: 056a2e15-8dcf-4b88-bca7-bc139a99feee
        children:
          -
            entry: 457aab77-bc38-4733-b7f6-8475c74c52a3
          -
            entry: b8cc2f54-0499-457a-b466-38d06a92e76a
          -
            entry: 0045a04e-bc4a-414a-b755-22c8c55f1bfb
          -
            entry: f89259c5-d648-41f8-8b93-a45b16dbc9f7
      -
        entry: 191eae81-1029-4bf6-b683-d2e1bf0aea9a
      -
        entry: 33c29af0-4185-425a-a94f-c70688868cf0
      -
        entry: 64d98167-2363-487b-ae6a-a8f66be2d705
    riversidemanor:
      -
        entry: 3a9625c9-cf86-4fdf-ac73-3c9bfe0693ac
      -
        entry: 873e1c1d-4005-49b1-89ea-50795e6f235d
        children:
          -
            entry: 92cfdc41-c6aa-4b1d-84cc-8dafa3547d5e
      -
        entry: 9921c0c9-3934-4fc2-a4c6-7a21f1a4624d
      -
        entry: 8281b015-ddb9-4f67-9cff-6459adc561ae
      -
        entry: dfd8ed53-b3cb-41dd-ba73-f42342887c85
      -
        entry: 20117afd-8296-4bd5-b7ee-2de8ed6d8e4e
      -
        entry: 17415b29-b4b8-45cf-a3ed-1bbc7b2a5835
      -
        entry: 54769fcd-6e85-47fe-bc20-2dbd4e509820
      -
        entry: b0add32a-7052-4cbe-bc48-400b9912ded0
      -
        entry: 6bf11f92-4b72-4f19-9b35-110850f12d76
        children:
          -
            entry: c4b2dd55-6c20-43a0-88ea-0a43e73a0ca1
          -
            entry: e717295c-d5e3-4d8a-b07a-400f8d327ef3
          -
            entry: 9dd39324-a738-4440-8569-cca8e8a4e49d
          -
            entry: bd861c51-0905-469b-bcc5-1e0e6cacfd85
      -
        entry: 56184787-d279-476d-9f1e-3d39a80c5c94
    royalcrescentgardens:
      -
        entry: 586b7aa3-4f88-48e2-bc4a-c663f4644da2
      -
        entry: 5ba3dad0-cb47-4fa2-8b32-172f87c40d85
        children:
          -
            entry: 35720b8e-fe3e-414b-9910-d85147e1ffd2
      -
        entry: 02e0e1df-1190-4eb1-9d74-6bca7e3aa08b
      -
        entry: 6389aca6-adfb-4713-9b25-ae9590d1cab4
      -
        entry: 4e8b20ea-ecf4-455e-802e-b159fdb3219b
      -
        entry: eb201f8d-54cf-4f46-a308-90998c672ac6
      -
        entry: b98fc448-aa53-4d94-9c32-c5705a99305d
      -
        entry: c71cb61e-0f25-43fc-b961-294006302cf6
      -
        entry: d6e21d34-46f9-4302-9c9b-5e681d6d89db
      -
        entry: f965ce9a-ee92-4fc7-a537-4dbefa636e97
        children:
          -
            entry: e22c6c8e-7019-4dcd-b1f6-a852ed4246de
          -
            entry: 610b4327-1e13-4e63-baf0-40f5da54391a
          -
            entry: e14cc92d-0378-4acf-95d6-2f88718643b8
          -
            entry: 33a37e3a-4233-463f-b332-c734b15fb2a1
      -
        entry: 1080ccef-1a57-445f-aa84-b43840cf4522
      -
        entry: f08987cf-a75b-44b5-a3e3-758d85c135ef
    westvancouvercarecentre: {  }
    willowmanor:
      -
        entry: fe328d6f-8af3-4d5b-8ba4-10bceca39d67
      -
        entry: c14d8c68-4b8f-4c27-81fb-72ccaaaaf0d1
        children:
          -
            entry: fd595d90-f79a-418a-b592-f78dffd3589e
      -
        entry: f1e6f82b-773f-412f-80be-8b30508c2ba2
      -
        entry: 2a3d9918-ab7b-4a61-878a-8f806540668e
      -
        entry: ed3fd8bf-19a6-4ae0-b696-d488c47013fb
      -
        entry: 6c2f0fdc-3f1c-4659-86f0-ebe0470a082c
      -
        entry: 82efa666-ce75-498c-b376-0eac2ee48263
      -
        entry: 9b3f9d9f-02fb-439f-b1de-6ccb5d01e28c
      -
        entry: 1c72291e-0e25-4885-95f4-8f8193ef647a
      -
        entry: 0de4a64d-d168-427d-814e-8c65cdc44f66
        children:
          -
            entry: 54c6c969-5f60-43b3-9035-cb23c290cd9f
          -
            entry: f8a94d9e-b05d-4529-84e9-ba5b1d8e8a74
          -
            entry: e50e7fd0-786d-4479-af0f-ecfb0df27bce
          -
            entry: 25046565-ab99-4df5-a8c8-32c3d553d7f0
      -
        entry: 6ab85bb0-93a7-44c4-af19-7cfa71b236f5
    whiteheathermanor:
      -
        entry: 529f7cf6-a63f-439e-9717-42820a9ded88
      -
        entry: 1936528c-0c23-4f0e-ad0e-706aa0883e05
        children:
          -
            entry: e74ee9d9-4ec1-4ec4-9686-30885bbf0ee0
      -
        entry: b5f4aab2-ff19-4cf0-a54b-238bcccfde6e
      -
        entry: 2be47bf5-6486-42fc-b117-40614dfcc779
      -
        entry: a8d9e2cd-7f9f-4b1f-b6f2-e1d4b0d011c1
      -
        entry: 6873c758-b34e-4d45-aea2-be002a841c80
      -
        entry: 3b6507bf-8668-4175-9019-0644f5b49d3e
      -
        entry: 276b3e86-8e79-4f12-b4b0-51211c856c82
      -
        entry: 68020378-0c22-40a3-bde5-f8cc2233a977
      -
        entry: 03b306a5-ed01-4743-9df1-3104523f5833
        children:
          -
            entry: bf080351-63c3-44e8-8388-df12043ebdaa
          -
            entry: 32f9517c-8313-4e21-8320-cd14ead0e95e
          -
            entry: 8695cc12-f7ec-4814-bcf5-ed1a533bc62a
          -
            entry: 5f5d1e12-35da-4770-84b3-afbe436bfea7
      -
        entry: 844a5760-bf9e-4004-ac6a-92062fa9307b
    aspenhousecareresidence:
      -
        entry: 143fc208-a02a-4a9a-b36e-c54c7d7a674b
      -
        entry: de0a2ea7-9501-4685-abdb-f67ec6e0b9be
      -
        entry: fc555d25-86c7-41ae-b753-910b9c144cb2
      -
        entry: f4f4aa61-1cfd-4e2e-90cf-03b0d3280e17
      -
        entry: a4c1b8f3-2408-4e17-928b-10bd6e69bcbc
      -
        entry: 751b8429-cc51-45dd-bcab-bfcd7eb6309d
      -
        entry: 4bd02c82-70a5-4770-b013-d9dfb1491c4f
      -
        entry: 4b0bb77a-e3c2-468c-b3c8-ad667a4ff03c
      -
        entry: 93dfa840-ee0b-4df9-9ec3-b7958f10c8d4
      -
        entry: 3373b902-dc64-476c-bf32-aea3e4a26c10
        children:
          -
            entry: b269f1e8-4c5f-4cbd-80da-240d065a2994
          -
            entry: e6f12226-c5cd-4cfb-9b01-a561f1cc52db
          -
            entry: 6d93e3e6-25cc-4857-bd2e-0e82f514c954
    astergardens:
      -
        entry: 00685b6a-0caf-4270-a5bd-12e80e5e91b0
      -
        entry: d0210baa-a512-4e1f-87cc-69e4ea16e82d
      -
        entry: 17a664b0-f256-4ee7-8bbd-910d1a658518
      -
        entry: f15d881a-a07c-4733-98fa-e09f20100537
      -
        entry: f266acb4-dc8a-481e-ac84-5dd20c6a6574
        children:
          -
            entry: 8adc245e-2438-4410-a0c5-ea580d446979
      -
        entry: a0277c84-3672-46f0-a7ef-ab111f1c9815
      -
        entry: 93f8f1b0-86fb-4173-85ee-124d618af248
        children:
          -
            entry: 9994e230-9895-45f0-bd9d-effd902bc4ef
          -
            entry: ffbc529a-b983-4b21-a7e0-b486c208a1c0
          -
            entry: 23b83afe-8986-487a-844b-3828722e162d
          -
            entry: 41fdb491-9fdd-4da1-ab1a-76b31d385061
          -
            entry: ef4f4e2a-fa5c-4344-b806-bc68ad79fa71
      -
        entry: acf274ce-69c3-47c3-8400-aaf81571d996
      -
        entry: f15d881a-a07c-4733-98fa-e09f20100537
      -
        entry: a0277c84-3672-46f0-a7ef-ab111f1c9815
      -
        entry: 17a664b0-f256-4ee7-8bbd-910d1a658518
    countrycottage:
      -
        entry: 1fd4b185-2b64-45ec-a2e4-cf59128d957f
      -
        entry: 2e9ebfc8-9680-4c18-947f-953a07a46e86
      -
        entry: 209a6659-1510-4905-a5df-e6ecde33e6a2
      -
        entry: cc23bb4f-432a-4377-a54a-3e6e68fecb45
      -
        entry: 34ea85cb-1145-47d0-8be0-0ef930b4d964
      -
        entry: a00ff0b4-6100-4169-834e-113f191865b0
      -
        entry: a9a4f2f1-a17b-4b8c-9602-836f565b15f1
      -
        entry: 86879599-96c2-47c4-86ba-70b0ef98d9d5
      -
        entry: d1d53373-518f-45a4-bf69-e9b0ffb7d672
        children:
          -
            entry: aef34d5f-c195-45c3-bb73-1b519c2685fd
          -
            entry: e7e89c5d-4aaf-4d7e-9ac5-6f9d4f2176c7
          -
            entry: 0c9993c2-5e3e-4574-a247-138b15ef63a9
          -
            entry: bf8a2b85-876e-47af-bac6-2ed8f3bd95c7

@duncanmcclean
Copy link
Author

duncanmcclean commented Jan 22, 2021

Hmm, this tool won't fix your collection's yaml file. It'll only fix the IDs in the entry files themselves. I could look into it if I have enough time this weekend.

@sheldonkotyk
Copy link

its ok, I found the dupes.

@jacksleight
Copy link

I tweaked this slightly to also check for duplicate users:

Artisan::command('identify-duplicates', function () {
    $duplicates = [];
    $shouldFixDuplicates = $this->confirm('Should Duplicate IDs be replaced with fresh IDs?');

    $items = collect()
        ->merge(\Illuminate\Support\Facades\File::allFiles(__DIR__.'/../content'))
        ->merge(\Illuminate\Support\Facades\File::allFiles(__DIR__.'/../users'))
        ->filter(function ($file) {
            return $file->isFile();
        })
        ->map(function (SplFileInfo $file) {
            $data = \Statamic\Facades\YAML::parse(file_get_contents($file->getRealPath()));

            return [
                'path' => $file->getRealPath(),
                'stache_id' => isset($data['id']) ? $data['id'] : null,
            ];
        })
        ->reject(function ($item) {
            return is_null($item['stache_id']);
        });

    $items->each(function ($item) use (&$duplicates, $items) {
        $itemsWithCurrentId = $items->where('stache_id', $item['stache_id']);

        if ($itemsWithCurrentId->count() > 1) {
            if (array_key_exists($item['stache_id'], $duplicates)) {
                $duplicates[$item['stache_id']] = array_merge($duplicates[$item['stache_id']], [
                    $item['path'],
                ]);
            } else {
                $duplicates[$item['stache_id']] = [
                    $item['path'],
                ];
            }
        }
    });

    foreach ($duplicates as $id => $items) {
        $this->error("Duplicate ID Found: {$id}");

        foreach ($items as $item) {
            $this->line($item);

            if ($shouldFixDuplicates) {
                $contents = file_get_contents($item);
                $contents = str_replace($id, \Statamic\Facades\Stache::generateId(), $contents);
                file_put_contents($item, $contents);
            }
        }

        $this->line('');
    }

    if ($shouldFixDuplicates) {
        Artisan::call('cache:clear');
        $this->info('Duplicate IDs have been replaced and your Cache has been cleared. Have a good day!');
    }
});

@duncanmcclean
Copy link
Author

Ah thanks! I'll add that to the main version of the script after work.

@Sennik
Copy link

Sennik commented Feb 16, 2024

I am trying this today on a multisite and it produces this error:

 Statamic\Yaml\ParseException

  The YAML value does not appear to be valid UTF-8.

  at storage/statamic/tmp/yaml/d985620e8891be4a9502b9a1b190e805:-1

Is this script still actual?

@duncanmcclean
Copy link
Author

It probably means you have some invalid characters in one of your YAML files. This script is no longer relevant since you can now resolve duplicate IDs in the Control Panel.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment