FOSMessage
FOSMessage copied to clipboard
Integrate FOSMessage with / use within Drupal CMS
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.
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?
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.
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
That's a good news! One problem solved :)
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:
- Dependency to Composer Manager
- composer.json file to
FOSMessage
and its dependencies and new libraryFOSMessageDrupalDriver
- A PersonUser or more appropriately named class extending the
PersonInterface
as described here https://github.com/FriendsOfSymfony/FOSMessage/issues/19#issuecomment-170245404 - Any other necessary Drupal related code and simple API along with a README.md file describing use
FOSMessageDrupalDriver (Abstract Drupal Driver) [This abstract driver may not be required, but may make things easier for developers.] Includes:
-
AbstractDrupalDriver
extendingAbstractDriver
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"
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?
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.
Okay :) . I'll be around if you need my help :) .
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!
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!
Many thanks for your work!!! :)
Hopefully this repo will have some good progress by end of next week: https://github.com/mccrodp/message_fos
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
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!
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 nextflush
-
flush
save the persisted entities in the database
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.