This documentation will help you get started with setting up a content type representing a "Reservation" that allows users to reserve a "Resource" using the Resource Conflict module.

Content Types Setup

  1. Create a content type called "Resource". This represents any type of object that can be reserved, like a room or location, a physical item, etc.
  2. Create a content type called "Reservation".
  3. Add a date field with a required end date. This module only works with date fields that have end dates. Node the date field in general does not need to be required. You can use either Date, ISO, or Unix storage types, it doesn't matter. Date Repeat fields will work just fine.
  4. Add an Entity Reference or References field that allows users to select a Resource
  5. After the content type is created, edit it and navigate to the Resource Conflict vertical tab. Click the checkbox to enable and select the date field you added.

This module ships with a default Rule that will detect conflicts within all resource conflict enabled nodes. In our example, we want to limit the conflict checking to only check against Reservation nodes that book the same Resource. We will create a new rule to demonstrate how this works.

Creating the Rule

  1. Create a new rule that reacts to event "A resource conflict node form is validated". This event will be fired anytime a node within a resource conflict enabled content type is validated. The unsaved node is passed as a variable to the Rule. At this point, no conflict checking has been done.
  2. Add a condition "Contains a resource conflict". This actually perform the conflict checking purely on the date field alone.
  3. Add an action "Load a list of conflicting nodes". Here, the conflicting nodes that were detected are loaded and passed to the Rule as a list. This allows us to loop through each one and perform an action.

Now we need to add the Rules behaviors to limit the result set based on the Resource that was reserved. We want compare the Resource field on the unsaved node that triggered the Rule against each of the nodes in conflicting list. To do this, we need to create a Rules Component, simply because we need to add a condition and a Rules Component lets us do that.

The Rules Component

  1. Click the Components tab on the top right, and create a new Component
  2. For "condition plugin", select "Rule". This means we're creating a little mini rule. The difference is that a Rules Component Rule doesn't get triggered by an event. In our case we will manually invoke it, passing in any variables manually that an event normally would pass automatically.
  3. We need to define parameters for this Rule Component, similar to how you'd define parameters to a function in PHP. Create two parameters:
    1. Data Type: "node", Label: "Unsaved Reservation", Machine Name: "unsaved_reservation"
    2. Data Type: "node", Label: "Conflicting Reservation", Machine Name: "conflicting_reservation"
  4. Now we need to add three conditions to this Rule Component. Two will be essentially "loading" the entity reference field data into Rules, and then the third will compare the two values to make sure they are equal:
    1. Entity has Field, select "unsaved-reservation" as the data selector. Select the resource entity reference field for the field dropdown.
    2. Entity has Field, select "conflicting-reservation" as the data selector. Select the resource entity reference field for the field dropdown.
    3. Data Comparison, select "unsaved-reservation:field-resource" as the data selector. Your exact field label may differ here. Then on the next screen, keep the operator at "equals". For the second data comparison, fill in "conflicting-reservation:field-resource" (try switching to the data selector if you need help filling in the appropriate value here).
  5. Now add an action "Set a form validation error". This action will execute for each conflicting reservation that has the same Resource value, adding a message to the node submission form and preventing the form from submitting. Type in something like: "Conflict with existing reservation: [conflicting-reservation:title]".

Now that the rule component is created, you need to go back to the original rule you created.

  1. Add new loop to the actions, and use "conflict-list" as the data selector. Rules will loop through each conflicting reservation.
  2. Click the "Add Action" button next to the Loop you just created. For the action drop down, scroll all the way to the bottom and select the Rules Component you created.
  3. Now you have to pass in two variables to the two parameters we created for this Rules Component. For the first parameter (unsaved-reservation), use "node" as the data selector. This is the node that originally fired the event our Rule is reacting on. For the second parameter, pass in "list-item". This will be the conflicting node that that loop has provided (remember, it's looping over our list and executing this Rules Component for each item)

Wrap up

Ok, that should be it! You can give it a whirl by creating two Reservations that are intentionally conflicting (both with the same Resource selected) and see if the error works. As noted above, this will work with repeat dates as well.

You can modify the rules however you want, for instance to limit the conflict result set further based on additional values.

Rules can be a bit overwhelming to work with if you've never used it in the past. Hopefully the instructions above are detailed enough. If you have trouble getting it working, drop a support request in the issue queue.

Performance

It should be noted that the initial conflict detection will always load all nodes in conflict, and then allow you to limit those results as we showed above. However, if you have hundreds or thousands of potentially conflicting nodes, there may be a performance issue.

You can alter the main query that is used to find the conflicting nodes. The query has a tag "resource_conflict", so you can use hook_query_alter to add your own conditions and joins. This should improve performance if you have a specialized need.

Multiple Resources

If you allow multiple resources to reserved with the same reservation (e.g. you have a combined room), you may need install Rules List Conditions. See this comment for details.

Rules Forms Support

If the Rules Forms Support module is enabled, this module will pass the form object to any rule that is trigged by the "A resource conflict was detected" event. This will expose the node submission form to the Rule, allowing you to use all of the great Actions that Rules Forms Support provides to manipulate the form.

For example, instead of using this modules action "Set a form validation error", you could instead use the similarly named one that is present in the Rules Forms Support module. Behind the scenes, it's handled much better than Resource Conflict handles it.