Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Publishing model doesn't follow casts #17

Closed
SergkeiM opened this issue Feb 20, 2023 · 11 comments
Closed

Publishing model doesn't follow casts #17

SergkeiM opened this issue Feb 20, 2023 · 11 comments
Labels
bug Something isn't working

Comments

@SergkeiM
Copy link
Contributor

SergkeiM commented Feb 20, 2023

I have a Model with a column that is casted to array

protected $casts = [
        'my_col' => 'array',
 ];

After calling publish()->save() array is saved as wrapped in double quotes
image

@oddvalue oddvalue added the bug Something isn't working label Feb 20, 2023
@oddvalue
Copy link
Owner

I've run some tests and haven't been able to replicate this issue. Could you share a minimal example app that shows the issue I could work from?

@SergkeiM
Copy link
Contributor Author

I've run some tests and haven't been able to replicate this issue. Could you share a minimal example app that shows the issue I could work from?

Hi @oddvalue I will test it later today, something tells me that I have this issue becuase of the column nameattributes

@SergkeiM
Copy link
Contributor Author

SergkeiM commented Feb 22, 2023

I've run some tests and haven't been able to replicate this issue. Could you share a minimal example app that shows the issue I could work from?

Hi @oddvalue I will test it later today, something tells me that I have this issue becuase of the column name attributes

Hi @oddvalue Nope is not the case, modified column name from attributes to traits and still the same

Basically I have a model Page

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

use Oddvalue\LaravelDrafts\Concerns\HasDrafts;

class Page extends Model
{
    use HasDrafts, SoftDeletes;

    protected $table = 'pages';

    protected $attributes = [
        'name' => null,
        'traits' => "[]"
    ];
    protected $fillable = [
        'name',
        'traits'
    ];

    protected $casts = [
        'traits' => 'array'
    ];
}

Creating Draft via $page->updateAsDraft($request->all()) works fine

But as soon as I call $draft->publish()->save()
This

[{"type":"Text","value":"H1 Text","key":"h1"}]

is saved as this (in both Rows)

"[{\"type\":\"Text\",\"value\":\"H1 Text\",\"key\":\"h1\"}]"

@oddvalue
Copy link
Owner

@FROXZ I'm afraid I'm still not able to replicate this.

Using the example model provided, this test passes:

it('can create revisions without breaking casted attributes', function () {
    $post = Page::createDraft(['name' => 'foo', 'traits' => ['en' => 'Foo', 'de' => 'Baz']]);

    $post->traits = ['en' => 'Bar', 'de' => 'Qux'];
    $post->publish()->save();

    expect(Page::first()->traits)->toBe(['en' => 'Bar', 'de' => 'Qux']);
});

@SergkeiM
Copy link
Contributor Author

Hi @oddvalue

I'm digging through this now and it sound like laravel issue

Also try chaning your test to this and you need to have $casts = ['traits => 'array]

it('can create revisions without breaking casted attributes', function () {
    $post = Page::createDraft(['name' => 'foo', 'traits' => ['en' => 'Foo', 'de' => 'Baz']]);

    $post->publish()->save();

    expect(Page::first()->traits)->toBe(['en' => 'Bar', 'de' => 'Qux']);
});

See below (code from setLive:

$published = $draft->revisions()->published()->first();

$oldAttributes = $published->getAttributes();
$newAttributes = $draft->getAttributes();

Arr::forget($oldAttributes, $draft->getKeyName());
Arr::forget($newAttributes, $draft->getKeyName());

$published->fill($newAttributes);
$draft->forceFill($oldAttributes);

dd($published);

image

As you can see $published after force fill is json_encoded one more time.

@SergkeiM
Copy link
Contributor Author

SergkeiM commented Feb 22, 2023

So @oddvalue is not related this package, the solution here is to remove:

protected $casts = [
    'traits' => 'object'
];

And add only getter

protected function attributes(): Attribute
    {
        return Attribute::make(
            get: fn ($value) => empty($value) ? json_decode("{}") : json_decode($value),
        );
    }

OR

public function getAttributes()
    {
        $attributes = parent::getAttributes();

        foreach ($attributes as $name => $attribute) {
            if ($this->isJsonCastable($name)) {
                $attributes[$name] = $this->fromJson($attribute);
            }
        }

        return $attributes;
    }

@SergkeiM
Copy link
Contributor Author

SergkeiM commented Feb 22, 2023

Hi @oddvalue unless is ok to change this (lines)(https://github.com/oddvalue/laravel-drafts/blob/main/src/Concerns/HasDrafts.php#L172)

to (Including for relationship)

$oldAttributes = $published?->getOriginal() ?? [];
$newAttributes = $this->getOriginal();

This actually solves my issue with casting

@SergkeiM SergkeiM reopened this Feb 22, 2023
@oddvalue
Copy link
Owner

Hi @FROXZ I'm afraid that would subtly alter the functionality of the package so I won't be able to make that change. Also, I replicated a test exactly as you specified and it passed so I'm still not sure as to why you're experiencing the issue and I'm not.

@SergkeiM
Copy link
Contributor Author

SergkeiM commented Feb 23, 2023

Hi @oddvalue understand,

Maybe it is possible then to extract this

$oldAttributes = $published?->getAttributes() ?? [];
$newAttributes = $this->getAttributes();

To a function that can be overriden to have control over it? Becuase currently I've overriden the whole setLive function

Example:

protected function getDraftableAttributes{
      return $this->getAttributes();
}

$oldAttributes = $published?->getDraftableAttributes() ?? [];
$newAttributes = $this->getDraftableAttributes();

@oddvalue
Copy link
Owner

Yeah, happy to do that if you want to submit a PR

@oddvalue
Copy link
Owner

Added to v1.3.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants