array( 'animal' => array( 'label' => t('Animal'), 'label_plural' => t('Animals'), 'view' => 'farm_animals', ), ), 'log' => array( 'farm_birth' => array( 'label' => t('Birth record'), 'label_plural' => t('Birth records'), 'view' => 'farm_log_birth', 'farm_asset' => 'animal', 'log_view_asset_arg' => 3, 'weight' => 20, ), 'farm_medical' => array( 'label' => t('Medical record'), 'label_plural' => t('Medical records'), 'view' => 'farm_log_medical', 'farm_asset' => 'animal', 'weight' => 20, ), ), 'taxonomy_term' => array( 'farm_animal_types' => array( 'label' => t('Type'), 'label_plural' => t('Types'), 'view' => 'farm_animal_types', 'farm_asset' => 'animal', 'asset_view_arg' => 2, ), ), ); } /** * Implements hook_farm_log_categories(). */ function farm_livestock_farm_log_categories() { // Provide an "Animals" log category. return array('Animals'); } /** * Implements hook_farm_log_categories_populate(). */ function farm_livestock_farm_log_categories_populate($log) { $categories = array(); if (in_array($log->type, array('farm_birth', 'farm_medical'))) { $categories[] = 'Animals'; } return $categories; } /** * Implements hook_restws_field_collection_info(). */ function farm_livestock_restws_field_collection_info() { return array( 'field_farm_animal_tag' => array( 'alias' => 'tag', 'label' => t('ID tags'), 'multiple' => TRUE, 'fields' => array( 'id' => array( 'field_name' => 'field_farm_animal_tag_id', 'field_label' => t('Tag ID'), 'field_type' => 'text', 'field_value' => 'value', ), 'location' => array( 'field_name' => 'field_farm_animal_tag_location', 'field_label' => t('Tag location'), 'field_type' => 'text', 'field_value' => 'value', ), 'type' => array( 'field_name' => 'field_farm_animal_tag_type', 'field_label' => t('Tag type'), 'field_type' => 'text', 'field_value' => 'value', ), ), ), ); } /** * Implements hook_farm_log_prepopulate_reference_fields(). */ function farm_livestock_farm_log_prepopulate_reference_fields($log_type) { // Allow field_farm_mother to be prepopulated in birth log forms. if ($log_type == 'farm_birth') { return array( 'field_farm_mother' => array( 'entity_type' => 'farm_asset', 'url_param' => 'farm_asset', ), ); } } /** * Implements hook_farm_log_prepopulate_reference_fields_alter(). */ function farm_livestock_farm_log_prepopulate_reference_fields_alter(&$fields, $log_type) { // Do not prepopulate field_farm_asset in birth log forms, because that is // the children reference field. When the "Add birth record" action is // clicked, we assume that the user wants to create a birth record from the // context of a mother animal. So field_farm_mother is prepopulated instead. // See farm_livestock_farm_log_prepopulate_reference_fields() above. if ($log_type == 'farm_birth') { if (!empty($fields['field_farm_asset'])) { unset($fields['field_farm_asset']); } } } /** * Implements hook_feeds_importer_default_alter(). */ function farm_livestock_feeds_importer_default_alter($importers) { // Add extra field mappings to animals. $name = 'farm_asset_animal'; if (!empty($importers[$name])) { $mappings = array( array( 'source' => 'Nicknames', 'target' => 'field_farm_animal_nicknames', 'unique' => FALSE, 'language' => 'und', ), array( 'source' => 'Date of birth', 'target' => 'field_farm_date:start', 'unique' => FALSE, 'language' => 'und', ), array( 'source' => 'Species/breed', 'target' => 'field_farm_animal_type', 'term_search' => '0', 'autocreate' => 1, 'language' => 'und', ), array( 'source' => 'Sex', 'target' => 'field_farm_animal_sex', 'unique' => FALSE, 'language' => 'und', ), array( 'source' => 'Castrated', 'target' => 'field_farm_animal_castrated', 'unique' => FALSE, 'language' => 'und', ), array( 'source' => 'Tag ID', 'target' => 'field_farm_animal_tag:field_farm_animal_tag_id', 'unique' => FALSE, 'language' => 'und', ), array( 'source' => 'Tag type', 'target' => 'field_farm_animal_tag:field_farm_animal_tag_type', 'unique' => FALSE, 'language' => 'und', ), array( 'source' => 'Tag location', 'target' => 'field_farm_animal_tag:field_farm_animal_tag_location', 'unique' => FALSE, 'language' => 'und', ), ); $importer_mappings =& $importers[$name]->config['processor']['config']['mappings']; $importer_mappings = array_merge($importer_mappings, $mappings); } // Add/alter field mappings on birth logs. $name = 'log_farm_birth'; if (!empty($importers[$name])) { // Add Mother ID and name mappings. $mappings = array( array( 'source' => 'Mother ID', 'target' => 'field_farm_mother:etid', 'unique' => FALSE, 'language' => 'und', ), array( 'source' => 'Mother name', 'target' => 'field_farm_mother:label', 'unique' => FALSE, 'language' => 'und', ), ); $importer_mappings =& $importers[$name]->config['processor']['config']['mappings']; $importer_mappings = array_merge($importer_mappings, $mappings); // Change "Asset IDs" to "Children IDs". foreach ($importer_mappings as &$mapping) { if ($mapping['source'] == 'Asset IDs') { $mapping['source'] = 'Children IDs'; } } // Change "Asset names" to "Children names". foreach ($importer_mappings as &$mapping) { if ($mapping['source'] == 'Asset names') { $mapping['source'] = 'Children names'; } } } } /** * Implements hook_feeds_tamper_default_alter(). */ function farm_livestock_feeds_tamper_default_alter(&$feeds_tampers) { // If farm_import is not installed, bail. if (!module_exists('farm_import')) { return; } // Make species/breed required. $feeds_tamper = farm_import_feeds_tamper_plugin('farm_asset', 'animal', 'Species/breed', 'required'); $feeds_tampers[$feeds_tamper->id] = $feeds_tamper; // Convert "male" to "M". $feeds_tamper = farm_import_feeds_tamper_plugin('farm_asset', 'animal', 'Sex', 'find_replace', array('find' => t('male'), 'replace' => 'M')); $feeds_tamper->id .= '-male'; $feeds_tamper->weight = 1; $feeds_tampers[$feeds_tamper->id] = $feeds_tamper; // Convert "female" to "F". $feeds_tamper = farm_import_feeds_tamper_plugin('farm_asset', 'animal', 'Sex', 'find_replace', array('find' => t('female'), 'replace' => 'F')); $feeds_tamper->id .= '-female'; $feeds_tamper->weight = 2; $feeds_tampers[$feeds_tamper->id] = $feeds_tamper; // Convert castrated to boolean. $feeds_tamper = farm_import_feeds_tamper_plugin('farm_asset', 'animal', 'Castrated', 'boolean_default_false'); $feeds_tampers[$feeds_tamper->id] = $feeds_tamper; // Convert date of birth to a Unix timestamp. $feeds_tamper = farm_import_feeds_tamper_plugin('farm_asset', 'animal', 'Date of birth', 'strtotime'); $feeds_tampers[$feeds_tamper->id] = $feeds_tamper; // Explode nicknames to allow multiple values, and trim whitespace. $feeds_tamper = farm_import_feeds_tamper_plugin('farm_asset', 'animal', 'Nicknames', 'explode'); $feeds_tampers[$feeds_tamper->id] = $feeds_tamper; $feeds_tamper = farm_import_feeds_tamper_plugin('farm_asset', 'animal', 'Nicknames', 'trim'); $feeds_tampers[$feeds_tamper->id] = $feeds_tamper; // Explode birth children IDs and names to allow multiple values, and trim // whitespace from names. $feeds_tamper = farm_import_feeds_tamper_plugin('log', 'farm_birth', 'Children IDs', 'explode'); $feeds_tampers[$feeds_tamper->id] = $feeds_tamper; $feeds_tamper = farm_import_feeds_tamper_plugin('log', 'farm_birth', 'Children names', 'explode'); $feeds_tampers[$feeds_tamper->id] = $feeds_tamper; $feeds_tamper = farm_import_feeds_tamper_plugin('log', 'farm_birth', 'Children names', 'trim'); $feeds_tampers[$feeds_tamper->id] = $feeds_tamper; } /** * Implements hook_preprocess_field(). */ function farm_livestock_preprocess_field(&$variables, $hook) { // Only act on field_farm_date on animal assets. $element = $variables['element']; if (empty($element['#field_name']) || $element['#field_name'] != 'field_farm_date') { return; } if (!($element['#entity_type'] == 'farm_asset' && $element['#bundle'] == 'animal')) { return; } // If the field is blank, bail. if (empty($element['#items'][0]['value']) || empty($variables['items'][0]['#markup'])) { return; } // Get the asset ID. if (empty($element['#object']->id)) { return; } $asset_id = $element['#object']->id; // Search for this asset's birth log. $query = new EntityFieldQuery(); $query->entityCondition('entity_type', 'log') ->entityCondition('bundle', 'farm_birth') ->fieldCondition('field_farm_asset', 'target_id', $asset_id); $result = $query->execute(); // Load only the first log. $log = NULL; if (isset($result['log'])) { $log_ids = array_keys($result['log']); $log_id = reset($log_ids); $log = log_load($log_id); } // If a log exists, link the birth date field to it. if (!empty($log)) { $birthdate = $variables['items'][0]['#markup']; $log_uri = entity_uri('log', $log); $variables['items'][0]['#markup'] = '' . $birthdate . ''; } } /** * Implements hook_entity_insert(). */ function farm_livestock_entity_insert($entity, $type) { // If this is a birth log, sync children. if ($type == 'log' && $entity->type == 'farm_birth') { farm_livestock_birth_log_sync($entity); } } /** * Implements hook_entity_update(). */ function farm_livestock_entity_update($entity, $type) { // If this is a birth log, sync children. if ($type == 'log' && $entity->type == 'farm_birth') { farm_livestock_birth_log_sync($entity); } } /** * Sync information in children animals if a birth log is saved. * * @param Log $log * The log entity that is being created or updated. */ function farm_livestock_birth_log_sync($log) { // Load log entity metadata wrapper. $log_wrapper = entity_metadata_wrapper('log', $log); // Get the mother animal asset ID from the birth log. $mother_id = $log_wrapper->field_farm_mother->getIdentifier(); // Iterate through the children assets. foreach ($log_wrapper->field_farm_asset->getIterator() as $delta => $child_wrapper) { // We will only save the child asset if we need to. $save = FALSE; // If the animal's date of birth does not match the timestamp of the birth // log, sync it. if ($child_wrapper->field_farm_date->value() != $log->timestamp) { $child_wrapper->field_farm_date->set($log->timestamp); drupal_set_message(t('@asset_label\'s date of birth has been updated to match their birth log.', array('!asset_path' => url('farm/asset/' . $child_wrapper->getIdentifier()), '@asset_label' => $child_wrapper->label()))); $save = TRUE; } // If a mother is specified, make sure that it is listed as one of the // child's parents. if (!empty($mother_id)) { // Iterate through the child's parents to see if the mother is listed. $mother_exists = FALSE; foreach ($child_wrapper->field_farm_parent->getIterator() as $delta => $parent_wrapper) { if ($parent_wrapper->getIdentifier() == $mother_id) { $mother_exists = TRUE; } } // If the mother is not one of the child's parents, add her. if (!$mother_exists) { $child_wrapper->field_farm_parent[] = $mother_id; $message_args = array( '!mother_path' => url('farm/asset/' . $log_wrapper->field_farm_mother->getIdentifier()), '@mother_label' => $log_wrapper->field_farm_mother->label(), '!child_path' => url('farm/asset/' . $child_wrapper->getIdentifier()), '@child_label' => $child_wrapper->label(), ); drupal_set_message(t('@mother_label was added to @child_label\'s parents.', $message_args)); $save = TRUE; } } // Save the asset, if necessary. if ($save) { $child_wrapper->save(); } } } /** * Implements hook_form_FORM_ID_alter(). */ function farm_livestock_form_log_form_alter(&$form, &$form_state, $form_id) { // Only act on the birth log form. if (!(!empty($form['log']['#value']->type) && $form['log']['#value']->type == 'farm_birth')) { return; } // If this is a new birth log form, display a link to the birth quick form // for convenience. if (!empty($form['log']['#value']->is_new)) { drupal_set_message(t('Tip: Use the Birth Quick Form to quickly record animal births and create child animal records at the same time.', array('@path' => url('farm/quick/birth')))); } // Add validation to make sure that the same child is not referenced in // multiple birth logs. $form['#validate'][] = 'farm_livestock_birth_log_form_validate'; } /** * Validate handler for the birth log form. * * @param array $form * The form array. * @param array $form_state * The form state array. */ function farm_livestock_birth_log_form_validate(array $form, array &$form_state) { // Get the log ID (if available). $log_id = 0; if (!empty($form_state['values']['log']->id)) { $log_id = $form_state['values']['log']->id; } // Get the referenced assets. $asset_ids = array(); if (!empty($form_state['values']['field_farm_asset'][LANGUAGE_NONE])) { foreach ($form_state['values']['field_farm_asset'][LANGUAGE_NONE] as $asset_reference) { if (empty($asset_reference['target_id'])) { continue; } $asset_ids[] = $asset_reference['target_id']; } } // If there are assets, look up birth logs that reference them. if (!empty($asset_ids)) { // Perform an entity field query to find logs that reference the assets. $query = new EntityFieldQuery(); $query->entityCondition('entity_type', 'log') ->entityCondition('bundle', 'farm_birth') ->propertyCondition('id', $log_id, '!=') ->fieldCondition('field_farm_asset', 'target_id', $asset_ids); $result = $query->execute(); if (isset($result['log'])) { $log_ids = array_keys($result['log']); $logs = entity_load('log', $log_ids); } // If matching logs were found, set form error(s). if (!empty($logs)) { foreach ($logs as $log) { $log_label = entity_label('log', $log); $log_uri = entity_uri('log', $log); form_set_error('field_farm_asset', t('The existing birth log %log_name already references one or more of the children. More than one birth log cannot reference the same child.', array('%child_name' => '', '@log_path' => url($log_uri['path']), '%log_name' => $log_label))); } } } } /** * Calculate the inventory for a given animal or group asset. * * This will recursively calculate the inventory of animal assets that are * members of a group at the given timestamp. * * @param \FarmAsset $asset * The animal or group asset. * @param int $time * Unix timestamp limiter. Only inventory and group membership logs before * this time will be included. Defaults to the current time. Set to 0 to load * the absolute last. * @param bool $done * Whether or not to only show logs that are marked as "done". TRUE will limit * to logs that are done, and FALSE will limit to logs that are not done. If * this is set to NULL, no filtering will be applied. Defaults to TRUE. * @param false $archived * Whether or not to include archived member assets. Defaults to FALSE. * * @return int * Returns the total inventory of animal assets, including group members. */ function farm_livestock_asset_inventory(FarmAsset $asset, $time = REQUEST_TIME, $done = TRUE, $archived = FALSE) { // Start count at 0. $count = 0; // Calculate inventory of a single animal asset. if ($asset->type == 'animal') { // Get inventory at the specified time. $inventory = farm_inventory($asset, $time, $done); // Use the inventory if valid. if (!empty($inventory) && is_numeric($inventory)) { $count += $inventory; } // Else increment count by 1. else { $count++; } } // Recursively calculate inventory of group assets. if ($asset->type == 'group') { // Get group members. $members = farm_group_members($asset, $time, $done, $archived); // Get inventory of each member. foreach ($members as $member) { $count += farm_livestock_asset_inventory($member, $time, $done, $archived); } } // Return total inventory count. return $count; }