Creating your own features
Each component within AbleOrganizer is designed as a feature. A feature is a small, useful application in Drupal that configures the system to work in a specific way.
If you want your code to be portable, and be able to run in just about any website, you will want to take the time to understand the best practices for creating features in AbleOrganizer.
Heads up! The best practices for feature development continue to be defined. In general, AbleOrganizer sticks to the best practices for feature development in CRM Core. A copy of the latest and greatest ideas for feature development can always be found on the Drupal.org website.
Best practices for feature development
Creating your own features is really a process of taking specific components from one site and packaging them in a way where they can work in other websites.
Consider the items listed on this page as guidelines towards ensuring your code will work on any website. They are useful in most cases, but not all. If you are developing a simple feature you plan to share with other AbleOrganizer users, these rules for the road will serve you well.
Use a Unique Namespace
Every feature should have its own unique namespace. This namespace should be reflected in all the elements used by your feature: field names, content types, views, paths, etc.
For instance, in feature foo, which is used to manage bars:
- A content type might be called foo_bar.
- A field in the content type might be called foo_date_started.
- A view displaying all the bars might be called foo_list_of_all_bars.
- A path to a report about the views might be created as such: crm-core/reports/foo/all-bars.
Respect the Reserved Paths
There are some reserved paths to be aware of in AbleOrganizer. While you can certainly use other paths if it is important to your feature, consider sticking with the following unless there is a good reason to do otherwise.
- Contacts: crm-core/contact, crm-core/contacts
- Reports: crm-core/reports
- Dashboard: crm-core, crm-core/dashboard
- Activities: crm-core/contact/%contact-id/activity/%activity-id, crm-core/activity/%activity-id,
- Relationships: crm-core/contact/%contact-id/relationships/%relationship-id, crm-core/relationships/%relationship-id
- Administration: admin/structure/crm-core, admin/config/crm-core
Clone and Override, Don't Overwrite
There are lots of situations that can arise where you might want to make some changes to a default display of a report / interface and distribute it to other users. Perhaps you have a really great way of displaying a list of contacts in the system, or maybe you have created a better way to work with activities. Hooray!
When you change the way something works in AbleOrganizer, you want to make a clone of the object and export that instead of the original item. This accomplishes 2 things: first, it ensures your new feature will not be overwritten the next time there's a release of AbleOrganizer. Second, and more importantly, it ensures someone can back out of your change in case things don't go as planned.
The best practice for distributing features that override the default settings in an AbleOrganizer site are as follows:
- Clone the view / panel used to display the item, whether it's a contact / activity / relationship / list of contacts / report / something else.
- Make your changes to the cloned view and export it as part of your feature. Give it the same path as the default item you are modifying.
- In your feature, disable the default view in CRM Core when the feature is enabled. Re-enable the default view when the feature is disabled.
Entities Should be Self-Contained
When building a feature, wherever possible, ensure the entities it defines are contained within the feature itself. The feature should declare the entity and the default fields used within it. Other features should not add or delete fields from the entity once it is defined.
For example: if you are building a feature that adds fields to the default meeting type, that is okay, but remember that you can't always count on it being present because users can delete it. It is often better to create a new feature with its own meeting type with all the fields needed for your module. This keeps you from having to make assumptions about what is there.
Use Bridge Features for Fields
If you really, really need to have 2 features that rely on a common set of fields, consider building a third feature that contains the entity / fields that they will use. This is a best practice for a couple of reasons. First off, it is really, really easy to get into situations where an entity / field is being exported in 2 features. It can create issues within features itself and make your life difficult. Second, and most importantly, people need to be able to turn features off within AbleOrganizer. Taking steps to ensure that each feature can operate independently of others is just good practice.
Don't Create Fields on Contact Entities
Depending on your use case, it's not always a good idea to build features that add fields to the contact entity.
When you do, you are making an assumption about how people have configured their installation of AbleOrganizer. It cuts down on the portability of features and forces people to use the fields you defined instead of the ones they might prefer.
When people are working with AbleOrganizer, they will configure their own fields with their own meaning. When you create features that rely on fields in the contact entity, you are forcing them to use the same fields the same way you have intended. There are some situations where this is appropriate - for instance, if you are adding fields that are simply not defined anywhere else.
In other situations, it is best to build features in a way where fields that affect a contact record can be configured through instructions to the user or a settings page. There are a lot of ways to set default fields for contact records, look at the contact type administration screen for wonderful examples of how to do this.
Sharing your features
In scientific circles, peer review is considered the ideal way to validate one's own work. It leads to insights and feedback from peers, helping researchers to think about problems in new and interesting ways.
AbleOrganizer is open-source software. If you have needed to take the time to create a new feature, the odds are someone else could benefit from it as well. Take the time to package your feature and share with other AbleOrganizer users. At worst, you will find out how your feature could be improved and learn something in the process. At best, you will get the insights of other sets of eyes and end up with something much more exciting that what you started with.