riasvdv / statamic-data-import

MIT License
14 stars 8 forks source link

Import data with Entries Fieldtypes #28

Open albertvisuals opened 1 month ago

albertvisuals commented 1 month ago

Hello,

I would like to use the add-on to import several collections. They are linked with multiple Entries Relationships between them. The issue is that the import writes the title in the md file, which leads to an "ID not found" error on the control panel. IT happens with relationships between collections (entry fields) as well as taxonomies.

Is there any way to get the import to actually create the related entry, if not already found the same title on the related collection?

Thanks a lot!

Collection photographer: --- id: 4d57d874-43ac-457a-a1bd-be5b0ce21671 blueprint: fotografen title: 'Eugéne Atget' ---

Collection Books: `--- id: be8816fb-5927-47fb-bdb2-b0441b139f78 blueprint: buecher title: 'Atget Eugène' herausgeber:

albertvisuals commented 1 month ago

I have found one possibility to fix it after importing the main collection with this script. I will look up all entries and create new ones in the related collection and correct the link to ID. It uses the title to match. You need to empty the cache afterwards as the entries appear duplicated in the CP, but they are not.

<?php

use Statamic\Facades\Entry;
use Statamic\Facades\YAML;

function findOrCreateEntry($collection, $title) {
    $title = trim($title);
    $entry = Entry::query()
        ->where('collection', $collection)
        ->where('title', $title)
        ->first();

    if (!$entry) {
        $entry = Entry::make()
            ->collection($collection)
            ->slug(strtolower(str_replace(' ', '-', $title)))
            ->data(['title' => $title]);
        $entry->save();
        echo "Created new entry in {$collection}: " . $title . "\n";
    }

    return $entry->id();
}

function updateEntries($sourceCollection, $targetCollection, $fieldToUpdate) {
    $entries = Entry::query()->where('collection', $sourceCollection)->get();
    $updatedCount = 0;

    foreach ($entries as $entry) {
        $data = $entry->data()->toArray();
        $updated = false;

        if (isset($data[$fieldToUpdate]) && is_array($data[$fieldToUpdate])) {
            $updatedField = [];
            foreach ($data[$fieldToUpdate] as $value) {
                if (!is_string($value)) {
                    $updatedField[] = $value; // Keep non-string values as-is
                    continue;
                }
                $targetId = findOrCreateEntry($targetCollection, $value);
                $updatedField[] = $targetId;
                $updated = true;
            }
            $data[$fieldToUpdate] = $updatedField;
        }

        if ($updated) {
            // Update the entry in place without creating a new one
            $entry->data($data)->save();

            // Update the markdown file
            $path = $entry->path();
            $content = YAML::dumpFrontMatter($data) . "---\n";
            file_put_contents($path, $content);

            echo "Updated entry in {$sourceCollection}: " . $entry->get('title') . "\n";
            $updatedCount++;
        } else {
            echo "No update needed for entry in {$sourceCollection}: " . $entry->get('title') . "\n";
        }
    }

    echo "Finished updating entries in {$sourceCollection}. Total updated: " . $updatedCount . "\n";
}

// Example usage (to be called from Tinker):
// updateEntries('buecher', 'fotografen', 'fotografie');
// updateEntries('$sourceCollection', '$targetCollection', '$fieldToUpdate');