availability_calendar.entity.inc in Availability Calendars 7.5
Contains Entity API and Search API hooks and callbacks.
@todo:
- Can the hybrid approach remain in place: calendar as a field and calendar as an entity without introducing too much overhead?
- Move field instance settings into the entity data model:
- default state: without knowing the default state, a calendar on its own cannot be rendered or queried about availability.
- allocation type: without knowing this setting, user interaction with the calendar is difficult, especially selecting end dates.
- Make a calendar entity renderable on its own.
- Move calendar functionality into an entity and entityController class.
- Define additional properties on the calendar like:
- availability
- isAvailable
- the definition values 'allocation_type' and 'default_state' for the (filtered) availability can be empty if we are filtering on calendar entities instead of calendar fields.
File
availability_calendar.entity.incView source
<?php
/**
* @file Contains Entity API and Search API hooks and callbacks.
*
* @todo:
* - Can the hybrid approach remain in place: calendar as a field and calendar
* as an entity without introducing too much overhead?
* - Move field instance settings into the entity data model:
* - default state: without knowing the default state, a calendar on its own
* cannot be rendered or queried about availability.
* - allocation type: without knowing this setting, user interaction with the
* calendar is difficult, especially selecting end dates.
* - Make a calendar entity renderable on its own.
* - Move calendar functionality into an entity and entityController class.
* - Define additional properties on the calendar like:
* - availability
* - isAvailable
* - the definition values 'allocation_type' and 'default_state' for the
* (filtered) availability can be empty if we are filtering on calendar
* entities instead of calendar fields.
*/
/**
* Implements hook_entity_info().
*
* Defines the "internals" of this module's data model to Drupal core and Entity
* API (from contrib):
* - availability_calendar_calendar is defined as entity.
* - availability_calendar_availability cannot be defined as entity as it does
* not have a numeric primary key. Will be defined as property of a calendar
* though (in a future version).
* - availability_calendar_state could be defined as configuration entities, so
* it could be exported, but has not been defined as such yet.
*
* Both Drupal core and Entity API keys and values are defined here.
*/
function availability_calendar_entity_info() {
$return = array(
'availability_calendar_calendar' => array(
'module' => 'availability_calendar',
'label' => t('Availability Calendar'),
'plural label' => t('Availability Calendars'),
'description' => t('An entity type used to store date based availability.'),
'base table' => 'availability_calendar_calendar',
'revision table' => null,
'entity keys' => array(
'id' => 'cid',
),
'fieldable' => FALSE,
'view modes' => array(
'full' => array(
'label' => t('Full content'),
'custom settings' => FALSE,
),
),
'controller class' => 'EntityAPIController',
'entity class' => 'Entity',
'label callback' => 'entity_class_label',
'uri callback' => 'entity_class_uri',
'views controller class' => 'AvailabilityCalendarViewsController',
),
);
return $return;
}
/**
* Implements hook_entity_property_info().
*
* Defines the labels and types of the properties of the
* 'availability_calendar_calendar' entity.
*/
function availability_calendar_entity_property_info() {
$return = array(
'availability_calendar_calendar' => array(
'properties' => array(
// Schema fields. We override to define the correct type and textual
// information.
'cid' => array(
'label' => t('Calendar ID'),
'description' => t('The unique ID of the calendar.'),
'type' => 'integer',
'schema field' => 'cid',
),
'created' => array(
'label' => t('Created date'),
'description' => t('The date the calendar was created.'),
'type' => 'date',
'schema field' => 'created',
),
'changed' => array(
'label' => t('Last updated date'),
'description' => t('The date the calendar was last updated.'),
'type' => 'date',
'schema field' => 'changed',
),
// Virtual, non stored properties.
// Filtered availability: should only be used in Search API indices.
'filtered_availability' => array(
'label' => t('Filtered availability'),
'description' => t('Availability for this calendar, filtered for search optimization.'),
'type' => 'list<date>',
'getter callback' => 'availability_calendar_calendar_entity_property_filtered_availability_get',
),
),
),
);
return $return;
}
/**
* Callback to alter the property info for fields, in our case the Availability
* Calendar field.
*
* @param array $info
* @param string $entity_type
* @param array $field
* @param array $instance
* param array $field_type
*/
function availability_calendar_field_property_info_alter(&$info, $entity_type, $field, $instance) {
$name = $field['field_name'];
$property =& $info[$entity_type]['bundles'][$instance['bundle']]['properties'][$name];
if ($field['cardinality'] != 1) {
$property['type'] = "list<{$property['type']}>";
}
$property['getter callback'] = 'entity_metadata_field_verbatim_get';
$property['setter callback'] = 'entity_metadata_field_verbatim_set';
$property['property info'] = array(
'cid' => array(
'type' => 'availability_calendar_calendar',
'label' => t('Availability Calendar'),
'description' => t('The reference to the Availability Calendar.'),
'getter callback' => 'entity_property_verbatim_get',
'setter callback' => 'entity_property_verbatim_set',
),
);
if (!empty($instance['settings']['allow_disable'])) {
$property['property info']['enabled'] = array(
'type' => 'boolean',
'label' => t('Enabled'),
'description' => t('If the calendar is enabled'),
'getter callback' => 'entity_property_verbatim_get',
'setter callback' => 'entity_property_verbatim_set',
);
}
if (!empty($instance['settings']['add_name'])) {
$property['property info']['name'] = array(
'type' => 'string',
'label' => t('Name'),
'description' => t('The name of the calendar'),
'sanitized' => FALSE,
'sanitize' => 'check_plain',
'getter callback' => 'entity_property_verbatim_get',
'setter callback' => 'entity_property_verbatim_set',
);
}
}
/**
* Entity property getter callback for the 'filtered availability' property.
*
* The filtered availability equals the availability but represented in a format
* optimised for the search API.
*
* @param object $entity
* param array $options
* param string $property_name
* param string $entity_type
* param array $property_info
*
* @return array|null
*
* @throws \Exception
*/
function availability_calendar_calendar_entity_property_filtered_availability_get($entity) {
module_load_include('inc', 'availability_calendar');
$cid = $entity->cid;
$from = new DateTime();
$to = new DateTime();
$months_to_index = variable_get('availability_calendar_months_to_index', 13);
$to
->add(new DateInterval("P{$months_to_index}M"));
$default_state = availability_calendar_get_field_setting('default_state');
if ($default_state === NULL) {
// We could use info from the field filter, but as we have no idea of that
// context, we just walk through all fields. Performance hit should be
// minimal in "normal" set-ups.
$field = availability_calendar_get_referring_field($cid);
if (!empty($field)) {
$field_info = field_info_field($field);
$default_state = $field_info['settings']['default_state'];
}
}
$availability = availability_calendar_get_availability($cid, $from, $to, $default_state);
$non_available_states = availability_calendar_get_states(FALSE);
$result = array();
foreach ($availability as $date => $sid) {
if (array_key_exists($sid, $non_available_states)) {
$timestamp = new DateTime($date);
$timestamp = (int) $timestamp
->format('U');
$result[] = $timestamp;
}
}
return $result;
}
/**
* Returns the value for an availability calendar field setting.
*
* A value is only returned if all availability calendar fields have the same
* value for the requested setting. If not, null is returned.
*
* @param string $setting
* @return mixed
*/
function availability_calendar_get_field_setting($setting) {
$settings =& drupal_static(__FUNCTION__, array());
if (!array_key_exists($setting, $settings)) {
$settings[$setting] = NULL;
$instances = field_info_field_map();
foreach ($instances as $field_name => $field_map) {
if ($field_map['type'] === 'availability_calendar') {
$field = field_info_field($field_name);
if ($settings[$setting] === NULL) {
// first field of this type: get value for the requested setting
$settings[$setting] = $field['settings'][$setting];
}
else {
if ($settings[$setting] !== $field['settings'][$setting]) {
// Multiple calendar fields with different values for the requested
// setting: we cannot return THE value for this setting; return null.
$settings[$setting] = NULL;
break;
}
}
// else: multiple calendar fields, but so far all these fields have the
// same value for this setting. Continue.
}
}
}
return $settings[$setting];
}
/**
* Returns the field name of the field that refers to the given calendar id.
*
* The search can be restricted to a given set of fields by passing in a 2nd
* parameter.
*
* @param int $cid
* @param array|NULL $restrict
* An array of fields to restrict the search to. NULL if the search should
* not be restricted. An empty array restricts the search to NO fields at
* all and thus will always return FALSE!
*
* @return string|false
* The name of the field or false if no field refers to this calendar.
*/
function availability_calendar_get_referring_field($cid, $restrict = NULL) {
$fields = is_array($restrict) ? $restrict : availability_calendar_get_fields_by_type('availability_calendar_calendar');
foreach ($fields as $field_name) {
$query = new EntityFieldQuery();
$query
->fieldCondition($field_name, 'cid', $cid, '=');
$result = $query
->execute();
if (!empty($result)) {
return $field_name;
}
}
return FALSE;
}
/**
* Returns all fields of the given type.
*
* @param string $type
*
* @return array
* An array with field (machine) names.
*/
function availability_calendar_get_fields_by_type($type) {
$result = array();
$fields = field_info_fields();
foreach ($fields as $field_name => $field) {
if ($field['type'] === $type && $field['deleted'] == 0) {
$result[] = $field_name;
}
}
return $result;
}
/**
* Implements hook_search_api_data_type_info().
*
* We define a new data type for indexed properties that should be used to
* filter on availability.
*
* @return array
*/
function availability_calendar_search_api_data_type_info() {
return array(
'availability_calendar_availability' => array(
'name' => t('Availability'),
'fallback' => 'date',
),
);
}
/**
* Implements hook_search_api_alter_callback_info().
*/
function availability_calendar_search_api_alter_callback_info() {
$callbacks['availability_calendar_alter_field_filter'] = array(
'name' => t('Field filter'),
'description' => t('Exclude items from indexing based on the fields that refer to them.'),
'class' => 'AvailabilityCalendarAlterFieldFilter',
// Filters should be executed first.
'weight' => -10,
);
return $callbacks;
}
Functions
Name![]() |
Description |
---|---|
availability_calendar_calendar_entity_property_filtered_availability_get | Entity property getter callback for the 'filtered availability' property. |
availability_calendar_entity_info | Implements hook_entity_info(). |
availability_calendar_entity_property_info | Implements hook_entity_property_info(). |
availability_calendar_field_property_info_alter | Callback to alter the property info for fields, in our case the Availability Calendar field. |
availability_calendar_get_fields_by_type | Returns all fields of the given type. |
availability_calendar_get_field_setting | Returns the value for an availability calendar field setting. |
availability_calendar_get_referring_field | Returns the field name of the field that refers to the given calendar id. |
availability_calendar_search_api_alter_callback_info | Implements hook_search_api_alter_callback_info(). |
availability_calendar_search_api_data_type_info | Implements hook_search_api_data_type_info(). |