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

PHP Extender: Serializing / forum api attributes #1624

Open
luceos opened this issue Nov 2, 2018 · 10 comments

Comments

@luceos
Copy link
Member

commented Nov 2, 2018

Previously in order to append attributes to the forum object in js, one would listen to the Serializing event. This event still exists mind you.

In flagrow/passport I would use this to add an attribute to the ForumSerializer that held the configured button title.

It would be useful to have an extender that allows setting attributes on returned payload. How about an Extend\Serializer class?



    /**
     * @param Serializing $event
     */
    public function prepareApiAttributes(Serializing $event)
    {
        if ($event->isSerializer(ForumSerializer::class)) {
            $event->attributes = array_merge($event->attributes, [
                'flagrow.passport.loginTitle' => $this->settings->get('flagrow.passport.button_title', 'Login')
            ]);
        }
    }
@tobyzerner

This comment has been minimized.

Copy link
Member

commented Nov 9, 2018

FYI the long term goal for this is to have a new "schema" API to define JSON-API attributes - see the following links:
tobyzerner/json-api-php#126 (comment)
https://gist.github.com/tobscure/5e514a700dcb471180369903ab4562c3

However this will not be ready for a while, in the meantime we can implement something like you've suggested :) Will leave the exact implementation to Franz.

@franzliedke

This comment has been minimized.

Copy link
Member

commented Nov 9, 2018

I am still hoping we can get close to it with the extender. even before tobscure/json-api sees that new release.

@franzliedke

This comment has been minimized.

Copy link
Member

commented Dec 19, 2018

@tobscure Now that tobscure/json-api-server is a thing... could you post a proposal of what the extender's signature could look like with the "schema" terminology?

@franzliedke

This comment has been minimized.

Copy link
Member

commented Dec 19, 2018

(I will then try to implement that signature even with the current code - we will see whether all official extensions' use-cases can then be mapped to that concept already.)

@tobyzerner

This comment has been minimized.

Copy link
Member

commented Dec 19, 2018

Basically:

    new Extend\Api('posts', function (Builder $schema) {
        // extend schema as per tobscure/json-api-server
    }),

We also need a way to register new resource types, which is the same but also need to specify an adapter. Maybe just a third param:

    new Extend\Api('posts', function (Builder $schema) {
        // build schema as per tobscure/json-api-server
    }, new EloquentAdapter(new Post)),
@franzliedke

This comment has been minimized.

Copy link
Member

commented Dec 20, 2018

Cheers, will try it out. Until tobscure/json-api-server is integrated, I'll probably provide an alternative implementation of the schema builder (which maps to the current constructs), which means no type-hint in the closure for now.

@luceos

This comment has been minimized.

Copy link
Member Author

commented Mar 22, 2019

My current serializing extender:

<?php

namespace Flagrow\Byobu\Extend;

use Flarum\Api\Event\Serializing;
use Flarum\Extend\ExtenderInterface;
use Flarum\Extension\Extension;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Events\Dispatcher;

class ApiAttribute implements ExtenderInterface
{
    protected $mutations = [];

    public function extend(Container $container, Extension $extension = null)
    {
        /** @var Dispatcher $events */
        $events = $container->make(Dispatcher::class);

        $events->listen(Serializing::class, function (Serializing $event) use ($container) {
            foreach ($this->mutations as $mutation) {
                list($serializer, $callable) = $mutation;

                if ($event->isSerializer($serializer)) {
                    $callable = $container->make($callable);
                    $callable($event);
                }
            }
        });
    }

    public function add(string $serializer, $callable)
    {
        $this->mutations[] = [$serializer, $callable];

        return $this;
    }
}

Used in extend.php:

    (new Extend\ApiAttribute)
        ->add(BasicUserSerializer::class, Api\UserAttributes::class),

Where the second argument is an invokable class:

<?php

namespace Flagrow\Byobu\Api;

use Flarum\Api\Event\Serializing;
use Flarum\Api\Serializer\BasicUserSerializer;
use Flarum\User\User;

class UserAttributes
{
    /**
     * @param Serializing $event
     */
    public function __invoke(Serializing $event)
    {
            /** @var User $user */
            $user = $event->model;
            $event->attributes['blocksPd'] = $user->getPreference('blocksPd', false);
    }
}
@franzliedke

This comment has been minimized.

Copy link
Member

commented Mar 22, 2019

Oh nice, that would even give us support for cases like this one.

Do we want to go with this now as a stop-gap solution? It will have to be deprecated as we move towards the "schema" approach, though.

@luceos

This comment has been minimized.

Copy link
Member Author

commented Mar 22, 2019

It will have to be deprecated as we move towards the "schema" approach, though.

@franzliedke Yeah but that was to be expected, I think it's fine. The benefit of having the extenders in core (before too many extensions adopt their own) is that we can globally deprecate them first and then remove them.

@tobyzerner

This comment has been minimized.

Copy link
Member

commented Mar 24, 2019

I think I would rather try and emulate the schema API as close as possible as a stop-gap

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.