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

Integrate FOSMessage with / use within Drupal CMS #19

Open
mccrodp opened this issue Jan 8, 2016 · 15 comments
Open

Integrate FOSMessage with / use within Drupal CMS #19

mccrodp opened this issue Jan 8, 2016 · 15 comments

Comments

@mccrodp
Copy link

mccrodp commented Jan 8, 2016

Drupal CMS uses many Symfony components now within Drupal 8, however it's use of Doctrine is limited to Annotations as far as I believe. It does not look like full Doctrine integration will be anytime soon, if ever. See: https://www.drupal.org/node/1817778

This library was highlighted to me in the Drupal.org issue queues for the Message Private module which I maintain. https://www.drupal.org/node/2613152#comment-10697278

When I upgrade Message Private to Drupal 8, which is ongoing, I will look to improve upon it. There is currently no Threading / Conversation ability, so if appropriate, this library could be a great solution.

A few initial questions / discussion items:

  • Determine if this library is appropriate (which it looks to be so far)
  • Find out what is involved and how much work it would be to create a Drupal driver
  • Create pull request here for Drupal driver to integrate directly with Message Private or preferrably with new Drupal FOSMessage bridge / API module (to be made available on drupal.org)

Perhaps you could help with answering the above. Some of this work would be a while away on my side, but just to start conversation now will help later on. Thanks.

@tgalopin
Copy link
Contributor

tgalopin commented Jan 8, 2016

Hello @mccrodp!

Thanks for your proposal, I think this is a great idea! Providing a framework-agnostic messaging data structure for more specific implementations is exactly the point of FOSMessage..

The idea when creating a Driver is to implement the DriverInterface (https://github.com/FriendsOfSymfony/FOSMessage/blob/master/src/Driver/DriverInterface.php). You can also extend the AbstractDriver to use its helpers (https://github.com/FriendsOfSymfony/FOSMessage/blob/master/src/Driver/AbstractDriver.php). Don't hesitate to check the Doctrine ORM driver for an example: https://github.com/FriendsOfSymfony/FOSMessage/blob/master/src/Driver/Doctrine/ORM/DoctrineORMDriver.php.

I don't know very well Drupal 8 (especially on the database level) but from what I remember they have their own ORM. The driver would be the "link" between this custom ORM and FOSMessage.

A difficulty could be to set up the user: currently the library needs a User entity implementing the PersonInterface. I'm not sure how Drupal is working on this level, so perhaps would this be difficult.

Another thing is that the library currently depends on Doctrine collections. I'm not sure how Drupal 8 handle modules and if you can add your own dependency easily using a bundle: is it a problem?

Other than these points, I think the library should be usable without problem in Drupal. I think a Drupal driver should be located in an external bridge as it's something very dependant of Drupal. However, we could add a link to the Drupal bridge in the documentation for Drupal users.

I am very interested by this idea, if you need a hand don't hesitate to ask :) . Where are you working on the 8.x version?

@mccrodp
Copy link
Author

mccrodp commented Jan 8, 2016

Thanks for your quick reply! I need some time to research and answer properly, but for now...

A difficulty could be to set up the user: currently the library needs a User entity implementing the
PersonInterface. I'm not sure how Drupal is working on this level, so perhaps would this be difficult.

Yes, this could be an issue unless I can extend our User class and implement that interface for use of messaging functionality. I need to get some advice on this and follow up.

Another thing is that the library currently depends on Doctrine collections. I'm not sure how Drupal 8
handle modules and if you can add your own dependency easily using a bundle: is it a problem?

Not 100% sure what you mean here as I'm not too well versed with Doctrine (yet), however we can add Symfony components / bundles and asscociated dependencies to our Drupal "modules" using Composer Manager module. I may not be answering your question here, but I found some Doctrine collections in Drupal 8 here in our vendor folder for example: https://api.drupal.org/api/drupal/vendor%21doctrine%21collections%21lib%21Doctrine%21Common%21Collections%21AbstractLazyCollection.php/8

Yes, I think all code could be located in a Drupal module for ease of use, or a Drupal module that fetches this driver library (dependency) on packagist using Composer Manager as I mentioned before. Perhaps the Drupal module could be FOSMessage Bridge and driver library FOSMessage Drupal Driver.

I'm interested in this too, however it's a bit far off from starting at the moment due to time. I am working on a simple 8.x-1.x port of the Message Private module and what we are discussing would be in a 8.x-2.x version down the line.

Thanks for your help and interest, it has raised a few items I need to get back to you on. Anything else on this so far, please let me know.

@mccrodp
Copy link
Author

mccrodp commented Jan 9, 2016

Got some good news / help via IRC re extending the PersonInterface:

bojanz: you can extend the User class, implement the new interface, then swap the entity class for yours. hook_entity_type_alter() $entity_types['user']->setClass() I think

https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Entity!entity.api.php/function/hook_entity_type_alter/8

@tgalopin
Copy link
Contributor

tgalopin commented Jan 9, 2016

That's a good news! One problem solved :)

@mccrodp
Copy link
Author

mccrodp commented Jan 10, 2016

Yes and I presume for the moment that pulling in the Doctrine Collections will be ok from what I know so far.

In terms of starting work on this and separation of code, I imagine it will be as below. Please make suggestions or corrections to this proposal.

FOSMessage Bridge (Drupal module)
[Available at http://drupal.org/project/fosmessage_bridge]
Includes:

FOSMessageDrupalDriver (Abstract Drupal Driver)
[This abstract driver may not be required, but may make things easier for developers.]
Includes:

  • AbstractDrupalDriver extending AbstractDriver providing any further Drupal related data
  • Any other necessary (Abstract) classes or configuration

Message Private (Example: Future usage in Drupal module)
[Available at http://drupal.org/project/message_private]

  • Make dependency to "FOSMessage Bridge" drupal module
  • Extend AbstractDrupalDriver class
  • Set up any other necessary items using API provided by "FOSMessage Bridge"

@tgalopin
Copy link
Contributor

That seems like a plan :) .

Composer Manager seems indeed to solve the Doctrine collections problem. I'm not sure why you want to separate the Driver and the Bridge though, I think the driver could be integrated in the bridge directly. Why do you want to split it?

@mccrodp
Copy link
Author

mccrodp commented Jan 10, 2016

Yep, you're probably right. I guess I was separating the driver in case other Drupal modules / Symfony integrations could use it, but it's probably unnecessary separation. Will keep it together and simple initially when I get around to it :)

I'm sure I'll have some more questions for you, sooner rather than later, I hope.

@tgalopin
Copy link
Contributor

Okay :) . I'll be around if you need my help :) .

@mccrodp
Copy link
Author

mccrodp commented Jun 18, 2016

Hi @tgalopin - I'm looking to sprint on this at Drupal Dev Days conf next week. If my Drupal driver exists outside of the FOSMessage library is there any issue? i.e. - does it require this Driver namespace FOS\Message\Driver\ or can it exist in my Drupal\MessageFOS\Driver\ namespace and just extend the abstract driver class to be correctly instantiated?

My plan is to create the bridge module at message_fos to fit with the naming convention of my current module stack, pull in fos_message library using composer. (D8 no longer needs Composer Manager bridge module: https://www.drupal.org/node/2404989). Then I will set up the Driver with similar namespace to what I listed above. I will get it working statically all going well, then I will make the driver dynamic, allowing the user of the bridge module to select their custom entities for; Message, Conversation, etc., through UI or code.

Any suggestions, pitfalls / limitations to be aware of etc., please let me know. Thanks again!

@tgalopin
Copy link
Contributor

tgalopin commented Jun 18, 2016

Hi @mccrodp,

There is no issue with using a completely different namespace than the library one (I would even recommand you to do so to avoid autoloading issues).

The Composer integration in Drupal 8 is a great news, it will be easier to install your module :) .

I don't have specific suggestions in mind now, but if I have, I'll post them here :) .

Thanks for your work!

@mccrodp
Copy link
Author

mccrodp commented Jun 20, 2016

Many thanks for your work!!! :)

Hopefully this repo will have some good progress by end of next week: https://github.com/mccrodp/message_fos

@mccrodp
Copy link
Author

mccrodp commented Jun 24, 2016

Hi @tgalopin. I've worked a bit on this an restructured for Drupal. I've added a new wrapper User class MessageFOSUser implementing the PersonInterface which I will wrap my Drupal user objects inside.

I talked to a few people in here at the conference and hijacking the Drupal user was not a good design. I tried this, but I was having issues where Drupal could not uninstall my module until I wiped the user table :P Not great way to start, haha. I think this wrapper method is better.

Can you let me know how I can re-appropriate the other class, most importantly the driver classes and explain the queries to me. i.e. - won't be writing database queries like in findPersonConversations, I'll most likely use a higher level of abstraction in the EntityQuery class in D8. I just don't know what the methods are doing, what they need, etc. I can set it up in Symfony and step through the demo using XDebug, but it could take me a while. If you're too busy, or if there is no docs on this, I will try to do this debugging, no problem.

Can you also let me know what the annotations in the Entity namespace are doing, I only see properties declared and I don't know what the Drupal equivalent will need.

Thanks again! https://github.com/mccrodp/message_fos

@mccrodp
Copy link
Author

mccrodp commented Jun 30, 2016

Now I have more specific questions:

The persist() calls are essentially saving your entities to the DB, correct?
I don't plan on having a Drupal entity for "Message Person" and "Conversation Person". I will have a Message and Conversation entity with reference fields on these entities, will that be ok? How should this be reflected in my AbstractDrupalDriver methods? https://github.com/mccrodp/message_fos/blob/8.x-1.x/src/AbstractDrupalDriver.php

Can you please explain each of the methods I should implement in DrupalDriver? https://github.com/mccrodp/message_fos/blob/8.x-1.x/src/DrupalDriver.php What should they query and what should they return? e.g. - findPersonConversations queries the message entities for a particular person and with a specific tag and returns them ordered by date. Does it require me to return an ArrayCollection etc.?

Thanks!

@tgalopin
Copy link
Contributor

The persist calls are essentially saying to Doctrine (the persistence layer) to take modifications into account. The entities will be saved into the database on the next flush call. So yes, essentially, persist calls are saving in the database, but in a "delayed" manner.

If you are saving the data directly in your persist methods, you won't need to implement anything in the flush method. However, you won't profit from the possibilities in term of transactions and performances if you do so (that not a big problem).

The idea of the driver system is to allow the library to use a different persistance layer. The library will use your driver and trust it to create/read/update/delete in the database (whathever it is) . You can find a lot of informations about the required behavior of the methods in the interface comments: https://github.com/FriendsOfSymfony/FOSMessage/blob/master/src/Driver/DriverInterface.php.

  • create*Model methods should return simple data object implementing the interface in the comment
  • find* methods are used by the library to read data from the database : check their return type
  • persist* methods are indicating a change in the given entity (either its creation or modification) and that this entity should be saved in the database on the next flush
  • flush save the persisted entities in the database

@mccrodp
Copy link
Author

mccrodp commented Jun 30, 2016

Thanks for this!

So yes, essentially, persist calls are saving in the database, but in a "delayed" manner.

Ok, so initially I'll call save / create operations directly on the entities and in future I'll implement the Queue API here for something similar to what you have for Doctrine.

create_Model methods should return simple data object implementing the interface in the comment
find_ methods are used by the library to read data from the database : check their return type

So, that looks like I need my entities to implement these interfaces. I thought I only needed to implement PersonInterface for the User object. It should be ok, just believed that was the case from the docs: http://fosmessage.readthedocs.io/en/latest/book/getting_started.html

flush save the persisted entities in the database

I presume the library itself calls this but it could also be implemented in the application that implements the FOSMessage library. I'll take a closer look soon.

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

2 participants