Code Monkey home page Code Monkey logo

Comments (28)

toonvandenbos avatar toonvandenbos commented on August 25, 2024 7

Alright everyone, we got it (nearly) working. This was really a hard issue to solve and it could still have some issues since I didn't have the time to test it more extensively.

First things first: why is it nearly working? Because we have to wait for a fix on advanced-nova-media-library. I'd suggest you give the existing PR a thumbs up over there to get it moving faster.

How does it work?

  1. Spatie's MediaLibrary\HasMedia\HasMedia interface & MediaLibrary\HasMedia\HasMediaTrait should both be implemented on the resource model (not on the Flexible layout!) ;
  2. You can now use Whitecube\NovaFlexibleContent\Concerns\HasMediaLibrary and implement Spatie\MediaLibrary\HasMedia\HasMedia interface on your custom layout :
namespace App\Nova\Flexible\Layouts;

use Whitecube\NovaFlexibleContent\Layouts\Layout;
use Whitecube\NovaFlexibleContent\Concerns\HasMediaLibrary;
use Spatie\MediaLibrary\HasMedia\HasMedia;

class MyCustomLayout extends Layout implements HasMedia
{
    use HasMediaLibrary;

    // ...
}

I sincerely hope the PR on advanced-nova-media-library will be merged soon and that this will fix this issue.

from nova-flexible-content.

alex-osborn avatar alex-osborn commented on August 25, 2024 4

Hi all.

We have had the same issue Call to a member function getMedia() on array which we have resolved in our code.

Hard to provide a full working example as we have custom layout classes and a custom resolver (which saves to Laravel models).

However, below is the relevant function we needed to extend in our layout:

    /**
     * Resolve the field for display and return the result.
     *
     * Note, we're extending the method from
     * Whitecube\NovaFlexibleContent\Layouts\Layout
     *
     * We need to override the logic to provide an actual resource (this model)
     * to each field for resolveForDisplay().
     *
     * The parent layout class is
     * calling getAttributes() and then passing an array of attributes to each
     * field, which doesn't work with Spatie\MediaLibrary (requires a model)
     *
     * @return array
     */
    public function getResolvedForDisplay()
    {
        $this->fields->each(function ($field) {
            $field->resolveForDisplay($this);
        });

        return $this->getResolvedValue();
    }

We traced the issue to a conflict between Laravel\Nova\Fields\Field::resolveForDisplay() and Whitecube\NovaFlexibleContent\Layouts\Layout::resolveForDisplay(). The standard nova field expects a $resource, but the layout is passing through an array of attributes from $this->getAttributes(), hence the Call to a member function getMedia() on array.

from nova-flexible-content.

chrispage1 avatar chrispage1 commented on August 25, 2024 1

@Nyratas - it would be great if we could get a fix to get it working properly with flexible content. It's a bit of a blocker for us at the minute - we'd be happy to send a bit of money your way to buy yourself some beautiful Belgium beers!

from nova-flexible-content.

toonvandenbos avatar toonvandenbos commented on August 25, 2024 1

Released in v0.1.10, still waiting an update of advanced-nova-media-library.

If you need a quick fix, you could use a fork of advanced-nova-media-library that changes line 105 of src/Fields/Media.php to:

$attr = $request['__media__'] ?? [];

from nova-flexible-content.

toonvandenbos avatar toonvandenbos commented on August 25, 2024 1

Hi @chrispage1,

Indeed, sorry about that. Am working on a fix as we speak.

from nova-flexible-content.

toonvandenbos avatar toonvandenbos commented on August 25, 2024 1

Fixed in v0.1.11.

from nova-flexible-content.

ineghi avatar ineghi commented on August 25, 2024 1

On my side, everything seems to work exept attributes field is somehow empty.

from nova-flexible-content.

GarethSomers avatar GarethSomers commented on August 25, 2024 1

Hi @rbijkercom you need to use the layout key to get the media. I use something like this;
app(MediaRepository::class)->getCollection($model, 'flexible_images_' . $layout_key, []);

from nova-flexible-content.

voidgraphics avatar voidgraphics commented on August 25, 2024

We'll take a look and see if we can get it working. We'd also accept a PR if anyone wants to give it a go.

from nova-flexible-content.

toonvandenbos avatar toonvandenbos commented on August 25, 2024

Hi @reinvanoyen,

I pushed a commit that should solve a similar issue we had with another package. Could you check if the problem still exists when using "whitecube/nova-flexible-content": "dev-master" ?

Thanks!

from nova-flexible-content.

chrispage1 avatar chrispage1 commented on August 25, 2024

Hi @Nyratas @reinvanoyen - I've just come across this myself and I'm having the same issue, even with the dev-master branch. I'll see if I can dig about...

from nova-flexible-content.

chrispage1 avatar chrispage1 commented on August 25, 2024

Hi @Nyratas @reinvanoyen - I've just come across this myself and I'm having the same issue, even with the dev-master branch. I'll see if I can dig about...

No joy :( It'd take a long time to truly understand what's going on there for me

from nova-flexible-content.

reinvanoyen avatar reinvanoyen commented on August 25, 2024

Hi @reinvanoyen,

I pushed a commit that should solve a similar issue we had with another package. Could you check if the problem still exists when using "whitecube/nova-flexible-content": "dev-master" ?

Thanks!

Hi @Nyratas,

Thanks for looking into this. However, this doesn't solve the issue. I wasn't really expecting it to, tbh. The problem is more that we just don't have a way to use the advanced-nova-media-library fields by using a custom Resolver.

For example, this is my "get" method in my ContentBlockResolver:

class ContentBlockResolver extends Resolver implements ResolverInterface
{
    public function get($resource, $attribute, $layouts)
    {
        $blocks = $resource->blocks()->orderBy('sort_index')->get();
        return $blocks->map(function($block) use ($layouts) {
            $layout = $layouts->find($block->type);
            if( !$layout) {
                return;
            }
            return $layout->duplicateAndHydrate($block->id, [
                'id' => $block->id,
                'title' => $block->title,
                'subtitle' => $block->subtitle,
                'text' => $block->text,
                'url' => $block->url,
                'lat' => $block->lat,
                'lng' => $block->lng,
                'video_id' => $block->video_id,
            ]);
        })->filter();
    }
}

There's just no way the media field will be able to call the "getMedia" method, since it's an array we're returning. This "getMedia" method is how we retrieve our media (https://docs.spatie.be/laravel-medialibrary/v7/basic-usage/retrieving-media/).

from nova-flexible-content.

toonvandenbos avatar toonvandenbos commented on August 25, 2024

Hi @reinvanoyen & @chrispage1,

I'm not sure where we're returning an array, because it seems to me we're returning a collection. Inside the map closure, we're returning layout objects.

This means both returned values are objects, which is good news since you could adapt the one getMedia should be called on.

I'm not sure which one is used by the media library, but I'm guessing it's not the collection (since its mainly used internally). In case I'm wrong and it is the collection, you could transform your get resolver in order to return a custom collection, which could contain a getMedia method (I have no idea what it should do, however).

It would make more sense if the getMedia method was called on the returned Layout objects, which is good news because you could assign custom layout classes containing the required method.

Hope this helps, but in case I'm not looking at the right spot, could you specify where the getMedia method is called on an array? Thanks!

from nova-flexible-content.

chrispage1 avatar chrispage1 commented on August 25, 2024

So it's triggered on line 198 of Layouts/Layout.php. The reason being is that the $empty flag is set to true. This forces the resolver to pass an empty array but the resolve method on Advanced Nova Media Library requires its first attribute to be the resource - it won't accept anything else.

So I wonder if in this case the fault is more with Nova Media Libraries resolve method? Either way - how can we work out that the specific series of images belongs to that particular flexible field?

from nova-flexible-content.

toonvandenbos avatar toonvandenbos commented on August 25, 2024

We had to pass an array in order to resolve conflicts with a Translatable field (#7) a few months back. Meanwhile we added the Arrayable interface to Layouts, so maybe we don't need to use the $empty flag anymore and pass the Layout resource to the resolver anyway.

I'll have to give it a look.

from nova-flexible-content.

tomhatzer avatar tomhatzer commented on August 25, 2024

For the Translatable field (#7) stuff, it's not working with the spatie/nova-translatable package.

The first problem: spatie/nova-translatable is not returning a nova field, instead it's returning a collection of nova fields. Nova flexible content is unable to use this with the current version. We can extend the constructor of Layouts/Layout.php file and loop over the collection and add the fields on their own which will allow us to output the fields. But then we come to problem 2.

The second problem: After the first problem is solved, we see all the additional fields. BUT we can not save them and we also can not see their values. There's some talk about fields with json values inside the issue from above. I haven't been able to resolve this using a custom resolver yet as I don't know the system of flexible content good enough to dig in deeper.

I'm not sure if this is of any help for your problem though (and sorry for hooking into your issue).

I'd be also willing to spend some money on a solution for this (and/or the translation stuff) as I'd need it in a custom package I'm building right now.

Thanks!

from nova-flexible-content.

voidgraphics avatar voidgraphics commented on August 25, 2024

Hi @tomhatzer, a solution to this issue is in the works as we speak and we're pretty close to have it fully working with advanced-nova-media-library fields.

If you have noticed problems with Spatie's nova-translatable package I would suggest opening a new issue unless you can confirm that the problem is related to this one, which I don't believe it is.

That being said, I have not tried using Spatie's translatable field in Flexible contents before, since we use mrmonat's field, which works fine. If you're in a hurry and can't afford to wait for a potential fix to Spatie's field, I suggest using this alternative which has worked very well for us.

from nova-flexible-content.

chrispage1 avatar chrispage1 commented on August 25, 2024

Thanks so much for doing this but I'm getting some issues with this unfortunately. I've forked advanced-nova-media-library and made the recommended modification. nova-flexible-content v0.1.10.

I've got a layout called GallerySection -

<?php

namespace App\Nova\Flexible\Layouts;

use Ebess\AdvancedNovaMediaLibrary\Fields\Images;
use Spatie\MediaLibrary\HasMedia\HasMedia;
use Whitecube\NovaFlexibleContent\Concerns\HasMediaLibrary;

class GallerySection extends Layout implements HasMedia
{
    use HasMediaLibrary;

    /**
     * The layout's unique identifier
     *
     * @var string
     */
    protected $name = 'gallery';

    /**
     * The displayed title
     *
     * @var string
     */
    protected $title = 'Gallery Section';

    /**
     * Get the fields displayed by the layout.
     *
     * @return array
     */
    public function fields()
    {
        return [
            Images::make('Gallery Images')
                ->conversionOnDetailView('small'),
        ];
    }
}

This is for my Post model which has implements Spatie HasMedia & uses HasMediaTrait.

Now in Nova when going to create a post, if I include this layout I get a load failure -

{
    "message": "No query results for model [App\\Models\\Post].",
    "exception": "Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException",
    "file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php",
    "line": 204,
    "trace": [
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php",
            "line": 180,
            "function": "prepareException",
            "class": "Illuminate\\Foundation\\Exceptions\\Handler",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 83,
            "function": "render",
            "class": "Illuminate\\Foundation\\Exceptions\\Handler",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 32,
            "function": "handleException",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/whitecube/nova-flexible-content/src/Http/Middleware/InterceptFlexibleAttributes.php",
            "line": 33,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Pipeline",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 163,
            "function": "handle",
            "class": "Whitecube\\NovaFlexibleContent\\Http\\Middleware\\InterceptFlexibleAttributes",
            "type": "->"
        },
        {
            "file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
            "line": 53,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        }
       ...
}

from nova-flexible-content.

GarethSomers avatar GarethSomers commented on August 25, 2024

Any progress on #64

from nova-flexible-content.

bernhardh avatar bernhardh commented on August 25, 2024

I still get the Call to a member function getMedia() on array error. I am on 0.1.13 of nova-flexible-content and on 2.9.1 of advanced-nova-media-library which are both the most recent I think.

My setup for this is:

use Ebess\AdvancedNovaMediaLibrary\Fields\Images;
use Spatie\MediaLibrary\HasMedia\HasMedia;
use Whitecube\NovaFlexibleContent\Concerns\HasMediaLibrary;

class HtmlLayout extends Layout  implements HasMedia {
    use HasMediaLibrary;
    
    public function fields() {
        return [
            Images::make("Image", "my_image")        
        ];    
    }
}

The fun thing is, that I can see the field and upload files and they are shown as well. But I get the Call to a member function getMedia() on array in the notification bubble twice (vendor/ebess/advanced-nova-media-library/src/Fields/Media.php:223).

from nova-flexible-content.

cgarofalo avatar cgarofalo commented on August 25, 2024

@voidgraphics @Nyratas I have encountered the exact same bug as @bernhardh. For some reason, resolveForDisplay() is being called twice (or so it seems). The first time it gets the proper data and the second time, it fails. I have been trying to track down exactly where it's being called twice, but I haven't had any luck. It is definitely happening within the vendor files.

from nova-flexible-content.

buttjer avatar buttjer commented on August 25, 2024

Same behaviour here.

from nova-flexible-content.

jornwildenbeest avatar jornwildenbeest commented on August 25, 2024

Hi @alex-osborn, did you ever get this to work?

from nova-flexible-content.

apepindev avatar apepindev commented on August 25, 2024

On my side, everything seems to work exept attributes field is somehow empty.

Same here

from nova-flexible-content.

RVxLab avatar RVxLab commented on August 25, 2024

I ran into exactly this issue. The attributes field is empty which then causes the cast to return null, see src/Concerns/HasFlexible.php:134.

I worked around it by overriding that method and removing that null check in a custom cast.

from nova-flexible-content.

rbijkercom avatar rbijkercom commented on August 25, 2024

Hi all,

I have been trying to make advanced-nova-media-library fields with nova-flexible-content work for a long time now.
I read this tread, and many others regarding this issue, and tried many suggestions but still no luck.
This is my setup:
"laravel/framework": "8.10",
"laravel/nova": "3.11.1",
"spatie/laravel-medialibrary": "8.10.1",
"ebess/advanced-nova-media-library": "3.3.0",
"whitecube/nova-flexible-content": "0.2.5"

This is how I've added de media to the flexible layout:

namespace App;

use Illuminate\Database\Eloquent\Model;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
use Whitecube\NovaFlexibleContent\Concerns\HasFlexible;

class Page extends Model implements HasMedia
{
    use HasFlexible;
    use InteractsWithMedia;

    protected $guarded = [ 'id' ];

    public function registerMediaCollections(): void {
        $this->addMediaCollection( 'flexible_images' );
    }
namespace App\Nova;

use App\Nova\Flexible\Layouts\ImageText;
use Illuminate\Http\Request;
use Whitecube\NovaFlexibleContent\Flexible;

class Page extends Resource
{
    public static $model = \App\Page::class;

    public function fields(Request $request)
    {
        return [
            Flexible::make('Body Flexible')
                    ->addLayout( ImageText::class )
        ];
    }
}
namespace App\Nova\Flexible\Layouts;

use Ebess\AdvancedNovaMediaLibrary\Fields\Images;
use Spatie\MediaLibrary\HasMedia;
use Whitecube\NovaFlexibleContent\Concerns\HasMediaLibrary;
use Whitecube\NovaFlexibleContent\Layouts\Layout;

class ImageText extends Layout implements HasMedia
{
    use HasMediaLibrary;
    protected $name = 'image_text';
    protected $title = 'Image Text';
    public function fields() {
        return [
            Images::make('Images', 'flexible_images'),
        ];
   }
}

In the view I loop through the flexible content but it doesn't get the image. I doesn't event run the foreach because it doesn't find a layout.

@foreach($page->flexible('body_flexible') as $layout)
       {{ $layout->getMedia('flexible_images') }}
@endforeach

This is what gets stored in the database in the table: pages, column: body_flexible :
[{"layout":"image_text","key":"P0DZKyRuxxncY4t4","attributes":[]}]

The image is also correctly uploaded to the table: media, collection_name: image_text_P0DZKyRuxxncY4t4

The image is also visible the Nova CMS in the flexible content box so somehow Nova knows how to get the image.

Any suggestions on how to display this image in the view?

from nova-flexible-content.

mouradsm avatar mouradsm commented on August 25, 2024

Has anyone managed to get this to work? I'm trying to use the field inside the flexible content but no success =(

from nova-flexible-content.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.