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

Proof of concept #135

Merged
merged 22 commits into from
Mar 20, 2014
Merged

Proof of concept #135

merged 22 commits into from
Mar 20, 2014

Conversation

bakura10
Copy link
Member

@bakura10 bakura10 commented Mar 8, 2014

ping @Ocramius @danizord

First try for #132 .

This PR does not work, it's just a quick prototype. As said in the issue, this assumes that we have an hydrator that only extract scalar names, and let associations untouched (so extract will actually return associations, BUT as object).

It's then the ResourceRenderer that recursively calls the hydrators.

I suspect this to be quite slow but... it seems the "best" way to do it no?

TODO:

  • tests
  • check circular rendering
  • allow to override association directly in ResourceModel.

@coveralls
Copy link

Coverage Status

Coverage decreased (-6.8%) when pulling 287bbc1 on extraction into 31a6713 on master.

@coveralls
Copy link

Coverage Status

Coverage decreased (-8.33%) when pulling 4ee5dbb on extraction into 31a6713 on master.


// Then, handle each association
$classMetadata = $resourceMetadata->getClassMetadata();
$associations = $classMetadata->getAssociationNames();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can't implement getAssociationsMetadata() in ResourceMetadata?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope. I know this is confusing. Actually, in the resource level, associations have mapping like the path, the name of the association. But if you want to retrieve the resource mapping for this association, it's something different (it's another instance of ResourceMetadataInterface, actually).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking about renaming "getAssociationMetadata" to "getAssociation", so that it is less confusing between the metadata you get for a given association and the specific metadata bound to an association inside a given resource metadata.

@danizord
Copy link
Contributor

Sounds great 👍 We just need to add more options to ResourceModel in order to allow developers to change the renderer behavior.

@bakura10
Copy link
Member Author

What are you thinking about for options? It's still very confusing in my own head, to be honest.

@danizord
Copy link
Contributor

@bakura10 See #132 (comment)

@bakura10
Copy link
Member Author

@danizord , I've made some more work on the renderer. Can you check it? :)

@bakura10
Copy link
Member Author

Note : I moved the JSON serialization from the renderer to the strategy instead. This brings much more flexibility as I can recursively render now.

@@ -16,23 +16,29 @@
* and is licensed under the MIT license.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did GIT simply get this one wrong? Or did you explicitly use git mv?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strange. It was supposed to be removed. I surely messed with it.

* @var string
*/
public $path;

/**
* @var string
*
* @Enum({"NONE", "EMBED", "ID"})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering if constants can be used here:

@Enum({Association::NONE, Association::EMBED, Association::ID})

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to! I'll test that once I finish it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be ignored for now

@bakura10
Copy link
Member Author

With this new code, skipping specific field is now super easy. For instance, let's say you don't want to output password from User entity, you simply define a new hydrator, and add a filter:

use Zend\Stdlib\Hydrator\ClassMethods;
use Zend\Stdlib\Hydrator\Filter\MethodMatchFilter;

class UserHydrator extends ClassMethods
{
    public function __construct()
    {
        parent::__construct();
        $this->filterComposite->addFilter("password", new MethodMatchFilter('getPassword'));
    }
}

And boom! No more need to define hydrate, extract...

@bakura10
Copy link
Member Author

If you have some time to review this @Ocramius it would be awesome :D. I'd like to merge this tomorrow or on tuesday, so I can test it in my app and know if it's viable.

@bakura10
Copy link
Member Author

Last update includes an important fix that is due to the way ZF2 hydrate data. Basically, the default ClassMethods output as underscore separated keys. This means that an association like "myAssociation" will be rendered as "my_association" by the hydrator. Therefore, the association name retrieved from Doctrine metadata will be "myAssociation", and checks will fail.

Therefore, I have added a similar parameter to the resource renderer, called underscoreSeparatedKeys (which is set to true to be on pair with default values of ClassMethods). This automatically inflects any association name to udnerscore_separated, so that everything can still work.

@@ -21,7 +21,7 @@
'factories' => [
/* Factories that do not map to a class */
'ZfrRest\Cache' => 'ZfrRest\Factory\CacheFactory',
'ZfrRest\View\Renderer\ResourceRenderer' => 'ZfrRest\Factory\SimpleResourceRendererFactory',
'ZfrRest\View\Renderer\ResourceRenderer' => 'ZfrRest\Factory\DefaultResourceRendererFactory',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ZfrRest\View\Renderer\DefaultResourceRenderer?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently it's configured through the factory. The strategy factory fetches the "ZfrRest\View\Renderer\ResourceRenderer" key, and if you want to switch factory, you need to override this key.

Maybe we could expose an option into ZfrRest config, like "renderer" => "foo". Or even a config like that:

'zfr_rest' => [
    'renderers' => [
       'application/json' => 'ZfrRest\View\Renderer\DefaultRenderer'
   ]
];

What do you think @Ocramius ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bakura10 that can be dealt with later, as an implementation detail of something like a ZfrRest\View\Renderer\RendererStrategy or such

@bakura10
Copy link
Member Author

I'll merge that tomorrow guys. If you want review, either do it today or throw any comments here after it being merged so that I can read the feedback.

* @var Tweet[]
*
* @ORM\OneToMany(targetEntity="Tweet", mappedBy="user")
* @REST\Association(routable=true, extraction="NONE")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the routable=false as current approach - makes it easier for us. Is the default false?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, false is default to avoid any leaking route.

@coveralls
Copy link

Coverage Status

Changes Unknown when pulling 3df1b95 on extraction into * on master*.

@bakura10
Copy link
Member Author

I'm merging for now. I've heard you about segregating the metadata hydrator, but that's something I'm not sure how to implement for now, and that's easy to change without breaking it.

bakura10 added a commit that referenced this pull request Mar 20, 2014
@bakura10 bakura10 merged commit d14aef3 into master Mar 20, 2014
@bakura10 bakura10 deleted the extraction branch March 20, 2014 16:20
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

Successfully merging this pull request may close these issues.

None yet

4 participants