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

FEATURE Custom "read model" layer for eel objects #3153

Open
mhsdesign opened this issue Sep 4, 2023 · 1 comment
Open

FEATURE Custom "read model" layer for eel objects #3153

mhsdesign opened this issue Sep 4, 2023 · 1 comment

Comments

@mhsdesign
Copy link
Member

mhsdesign commented Sep 4, 2023

In the Dresden sprint i experimented with @kitsunet to make the ProtectContextAware interface obsolete. The goal was to remove the coupling of EEL helpers in the php code - as this is imo not really clean and using this helper in pure php land fells odd. My proposal would be kind of breaking and introduce some complexity in the backwards compatible layer.
#2976

After implementing this, i came to the conclusion, that i want to have a "allow" list for methods on other arbitrary context objects as well. Like i want to configure Psr\\Http\\Message\\Uri to allow withPath to be called (as its immutable).

While discussion how node.properties.foo could work in the Neos 9 cr neos/neos-development-collection#4464 (comment) @bwaidelich and me also thought about an additional "read model" layer between php objects and eel.

And surprise - this is imo - with relatively okay work doable.

A few examples:

Make any Helper an EEL Helper (without implementing the ProtectedContextAwareInterface):

Neos:
  Eel:
    globalContext:
      My\Foo\BarHelper:
        contextFactory: Neos\Eel\CallableContextFactory
        options:
          allowMethods: *

Make the prs uri work in eel (enable with* methods)

Neos:
  Eel:
    globalContext:
      Psr\Http\Message\Uri:
        contextFactory: Neos\Eel\CallableContextFactory
        options:
          allowMethods:
            - with*

Make the node.properties behave like an array access (without "polluting" php code with ArrayAccess)

Neos:
  Eel:
    globalContext:
      Neos\ContentRepository\Core\Projection\ContentGraph\PropertyCollection:
        contextFactory: Neos\Eel\ArrayLikeContextFactory
        options:
          offsetGet: 'getProperty'

or make getProperty and hasProperty as well as equals work directly on the node object:

Neos:
  Eel:
    globalContext:
      Neos\ContentRepository\Core\Projection\ContentGraph\Node:
        contextFactory: Neos\Eel\CallableContextFactory
        options:
          allowMethods:
            - getProperty
            - hasProperty
            - equals

(of course we could also just go ahead and introduce "new" computed properties in the read models - but this is not "public" api and might be a foot gun)

Low level API and implementation

Technically anyone can create their own contextFactory - even if we might not document it at first as we dont want to make things less obvious. For example things are already quite confusing how magic ArrayAccess __get and getters all play together: #2785

The above example where we make the PropertyCollection of the node work as an array would look like:

Neos:
  Eel:
    globalContext:
      Neos\ContentRepository\Core\Projection\ContentGraph\Node:
        contextFactory: Neos\Neos\Eel\NodePropertyCollectionReadModelFactory
interface ContextFactory
{
    public function create(mixed $value): Context;
}
interface Context
{
    public function get(string $path): mixed;
    public function call(string $path): mixed;
    public function unwrap(): mixed;
}
class ArrayLikeContextFactory implements ContextFactory
{
    public function create(mixed $value, array $options): ArrayLikeContext
    {
        return new ArrayLikeContext($value, $options['offsetGet']);
    }
}
class ArrayLikeContext implements Context
{
   public function __construct(private readonly object $value, private readonly string $offsetGetter) {}
 
   public function call(string $path): mixed
   {
      throw new \RuntimeException(get_class($value) . " was only allowed to behave like an array.");
   }

   public function get(string $path): mixed
   {
      return $this->value->{$this->offsetGetter}($path);
   }

   public function unwrap(): mixed
   {
      return $this->value;
   }
}
@mhsdesign
Copy link
Member Author

I discussed this concept in the todays weekly and on slack, and we are not sure if this magic layer is a good idea, general consent: no

slack: https://neos-project.slack.com/archives/C3MCBK6S2/p1693826446394949?thread_ts=1693816556.852519&cid=C3MCBK6S2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant