Laravel-Backpack / revise-operation

An admin interface for venturecraft/revisionable - audit log for your Eloquent entries.
Other
42 stars 10 forks source link

Revisions and Translation Issue - double json encode #20

Open Spodnet opened 7 years ago

Spodnet commented 7 years ago

I've been testing the revisions code with translations, and it appears to double encode and add the content as a language when a revision is made.

Change 1 From: {"en":"Test"}

Change 1 To: {"en":"Changed Test"}

Then undo the change:

Change 2 From: {"en":"Changed Test"}

Change 2 To: {"en":"{\"en\":\"Test\"}"}

This appears to happen when update() is called, the translation trait checks the field is translatable and adds the locale on. I thought possibly saving direct:

$entry->{$revision->key} = $revision->old_value; $entry->save();

would work but it doesn't seem to save correctly either

welcome[bot] commented 2 years ago

Hello there! Thanks for opening your first issue on this repo!

Just a heads-up: Here at Backpack we use Github Issues only for tracking bugs. Talk about new features is also acceptable. This helps a lot in keeping our focus on improving Backpack. If you issue is not a bug/feature, please help us out by closing the issue yourself and posting in the appropriate medium (see below). If you're not sure where it fits, it's ok, a community member will probably reply to help you with that.

Backpack communication channels:

Please keep in mind Backpack offers no official / paid support. Whatever help you receive here, on Gitter, Slack or Stackoverflow is thanks to our awesome awesome community members, who give up some of their time to help their peers. If you want to join our community, just start pitching in. We take pride in being a welcoming bunch.

Thank you!

-- Justin Case The Backpack Robot

tabacitu commented 7 years ago

Hi @Spodnet , thank you for reporting this. It seems to be the same issue as Laravel-Backpack/revise-operation#20 so let's move the conversation there. Cheers!

ASVVIZIT commented 3 years ago

Hello. Sorry for my bad english.

Is this problem still not resolved?

On any return of the revision, there is a wrapper in the default localization

It looks like this {"ru": "{\" ru \ ": \" {\\ "ru \\": \\ "\\ u041e \\ u0442 \\ u0447 \\ u0451 \\ u0442 Voluptas quidem assumenda et non beatae. \\ "} \"} "}

This is three times the return of the field revision

It looks like the HasTranslations component

when creating any entry in $ translatable fields

Creates a json "en" wrapper

Please help me to figure out at what stage the localization key is substituted.

pxpm commented 3 years ago

Hello @ASVVIZIT this issue is from 2017.

Not sure what was it though. What version are you using ? Run:

php artisan backpack:version

Also when you change languages in configs clear config cache `php artisan config:clear.

If in the later versions 4.1 of backpack, please open a new issue, and provide steps to reproduce it.

Thanks, Pedro

phpust commented 2 years ago

dear @tabacitu , i changed restoreRevision function in ReviseOperation.

https://github.com/Laravel-Backpack/revise-operation/blob/eb0401021fc784e35a948d5a56040279b82c4d68/src/ReviseOperation.php#L109

new code is :

public function restoreRevision($id)
    {
        $this->crud->hasAccessOrFail('revise');

        $revisionId = \Request::input('revision_id', false);
        if (! $revisionId) {
            abort(500, 'Can\'t restore revision without revision_id');
        } else {
            $entry = $this->crud->getEntryWithoutFakes($id);
            $revision = Revision::findOrFail($revisionId);

            // save current entry and revision temporary
            $this->data['entry'] = $entry;
            $this->data['revision'] = $revision; 

            // check if revision key is translatable in $entry model
            if( $this->isTranslatable($revision->key) ) {
                $this->prepareTranslationsForRevision();

                $this->forgetLocalesThatAreNotExistInRevision();

                $this->returnForgettenLocalesThatAreNotExistInCurrentVersion();

                $this->updateAllLocalesThatAreCommonInOldAndCurrentVersion();

                $entry->update();
            } 
            else {
                // Update the revisioned field with the old value
                $entry->update([$revision->key => $revision->old_value]);
            }

            $this->data['entry'] = $this->crud->getEntry($id);
            $this->data['crud'] = $this->crud;
            $this->data['revisions'] = $this->crud->getRevisionsForEntry($id); // Reload revisions as they have changed

            // Rebuild the revision timeline HTML and return it to the AJAX call
            return view($this->crud->get('revise.timelineView') ?? 'revise-operation::revision_timeline', $this->data);
        }
    }

    private function isTranslatable($key)
    {
        return method_exists($this->data['entry'], 'isTranslatableAttribute') && 
                $this->data['entry']->isTranslatableAttribute($key);
    }

    private function prepareTranslationsForRevision()
    {
        $this->data['old_values'] = $this->data['entry']->fromJson($this->data['revision']->old_value, false);
        $this->data['current_values_locales'] = collect($this->data['entry']->getTranslatedLocales($this->data['revision']->key));
        $this->data['old_values_locales'] = collect(array_keys($this->data['old_values']));   
    }

    private function forgetLocalesThatAreNotExistInRevision()
    {
        foreach ($this->data['current_values_locales']->diff($this->data['old_values_locales']) as $locale) {
            $this->data['entry']->forgetTranslation($this->data['revision']->key, $locale);
        }
    }

    private function returnForgettenLocalesThatAreNotExistInCurrentVersion()
    {
        foreach ($this->data['old_values_locales']->diff($this->data['current_values_locales']) as $locale) {
            $this->data['entry']->setTranslation($this->data['revision']->key, $locale, $this->data['old_values'] [$locale]);
        }
    }

    private function updateAllLocalesThatAreCommonInOldAndCurrentVersion()
    {
        foreach ($this->data['old_values'] as $locale => $revisionTranslation) {
            if( $revisionTranslation !=  $this->data['entry']->getTranslation($this->data['revision']->key, $locale)) {
                $this->data['entry']->setTranslation($this->data['revision']->key, $locale, $revisionTranslation);
            }
        }
    }

it is ugly but do the trick

tabacitu commented 2 years ago

Hi @phpust ,

Thanks for sharing your code. What version of Backpack are you using?

Cheers!

phpust commented 2 years ago

Hi @phpust ,

Thanks for sharing your code. What version of Backpack are you using?

Cheers!

I use backpack version 5.

request-info[bot] commented 2 years ago

Hi there!

Could you please provide us with more info about this? Looks like you skipped the title/body.

Thank you!

-- Justin Case The Backpack Robot