date_repeat_entity.update.inc in Date Repeat Entity 7
Same filename and directory in other branches
Contains functions that support update of entities with repeating date fields.
File
includes/date_repeat_entity.update.incView source
<?php
/**
* @file
* Contains functions that support update of entities with repeating
* date fields.
*/
/**
* Update or replaces date entities based on a scope determined by user.
*
* @param object $entity
* The entity being updated.
*
* @param string $entity_type
* the entity type to load, e.g. node.
*/
function date_repeat_entity_update_dates($entity, $entity_type) {
// Get entity wrapper.
$entity_wrapper = entity_metadata_wrapper($entity_type, $entity);
$bundle = $entity_wrapper
->getBundle();
// Get value of clone state - a new node will have the default state
// of FALSE while a cloned node will have a state of TRUE.
$field_clone_state = $entity_wrapper->field_clone_state
->value();
// Only act on entities that are not clones or equivalent.
if ($field_clone_state === FALSE) {
$scope = $entity->date_repeat_entity['scope'];
// Determine if there is has been a material change between the
// original and updated entity.
$repeating_date_has_changed = module_invoke_all('repeating_date_has_changed', $entity->original, $entity, $entity_type);
// If the repeating date pattern has changed then replace the entities.
if (in_array(TRUE, $repeating_date_has_changed)) {
// Replace dates and update entity with new master uuid and related
// properties.
$entity = _date_repeat_entity_replace_dates($entity, $entity_type, $bundle, $scope);
}
else {
// Update dates, keeping same master uuid.
_date_repeat_entity_update_dates($entity_wrapper, $entity, $entity_type, $bundle, $scope);
}
}
// Find out which field we are operating on.
$repeating_date_field = date_repeat_entity_get_repeating_date_field($entity_type, $bundle);
$repeating_date_field_name = $repeating_date_field['field_name'];
$repeating_date_field_language = field_language($entity_type, $entity, $repeating_date_field_name);
// Remove any date field delta values that were created during the save
// operation - any existing entities should not have these deltas.
array_splice($entity->{$repeating_date_field_name}[$repeating_date_field_language], 1);
// Make sure entity clone state is set to FALSE - this should be normal state.
$entity_wrapper->field_clone_state = FALSE;
}
/**
* Replace dates associated with a repeating date series.
*
* @param object $entity
* The entity being updated.
* @param string $entity_type
* The entity type to load, e.g. node.
* @param string $bundle
* The bundle type, e.g. event.
* @param string $scope
* Defines the extent to which date series should be searched.
* Can be one of:
* current (for the current date instance only),
* future (for the current and all future date instances),
* all (all instances of a date series).
*
* @return object
* Represents the entity that has been updated with a new uuid.
*/
function _date_repeat_entity_replace_dates($entity, $entity_type, $bundle, $scope = 'current') {
// Clone the entity before the UUID gets changed.
// Notes:
// - use the clone method rather than replicate_clone_entity which resets
// the entity_id.
// - cannot clone the original wrapper because it still points to the original
// entity.
// - clone the entity's original state as stored in entity->original. This
// is because we need to use the original start date when the scope is
// 'future'.
$original_entity = clone $entity->original;
$original_entity_wrapper = entity_metadata_wrapper($entity_type, $original_entity);
// Generate a new master UUID.
$master_uuid_new = uuid_generate();
// Change the entity uuid and set its status to new.
$entity->uuid = $master_uuid_new;
$entity->vuuid = $master_uuid_new;
// Create new dates based on the current entity and RRULE defined with it.
date_repeat_entity_create_dates($entity, $entity_type);
// Make sure repeating date delete functions are available.
module_load_include('inc', 'date_repeat_entity', 'includes/date_repeat_entity.delete');
// Delete original date entities that were replaced
// - excluding the current entity date because it will be updated by the save
// action that called this function.
$exclude_current_entity = TRUE;
date_repeat_entity_delete_dates($original_entity_wrapper, $entity_type, $bundle, $scope, $exclude_current_entity);
return $entity;
}
/**
* Update dates associated with a repeating date series.
*
* @param EntityDrupalWrapper $entity_wrapper
* A property wrapper for an entity.
* @param object $entity
* The entity being updated.
* @param string $entity_type
* The entity type to load, e.g. node.
* @param string $bundle
* The bundle type, e.g. event.
* @param string $scope
* Defines the extent to which date series should be searched.
* Can be one of:
* current (for the current date instance only),
* future (for the current and all future date instances),
* all (all instances of a date series).
*/
function _date_repeat_entity_update_dates($entity_wrapper, $entity, $entity_type, $bundle, $scope = 'current') {
// Get entities in date series
// - excluding the current entity date because it will be updated by the save
// action that called this function.
$exclude_current_entity = TRUE;
$result = date_repeat_entity_get_date_entities($entity_wrapper, $entity_type, $bundle, $scope, $exclude_current_entity);
// If query successful, update retrieved entities.
if (isset($result[$entity_type])) {
// Build an array of entity ids for for the entity type.
$date_entity_ids = array_keys($result[$entity_type]);
// Retrieve entities based on entity ids.
$date_entities = entity_load($entity_type, $date_entity_ids);
// Update each date entity as required.
foreach ($date_entities as $date_entity) {
// Let other modules update the date entity.
module_invoke_all('repeating_date_update', $date_entity, $entity, $entity_type);
// Get a wrapper for the entity.
$date_entity_wrapper = entity_metadata_wrapper($entity_type, $date_entity);
// Set clone state to TRUE so the cloning procedures are skipped
// when hook_entity_presave is triggered.
$date_entity_wrapper->field_clone_state = TRUE;
// Save the entity.
entity_save($entity_type, $date_entity);
}
}
}
/**
* Implements hook_repeating_date_has_changed().
*
* see @date_repeat_entity.api.php
*
* Determines if an entity with a repeating date has changed. Compares the
* start date, end date and RRULE of new and old entity.
*/
function date_repeat_entity_repeating_date_has_changed($original_entity, $updated_entity, $entity_type = 'node') {
$repeating_date_has_changed = FALSE;
// Check that entity aleady exists - we are not validating new entities.
if (!is_null($original_entity) && !is_null($updated_entity)) {
// Create two wrappers.
$original_wrapper = entity_metadata_wrapper($entity_type, $original_entity);
$updated_wrapper = entity_metadata_wrapper($entity_type, $updated_entity);
// Get bundle type from original entity.
$bundle = $original_wrapper
->getBundle();
// Make sure utility functions are available.
module_load_include('inc', 'date_repeat_entity', 'includes/date_repeat_entity.utility');
$repeating_date_field = date_repeat_entity_get_repeating_date_field($entity_type, $bundle);
// Check that the entity form has a repeating date field.
if ($repeating_date_field != NULL) {
// Get the name of the repeating field.
$repeating_date_field_name = $repeating_date_field['field_name'];
// Get original date field properties.
$original_date = $original_wrapper->{$repeating_date_field_name}[0]
->value();
$original_date_start_value = $original_date['value'];
$original_date_end_value = $original_date['value2'];
$original_rrule = $original_date['rrule'];
// Get updated date field properties.
$updated_date = $updated_wrapper->{$repeating_date_field_name}[0]
->value();
$updated_date_start_value = $updated_date['value'];
$updated_date_end_value = $updated_date['value2'];
$updated_rrule = $updated_date['rrule'];
// Check if the entity date has changed to the extent that
// the repeating date series has changed and therefore dependent data
// like date exceptions and referencing entities will need to be reset.
$updated_date_data = array(
$updated_date_start_value,
$updated_date_end_value,
$updated_rrule,
);
$original_date_data = array(
$original_date_start_value,
$original_date_end_value,
$original_rrule,
);
if ($updated_date_data !== $original_date_data) {
$repeating_date_has_changed = TRUE;
}
}
}
return $repeating_date_has_changed;
}
/**
* Implements hook_repeating_date_update().
*
* see @date_repeat_entity.api.php
*/
function date_repeat_entity_repeating_date_update($date_entity, $updated_entity, $entity_type = 'node') {
$date_entity_wrapper = entity_metadata_wrapper($entity_type, $date_entity);
$updated_entity_wrapper = entity_metadata_wrapper($entity_type, $updated_entity);
// Update date entity title from updated entity.
$date_entity_wrapper->title = $updated_entity_wrapper
->label();
}
/**
* Get new date series if an entity with a repeating date has changed.
*
* Note: this function is not currently used but could be useful if we decide
* to allow all dates in a series to be shifted based on the revised RRULE,
* start and end dates of the instance that changed.
*
* @param array $form_state
* represents the current state of the form
* @param int $entity_id
* entity identifier
* @param string $entity_type
* The entity type to load, e.g. node.
* @param string $bundle
* The bundle type, e.g. event.
* @param string $scope
* Defines the extent to which date series should be searched.
* Can be one of:
* current (for the current date instance only),
* future (for the current and all future date instances),
* all (all instances of a date series).
*
* @return array
* NULL if the repeating date has not changed.
*/
function _date_repeat_entity_get_updated_dates($form_state, $entity_id, $entity_type, $bundle, $scope = 'all') {
$new_dates = array();
// Make sure utility functions are available.
module_load_include('inc', 'date_repeat_entity', 'includes/date_repeat_entity.utility');
// Check that the entity form has a repeating date field.
$repeating_date_field = date_repeat_entity_get_repeating_date_field($entity_type, $bundle);
if ($repeating_date_field != NULL) {
// Get the name of the repeating field.
$repeating_date_field_name = $repeating_date_field['field_name'];
$language = $form_state['values']['language'];
$new_date_start_value = $form_state['values'][$repeating_date_field_name][$language][0]['value'];
$new_date_end_value = $form_state['values'][$repeating_date_field_name][$language][0]['value2'];
$new_rrule = $form_state['values'][$repeating_date_field_name][$language][0]['rrule'];
$old_entity = entity_load_unchanged($entity_type, $entity_id);
$old_date_start_value = $old_entity->{$repeating_date_field_name}[$old_entity->language][0]['value'];
$old_date_end_value = $old_entity->{$repeating_date_field_name}[$old_entity->language][0]['value2'];
// Get timezone associated with the field instance.
$timezone = date_get_timezone($repeating_date_field['settings']['tz_handling']);
// Create DateObjects (extensions of PHP DateTime objects)
// from the new start date and old start date.
$new_date_start = new DateObject($new_date_start_value, $timezone, date_type_format($repeating_date_field['type']));
$new_date_end = new DateObject($new_date_end_value, $timezone, date_type_format($repeating_date_field['type']));
$old_date_start = new DateObject($old_date_start_value, $timezone, date_type_format($repeating_date_field['type']));
$old_date_end = new DateObject($old_date_end_value, $timezone, date_type_format($repeating_date_field['type']));
// Return the time difference (seconds) between:
// a) the new start date and old start date and
// b) the new start date and new end date.
$seconds_between_new_and_old_start_date = $new_date_start
->difference($old_date_start);
$seconds_between_new_start_and_new_end_date = $new_date_end
->difference($new_date_start);
// Define PHP Interval objects.
$interval_between_new_and_old_start_date = new DateInterval('PT' . $seconds_between_new_and_old_start_date . 'S');
$interval_between_new_start_and_new_end_date = new DateInterval('PT' . $seconds_between_new_start_and_new_end_date . 'S');
// Get the series master entity uuid from the current entity.
$master_uuid_field_name = 'field_master_uuid';
$master_uuid = $old_entity->{$master_uuid_field_name}[$old_entity->language][0]['value'];
// Get the master entity using the master entity uuid.
$master_entity = date_repeat_entity_get_master_entity($entity_type, $bundle, $master_uuid);
// Get a start date value for the new date series.
if (!empty($master_entity)) {
// If the master entity exists, then use it as the start date value
// for calculating new date series.
$master_date_start_value = $master_entity->{$repeating_date_field_name}[$master_entity->language][0]['value'];
}
else {
// Otherwise, use the value in the value of the
// repeat_date_start field.
$master_date_start_value = $new_date_start_value;
}
// Convert master entity start date to a DateObject.
$master_date_start = new DateObject($master_date_start_value, $timezone, date_type_format($repeating_date_field['type']));
// Apply the calculated interval between the new and old start
// dates of the current entity to the master entity start date.
if ($new_date_start > $old_date_start) {
$new_master_date_start = $master_date_start
->add($interval_between_new_and_old_start_date);
}
else {
$new_master_date_start = $master_date_start
->sub($interval_between_new_and_old_start_date);
}
// Create a new master entity end date based on the adjusted
// master start date.
$new_master_date_start_clone = clone $new_master_date_start;
// Apply the calculated interval between the new start and
// new end date of the current entity to the new master entity
// end date. This will yield a new master end date.
if ($new_date_end > $old_date_end) {
$new_master_date_end = $new_master_date_start_clone
->add($interval_between_new_start_and_new_end_date);
}
else {
$new_master_date_end = $new_master_date_start_clone
->sub($interval_between_new_start_and_new_end_date);
}
// Get formatted strings representing new master start date and
// end date.
$new_master_date_start_value = date_format($new_master_date_start, date_type_format($repeating_date_field['type']));
$new_master_date_end_value = date_format($new_master_date_end, date_type_format($repeating_date_field['type']));
// Create an item array to simulate the field instance structure
// used in Date module's Form API functions.
$item = array(
'value' => $new_master_date_start_value,
'value2' => $new_master_date_end_value,
'timezone' => $timezone,
);
// Get new date series based on the new master start and end dates.
$new_dates = date_repeat_build_dates($new_rrule, NULL, $repeating_date_field, $item);
}
return $new_dates;
}
Functions
Name![]() |
Description |
---|---|
date_repeat_entity_repeating_date_has_changed | Implements hook_repeating_date_has_changed(). |
date_repeat_entity_repeating_date_update | Implements hook_repeating_date_update(). |
date_repeat_entity_update_dates | Update or replaces date entities based on a scope determined by user. |
_date_repeat_entity_get_updated_dates | Get new date series if an entity with a repeating date has changed. |
_date_repeat_entity_replace_dates | Replace dates associated with a repeating date series. |
_date_repeat_entity_update_dates | Update dates associated with a repeating date series. |