One thing I think makes FarCry extremely powerful and flexible is the ability to customize or extend just about everything. One requirement we had for the new Alagad site was that we wanted to be able to store additional information about each employee of Alagad. To accomplish this we needed to do quite a few customizations. First, we needed to extend the core ‘dmProfile’ object to add the fields we wished to store. Second, we needed to modify the forms users see to modify their own information. We also created a new form that administrators can use to add and modify user information that we may not want users to modify themselves. Lastly, we customized the menu so that our new form was used when a user wanted to update their profile. In this post I will discuss the steps we took to extend the native ‘dmProfile’ object. In subsequent posts, which I plan to do over the next 2 days, I will discuss how we created our custom form and lastly how we customized the menu to be able to use our new form.
Whenever you create custom content you must extend one of the core FarCry objects. In our case, we didn’t want to extend one of the base objects, we wanted to extend the ‘dmProfile’ object. To do this, we simply created a CFC named ‘dmProfile’ and put it in the {farcry Project}/packages/types directory, the CFC initially contained just the following.
<cfcomponent extends="farcry.core.packages.types.dmProfile" displayName="Profiles" hint="FarCry User Profile. Authentication and authorisation handled seperately by associated user directory model."> </cfcomponent>
All FarCry objects contain <cfproprty> tags to define the object’s, well, umm, properties. FarCry uses this informtion to create the database tables used to store the information that is defined. You read that correctly, FarCry actually creates all your DB tables for you when creating custom content types, or objects. So, becasue we wanted to store more information than dmProfile allowed natively, all we needed to do was to add <cfproperty> tags for the new data. For example:
<cfproperty name="bio" type="longchar hint="User's Bio" required="no" ftseq="60" ftfieldset="User" ftlabel="Bio" /><cfproperty name="image" type="uuid"& required="false" default="" hint="Image" ftFieldSet="Picture" ftJoin="dmImage"& ftLabel="Picture"& ftType="UUID" ftSeq="90" />
The first item is a palce for us to store a short Bio about each employee. The second item is used to store an picture of the employee. Both of these items are used in the ‘About the Author’ section of any blog entry. Just look to the right and up a little bit, you’ll see what I mean.
If you look closely, you will see some standard attributes, ‘name’, ‘type’, ‘hint’, etc, however, you will also see some that begin with ‘ft’. These attributes describe to FarCry how the item should be handled when using ‘formtools’ (hence, the ‘ft’). Formtools are new to FarCry 4. Basically formtools are a quick, easy way to create forms for adding/editing information stored in any of your objects. Formtools will be discussed in depth in a future post. For now, it helps to know that FarCry itself uses formtools to create/edit content, and that is why we use them here. Let’s look at the ‘bio’ property first.
You will see that one attribute is ‘ftlabel’. This is what will be displayed in the <label> tag for the form item. So when farCry displays the form to edit a profile, ‘Bio’ will appear next to the actual form field.
‘ftfieldset’ breaks grouped form field items into different <fieldset>s. For each unique ftfieldset value in the entire object, FarCry will create a new fieldset and a <legend> that dspalys the value of the ‘ftfieldset’ attribute.
Lastly, ‘ftseq’ tells farcry what order to display the form fields within the form.
One other attribute that is frequently used is ‘ftWizardStep’ which breaks your form out into multiple pages with one page for each unique ‘ftwizardstep’ in an object. When using ftwizardstep, you do not need to worry about persisting data from one page to the next, FarCry handles that all on its own.
You probably noticed that the ‘image’ property has a few other ‘ft’ attributes. Specifically, ‘ftype’ and ‘ftjoin’ ‘fttype’ tells farCry what type of data is being stored, for more detais about the data types of formtools, check out this page in the FarCry wiki . In this case, the value is ‘UUID’ which tells FarCry that this will hold data related to another object, spcifically, it will hold the ‘objectID’ of another object.
You relate one object to another using ‘ftjoin’. The value of ‘ftjoin’ is the name of the object we want to link to, in this case ‘dmImage’. Basically, its like creating a foreign key relationship. So our code is telling FarCry, in the database we will have a column in the ‘dmProfile’ table named ‘image’. The value of this column will relate to the ‘obejctID’ column of the ‘dmImage’ table. If we wnated to allow multiple images to be linked to a profile, we would have used ‘ftType=”array”‘. FarCry would then create an ‘array table’ that joins both dmProfile and dmImage.
I should note here, and I will go into more details in my next post about the custom profile form, I copied over all of the properties for ‘dmProfile’ into our new object. Why? Well, becasue migrating all the native stuff over to to use formtools is a daunting task, and the FarCry team is doing a great job, but when we started the Alagad project, dmProfile had not yet been updated. To make it possible to use formtools to their full extent, we needed to add ‘ft’ attributes to all the existing properties.
OK, now that we have extended one of the core objects, how do we let FarCry know about our changes? You need to login to the admin sectoin of your FarCry site. Click on the ‘Admin’ tab and then select ‘COAPI Management’ from the drop down on the left side. Lastly, click on the ‘Type Classes’ link. On this page, you will see a list of all the content types you have available to you in your FarCry site. Even if you have not created any custom content types, you will still see entries here as some content types are included with a default FarCry install.
If you were following along with this post, you should see an item in the section labeled ‘Custom Content Types’ named ‘Profiles’ or ‘dmProfile’. Under that item you should see something that looks similar to this:
This is FarCry telling you that your object and the database are out of synch. In our case, its telling us there is a property in the object that is not represented in the database. To synch them up you simply select ‘Deploy property’ under ‘Action:’ and click the ‘Go’ button. FarCry will then create the necessary column for that property. You will need to follow this process for every new property you defined. One thing I wiash FarCry could do is to deploy all properties at once. It may not seem like abig deal now, but if you have a lot of changes to your properties, which is not unheard of during development, it can be a bit of a pain to have to deploy all properties individualy.
Once you have successfully deployed all your new properties, FarCry is now ready to use them. We will discuss in my next post how we used these new properties to create a custom profile form.
Comments on: "Farcry – Extending Just About Everything" (4)
Is there any particular reason you chose to extend dmProfile, rather than say build your own profile content type?
LikeLike
Mate, this is an excellent explanation of things. Keep it coming.
LikeLike
@Geoff – We chose to extend dmProfile because we wanted to keep the profile tied to a user login. At the time it just seemed easier to extend dmProfile rather than to muck around with the security to link the user to a different object.
I would not be surprised if you respond back saying, ‘Well, you could have done this …’. I have found that there usually is more than one way to accomplish something in FarCry (another reason why I like it as much as I do). This was a way that worked for us, and at the time, seemed like the most efficient use of our time to meet the requirement.
LikeLike
@Scott – both approaches are totally valid; it’s always interesting to hear why a team goes one way or another.
I ask because we’re looking at overhauling the security sub-system in 4.1 and one feature I’m lobbying for is the ability to more easily hook up a custom content type to user login.
Now that it’s so easy to construct content types with formtools, we’re trying to give folks the opportunity to swap in whatever they want.
In any event great article, and as Mat says, “keep it coming”!
LikeLike