2

I have an entry with a readonly json field (Jason plugin). This field is populate with data from an external api. So I have a button in my entry page that call a custom route which call the api and save the data in the entry. This part works fine.

My problem is when I click on my button, a draft is created before action is done. Since I'm not using the save button from craft, the draft is not deleted and when I go back to the entry I have this notice:

Recent changes to the Current revision have been merged into this draft.

But the json data is not updated. If I cancel the changes (Showing your unsaved changes), the entry is fine.

Is there a way to avoid the creation of the draft when I click the button, or if I can delete the current in my custom code before saving the data?

Here's a snippet of the save:

$restaurant = Entry::find()
                ->section('restaurants')
                ->slug('restaurant-1')
                ->one();
$restaurant->setFieldValue('restaurant_schedules', Json::encode($schedules));
Craft::$app->elements->saveElement($restaurant);

Edit 1 :

The button is a simple route with the entry slug in the url that called this controller. (/sync/schedule/my-entry-slug) This controller create a new job in the queue that will update the entry.

public function actionSync($restaurantSlug)
{
    $restaurantService = new RestaurantsService();
    $restaurant = $restaurantService->getRestaurantBySlug($restaurantSlug);

    Queue::push(new ScheduleSingleJob([
                    'restaurant' => $restaurant,
                    ]),
                self::JOBS_PRIORITY
    );

    return $this->redirect('/admin/entries/restaurants');
}

Here's some screenshots of my steps.

  1. I click on the button in the sidebar
  2. Before the page is redirect to the link, a draft is created for my entry.

screenshot1

and when I come back after the queue is done, the draft is shown without the changes applied to the entry. (I need to click cancel draft to see them)

screenshot2

1
  • Hi. it seems the job is about one restaurant. so what if update and save the restaurant element in sync action and redirect to edit page like : return $this->redirect($restaurant->getCpEditUrl());
    – user9975
    Commented Jan 6, 2023 at 7:05

2 Answers 2

2

If I understand you correctly, this can work?:

if ($restraunt->isDraft) {
  return; // Skip draft
}

Or if not and you really want to purge ALL drafts, you can do this:

use craft\services\Drafts;
...

((new Drafts())->purgeUnsavedDrafts());

Just to clarify, does your button fire custom controller? Or are you saving data from the API in the event hook?

UPD:

Can you try this after you have saved your entry?

I just stole this piece of code from the entry controller

$provisional = Entry::find()
            ->provisionalDrafts()
            ->draftOf($restraunt->id)
            ->siteId($restraunt->siteId)
            ->anyStatus()
            ->one();
if ($provisional) {
            Craft::$app->getElements()->deleteElement($provisional, true);
 }
2
  • I 've edited my post with more informations. The button fire a custom controller that will create a job in a queue to update the entry. Commented Jan 5, 2023 at 14:25
  • The purgeUnsavedDrafts doesn't seem to work, I need to test furthermore if I can manage something while changing the purgeUnsavedDraftsDuration config. Commented Jan 5, 2023 at 14:34
1

I found a temporary workaround by deleting draft from my entry Id with a simple query.

use craft\db\Query;
use craft\db\Table;
    
(new Query)
     ->createCommand()
     ->delete(Table::DRAFTS, ['canonicalId' => $entry->id])
     ->execute();
2
  • Can you try my updated answer?
    – RomanAvr
    Commented Jan 5, 2023 at 21:45
  • The updated answer works after the entry save. Commented Jan 6, 2023 at 13:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.