class MerciDefaultController in MERCI (Manage Equipment Reservations, Checkout and Inventory) 7.3
A null implementation of EntityReference_SelectionHandler.
Hierarchy
- class \MerciDefaultController
Expanded class hierarchy of MerciDefaultController
1 string reference to 'MerciDefaultController'
- merci_get_controller in merci_core/
merci_core.module
File
- merci_core/
reservation.handler.inc, line 14 - Abstraction of the selection logic of an entity reference field.
View source
class MerciDefaultController {
protected $parent_table, $parent_index, $dates, $date_table, $date_column, $date_column2, $item_table, $item_column, $items, $item_type, $entity, $context;
protected $conflicting_entities;
protected $quantity_reserved, $entity_quantity;
protected $validated = FALSE;
protected $parent_has_quantity, $parent_has_status, $items_is_list = FALSE;
protected $errors = NULL;
public static function getInstance($entity, $item_type, $context) {
if (class_exists($class_name = 'MerciDefaultController_' . $item_type)) {
return new $class_name($entity, $item_type, $context);
}
else {
return new MerciDefaultController($entity, $item_type, $context);
}
}
public function __construct($entity, $item_type, $context) {
$this->context = $context;
$this->item_type = $item_type;
$this->entity = $entity;
$this->items = array();
// Determine if dealing with multiple values.
if (substr($entity->{$context['item_field']}
->type(), 0, 5) == 'list<') {
foreach ($entity->{$context['item_field']}
->getIterator() as $delta => $item) {
if ($item
->getIdentifier()) {
$this->items[$delta] = $item;
}
}
$this->items_is_list = TRUE;
}
else {
$this->items[0] = $entity->{$context['item_field']};
}
if (substr($entity->{$context['date_field']}
->type(), 0, 5) == 'list<') {
foreach ($entity->{$context['date_field']}
->getIterator() as $delta => $item) {
$this->dates[$delta] = $item
->value();
}
}
else {
$this->dates[0] = $entity->{$context['date_field']}
->value();
}
// Storage location for date field.
$date_field_info = field_info_field($context['date_field']);
$date_storage = $date_field_info['storage']['details']['sql']['FIELD_LOAD_CURRENT'];
$keys = array_keys($date_storage);
$this->date_table = reset($keys);
$this->date_column = $date_storage[$this->date_table]['value'];
$this->date_column2 = $date_storage[$this->date_table]['value2'];
// Storage location for item field.
$item_field_info = field_info_field($context['item_field']);
$item_storage = $item_field_info['storage']['details']['sql']['FIELD_LOAD_CURRENT'];
$keys = array_keys($item_storage);
$this->item_table = reset($keys);
$keys = array_keys($item_field_info['indexes']);
$item_key = reset($keys);
$this->item_column = $item_storage[$this->item_table][$item_key];
$entity_info = $entity
->entityInfo();
$this->parent_index = $entity
->entityKey('id');
$this->parent_table = $entity_info['base table'];
$this->parent_has_quantity = in_array('quantity', $entity_info['schema_fields_sql']['base table']);
$this->parent_has_status = in_array('status', $entity_info['schema_fields_sql']['base table']);
try {
$this->entity_quantity = $entity->quantity
->value();
} catch (EntityMetadataWrapperException $e) {
$this->entity_quantity = 1;
}
}
public function getErrors($delta = NULL, $dates = array()) {
// Determine if reserving too many of the same item.
if ($this->errors === NULL) {
$this
->validate();
$entity = $this->entity;
$entity_type = $entity
->type();
$context = $this->context;
$errors = array();
if ($this->items_is_list) {
foreach ($entity->{$context['item_field']}
->getIterator() as $delta => $resource) {
$item_id = $resource
->getIdentifier();
if (empty($item_id)) {
continue;
}
if (empty($item_count[$item_id])) {
$item_count[$item_id] = 0;
}
$item_count[$item_id]++;
try {
$quantity_reservable = $resource->field_quantity
->value();
} catch (EntityMetadataWrapperException $e) {
$quantity_reservable = 1;
}
if ($item_count[$item_id] > $quantity_reservable) {
// Selected to many.
if (!array_key_exists($delta, $errors)) {
$errors[$delta] = array();
}
$parents_path = implode('][', array(
$context['item_field'],
'und',
$delta,
'target_id',
));
$errors[$delta][MERCI_ERROR_TOO_MANY] = t('%name: You have selected too many of the same item. We only have %quantity available but you reserved %reserved.', array(
'%name' => $resource
->label(),
'%quantity' => $quantity_reservable,
'%reserved' => $item_count[$item_id],
));
}
}
}
else {
$resource = $entity->{$context['item_field']};
$item_count[$resource
->getIdentifier()] = $this->entity_quantity;
try {
$quantity_reservable = $resource->field_quantity
->value();
} catch (EntityMetadataWrapperException $e) {
$quantity_reservable = 1;
}
if ($this->entity_quantity > $quantity_reservable) {
if (!array_key_exists($delta, $errors)) {
$errors[$delta] = array();
}
$errors[$delta][MERCI_ERROR_TOO_MANY] = t('%name: You have selected too many of the same item. We only have %quantity available but you reserved %reserved.', array(
'%name' => $resource
->label(),
'%quantity' => $quantity_reservable,
'%reserved' => $this->entity_quantity,
));
// Selected to many.
}
}
$reserved = $this
->getQuantityReserved();
$reserved = $reserved ? $reserved : array();
$reserved_so_far_by_me = array();
foreach ($reserved as $delta => $start_dates) {
$conflict_errors = array();
// Load the resource being reserved.
if ($this->items_is_list) {
$resource = $entity->{$context['item_field']}[$delta];
}
else {
$resource = $entity->{$context['item_field']};
}
// Determine if the quantity field exists. If so use it.
try {
$quantity_reservable = $resource->field_quantity
->value();
} catch (EntityMetadataWrapperException $e) {
$quantity_reservable = 1;
}
$item_id = $resource
->getIdentifier();
if (empty($reserved_so_far_by_me[$item_id])) {
$reserved_so_far_by_me[$item_id] = 0;
}
$reserved_so_far_by_me[$item_id]++;
foreach ($this->dates as $dates) {
$quantity_reserved = $this
->getQuantityReserved($delta, $dates);
// Determine if there are conflicts for this date and item.
if ($quantity_reservable >= $quantity_reserved + $reserved_so_far_by_me[$item_id]) {
continue;
}
// Load each conflicting entity so we can show information about it to
// the user.
$ids = array();
foreach ($this
->getConflicts($delta, $dates) as $conflict) {
$ids[] = $conflict->parent_id;
}
// Load the entities which hold the conflicting item.
$entities = entity_load($entity_type, $ids);
$line_items = array();
foreach ($entities as $id => $line_item) {
$entity_uri = entity_uri($entity_type, $line_item);
$entity_label = entity_label($entity_type, $line_item);
$line_items[] = l(t("@label", array(
'@label' => $entity_label,
)), $entity_uri['path']);
}
$date_start = $dates['value'];
// Don't show the date repeat rule in the error message.
unset($dates['rrule']);
$render_dates = field_view_value($entity_type, $entity
->value(), $context['date_field'], $dates);
$conflict_errors[$date_start] = t('%name is already reserved by: !items for selected dates !dates', array(
'%name' => $resource
->label(),
'!items' => implode(', ', $line_items),
'!dates' => render($render_dates),
));
}
if ($conflict_errors) {
if (!array_key_exists($delta, $errors)) {
$errors[$delta] = array();
}
$errors[$delta][MERCI_ERROR_CONFLICT] = $conflict_errors;
}
}
$this->errors = $errors;
}
return $this->errors;
}
protected function validate() {
if (!$this->validated) {
$this->conflicting_entities = $this
->conflicts();
$this->validated = TRUE;
foreach ($this->conflicting_entities as $delta => $dates) {
foreach ($dates as $date_start => $conflicts) {
if (!array_key_exists($delta, $this->quantity_reserved)) {
$this->quantity_reserved[$delta] = array();
}
$this->quantity_reserved[$delta][$date_start] = 1;
}
}
}
}
public function getConflicts($delta = NULL, $dates = array()) {
$this
->validate();
$conflicts = $this->conflicting_entities;
if ($delta === NULL) {
return $conflicts;
}
if (empty($dates)) {
return array_key_exists($delta, $conflicts) ? $conflicts[$delta] : FALSE;
}
$date_value = $dates['value'];
return (array_key_exists($delta, $conflicts) and array_key_exists($date_value, $conflicts[$delta])) ? $conflicts[$delta][$date_value] : FALSE;
}
public function getQuantityReserved($delta = NULL, $dates = array()) {
$this
->validate();
$quantity_reserved = $this->quantity_reserved;
if ($delta === NULL) {
return $quantity_reserved;
}
if (empty($dates)) {
return array_key_exists($delta, $quantity_reserved) ? $quantity_reserved[$delta] : 0;
}
$date_value = $dates['value'];
return (array_key_exists($delta, $quantity_reserved) and array_key_exists($date_value, $quantity_reserved[$delta])) ? $quantity_reserved[$delta][$date_value] : 0;
}
/*
* Determine if merci_line_item $entity conflicts with any other existing line_items.
*
* Returns array of conflicting line items.
*/
protected function conflicts() {
$conflicts = array();
foreach ($this->dates as $dates) {
$date_value = $dates['value'];
$query = $this
->buildConflictQuery($dates);
$result = $query
->execute();
foreach ($result as $record) {
if (!isset($conflicts[$record->item_id])) {
$conflicts[$record->item_id] = array();
}
if (!isset($conflicts[$record->item_id][$date_value])) {
$conflicts[$record->item_id][$date_value] = array();
}
$conflicts[$record->item_id][$date_value][] = $record;
}
}
$return = array();
foreach ($this->items as $delta => $item) {
if (isset($conflicts[$item
->getIdentifier()])) {
$return[$delta] = $conflicts[$item
->getIdentifier()];
}
}
return $return;
}
protected function buildConflictQuery($dates) {
$context = $this->context;
$exclude_id = $this->entity
->getIdentifier();
$entity_type = $this->entity
->type();
$item_table = $this->item_table;
$item_column = $this->item_column;
$date_table = $this->date_table;
$date_column = $this->date_column;
$date_column2 = $this->date_column2;
$parent_table = $this->parent_table;
$parent_index = $this->parent_index;
$items = array();
foreach ($this->items as $delta => $item) {
$items[] = $item
->getIdentifier();
}
// Build the query.
$query = db_select($item_table, 'item_table');
$query
->addField('item_table', $item_column, 'item_id');
$query
->addField('item_table', 'entity_id', 'parent_id');
if (count($this->items) == 1) {
$query
->condition($item_column, reset($items));
}
else {
$query
->condition($item_column, $items, 'IN');
}
// Ignore myself.
if ($exclude_id) {
$query
->condition('item_table.entity_id', $exclude_id, '!=');
}
$query
->join($parent_table, 'merci_line_item', 'item_table.entity_id = merci_line_item.' . $parent_index);
if ($this->parent_has_quantity) {
$query
->addField('merci_line_item', 'quantity', 'quantity');
}
else {
$query
->addExpression('1', 'quantity');
}
if ($this->parent_has_status) {
$query
->condition('merci_line_item.status', 1, '=');
}
$query
->join($date_table, 'date_table', 'item_table.entity_id = date_table.entity_id');
$query
->addField('date_table', $date_column);
//, MERCI_DATE_FIELD_ALIAS);
$query
->addField('date_table', $date_column2);
//, MERCI_DATE_FIELD_ALIAS2);
$query
->condition('date_table.entity_type', $entity_type, '=');
$query
->condition('date_table.deleted', 0, '=');
// TODO handled multiple dates.
$query
->condition(db_or()
->condition(db_and()
->condition($date_column, $dates['value'], '<=')
->condition($date_column2, $dates['value'], '>='))
->condition(db_and()
->condition($date_column, $dates['value2'], '<=')
->condition($date_column2, $dates['value2'], '>='))
->condition(db_and()
->condition($date_column, $dates['value'], '>')
->condition($date_column2, $dates['value2'], '<')));
$query
->orderBy($date_column, 'ASC');
// Add a generic entity access tag to the query.
$query
->addTag('merci_resource');
$query
->addMetaData('merci_reservable_handler', $this);
return $query;
}
}
Members
Name![]() |
Modifiers | Type | Description | Overrides |
---|---|---|---|---|
MerciDefaultController:: |
protected | property | ||
MerciDefaultController:: |
protected | property | ||
MerciDefaultController:: |
protected | property | ||
MerciDefaultController:: |
protected | property | ||
MerciDefaultController:: |
protected | property | ||
MerciDefaultController:: |
protected | property | ||
MerciDefaultController:: |
protected | function | ||
MerciDefaultController:: |
protected | function | ||
MerciDefaultController:: |
public | function | ||
MerciDefaultController:: |
public | function | ||
MerciDefaultController:: |
public static | function | ||
MerciDefaultController:: |
public | function | ||
MerciDefaultController:: |
protected | function | 1 | |
MerciDefaultController:: |
public | function |