How to mix Drupal Content profile module and node reference fields to let create user’s company profile in a wiki / proprietary mode
In this post we’ll try to figure out how to :
- Combine content profiles with extended Profiles built with a node reference field
- Compare different way to build them in Drupal based on a use case of the site archiref.com
- Create a mix wiki proprietary permission scheme for those extended profile nodes
- Put this solution in perspective to be portable to Drupal 7
Often a user need to have a content that is related to him.
This is due to the fact that a user is in drupal 6 a seperate entity and not fieldable.
In drupal 7 the fieldable property of the user would simplify the thing.
That could be as simple as an additional image picturing the user face or
a complicated content describing the user company.
The basic strategy is to use the content profile module that allow to link a user to a node of one or various content type.
This modules is very useful, but it has also its drawbacks not because of bugs but because of the way it is conceived.
There is also some other ways to link a node to a user that we will examine further. They are a bit more complicated to implement, but could achieve more flexibilty.
1/ Content profile module
What does it do :
You define a content type that should be handled as a content profile.
This will have a consequence on how this content will behave. This choice is reversible, so don’t panic !
Once’s set as a content profile, the content will obey content profile rules :
- One user can only have one content profile of a defined type
- It can have different content profile of different content type but only one of a type
- The link between a content profile and its user is made by the author property
Advantages of using content profile :
- the content profile will manage for you a content edit form accessible on the my account page
- it dispose of view integration that allow to load a specific content profile from the relationship part of view UI
- it has API function that allow to easily load a content profile account of a defined user.
Drawbacks :
- it has limited way to filter content profile type by role using the permission to filter them out
- it has no way to let other users create the content profile node before the actual user, whose society is described by this content profile. This behavior is what I call a wiki/proprietary mode where the node that describe a society, is first created by a user of the site and then if it occur that the legitimate society’s user create an account, will later be assigned to him.
- What if you want a user need to have more that one profile of one type, more than one society ?
Turn arrounds of the drawbacks described above
- If you want to filter the available content profile type by role, you can use the node permissions allowing only defined role to create and modify the content profile they are suppose to use.
- If you want other people to create a content profile node even if the legitimate user has not created an account I will describe some possibilies. The problem is that when somebody create a new node that is used as a content profile, it’ll be considered as this user content profile and a user can only have one (remember the association is made via the author properties of the node). To be clearer I’ll use my usecase example :
I have two roles ‘photographer’ and ‘architect’. I want the architect to have a content profile of type ‘architect’, and photographer to have a content profile of type ‘photographer’. I want architect to reference architect ‘content profile’, when indexing their images but without this architect node being considered as their content profile. When later the architect described in the node, create effectively an account, I want him to be able to inherit this content profile and all the information and architectural projects linked to it.
I see two main solutions to achieve that with the profile nodes being managed by content profile module :
- hook form alter the creation form of architect node to set the author property only if the user has the architect role.
If the user is not an architect set the author to anonymous : it’s the wiki mode. This allow the node not to be associated with the acting user, and let him create more than one pre-content profile node
The drawbacks of this strategy is that an architect could not create other architect that him, and has not a standard wiki user role.
It need also to patch some other module involved in node creation to undo the author property to be written. It need also to grant the user with the ‘administrate node’ permission (I don’t know exactly why) and that bypass the fine grain permission the content access module can give us.
It seem us for all this reasons a bit too tricky.
- create a false user in advance every time an architect node is created, and change the author to this fake user. This can be realized thanks to a rule when a photographer create a new architect node
The drawbacks of this strategy is the creation of false users that probably would never be used. It complicated the user management.
So let’s examine other solutions :
2/ Use a userference field in the profile node that point to the user
In normal cases, the node architect node is only created, and the cck user reference node is not populated
When the node is supposed to be the profile of the architect user the field is populated.
But when this cases could be identified, so that we can create the adequate rules.
First case, the architect doesn’t exist yet in the system, each time a new architect user account is created, a new architect node is created and assigned to this user with the userreference field referencing the newly created user.
Second case the user want to associate its profile with an existing architect profile.
Here is how it could occur :
- An architect create an account with a account creation form that have the folowing fields :
. login or email
. password
. type of account
. name of the compagny
After he submit the form he is redirected to a second screen that let him do the following :
. create my company profile
A view found existing architect node that have part of their title in common with the name of the company field.
If this view has a result a second option is available to the user to select existing profile he wants to use instead of creating a new one.
He can choose only one choice between the possible various view results.
If he choose to create a new profile, a content of type architect is created,
the userreference field is populated by the userid and the user is redirected to fill some information about it’s company.
The interface need to let the user understand he could fill this content later if he doesn’t have time.
If he choose an existing node to be its profile, an action should be created via a rules set for example.
This rule set will do the following on the node selected by the new user via the View VBO interface :
. populate the node with the userid
. set this user as the author of the node
The problem of this technique is how to select the profile node :
. to make a link to it in the interface of the user
. in other context when we want to show the profile related to a user
In a view we could use reverse reference module, but to what I know it doesn’t work for userreference.
We could use auto populated reverse reference, but I don’t know it exist such a module for user reference.
In a menu it is more difficult, and this menu item needs to be a view result.
So this solution doesn’t seem to work mostly because of the user of user reference and the node > user relation. We’ll try to use a node reference instead, and has a user > node relation which is more easily manageable.
3/ Use a nodereference field in a simple content profile node that point to the complete company node
The problem with the previous solution was mostly the difficulty to retrieve the content that point a user.
It’s a reverse reference, I have one user. I want to find in all the nodes of this type, that point this user and thus I need a sql select query.
It’s easier to use content profile solution that make a link between the user and the content, and to create in the content profile a nodereference fields that point to a different detailed profiles the user can have.
The greatness of this strategy is that it allow to reference several content profile by user of every type.
A user can then have different companies if he need to. I don’t know how facebook really work, but if I try a comparison, the content profile managed by content profile module would be the user facebook profile, and the other profiles would be the facebook pages.
This profiles could be described as extended profiles, connected but not identical to the main profile attached to the user account.
A view can be used to retrieve this extended profiles node, the view can retrieve different node if the user have several profiles.
A architect user can then have several architect companies if he want and a photographer and media owner profile if he has several activities.
To ease the selection of this node a reverse node reference field in the profile node can reference the content profile of the user. This could be achieved throught the use of the excellent CNR module or Corresponding Node Reference.
When an architect create an account a rule create for him a profile, an architect profile and populated the node reference field of architect profile with the nid of the content profile node.
When an architect want to reuse an existing profile, a rule set define an action that populate the nodereferenc field for him.
Possible solutions for permission management in a wiki/proprietary node
For my use case I needed also that when a architect profile be assigned to a user, the other users could no more modify the node. It’s what I call the wiki/proprietary mode. As long as the content has no propriétary, it’s in wiki mode, it could be modified by every user. When the appropriate people has created an account, the node is locked for others.
For the moment I can see two solutions to achieve such a permission limitation :
- Use the content mode of content access module, that allow to content access to work at the node granularity (and not the content type one). The node that have a owner would only be modifiable by him, the others could be modified by every body. Content_access need to be changed automatically via a custom module or a rule
- a version of user reference access module that would allow only a node being user referenced to modify it. The problem is that the rights would be modified during the node’s life. When the user reference field is empty everybody could modify it, when it’s filled only the user referenced will can. I don’t know if this is possible.
This permission issue sould be part of a future blog post comparing permission and access solution.
Drupal 6 to Drupal 7 migration perspective
This solution describe in the point 3 seem the most adecate to allow wiki/proprietary profile node. In the perspective of a migration to drupal 7 let’s examine how it’ll behave.
In drupal 7, the user is an entity as a node and is fieldable alike. There is no need to use the content profile module any longer. As far as I know the user is a pretty private entity, not sure it’ll be possible for other users to modify it in a wiki mode. So the separation of node related to the user and the user’s content profile in D6, user’s fields in D7, seems accurate.
But if the user entity is sufficient to create fields without the content profile and the content profile module is not ported to D7, what will occure to our node reference field referencing the content profile node? The node reference fields that link the extended profile node to the content profile won’t be valid any more ? We’ll need to tranform it in a usereference instead ? These are open questions as I’ve not try sufficiently D7 to answer it but need to think be thought about.
Conclusion :
Content profile module is the easyest way to link a user to a node that describe it’s profile
It a very stable module, but it cannot be use when the usecase allow other people to create in advance this type of content.
This is mostly due to the authoring property used to make the relation and the condition that a content profile need to be unique.
The association of a basic profile common to all users whatever are their type, and specialized extended profile linked via a node reference field to this content profile seems to be a good solution to answer this use case and give more flexibility.
This d7 porting of this solution needs to be clarified, and the permissions change when then the node change from wiki to proprietary mode.