diff --git a/alma.features.field.inc b/alma.features.field.inc deleted file mode 100644 index 27dcaa0..0000000 --- a/alma.features.field.inc +++ /dev/null @@ -1,404 +0,0 @@ - array( - 'active' => '1', - 'cardinality' => '1', - 'deleted' => '0', - 'entity_types' => array(), - 'field_name' => 'field_absent_id', - 'foreign keys' => array( - 'format' => array( - 'columns' => array( - 'format' => 'format', - ), - 'table' => 'filter_format', - ), - ), - 'indexes' => array( - 'format' => array( - 0 => 'format', - ), - ), - 'module' => 'text', - 'settings' => array( - 'max_length' => '255', - 'profile2_private' => 0, - ), - 'translatable' => '0', - 'type' => 'text', - ), - 'field_instance' => array( - 'bundle' => 'provider_alma', - 'default_value' => NULL, - 'deleted' => '0', - 'description' => '', - 'display' => array( - 'default' => array( - 'label' => 'hidden', - 'settings' => array(), - 'type' => 'hidden', - 'weight' => '4', - ), - ), - 'entity_type' => 'profile2', - 'field_name' => 'field_absent_id', - 'label' => 'Absent id', - 'required' => 0, - 'settings' => array( - 'text_processing' => '0', - 'user_register_form' => FALSE, - ), - 'widget' => array( - 'active' => 1, - 'module' => 'text', - 'settings' => array( - 'size' => '60', - ), - 'type' => 'text_textfield', - 'weight' => '4', - ), - ), - ); - - // Exported field: 'profile2-provider_alma-field_alma_interest_period' - $fields['profile2-provider_alma-field_alma_interest_period'] = array( - 'field_config' => array( - 'active' => '1', - 'cardinality' => '1', - 'deleted' => '0', - 'entity_types' => array(), - 'field_name' => 'field_alma_interest_period', - 'foreign keys' => array(), - 'indexes' => array( - 'value' => array( - 0 => 'value', - ), - ), - 'module' => 'list', - 'settings' => array( - 'allowed_values' => array( - 30 => '1 month', - 60 => '2 months', - 90 => '3 months', - 180 => '6 months', - ), - 'allowed_values_function' => '', - 'profile2_private' => 0, - ), - 'translatable' => '0', - 'type' => 'list_text', - ), - 'field_instance' => array( - 'bundle' => 'provider_alma', - 'default_value' => array( - 0 => array( - 'value' => '30', - ), - ), - 'deleted' => '0', - 'description' => '', - 'display' => array( - 'default' => array( - 'label' => 'above', - 'module' => 'list', - 'settings' => array(), - 'type' => 'list_default', - 'weight' => '1', - ), - ), - 'entity_type' => 'profile2', - 'field_name' => 'field_alma_interest_period', - 'label' => 'Interest period', - 'required' => 0, - 'settings' => array( - 'user_register_form' => FALSE, - ), - 'widget' => array( - 'active' => 1, - 'module' => 'options', - 'settings' => array(), - 'type' => 'options_select', - 'weight' => '2', - ), - ), - ); - - // Exported field: 'profile2-provider_alma-field_alma_mobile_phone' - $fields['profile2-provider_alma-field_alma_mobile_phone'] = array( - 'field_config' => array( - 'active' => '1', - 'cardinality' => '1', - 'deleted' => '0', - 'entity_types' => array(), - 'field_name' => 'field_alma_mobile_phone', - 'foreign keys' => array( - 'format' => array( - 'columns' => array( - 'format' => 'format', - ), - 'table' => 'filter_format', - ), - ), - 'indexes' => array( - 'format' => array( - 0 => 'format', - ), - ), - 'module' => 'text', - 'settings' => array( - 'max_length' => '16', - 'profile2_private' => 0, - ), - 'translatable' => '0', - 'type' => 'text', - ), - 'field_instance' => array( - 'bundle' => 'provider_alma', - 'default_value' => NULL, - 'deleted' => '0', - 'description' => '', - 'display' => array( - 'default' => array( - 'label' => 'above', - 'module' => 'text', - 'settings' => array(), - 'type' => 'text_default', - 'weight' => '3', - ), - ), - 'entity_type' => 'profile2', - 'field_name' => 'field_alma_mobile_phone', - 'label' => 'Mobile phone', - 'required' => 0, - 'settings' => array( - 'text_processing' => '0', - 'user_register_form' => FALSE, - ), - 'widget' => array( - 'active' => 1, - 'module' => 'text', - 'settings' => array( - 'size' => '12', - ), - 'type' => 'text_textfield', - 'weight' => '5', - ), - ), - ); - - // Exported field: 'profile2-provider_alma-field_alma_phone_id' - $fields['profile2-provider_alma-field_alma_phone_id'] = array( - 'field_config' => array( - 'active' => '1', - 'cardinality' => '1', - 'deleted' => '0', - 'entity_types' => array(), - 'field_name' => 'field_alma_phone_id', - 'foreign keys' => array( - 'format' => array( - 'columns' => array( - 'format' => 'format', - ), - 'table' => 'filter_format', - ), - ), - 'indexes' => array( - 'format' => array( - 0 => 'format', - ), - ), - 'module' => 'text', - 'settings' => array( - 'max_length' => '255', - ), - 'translatable' => '0', - 'type' => 'text', - ), - 'field_instance' => array( - 'bundle' => 'provider_alma', - 'default_value' => NULL, - 'deleted' => '0', - 'description' => '', - 'display' => array( - 'default' => array( - 'label' => 'hidden', - 'settings' => array(), - 'type' => 'hidden', - 'weight' => '5', - ), - ), - 'entity_type' => 'profile2', - 'field_name' => 'field_alma_phone_id', - 'label' => 'phone id', - 'required' => FALSE, - 'settings' => array( - 'text_processing' => 0, - 'user_register_form' => FALSE, - ), - 'widget' => array( - 'module' => 'text', - 'settings' => array( - 'size' => 60, - ), - 'type' => 'text_textfield', - 'weight' => '6', - ), - ), - ); - - // Exported field: 'profile2-provider_alma-field_alma_preferred_branch' - $fields['profile2-provider_alma-field_alma_preferred_branch'] = array( - 'field_config' => array( - 'active' => '1', - 'cardinality' => '1', - 'deleted' => '0', - 'entity_types' => array(), - 'field_name' => 'field_alma_preferred_branch', - 'foreign keys' => array(), - 'indexes' => array( - 'value' => array( - 0 => 'value', - ), - ), - 'module' => 'list', - 'settings' => array( - 'allowed_values' => array(), - 'allowed_values_function' => 'alma_reservation_pickup_branches', - 'profile2_private' => 0, - ), - 'translatable' => '0', - 'type' => 'list_text', - ), - 'field_instance' => array( - 'bundle' => 'provider_alma', - 'default_value' => NULL, - 'deleted' => '0', - 'description' => '', - 'display' => array( - 'default' => array( - 'label' => 'above', - 'module' => 'list', - 'settings' => array(), - 'type' => 'list_default', - 'weight' => '0', - ), - ), - 'entity_type' => 'profile2', - 'field_name' => 'field_alma_preferred_branch', - 'label' => 'Alma preferred branch', - 'required' => 0, - 'settings' => array( - 'user_register_form' => FALSE, - ), - 'widget' => array( - 'active' => 1, - 'module' => 'options', - 'settings' => array(), - 'type' => 'options_select', - 'weight' => '1', - ), - ), - ); - - // Exported field: 'profile2-provider_alma-field_alma_reservation_pause' - $fields['profile2-provider_alma-field_alma_reservation_pause'] = array( - 'field_config' => array( - 'active' => '1', - 'cardinality' => '1', - 'deleted' => '0', - 'entity_types' => array(), - 'field_name' => 'field_alma_reservation_pause', - 'foreign keys' => array(), - 'indexes' => array(), - 'module' => 'date', - 'settings' => array( - 'granularity' => array( - 'day' => 'day', - 'hour' => 0, - 'minute' => 0, - 'month' => 'month', - 'second' => 0, - 'year' => 'year', - ), - 'profile2_private' => 0, - 'repeat' => 0, - 'timezone_db' => '', - 'todate' => 'required', - 'tz_handling' => 'none', - ), - 'translatable' => '0', - 'type' => 'date', - ), - 'field_instance' => array( - 'bundle' => 'provider_alma', - 'deleted' => '0', - 'description' => 'Set your reservations on pause.', - 'display' => array( - 'default' => array( - 'label' => 'above', - 'module' => 'date', - 'settings' => array( - 'format_type' => 'long', - 'fromto' => 'both', - 'multiple_from' => '', - 'multiple_number' => '', - 'multiple_to' => '', - ), - 'type' => 'date_default', - 'weight' => '2', - ), - ), - 'entity_type' => 'profile2', - 'field_name' => 'field_alma_reservation_pause', - 'label' => 'Reservation pause', - 'required' => 0, - 'settings' => array( - 'default_value' => 'blank', - 'default_value2' => 'blank', - 'default_value_code' => '', - 'default_value_code2' => '', - 'user_register_form' => FALSE, - ), - 'widget' => array( - 'active' => 1, - 'module' => 'date', - 'settings' => array( - 'display_all_day' => 0, - 'increment' => '15', - 'input_format' => 'Y-m-d H:i:s', - 'input_format_custom' => '', - 'label_position' => 'above', - 'repeat_collapsed' => 0, - 'text_parts' => array(), - 'year_range' => '-3:+3', - ), - 'type' => 'date_popup', - 'weight' => '3', - ), - ), - ); - - // Translatables - // Included for use with string extractors like potx. - t('Absent id'); - t('Alma preferred branch'); - t('Interest period'); - t('Mobile phone'); - t('Reservation pause'); - t('Set your reservations on pause.'); - t('phone id'); - - return $fields; -} diff --git a/alma.features.field_base.inc b/alma.features.field_base.inc new file mode 100644 index 0000000..f8a527f --- /dev/null +++ b/alma.features.field_base.inc @@ -0,0 +1,512 @@ + 1, + 'cardinality' => 1, + 'deleted' => 0, + 'entity_types' => array(), + 'field_name' => 'field_alma_absent_id', + 'foreign keys' => array( + 'format' => array( + 'columns' => array( + 'format' => 'format', + ), + 'table' => 'filter_format', + ), + ), + 'indexes' => array( + 'format' => array( + 0 => 'format', + ), + ), + 'locked' => 0, + 'module' => 'text', + 'settings' => array( + 'max_length' => 255, + 'profile2_private' => 0, + ), + 'storage' => array( + 'active' => 1, + 'module' => 'virtual_field', + 'settings' => array(), + 'type' => 'virtual_field', + ), + 'translatable' => 0, + 'type' => 'text', + 'virtual_field' => array( + 'entity_types' => array( + 0 => 'profile2', + ), + ), + ); + + // Exported field_base: 'field_alma_city' + $field_bases['field_alma_city'] = array( + 'active' => 1, + 'cardinality' => 1, + 'deleted' => 0, + 'entity_types' => array(), + 'field_name' => 'field_alma_city', + 'foreign keys' => array( + 'format' => array( + 'columns' => array( + 'format' => 'format', + ), + 'table' => 'filter_format', + ), + ), + 'indexes' => array( + 'format' => array( + 0 => 'format', + ), + ), + 'locked' => 0, + 'module' => 'text', + 'settings' => array( + 'max_length' => 255, + 'profile2_private' => 0, + ), + 'storage' => array( + 'active' => 1, + 'module' => 'virtual_field', + 'settings' => array(), + 'type' => 'virtual_field', + ), + 'translatable' => 0, + 'type' => 'text', + 'virtual_field' => array( + 'entity_types' => array( + 0 => 'profile2', + ), + ), + ); + + // Exported field_base: 'field_alma_full_name' + $field_bases['field_alma_full_name'] = array( + 'active' => 1, + 'cardinality' => 1, + 'deleted' => 0, + 'entity_types' => array(), + 'field_name' => 'field_alma_full_name', + 'foreign keys' => array( + 'format' => array( + 'columns' => array( + 'format' => 'format', + ), + 'table' => 'filter_format', + ), + ), + 'indexes' => array( + 'format' => array( + 0 => 'format', + ), + ), + 'locked' => 0, + 'module' => 'text', + 'settings' => array( + 'max_length' => 255, + 'profile2_private' => 0, + ), + 'storage' => array( + 'active' => 1, + 'module' => 'virtual_field', + 'settings' => array(), + 'type' => 'virtual_field', + ), + 'translatable' => 0, + 'type' => 'text', + 'virtual_field' => array( + 'entity_types' => array( + 0 => 'profile2', + ), + ), + ); + + // Exported field_base: 'field_alma_interest_period' + $field_bases['field_alma_interest_period'] = array( + 'active' => 1, + 'cardinality' => 1, + 'deleted' => 0, + 'entity_types' => array(), + 'field_name' => 'field_alma_interest_period', + 'foreign keys' => array(), + 'indexes' => array( + 'value' => array( + 0 => 'value', + ), + ), + 'locked' => 0, + 'module' => 'list', + 'settings' => array( + 'allowed_values' => array( + 30 => '1 måned', + 60 => '2 months', + 90 => '3 months', + 180 => '6 months', + 360 => '12 months', + ), + 'allowed_values_function' => '', + 'profile2_private' => 0, + ), + 'translatable' => 0, + 'type' => 'list_text', + ); + + // Exported field_base: 'field_alma_mail' + $field_bases['field_alma_mail'] = array( + 'active' => 1, + 'cardinality' => 1, + 'deleted' => 0, + 'entity_types' => array(), + 'field_name' => 'field_alma_mail', + 'foreign keys' => array(), + 'indexes' => array(), + 'locked' => 0, + 'module' => 'email', + 'settings' => array( + 'profile2_private' => 0, + ), + 'storage' => array( + 'active' => 1, + 'module' => 'virtual_field', + 'settings' => array(), + 'type' => 'virtual_field', + ), + 'translatable' => 0, + 'type' => 'email', + ); + + // Exported field_base: 'field_alma_mobile_phone' + $field_bases['field_alma_mobile_phone'] = array( + 'active' => 1, + 'cardinality' => 1, + 'deleted' => 0, + 'entity_types' => array(), + 'field_name' => 'field_alma_mobile_phone', + 'foreign keys' => array( + 'format' => array( + 'columns' => array( + 'format' => 'format', + ), + 'table' => 'filter_format', + ), + ), + 'indexes' => array( + 'format' => array( + 0 => 'format', + ), + ), + 'locked' => 0, + 'module' => 'text', + 'settings' => array( + 'max_length' => 16, + 'profile2_private' => 0, + ), + 'storage' => array( + 'active' => 1, + 'module' => 'virtual_field', + 'settings' => array(), + 'type' => 'virtual_field', + ), + 'translatable' => 0, + 'type' => 'text', + 'virtual_field' => array( + 'entity_types' => array( + 0 => 'profile2', + ), + ), + ); + + // Exported field_base: 'field_alma_phone_id' + $field_bases['field_alma_phone_id'] = array( + 'active' => 1, + 'cardinality' => 1, + 'deleted' => 0, + 'entity_types' => array(), + 'field_name' => 'field_alma_phone_id', + 'foreign keys' => array( + 'format' => array( + 'columns' => array( + 'format' => 'format', + ), + 'table' => 'filter_format', + ), + ), + 'indexes' => array( + 'format' => array( + 0 => 'format', + ), + ), + 'locked' => 0, + 'module' => 'text', + 'settings' => array( + 'max_length' => 255, + ), + 'storage' => array( + 'active' => 1, + 'module' => 'virtual_field', + 'settings' => array(), + 'type' => 'virtual_field', + ), + 'translatable' => 0, + 'type' => 'text', + 'virtual_field' => array( + 'entity_types' => array( + 0 => 'profile2', + ), + ), + ); + + // Exported field_base: 'field_alma_postal_code' + $field_bases['field_alma_postal_code'] = array( + 'active' => 1, + 'cardinality' => 1, + 'deleted' => 0, + 'entity_types' => array(), + 'field_name' => 'field_alma_postal_code', + 'foreign keys' => array( + 'format' => array( + 'columns' => array( + 'format' => 'format', + ), + 'table' => 'filter_format', + ), + ), + 'indexes' => array( + 'format' => array( + 0 => 'format', + ), + ), + 'locked' => 0, + 'module' => 'text', + 'settings' => array( + 'max_length' => 255, + 'profile2_private' => 0, + ), + 'storage' => array( + 'active' => 1, + 'module' => 'virtual_field', + 'settings' => array(), + 'type' => 'virtual_field', + ), + 'translatable' => 0, + 'type' => 'text', + 'virtual_field' => array( + 'entity_types' => array( + 0 => 'profile2', + ), + ), + ); + + // Exported field_base: 'field_alma_preferred_branch' + $field_bases['field_alma_preferred_branch'] = array( + 'active' => 1, + 'cardinality' => 1, + 'deleted' => 0, + 'entity_types' => array(), + 'field_name' => 'field_alma_preferred_branch', + 'foreign keys' => array(), + 'indexes' => array( + 'value' => array( + 0 => 'value', + ), + ), + 'locked' => 0, + 'module' => 'list', + 'settings' => array( + 'allowed_values' => array(), + 'allowed_values_function' => 'alma_reservation_pickup_branches', + 'profile2_private' => 0, + ), + 'storage' => array( + 'active' => 1, + 'module' => 'virtual_field', + 'settings' => array(), + 'type' => 'virtual_field', + ), + 'translatable' => 0, + 'type' => 'list_text', + 'virtual_field' => array( + 'entity_types' => array( + 0 => 'profile2', + ), + ), + ); + + // Exported field_base: 'field_alma_reservation_pause' + $field_bases['field_alma_reservation_pause'] = array( + 'active' => 1, + 'cardinality' => 1, + 'deleted' => 0, + 'entity_types' => array(), + 'field_name' => 'field_alma_reservation_pause', + 'foreign keys' => array(), + 'indexes' => array(), + 'locked' => 0, + 'module' => 'date', + 'settings' => array( + 'granularity' => array( + 'day' => 'day', + 'hour' => 0, + 'minute' => 0, + 'month' => 'month', + 'second' => 0, + 'year' => 'year', + ), + 'profile2_private' => 0, + 'repeat' => 0, + 'timezone_db' => '', + 'todate' => 'required', + 'tz_handling' => 'none', + ), + 'storage' => array( + 'active' => 1, + 'module' => 'virtual_field', + 'settings' => array(), + 'type' => 'virtual_field', + ), + 'translatable' => 0, + 'type' => 'datetime', + 'virtual_field' => array( + 'entity_types' => array( + 0 => 'profile2', + ), + ), + ); + + // Exported field_base: 'field_alma_sms' + $field_bases['field_alma_sms'] = array( + 'active' => 1, + 'cardinality' => 1, + 'deleted' => 0, + 'entity_types' => array(), + 'field_name' => 'field_alma_sms', + 'foreign keys' => array( + 'format' => array( + 'columns' => array( + 'format' => 'format', + ), + 'table' => 'filter_format', + ), + ), + 'indexes' => array( + 'format' => array( + 0 => 'format', + ), + ), + 'locked' => 0, + 'module' => 'text', + 'settings' => array( + 'max_length' => 255, + 'profile2_private' => 0, + ), + 'storage' => array( + 'active' => 1, + 'module' => 'virtual_field', + 'settings' => array(), + 'type' => 'virtual_field', + ), + 'translatable' => 0, + 'type' => 'text', + 'virtual_field' => array( + 'entity_types' => array( + 0 => 'profile2', + ), + ), + ); + + // Exported field_base: 'field_alma_sms_id' + $field_bases['field_alma_sms_id'] = array( + 'active' => 1, + 'cardinality' => 1, + 'deleted' => 0, + 'entity_types' => array(), + 'field_name' => 'field_alma_sms_id', + 'foreign keys' => array( + 'format' => array( + 'columns' => array( + 'format' => 'format', + ), + 'table' => 'filter_format', + ), + ), + 'indexes' => array( + 'format' => array( + 0 => 'format', + ), + ), + 'locked' => 0, + 'module' => 'text', + 'settings' => array( + 'max_length' => 255, + 'profile2_private' => 0, + ), + 'storage' => array( + 'active' => 1, + 'module' => 'virtual_field', + 'settings' => array(), + 'type' => 'virtual_field', + ), + 'translatable' => 0, + 'type' => 'text', + 'virtual_field' => array( + 'entity_types' => array( + 0 => 'profile2', + ), + ), + ); + + // Exported field_base: 'field_alma_street_name' + $field_bases['field_alma_street_name'] = array( + 'active' => 1, + 'cardinality' => 1, + 'deleted' => 0, + 'entity_types' => array(), + 'field_name' => 'field_alma_street_name', + 'foreign keys' => array( + 'format' => array( + 'columns' => array( + 'format' => 'format', + ), + 'table' => 'filter_format', + ), + ), + 'indexes' => array( + 'format' => array( + 0 => 'format', + ), + ), + 'locked' => 0, + 'module' => 'text', + 'settings' => array( + 'max_length' => 255, + 'profile2_private' => 0, + ), + 'storage' => array( + 'active' => 1, + 'module' => 'virtual_field', + 'settings' => array(), + 'type' => 'virtual_field', + ), + 'translatable' => 0, + 'type' => 'text', + 'virtual_field' => array( + 'entity_types' => array( + 0 => 'profile2', + ), + ), + ); + + return $field_bases; +} diff --git a/alma.features.field_instance.inc b/alma.features.field_instance.inc new file mode 100644 index 0000000..6d03c53 --- /dev/null +++ b/alma.features.field_instance.inc @@ -0,0 +1,462 @@ + 'provider_alma', + 'default_value' => NULL, + 'deleted' => 0, + 'description' => '', + 'display' => array( + 'default' => array( + 'label' => 'hidden', + 'settings' => array(), + 'type' => 'hidden', + 'weight' => 10, + ), + ), + 'entity_type' => 'profile2', + 'field_name' => 'field_alma_absent_id', + 'label' => 'Absent id', + 'required' => 0, + 'settings' => array( + 'text_processing' => 0, + 'user_register_form' => FALSE, + ), + 'widget' => array( + 'module' => 'virtual_field', + 'settings' => array(), + 'type' => 'hidden', + 'weight' => 10, + ), + ); + + // Exported field_instance: 'profile2-provider_alma-field_alma_city' + $field_instances['profile2-provider_alma-field_alma_city'] = array( + 'bundle' => 'provider_alma', + 'default_value' => NULL, + 'deleted' => 0, + 'description' => '', + 'display' => array( + 'default' => array( + 'label' => 'inline', + 'module' => 'text', + 'settings' => array(), + 'type' => 'text_default', + 'weight' => 3, + ), + ), + 'entity_type' => 'profile2', + 'field_name' => 'field_alma_city', + 'label' => 'City', + 'required' => 0, + 'settings' => array( + 'text_processing' => 0, + 'user_register_form' => FALSE, + ), + 'widget' => array( + 'module' => 'virtual_field', + 'settings' => array(), + 'type' => 'hidden', + 'weight' => 3, + ), + ); + + // Exported field_instance: 'profile2-provider_alma-field_alma_full_name' + $field_instances['profile2-provider_alma-field_alma_full_name'] = array( + 'bundle' => 'provider_alma', + 'default_value' => NULL, + 'deleted' => 0, + 'description' => '', + 'display' => array( + 'default' => array( + 'label' => 'inline', + 'module' => 'text', + 'settings' => array(), + 'type' => 'text_default', + 'weight' => 0, + ), + ), + 'entity_type' => 'profile2', + 'field_name' => 'field_alma_full_name', + 'label' => 'Full name', + 'required' => 0, + 'settings' => array( + 'text_processing' => 0, + 'user_register_form' => FALSE, + ), + 'widget' => array( + 'module' => 'virtual_field', + 'settings' => array(), + 'type' => 'hidden', + 'weight' => 0, + ), + ); + + // Exported field_instance: 'profile2-provider_alma-field_alma_interest_period' + $field_instances['profile2-provider_alma-field_alma_interest_period'] = array( + 'bundle' => 'provider_alma', + 'default_value' => array( + 0 => array( + 'value' => 180, + ), + ), + 'deleted' => 0, + 'description' => '', + 'display' => array( + 'default' => array( + 'label' => 'inline', + 'module' => 'list', + 'settings' => array(), + 'type' => 'list_default', + 'weight' => 9, + ), + ), + 'entity_type' => 'profile2', + 'field_name' => 'field_alma_interest_period', + 'label' => 'Interest period', + 'required' => 0, + 'settings' => array( + 'user_register_form' => FALSE, + ), + 'widget' => array( + 'active' => 1, + 'module' => 'options', + 'settings' => array(), + 'type' => 'options_select', + 'weight' => 5, + ), + ); + + // Exported field_instance: 'profile2-provider_alma-field_alma_mail' + $field_instances['profile2-provider_alma-field_alma_mail'] = array( + 'bundle' => 'provider_alma', + 'default_value' => NULL, + 'deleted' => 0, + 'description' => 'The e-mail address is not made public and will only be used if you wish to receive certain news or notifications by e-mail.', + 'display' => array( + 'default' => array( + 'label' => 'inline', + 'module' => 'email', + 'settings' => array(), + 'type' => 'email_plain', + 'weight' => 4, + ), + ), + 'entity_type' => 'profile2', + 'field_name' => 'field_alma_mail', + 'label' => 'E-mail', + 'required' => 0, + 'settings' => array( + 'user_register_form' => FALSE, + ), + 'widget' => array( + 'active' => 1, + 'module' => 'email', + 'settings' => array( + 'size' => 60, + ), + 'type' => 'email_textfield', + 'weight' => 7, + ), + ); + + // Exported field_instance: 'profile2-provider_alma-field_alma_mobile_phone' + $field_instances['profile2-provider_alma-field_alma_mobile_phone'] = array( + 'bundle' => 'provider_alma', + 'default_value' => NULL, + 'deleted' => 0, + 'description' => '', + 'display' => array( + 'default' => array( + 'label' => 'inline', + 'module' => 'text', + 'settings' => array(), + 'type' => 'text_default', + 'weight' => 6, + ), + ), + 'entity_type' => 'profile2', + 'field_name' => 'field_alma_mobile_phone', + 'label' => 'Phone', + 'required' => 0, + 'settings' => array( + 'text_processing' => 0, + 'user_register_form' => FALSE, + ), + 'widget' => array( + 'active' => 1, + 'module' => 'text', + 'settings' => array( + 'size' => 12, + ), + 'type' => 'text_textfield', + 'weight' => 9, + ), + ); + + // Exported field_instance: 'profile2-provider_alma-field_alma_phone_id' + $field_instances['profile2-provider_alma-field_alma_phone_id'] = array( + 'bundle' => 'provider_alma', + 'default_value' => NULL, + 'deleted' => 0, + 'description' => '', + 'display' => array( + 'default' => array( + 'label' => 'hidden', + 'settings' => array(), + 'type' => 'hidden', + 'weight' => 11, + ), + ), + 'entity_type' => 'profile2', + 'field_name' => 'field_alma_phone_id', + 'label' => 'Phone id', + 'required' => FALSE, + 'settings' => array( + 'text_processing' => 0, + 'user_register_form' => FALSE, + ), + 'widget' => array( + 'module' => 'virtual_field', + 'settings' => array(), + 'type' => 'hidden', + 'weight' => 12, + ), + ); + + // Exported field_instance: 'profile2-provider_alma-field_alma_postal_code' + $field_instances['profile2-provider_alma-field_alma_postal_code'] = array( + 'bundle' => 'provider_alma', + 'default_value' => NULL, + 'deleted' => 0, + 'description' => '', + 'display' => array( + 'default' => array( + 'label' => 'inline', + 'module' => 'text', + 'settings' => array(), + 'type' => 'text_default', + 'weight' => 2, + ), + ), + 'entity_type' => 'profile2', + 'field_name' => 'field_alma_postal_code', + 'label' => 'Postal code', + 'required' => 0, + 'settings' => array( + 'text_processing' => 0, + 'user_register_form' => FALSE, + ), + 'widget' => array( + 'module' => 'virtual_field', + 'settings' => array(), + 'type' => 'hidden', + 'weight' => 2, + ), + ); + + // Exported field_instance: 'profile2-provider_alma-field_alma_preferred_branch' + $field_instances['profile2-provider_alma-field_alma_preferred_branch'] = array( + 'bundle' => 'provider_alma', + 'default_value' => NULL, + 'deleted' => 0, + 'description' => '', + 'display' => array( + 'default' => array( + 'label' => 'inline', + 'module' => 'list', + 'settings' => array(), + 'type' => 'list_default', + 'weight' => 7, + ), + ), + 'entity_type' => 'profile2', + 'field_name' => 'field_alma_preferred_branch', + 'label' => 'Preferred branch', + 'required' => 0, + 'settings' => array( + 'user_register_form' => FALSE, + ), + 'widget' => array( + 'active' => 1, + 'module' => 'options', + 'settings' => array(), + 'type' => 'options_select', + 'weight' => 4, + ), + ); + + // Exported field_instance: 'profile2-provider_alma-field_alma_reservation_pause' + $field_instances['profile2-provider_alma-field_alma_reservation_pause'] = array( + 'bundle' => 'provider_alma', + 'deleted' => 0, + 'description' => 'Set your reservations on pause.', + 'display' => array( + 'default' => array( + 'label' => 'inline', + 'module' => 'date', + 'settings' => array( + 'format_type' => 'long', + 'fromto' => 'both', + 'multiple_from' => '', + 'multiple_number' => '', + 'multiple_to' => '', + ), + 'type' => 'date_default', + 'weight' => 8, + ), + ), + 'entity_type' => 'profile2', + 'field_name' => 'field_alma_reservation_pause', + 'label' => 'Reservation pause', + 'required' => 0, + 'settings' => array( + 'default_value' => 'blank', + 'default_value2' => 'blank', + 'default_value_code' => '', + 'default_value_code2' => '', + 'user_register_form' => FALSE, + ), + 'widget' => array( + 'active' => 1, + 'module' => 'date', + 'settings' => array( + 'display_all_day' => 0, + 'increment' => 15, + 'input_format' => 'd/m/Y', + 'input_format_custom' => '', + 'label_position' => 'above', + 'repeat_collapsed' => 0, + 'text_parts' => array(), + 'year_range' => '-3:+3', + ), + 'type' => 'date_popup', + 'weight' => 6, + ), + ); + + // Exported field_instance: 'profile2-provider_alma-field_alma_sms' + $field_instances['profile2-provider_alma-field_alma_sms'] = array( + 'bundle' => 'provider_alma', + 'default_value' => NULL, + 'deleted' => 0, + 'description' => '', + 'display' => array( + 'default' => array( + 'label' => 'inline', + 'module' => 'text', + 'settings' => array(), + 'type' => 'text_default', + 'weight' => 5, + ), + ), + 'entity_type' => 'profile2', + 'field_name' => 'field_alma_sms', + 'label' => 'SMS', + 'required' => 0, + 'settings' => array( + 'text_processing' => 0, + 'user_register_form' => FALSE, + ), + 'widget' => array( + 'active' => 1, + 'module' => 'text', + 'settings' => array( + 'size' => 60, + ), + 'type' => 'text_textfield', + 'weight' => 8, + ), + ); + + // Exported field_instance: 'profile2-provider_alma-field_alma_sms_id' + $field_instances['profile2-provider_alma-field_alma_sms_id'] = array( + 'bundle' => 'provider_alma', + 'default_value' => NULL, + 'deleted' => 0, + 'description' => '', + 'display' => array( + 'default' => array( + 'label' => 'hidden', + 'settings' => array(), + 'type' => 'hidden', + 'weight' => 12, + ), + ), + 'entity_type' => 'profile2', + 'field_name' => 'field_alma_sms_id', + 'label' => 'SMS id', + 'required' => 0, + 'settings' => array( + 'text_processing' => 0, + 'user_register_form' => FALSE, + ), + 'widget' => array( + 'module' => 'virtual_field', + 'settings' => array(), + 'type' => 'hidden', + 'weight' => 11, + ), + ); + + // Exported field_instance: 'profile2-provider_alma-field_alma_street_name' + $field_instances['profile2-provider_alma-field_alma_street_name'] = array( + 'bundle' => 'provider_alma', + 'default_value' => NULL, + 'deleted' => 0, + 'description' => '', + 'display' => array( + 'default' => array( + 'label' => 'inline', + 'module' => 'text', + 'settings' => array(), + 'type' => 'text_default', + 'weight' => 1, + ), + ), + 'entity_type' => 'profile2', + 'field_name' => 'field_alma_street_name', + 'label' => 'Street name', + 'required' => 0, + 'settings' => array( + 'text_processing' => 0, + 'user_register_form' => FALSE, + ), + 'widget' => array( + 'module' => 'virtual_field', + 'settings' => array(), + 'type' => 'hidden', + 'weight' => 1, + ), + ); + + // Translatables + // Included for use with string extractors like potx. + t('Absent id'); + t('City'); + t('E-mail'); + t('Full name'); + t('Interest period'); + t('Phone'); + t('Phone id'); + t('Postal code'); + t('Preferred branch'); + t('Reservation pause'); + t('SMS'); + t('SMS id'); + t('Set your reservations on pause.'); + t('Street name'); + t('The e-mail address is not made public and will only be used if you wish to receive certain news or notifications by e-mail.'); + + return $field_instances; +} diff --git a/alma.features.inc b/alma.features.inc new file mode 100644 index 0000000..70cdb4b --- /dev/null +++ b/alma.features.inc @@ -0,0 +1,21 @@ + 'SimpleXML', + 'description' => $t('The Alma module requires SimpleXML to function. Please install and/or enable SimpleXML in your PHP configuration.'), + 'severity' => REQUIREMENT_ERROR, + ); + } + if ($phase == 'runtime') { + $requirements['alma'] = array( + 'title' => $t('Alma'), + 'value' => $t('Alma configured'), + 'severity' => REQUIREMENT_OK, + ); + if (!variable_get('alma_base_url', FALSE) || !variable_get('ting_agency', FALSE)) { + $requirements['alma']['value'] = $t('Alma not configured'); + $requirements['alma']['description'] = $t('Alma is not properly configured, please visit the settings page.', array('@link' => url('admin/config/ding/provider/alma'))); + $requirements['alma']['severity'] = REQUIREMENT_ERROR; + } + } + return $requirements; +} + +/** + * Update system table set alma weight=10 to ensure form_alter hooks are called + * AFTER ding_user and ding_provider + */ function alma_update_7001() { $num_upd = db_update('system') + ->fields(array('weight' => 10)) + ->condition('name', 'alma', '=') + ->execute(); +} + +/** + * Convert field storage to virtual field. + */ +function alma_update_7002() { + return db_update('field_config') ->fields(array( - 'weight'=>10, + 'storage_type' => 'virtual_field', + 'storage_module' => 'virtual_field', )) - ->condition('name','alma','=') - ->execute(); + ->condition('field_name', '%alma%', 'LIKE') + ->condition('field_name', 'field_alma_interest_period', '!=') + ->execute(); +} + +/** + * Covert reservation field form data to datetime. + */ +function alma_update_7003() { + return db_update('field_config') + ->fields(array( + 'type' => 'datetime', + )) + ->condition('field_name', 'field_alma_reservation_pause', '=') + ->execute(); +} + +/** + * Remove old field_sql_storage file data from the database as they are using + * virtual fields now and don't need a database table. + */ +function alma_update_7004() { + // Absent id have been renamed to field_alma_absent_id as virtual field. + field_delete_field('field_absent_id'); + field_purge_batch(100); + + // Mobile phone. + db_drop_table('field_data_field_alma_mobile_phone'); + db_drop_table('field_revision_field_alma_mobile_phone'); + + // Mobile phone id. + db_drop_table('field_data_field_alma_phone_id'); + db_drop_table('field_revision_field_alma_phone_id'); + + // Preferred branch. + db_drop_table('field_data_field_alma_preferred_branch'); + db_drop_table('field_revision_field_alma_preferred_branch'); - echo $num_upd; - return t('system weight for alma updated to 10'); + // Reservation pause. + db_drop_table('field_data_field_alma_reservation_pause'); + db_drop_table('field_revision_field_alma_reservation_pause'); } diff --git a/alma.make b/alma.make index 7370362..140f067 100644 --- a/alma.make +++ b/alma.make @@ -1,9 +1,31 @@ api = 2 core = 7.x +; Contrib + +projects[date][subdir] = "contrib" +projects[date][version] = "2.8" + +projects[email][subdir] = "contrib" +projects[email][version] = "1.3" + +projects[features][subdir] = "contrib" +projects[features][version] = "2.0" + +projects[profile2][subdir] = "contrib" +projects[profile2][version] = "1.3" + +projects[virtual_field][subdir] = "contrib" +projects[virtual_field][version] = "1.2" + ; Ding! modules projects[ding_provider][type] = "module" projects[ding_provider][download][type] = "git" -projects[ding_provider][download][url] = "git@github.com:ding2tal/ding_provider.git" -projects[ding_provider][download][branch] = "development" +projects[ding_provider][download][url] = "git@github.com:ding2/ding_provider.git" +projects[ding_provider][download][branch] = "master" + +projects[ding_reservation][type] = "module" +projects[ding_reservation][download][type] = "git" +projects[ding_reservation][download][url] = "git@github.com:ding2/ding_reservation.git" +projects[ding_reservation][download][branch] = "master" diff --git a/alma.module b/alma.module index c163a92..d4dccde 100644 --- a/alma.module +++ b/alma.module @@ -1,51 +1,53 @@ data); + if (!isset($alma_pickup_branches)) { + $cache = cache_get('alma_pickup_branches'); + if (!$reset && $cache && $cache->expire > REQUEST_TIME) { + $alma_pickup_branches = $cache->data; } else { $alma_pickup_branches = alma_client_invoke('get_reservation_branches'); - cache_set( 'alma_pickup_branches', serialize($alma_pickup_branches),'cache'); + + // Cache output for 24 hours. + cache_set('alma_pickup_branches', $alma_pickup_branches, 'cache', REQUEST_TIME + 86400); } } return $alma_pickup_branches; } /** - * Implements hook_requirements(). + * Get a list of allowed interest periods. + * + * The values are extracted from the interest period field in the provider + * profile2 user profile. + * + * @return array + * Array with the allowed interest period values. */ -function alma_requirements($phase) { - $requirements = array(); - // Ensure translations don't break at install time. - $t = get_t(); - - if (!function_exists('simplexml_load_string')) { - $requirements['simplexml'] = array( - 'title' => 'SimpleXML', - 'description' => $t('The Alma module requires SimpleXML to function. Please install and/or enable SimpleXML in your PHP configuration.'), - 'severity' => REQUIREMENT_ERROR, - ); - } +function alma_get_interest_periods() { + // Get the interest period profile fields allowed values. + $field_info = field_info_field('field_alma_interest_period'); + $interest_periods = isset($field_info['settings']['allowed_values']) ? $field_info['settings']['allowed_values'] : array(); - return $requirements; + return $interest_periods; } /** @@ -78,6 +80,10 @@ function alma_ding_provider() { 'prefix' => 'user', 'file' => $path . '/includes/alma.user.inc', ), + 'wayf' => array( + 'prefix' => 'wayf', + 'file' => $path . '/includes/alma.wayf.inc', + ), ), ); } @@ -88,6 +94,8 @@ function alma_ding_provider() { * This is a regular form callback. */ function alma_settings_form() { + $form = array(); + $form['alma'] = array( '#type' => 'fieldset', '#title' => t('Alma service settings'), @@ -102,6 +110,20 @@ function alma_settings_form() { '#default_value' => variable_get('alma_base_url', ''), ); + // Add the option to select a default interest period for reservations, if not + // selected it will default to 180 days (6 months). The users can override + // this during reservation. + $periods = alma_get_interest_periods(); + $default = variable_get('alma_default_interest_period', 180); + $form['alma'] += ding_reservation_interest_period_selector('alma_default_interest_period', $default, $periods); + + $form['alma']['alma_enable_reservation_deletion'] = array( + '#type' => 'checkbox', + '#title' => t('Enable reservation deletion'), + '#default_value' => variable_get('alma_enable_reservation_deletion', FALSE), + '#description' => t('Allow users to delete their reservations as well as ready for pickup ones.'), + ); + $form['alma']['alma_enable_logging'] = array( '#type' => 'checkbox', '#title' => t('Enable logging'), @@ -112,41 +134,16 @@ function alma_settings_form() { return system_settings_form($form); } -/** - * Implements hook_form_FORM_ID_alter(). - * pjo notes: user_profile_form - * Add in pincode validation. - */ -function alma_form_user_profile_form_alter(&$form, &$form_state) { - // Ensure that we're dealing with a provider user. - if (!ding_user_is_provider_user($form_state['user'])) { - return; - } - - // change size and length of pincode - $form['account']['pincode']['#size'] = 32; - $form['account']['pincode']['#maxlength'] = 32; - - // @todo; WHAT are the rules for alma pincode - // HOW do we validate - - // custom validator ?? maybe pincode validator ?? - // $form['#validate'][] = 'alma_profile_form_validate'; -} - - - /** * Return a fully instantiated AlmaClient instance. */ function alma_client() { // This is basically a singleton. We also wait until right before // instantiating to include our required classes. That seems like a - // decent performance tradeoff instead of loading everything on every + // decent performance trade-off instead of loading everything on every // page load. static $client; if (!isset($client)) { - $path = drupal_get_path('module', 'alma'); try { $client = new AlmaClient(variable_get('alma_base_url', '')); } @@ -162,18 +159,21 @@ function alma_client() { /** * Calls the Alma backend, possibly caching the result. * - * @param $method + * @param string $method * The desired method. - * @param ... - * Arguments to the method. * - * @return mixed + * @throws Exception + * Provider exception if communication fails. + * + * @return array * NULL on error, or the result of the method call. */ function alma_client_invoke($method) { $args = func_get_args(); - array_shift($args); // Lose the method. + // Lose the method. + array_shift($args); $client = alma_client(); + try { $result = call_user_func_array(array($client, $method), $args); } @@ -181,26 +181,30 @@ function alma_client_invoke($method) { watchdog('alma', '@method error: “@message”', array('@method' => $method, '@message' => $e->getMessage()), WATCHDOG_ERROR); throw $e; } + return $result; } + /** * Get the complete organisation info from Alma. * - * Includes branches, departments, locations, sublocations and collections. The + * Includes branches, departments, locations, sub-locations and collections. The * information is cache until the cache is cleared or the reset parameter is * TRUE. * - * @param boolean $reset - * Optional. If TRUE reset the cached data and reload. + * @param bool $reset + * Optional. If TRUE reset the cached data and reload. + * * @return array - * Array of the different organisational unit, each an array of their - * member units. + * Array of the different organisational unit, each an array of their + * member units. */ function alma_get_organisation($reset = FALSE) { // Return data from cache if available. static $organisation; if (!$organisation || $reset) { - if (($cache = cache_get('alma_organisation')) && !empty($cache->data) && !$reset) { + $cache = cache_get('alma_organisation'); + if (!$reset && $cache && isset($cache->data) && $cache->expire > REQUEST_TIME) { $organisation = $cache->data; } else { @@ -210,14 +214,14 @@ function alma_get_organisation($reset = FALSE) { 'location' => alma_client_invoke('get_locations'), 'sublocation' => alma_client_invoke('get_sublocations'), 'collection' => alma_client_invoke('get_collections'), - 'reservation' => alma_reservation_pickup_branches(),//alma_client_invoke('get_reservation_branches'), + 'reservation' => alma_reservation_pickup_branches(), ); // Cache output for 24 hours if we got all the data correctly. if ($organisation['branch'] && $organisation['department'] && $organisation['location'] && $organisation['sublocation'] && $organisation['collection'] && $organisation['reservation']) { - cache_set('alma_organisation', $organisation, 'cache'); + cache_set('alma_organisation', $organisation, 'cache', REQUEST_TIME + 86400); } } } @@ -226,47 +230,17 @@ function alma_get_organisation($reset = FALSE) { } /** - * Implements hook_user_view - */ -function alma_user_view($account, $view_mode, $langcode) { - try{ - $creds = ding_user_get_creds($account); - } - catch(DingProviderAuthException $e){ - return NULL; - } - if (($userInfo = _alma_user_info($creds)) && isset($userInfo)) { - foreach ($userInfo as $key => $prop) { - $data[$key] = isset($prop) ? $prop : ''; - } - - $account->content['name'] = array( - '#type' => 'item', - '#title' => t('Name'), - '#markup' => $data['firstname'], - ); - - $address_parts = array($data['address']); - if (!empty($data['postal']) || !empty($data['city'])) { - $address_parts[] = join('
', array_filter(array($data['postal'], $data['city']))); - } - - // @todo: really, there should be a template for this. - $account->content['address'] = array( - '#type' => 'item', - '#title' => t('Address'), - '#markup' => '

' . join('
',$address_parts) . '

', - ); - }; - // @todo: add provider specific fields - alma_set_profile2_fields($account); -} - -/** - * Callback function to get OpenRuth user information + * Callback function to get user information from Alma. + * + * @param array $creds + * The credentials for the user for which the information should be retrieved + * from Alma. + * + * @return array + * Available information about the patron from Alma. */ function _alma_user_info($creds = NULL) { - // Get patron informations from ALMA. + // Get patron information from Alma. $status = alma_get_patron($creds); // Build basic information array, with patron information. @@ -284,335 +258,325 @@ function _alma_user_info($creds = NULL) { return $info; } -function alma_set_profile2_fields($account) { - if( !module_exists('profile2') ) { - return; - } - - $profile2 = profile2_load_by_user($account, 'provider_alma'); - if( empty($profile2) ) { - return; - } - - // wrapper for profile2-fields - $account->content['profile2'] = array( - '#type' => 'item', - '#title' => t('My library'), - '#prefix' => '
', - '#suffix' => '
', - ); - - // set preferred branch - if( $pref_branch = alma_get_preferred_branch( $profile2 ) ) { - $account->content['profile2']['preferred_branch'] = array( - '#type' => 'item', - '#title' => t('Pickup branch'), - '#markup' => ''.$pref_branch.'', - ); - } - - // set interest period - if( $interest_period = alma_get_interest_period($profile2) ) { - $account->content['profile2']['interest_period'] = array( - '#type' => 'item', - '#title' => t('Interest period'), - '#markup' => ''.$interest_period['value'].'', - ); - } - - // set mobile phone - if( $mob = alma_get_mobile_phone($profile2) ) { - $account->content['profile2']['mobile'] = array( - '#type' => 'item', - '#title' => t('Mobile phone'), - '#markup' => ''.$mob.'', - ); - } - - // set reservation pause - if( $reservation_pause = alma_get_reservation_pause( $profile2 ) ) { - //wrapper for reservation pause - $account->content['profile2']['reservation_pause'] = array( - '#type' => 'item', - '#title' => t('Reservation pause'), - '#prefix' => '
', - '#suffix' => '
', - ); - - $account->content['profile2']['reservation_pause']['start'] = array( - '#type' => 'item', - '#title' => t('Start'), - '#markup' => ''.str_replace('T00:00:00','',$reservation_pause['start']).'', - ); - - $account->content['profile2']['reservation_pause']['stop'] = array( - '#type' => 'item', - '#title' => t('Stop'), - '#markup' => ''.str_replace('T00:00:00','',$reservation_pause['stop']).'', - ); - } -} +/** + * Implements hook_profile2_presave(). + * + * Updates changes add to the profile when its saved. + */ +function alma_profile2_presave($entity) { + // Check if the profile is just being created and is an alma_provider profile. + // If it's being created the fields are not yet loaded and can't be saved back + // to the provider. + $try_to_save = ($entity->created == $entity->changed) ? FALSE : TRUE; + if ($entity->type == 'provider_alma' && $try_to_save) { + $changes = array(); + + // Use a metadata wrapper to access the data. + $wrapper_original = entity_metadata_wrapper('profile2', $entity->original); + $wrapper = entity_metadata_wrapper('profile2', $entity); + + // Reservation pause (Start). + $value = $wrapper->field_alma_reservation_pause->value(); + $start = ''; + if (!is_null($value['value'])) { + $start = date(ALMA_DATE, strtotime($value['value'])); + } + $stop = ''; + if (!is_null($value['value2'])) { + $stop = date(ALMA_DATE, strtotime($value['value2'])); + } -function alma_get_mobile_phone( $profile2 ) { - $langs = field_language('profile2', $profile2); + // Reservation pause (Stop). + $value = $wrapper_original->field_alma_reservation_pause->value(); + $org_start = ''; + if (!is_null($value['value'])) { + $org_start = date(ALMA_DATE, strtotime($value['value'])); + } + $org_stop = ''; + if (!is_null($value['value2'])) { + $org_stop = date(ALMA_DATE, strtotime($value['value2'])); + } - if( empty($profile2->field_alma_mobile_phone[$langs['field_alma_mobile_phone']] ) ) { - return false; - } + // Check if the reservation pause have changed. + if ($start != $org_start || $stop != $org_stop) { + $changes['reservation_pause_start'] = $start; + $changes['reservation_pause_stop'] = $stop; - $mob = - isset($profile2->field_alma_mobile_phone[$langs['field_alma_mobile_phone']][0]['value']) ? - $profile2->field_alma_mobile_phone[$langs['field_alma_mobile_phone']][0]['value'] : FALSE; + // Set absent id. + $value = $wrapper->field_alma_absent_id->value(); + $changes['absent_id'] = is_null($value) ? '' : $value; + } - return $mob; -} + // Get preferred branch (patronBranch). + $value = $wrapper->field_alma_preferred_branch->value(); + if (!is_null($value)) { + if ($value != $wrapper_original->field_alma_preferred_branch->value()) { + $changes['preferred_branch'] = $value; + } + } -function alma_get_reservation_pause($profile2){ - // get field languages - $langs = field_language('profile2', $profile2); + // SMS number. + $value = $wrapper->field_alma_sms->value(); + if (!is_null($wrapper_original->field_alma_sms->value())) { + // Update sms phone number. + $value = is_null($value) ? 'DELETE' : $value; + if ($value != $wrapper_original->field_alma_sms->value()) { + $changes['sms'] = $value; - if( empty($profile2->field_alma_reservation_pause[$langs['field_alma_reservation_pause']] ) ) { - return false; - } + // Get sms id. + $changes['sms_id'] = $wrapper->field_alma_sms_id->value(); + } + } + elseif (!is_null($value) && is_null($wrapper_original->field_alma_sms->value())) { + $changes['sms'] = $value; + } - $res_pause['start'] = $profile2->field_alma_reservation_pause[$langs['field_alma_reservation_pause']][0]['value']; - $res_pause['stop'] = $profile2->field_alma_reservation_pause[$langs['field_alma_reservation_pause']][0]['value2']; + // Mobile phone. + $value = $wrapper->field_alma_mobile_phone->value(); + if (!is_null($wrapper_original->field_alma_mobile_phone->value())) { + // Update mobile phone number. + $value = is_null($value) ? 'DELETE' : $value; + if ($value != $wrapper_original->field_alma_mobile_phone->value()) { + $changes['mobile'] = $value; - if( strlen($res_pause['start']) < 2 || strlen($res_pause['stop']) < 2 ) { - return false; - } + // Get phone id. + $changes['phone_id'] = $wrapper->field_alma_phone_id->value(); + } + } + elseif (!is_null($value) && is_null($wrapper_original->field_alma_mobile_phone->value())) { + $changes['mobile'] = $value; + } - return $res_pause; -} + // Get the mail. + $value = $wrapper->field_alma_mail->value(); + if (!is_null($value) && $value != $wrapper_original->field_alma_mail->value()) { + $changes['mail'] = $value; + } -function alma_get_interest_period( $profile2 ) { - // get field languages - $langs = field_language('profile2', $profile2); - // get field-info to retrieve values for select list - $field_info = field_info_field('field_alma_interest_period'); + // Update provider. + if (!empty($changes)) { + alma_update_provider($changes, $entity); + + // Update local drupal user (mail and display name). + if (isset($changes['mail'])) { + $creds = ding_user_get_creds($entity); + $auth_name = ding_user_default_authname($creds['name']); + _ding_user_create_account($auth_name, array( + 'user' => array( + 'mail' => $changes['mail'], + 'data' => array( + 'display_name' => $wrapper->field_alma_full_name->value(), + ), + ), + )); + } - $interest_period = FALSE; - $int_values = isset( $field_info['settings']['allowed_values'] ) ? $field_info['settings']['allowed_values']: FALSE; - if( $int_values ) { - $int_period = $profile2->field_alma_interest_period[$langs['field_alma_interest_period']][0]['value']; - $interest_period = isset($int_values[$int_period]) ? array('key'=>$int_period,'value'=>$int_values[$int_period]) : FALSE; + // Clear local session cache by reloading patron from Alma. + alma_get_patron(NULL, TRUE); + } } - return $interest_period; -} - -function alma_get_preferred_branch( $profile2 ) { - // get field languages - $langs = field_language('profile2', $profile2); - - //get preferred branch - $pref_branch = - isset($profile2->field_alma_preferred_branch[$langs['field_alma_preferred_branch']][0]['value']) ? - $profile2->field_alma_preferred_branch[$langs['field_alma_preferred_branch']][0]['value']:''; - - $branches = alma_reservation_pickup_branches(); - $pref = isset($branches[$pref_branch]) ? $branches[$pref_branch] : FALSE; - - return $pref; } /** - * Implements hook_profile2_presave(). + * Update user information at the provider. + * + * @global object $user + * The user object for the currently logged in user. * - * Sends changes to Alma + * @param array $changes + * Array with the fields/information that have changed and should be updated + * at the provider. + * @param object $entity + * An profile2 entity, mainly used to the user credentials. */ -function alma_profile2_presave($profile2) { - if( !$profile2->type == 'provider_alma' ) { - return; - } - // do not presave when initializing - // @see alma.user/alma_user_profile_init - if( isset($profile2->alma_init) ) { - return; - } - // providerfields: field_alma_preferred_branch, field_alma_interest_period, field_alma_reservation_pause; field_alma_mobile_phone - $langs = field_language('profile2', $profile2); - - // reservation pause - if( !empty( $profile2->original->field_alma_reservation_pause ) ) { - $start = - isset($profile2->field_alma_reservation_pause[$langs['field_alma_reservation_pause']][0]['value']) ? - $profile2->field_alma_reservation_pause[$langs['field_alma_reservation_pause']][0]['value'] : ''; - $start = str_replace('T00:00:00','',$start); - - $stop = - isset($profile2->field_alma_reservation_pause[$langs['field_alma_reservation_pause']][0]['value2']) ? - $profile2->field_alma_reservation_pause[$langs['field_alma_reservation_pause']][0]['value2'] : ''; - $stop = str_replace('T00:00:00','',$stop); - - $org_start = $profile2->original->field_alma_reservation_pause[$langs['field_alma_reservation_pause']][0]['value']; - $org_start = str_replace('T00:00:00','',$org_start); - - $org_stop = $profile2->original->field_alma_reservation_pause[$langs['field_alma_reservation_pause']][0]['value2']; - $org_stop = str_replace('T00:00:00','',$org_stop); - - if( $start != $org_start || $stop != $org_stop ) { - $changes['reservation_pause_start'] = $start; - $changes['reservation_pause_stop'] = $stop; - $changes['absent_id'] = $profile2->field_absent_id[$langs['field_absent_id']][0]['value']; - } - } - - // alma_preferred_branch (patronBranch) - if( !empty( $profile2->original->field_alma_preferred_branch ) ) { - $org_branch = $profile2->original->field_alma_preferred_branch[$langs['field_alma_preferred_branch']][0]['value']; - $new_branch = $profile2->field_alma_preferred_branch[$langs['field_alma_preferred_branch']][0]['value']; - - if( $org_branch != $new_branch ) { - $changes['preferred_branch'] = $new_branch; - } - } - - //change or remove - if( !empty($profile2->original->field_alma_mobile_phone ) ) { - $org_phone = $profile2->original->field_alma_mobile_phone[$langs['field_alma_mobile_phone']][0]['value']; - $new_phone = - !empty( $profile2->field_alma_mobile_phone[$langs['field_alma_mobile_phone']][0]['value']) ? - $profile2->field_alma_mobile_phone[$langs['field_alma_mobile_phone']][0]['value'] : - 'DELETE'; - if( $org_phone != $new_phone ) { - $changes['mobile'] = $new_phone; - $changes['phone_id'] = $profile2->field_alma_phone_id[$langs['field_alma_phone_id']][0]['value']; - } - } - // add - elseif( isset( $profile2->field_alma_mobile_phone[$langs['field_alma_mobile_phone']][0]['value'] ) && - !isset( $profile2->original->field_alma_mobile_phone[$langs['field_alma_mobile_phone']][0]['value'] )) { - $changes['mobile'] = $profile2->field_alma_mobile_phone[$langs['field_alma_mobile_phone']][0]['value']; - } - - - // Interest period ? apparently not an alma parameter.. @todo; check if Interest period should be saved on provider - - // update provider - if( isset($changes) ) { - alma_update_provider( $changes,$profile2 ); - } - -} - -function alma_update_provider( $changes, $profile2 ) { - $error_message = t('Error communicating with library system. '); +function alma_update_provider($changes, $entity) { + $error_message = t('Error communicating with library system.'); try { - $creds = ding_user_get_creds($profile2); + $creds = ding_user_get_creds($entity); } - catch (Exception $e){ - // rethrow ?? - throw $e; + catch (Exception $exception) { + watchdog_exception('Alma provider', $exception); + throw $exception; } - // mobile phone; add, change, delete + // Mobile phone; add, change, delete. if (isset($changes['phone_id'])) { if ($changes['mobile'] == 'DELETE') { - //delete mobile + // Delete mobile. try { $res = alma_client_invoke('remove_phone_number', $creds['name'], $creds['pass'], $changes['phone_id']); } - catch (Exception $e) { - watchdog('Alma provider', $e->getMessage(), array(), WATCHDOG_ERROR); + catch (Exception $exception) { + watchdog_exception('Alma provider', $exception); } - if (!$res) { - $error_message .= t('mobile not deleted'); - drupal_set_message($error_message,'warning'); + if (empty($res)) { + $error_message .= t('phone not deleted'); + drupal_set_message($error_message, 'warning'); } } else { - //update mobile - try { - $res = alma_client_invoke('change_phone_number', $creds['name'], $creds['pass'], $changes['phone_id'], $changes['mobile']); - } - catch (Exception $e) { - watchdog('Alma provider', $e->getMessage(), array(), WATCHDOG_ERROR); - } - if (!$res) { - $error_message .= t('mobile not updated'); - drupal_set_message($error_message,'warning'); + // Update mobile. + try { + $res = alma_client_invoke('change_phone_number', $creds['name'], $creds['pass'], $changes['phone_id'], $changes['mobile'], FALSE); + } + catch (Exception $exception) { + watchdog_exception('Alma provider', $exception); + } + + if (!$res) { + $error_message .= t('mobile not updated'); + drupal_set_message($error_message, 'warning'); } } } - elseif (isset($changes['mobile'])){ - // add mobile + elseif (isset($changes['mobile'])) { + // Add mobile. try { - $res = alma_client_invoke('add_phone_number', $creds['name'], $creds['pass'], $changes['mobile'] ); + $res = alma_client_invoke('add_phone_number', $creds['name'], $creds['pass'], $changes['mobile'], FALSE); } - catch (Exception $e){ - watchdog('Alma provider', $e->getMessage(), array(), WATCHDOG_ERROR); + catch (Exception $exception) { + watchdog_exception('Alma provider', $exception); } if (!$res) { $error_message .= t('mobile not added'); - drupal_set_message($error_message,'warning'); + drupal_set_message($error_message, 'warning'); } } - // update reservation pause (absentPeriod) - if (!empty( $changes['absent_id']) && - !empty($changes['reservation_pause_start']) && - !empty( $changes['reservation_pause_stop'])) { + // Mobile phone; add, change, delete. + if (isset($changes['sms_id'])) { + if ($changes['sms'] == 'DELETE') { + // Delete mobile. + try { + $res = alma_client_invoke('remove_phone_number', $creds['name'], $creds['pass'], $changes['sms_id']); + } + catch (Exception $exception) { + watchdog_exception('Alma provider', $exception); + } + if (empty($res)) { + $error_message .= t('sms not deleted'); + drupal_set_message($error_message, 'warning'); + } + } + else { + // Update mobile. + try { + $res = alma_client_invoke('change_phone_number', $creds['name'], $creds['pass'], $changes['sms_id'], $changes['sms']); + } + catch (Exception $exception) { + watchdog_exception('Alma provider', $exception); + } + + if (!$res) { + $error_message .= t('sms not updated'); + drupal_set_message($error_message, 'warning'); + } + } + } + elseif (isset($changes['sms'])) { + // Add mobile. try { - $res = alma_client_invoke('change_absent_period',$creds['name'], $creds['pass'], $changes['absent_id'], $changes['reservation_pause_start'],$changes['reservation_pause_stop'] ); + $res = alma_client_invoke('add_phone_number', $creds['name'], $creds['pass'], $changes['sms']); + } + catch (Exception $exception) { + watchdog_exception('Alma provider', $exception); } - catch(Exception $e){ - watchdog('Alma provider', $e->getMessage(), array(), WATCHDOG_ERROR); + if (!$res) { + $error_message .= t('sms not added'); + drupal_set_message($error_message, 'warning'); } - if( !$res ) { + } + + // Update reservation pause (absentPeriod). + if (!empty($changes['absent_id']) && + !empty($changes['reservation_pause_start']) && + !empty($changes['reservation_pause_stop'])) { + + try { + $res = alma_client_invoke('change_absent_period', $creds['name'], $creds['pass'], $changes['absent_id'], $changes['reservation_pause_start'], $changes['reservation_pause_stop']); + } + catch (Exception $exception) { + watchdog_exception('Alma provider', $exception); + } + if (empty($res)) { $error_message .= t('reservation pause not updated'); - drupal_set_message($error_message,'warning'); + drupal_set_message($error_message, 'warning'); } } - // add reservation pause - elseif (!empty($changes['reservation_pause_start']) && - !empty($changes['reservation_pause_stop'])) { + // Add reservation pause. + elseif (!empty($changes['reservation_pause_start']) && !empty($changes['reservation_pause_stop'])) { try { - $res = alma_client_invoke('add_absent_period',$creds['name'], $creds['pass'], $changes['reservation_pause_start'],$changes['reservation_pause_stop']); + $res = alma_client_invoke('add_absent_period', $creds['name'], $creds['pass'], $changes['reservation_pause_start'], $changes['reservation_pause_stop']); } - catch (Exception $e){ - watchdog('Alma provider', $e->getMessage(), array(), WATCHDOG_ERROR); + catch (Exception $exception) { + watchdog_exception('Alma provider', $exception); } - if (!$res) { + if (empty($res)) { $error_message .= t('reservation pause not added'); - drupal_set_message($error_message,'warning'); + drupal_set_message($error_message, 'warning'); } } - // delete reservation pause - elseif (!empty( $changes['absent_id'])) { + // Delete reservation pause. + elseif (!empty($changes['absent_id'])) { try { $res = alma_client_invoke('remove_absent_period', $creds['name'], $creds['pass'], $changes['absent_id']); } - catch (Exception $e){ - watchdog('Alma provider', $e->getMessage(), array(), WATCHDOG_ERROR); + catch (Exception $exception) { + watchdog_exception('Alma provider', $exception); } - - // this one actually deletes the reservation pause, but returns an error ?? - // for now disable messages...@todo; fix it. - /* if( !$res ) { - $error_message .= t('reservation pause not deleted'); - drupal_set_message($error_message,'warning'); - }*/ } - // update preferred branch (patronBranch) + // Update preferred branch (patronBranch). if (!empty($changes['preferred_branch'])) { try { - $res = alma_client_invoke( 'change_patron_preferences' , $creds['name'], $creds['pass'], $changes['preferred_branch']); + $res = alma_client_invoke('change_patron_preferences', $creds['name'], $creds['pass'], $changes['preferred_branch']); } - catch(Exception $e){ - watchdog('Alma provider', $e->getMessage(), array(), WATCHDOG_ERROR); + catch (Exception $exception) { + watchdog_exception('Alma provider', $exception); } - if (!$res) { + if (empty($res)) { $error_message .= t('pickup branch not saved'); - drupal_set_message($error_message,'warning'); + drupal_set_message($error_message, 'warning'); } } - // refresh patron - alma_get_patron($creds, TRUE); + // Update email (remember to update the drupal user account). + if (!empty($changes['mail'])) { + global $user; + + // Update or add mail to ALMA. + try { + // Add email. + if (empty($user->mail) && !empty($changes['mail'])) { + $res = alma_client_invoke('add_email_address', $creds['name'], $creds['pass'], $changes['mail']); + } + // Change email. + elseif (isset($user->mail) && !empty($changes['mail'])) { + $res = alma_client_invoke('change_email_address', $creds['name'], $creds['pass'], $user->mail, $changes['mail']); + } + } + catch (Exception $exception) { + watchdog_exception('Alma provider', $exception); + } + + if (empty($res)) { + $error_message .= t('mail was not saved'); + drupal_set_message($error_message, 'warning'); + } + else { + // Update drupal user account mail. + $user->mail = $changes['mail']; + user_save($user); + } + } + + // Update patron information and update cache. + if (!empty($changes)) { + alma_get_patron($creds, TRUE); + } } /** @@ -620,8 +584,11 @@ function alma_update_provider( $changes, $profile2 ) { * * @param array $creds * Array with 'name' and 'pass' keys, used to authenticate user with Alma. - * @param boolean $reset + * @param bool $reset * Reset static caching for this function. + * @param bool $as_array + * Return the patron information as an array. + * * @return stdClass * Patron object. */ @@ -632,26 +599,143 @@ function alma_get_patron($creds = NULL, $reset = FALSE, $as_array = FALSE) { $creds = ding_user_get_creds($user); } - static $patron; + // Try static cache. + $patron = &drupal_static(__FUNCTION__); if (!$patron || $reset) { - $info = alma_client_invoke('get_patron_info', $creds['name'], $creds['pass'], TRUE); - $organisation = alma_get_organisation(); - $patron = array( - 'name' => $info['user_name'], - 'email' => isset($info['mails'][0]) ? $info['mails'][0]['mail'] : '', - 'address' => isset($info['addresses'][0]) ? $info['addresses'][0]['street'] : '', - 'postal' => isset($info['addresses'][0]) ? $info['addresses'][0]['postal_code'] : '', - 'city' => isset($info['addresses'][0]) ? $info['addresses'][0]['city'] : '', - 'mobiles' => isset($info['phones']) ? $info['phones'] : '', - 'branch' => $info['preferences']['patron_branch'], - 'branchName' => $organisation['branch'][$info['preferences']['patron_branch']], - 'absentPeriods'=>isset($info['absent_periods']) ? $info['absent_periods'] : '', - ); + // Try session cache. + if (!$reset && isset($_SESSION['alma_patron_info'])) { + $patron = $_SESSION['alma_patron_info']; + } + else { + $info = alma_client_invoke('get_patron_info', $creds['name'], $creds['pass'], TRUE); + $organisation = alma_get_organisation(); + $patron = array( + 'name' => $info['user_name'], + 'email' => isset($info['mails'][0]) ? $info['mails'][0]['mail'] : '', + 'address' => isset($info['addresses'][0]) ? $info['addresses'][0]['street'] : '', + 'postal' => isset($info['addresses'][0]) ? $info['addresses'][0]['postal_code'] : '', + 'city' => isset($info['addresses'][0]) ? $info['addresses'][0]['city'] : '', + 'mobiles' => isset($info['phones']) ? $info['phones'] : '', + 'branch' => empty($info['preferences']['patron_branch']) ? FALSE : $info['preferences']['patron_branch'], + 'branchName' => !empty($info['preferences']['patron_branch']) ? $organisation['branch'][$info['preferences']['patron_branch']] : FALSE, + 'absentPeriods' => isset($info['absent_periods']) ? $info['absent_periods'] : '', + ); + + // Store information in session cache. + $_SESSION['alma_patron_info'] = $patron; + } } - if( $as_array ) { - return $patron; + + // Cast patron to object. + if (!$as_array) { + $patron = (object) $patron; + } + + return $patron; +} + +/** + * Implements hook_profile2_load(). + * + * When every a profile2 profile is load this hook it called and as we are using + * virtual fields the content has to be field in from Alma just in time. So this + * seams to be the right place and at the same time ensure that the information + * is not stored locally. + * + * Note: that the interest period is store locally in the database as alma do + * not have the ability to store it. So that field is not fill in here. + */ +function alma_profile2_load($entities) { + foreach ($entities as $id => &$entity) { + if ($entity->type == 'provider_alma') { + + // User static cache to ensure that alma is not asked more than once. + $patron = &drupal_static(__FUNCTION__); + if (!isset($patron)) { + // Get information from alma about the current user. + global $user; + try { + $creds = ding_user_get_creds($user); + } + catch (DingProviderAuthException $e) { + // The user was not logged in, hence we can't fill out the profile. + return; + } + + // Get user information from alma. + $patron = alma_get_patron($creds); + } + + // Use a metadata wrapper to access the data. + $wrapper = entity_metadata_wrapper('profile2', $entity); + + // Reservation pause. + $wrapper->field_alma_reservation_pause->set(array( + 'value' => '', + 'value2' => '', + )); + if (isset($patron->absentPeriods[0]) && + isset($patron->absentPeriods[0]['from_date']) && isset($patron->absentPeriods[0]['to_date'])) { + $wrapper->field_alma_reservation_pause->set(array( + 'value' => date(ALMA_DATE_LONG, strtotime($patron->absentPeriods[0]['from_date'])), + 'value2' => date(ALMA_DATE_LONG, strtotime($patron->absentPeriods[0]['to_date'])), + )); + $wrapper->field_alma_absent_id->set($patron->absentPeriods[0]['id']); + } + + // Full name. + $wrapper->field_alma_full_name->set($patron->name); + + // Set full address. + $wrapper->field_alma_street_name->set($patron->address); + $wrapper->field_alma_postal_code->set($patron->postal); + $wrapper->field_alma_city->set($patron->city); + + // Preferred_branch. + $wrapper->field_alma_preferred_branch->set($patron->branch); + + // Mobile (SMS and telephone). + foreach ($patron->mobiles as $mobile) { + if ($mobile['sms']) { + $wrapper->field_alma_sms->set(isset($mobile['phone']) ? $mobile['phone'] : ''); + $wrapper->field_alma_sms_id->set(isset($mobile['id']) ? $mobile['id'] : NULL); + } + else { + $wrapper->field_alma_mobile_phone->set(isset($mobile['phone']) ? $mobile['phone'] : ''); + $wrapper->field_alma_phone_id->set(isset($mobile['id']) ? $mobile['id'] : NULL); + } + } + + // Mail address. + $wrapper->field_alma_mail->set($patron->email); + } } +} - return (object) $patron; +/** + * Implements hook_field_attach_view_alter(). + * + * Alter user profile view with SMS fee. + */ +function alma_field_attach_view_alter(&$output, $context) { + if (isset($output['field_alma_sms'][0]['#markup'])) { + $ding_user_fee_sms = variable_get('ding_user_fee_sms', t('Notice that there is a fee for receiving a SMS')); + if ($ding_user_fee_sms) { + $output['field_alma_sms'][0]['#markup'] .= '(' . $ding_user_fee_sms . ')'; + } + } } +/** + * Implements hook_ding_session_cache_defaults(). + * + * Set default ding_session_cache settings and tell ding_session_cache that this + * module supports it. + */ +function alma_ding_session_cache_defaults() { + return array( + 'titel' => 'Alma (reservations, loans)', + 'enabled' => TRUE, + 'expire' => 3600, + ); +} diff --git a/includes/alma.availability.inc b/includes/alma.availability.inc index 8546153..d194662 100644 --- a/includes/alma.availability.inc +++ b/includes/alma.availability.inc @@ -1,234 +1,240 @@ $record) { - $holding = array( - 'local_id' => $alma_id, - 'available' => ($record['available_count'] > 0), - 'reservable' => $record['show_reservation_button'], - 'show_reservation_button' => $record['show_reservation_button'], - 'holdings' => array(), - 'holdings_available' => array(), - 'reserved_count' => (int) $record['reservation_count'], - 'total_count' => _alma_count_total($record['holdings'], $record['media_class'] == 'periodical'), - 'deferred_period' => FALSE, - 'issues' => array(), - 'is_periodical' => ($record['media_class'] == 'periodical'), - ); - - $result[$alma_id] = $holding; - - $result[$alma_id]['html'] = _alma_get_holdings($details, $holding['is_periodical']); - } - } - return $result; - -} /** - * @param type $holdings; array containing holding informations - * @param type $is_periodical; Boolean that indicates whether the shown record is a periodical or not - * @return sum of all total_count in $holdings + * Implements provider availability, items. */ -function _alma_count_total($holdings, $is_periodical) { - $total = 0; - if ($is_periodical) { - foreach ($holdings as $year => $issues) { - foreach ($issues as $issue) { - foreach ($issue as $holding) { - $total += $holding['total_count']; - } - } - } +function alma_availability_items($provider_ids) { + $ids = implode(',', $provider_ids); + $result = alma_client_invoke('get_availability', $ids); + if (!$result) { + $result = array(); } - else { - foreach ($holdings as $holding) { - $total += $holding['total_count']; - } - } - return $total; -} + return $result; +} /** - * @param type $res; returned array from alma_client class - * @param type $is_periodical; Boolean that indicates whether the shown record is a periodical or not - * @return html to be shown. Returns FALSE if no data is received from alma_client class + * Implements provider availability, holdings. */ -function _alma_get_holdings($res, $is_periodical = FALSE) { - if(isset($res['records'])) { - if($is_periodical){ - return _alma_set_holdings_periodical($res); - } - else { - return _alma_set_holdings($res); - } +function alma_availability_holdings($provider_ids, $reset = FALSE) { + // Create cache id. + $cid = md5(serialize($provider_ids)); + + // Check the check to speed up the process, it's only cached for 10 min. to + // ensure freshness. + $cache = cache_get($cid, 'cache'); + if (!$reset && $cache && $cache->expire > REQUEST_TIME) { + $result = $cache->data; } else { - return FALSE; - } -} + $ids = implode(',', $provider_ids); + $details = alma_client_invoke('catalogue_record_detail', $ids); + $result = array(); - /** - * set holdings for all kinds of material except periodicals - * @param array $res - * @return array $result; - */ -function _alma_set_holdings($res) { - $holdings = array(); - foreach ($res['records'] as $alma_id => $records) { - foreach ($records['holdings'] as $holding) { - $holdings[] = $holding; - } - } - - $result = _alma_set_table_html($holdings); - return $result; -} + if ($details && isset($details['records'])) { + foreach ($details['records'] as $alma_id => $record) { + $holding = array( + 'local_id' => $alma_id, + 'title' => $record['titles'][0], + 'available' => ($record['available_count'] > 0), + 'reservable' => $record['show_reservation_button'], + 'show_reservation_button' => $record['show_reservation_button'], + 'holdings' => $record['holdings'], + 'reserved_count' => (int) $record['reservation_count'], + 'deferred_period' => FALSE, + 'issues' => FALSE, + 'is_periodical' => ($record['media_class'] == 'periodical'), + 'is_internet' => ($record['media_class'] == 'internet'), + ); + + // If periodical render issue information. + if ($holding['is_periodical']) { + $holding['issues'] = _alma_populate_issues($record['holdings']); + } + + // If it's an internet holding, don't display holdings information. + if ($holding['is_internet']) { + $holding['holdings'] = FALSE; + } + + // Get pretty location name (placement) as an array. + if (isset($holding['holdings'])) { + $org = alma_get_organisation(); + foreach ($holding['holdings'] as $index => $data) { + $holding['holdings'][$index]['placement'] = array(); + + if (!empty($data['branch_id'])) { + $holding['holdings'][$index]['placement'][] = $org['branch'][$data['branch_id']]; + } + + if (!empty($data['department_id'])) { + $holding['holdings'][$index]['placement'][] = $org['department'][$data['department_id']]; + } + + if (!empty($data['location_id'])) { + $holding['holdings'][$index]['placement'][] = $org['location'][$data['location_id']]; + } + + if (!empty($data['sublocation_id'])) { + $holding['holdings'][$index]['placement'][] = $org['sublocation'][$data['sublocation_id']]; + } + + if (!empty($data['collection_id'])) { + $holding['holdings'][$index]['placement'][] = $org['collection'][$data['collection_id']]; + } + + if (!empty($data['shelf_mark'])) { + $holding['holdings'][$index]['placement'][] = $data['shelf_mark']; + } + } + } - /** - * set holdings if material is periodical only - * @param array $res - * @return array $result - */ -function _alma_set_holdings_periodical($res){ - $holdings = array(); - foreach ($res['records'] as $alma_id => $records) { - foreach ($records['holdings'] as $holding => $issue_year) { - foreach ($issue_year as $key) { - $holdings[] = $key[0]; + // Count total materials. + $holding['total_count'] = _alma_holdings_total_count($holding['holdings']); + + // Set holdings. + $result[$alma_id] = $holding; } + + // Cache the result for 10 min. This will speed up materials with many + // copies and loans. + cache_set($cid, $result, 'cache', REQUEST_TIME + 600); } } - - $result = _alma_set_table_html($holdings); + return $result; } - /** - * Make the html-table - * @params $h; holding information for a given material - * @return html-table - */ -function _alma_set_table_html($h) { - // set a classname for styling the table - $variables['attributes']= - array('class'=>array(drupal_html_class('availability_holdings_table'))); - // set table header - $variables['header'] = - array('placement'=>t('Placement'), 'copies'=>t('Copies'), 'Home'=>t('At home'),'reservations'=>t('Reservations')); - // set table rows - $variables['rows'] = _alma_set_rows($h); - // theme the table - // @TODO; move this to ding_availability ?? - $html = theme('table',$variables ); - - return $html; -} - /** - * set rows in table for given holdings - * @param $h; holding information for a given material - * @return array; - */ -function _alma_set_rows($h) { - $rows = array(); - $org = alma_get_organisation(); - - $copies_total = 0; - $home_total = 0; - $reservations_total = 0; - foreach ($h as $key => $data) { - $row = array(); - $row['placement'] = $org['branch'][$data['branch_id']]; - - if(!empty($data['department_id'])){ - $row['placement'] = $row['placement'] .' → '. $org['department'][$data['department_id']]; - } - - if(!empty($data['collection_id'])){ - $row['placement'] = $row['placement'] .' → '. $org['collection'][$data['collection_id']]; +/** + * Sums the total number of materials from holdings information. + * + * @param array $holdings + * Holdings information return form alma. + * + * @return int + * Total number of materials in the holding. + */ +function _alma_holdings_total_count($holdings) { + $total = 0; + foreach ($holdings as $holding) { + if (isset($holding['total_count'])) { + $total += (int) $holding['total_count']; } - - $row['copies'] = (int) $data['total_count']; - $copies_total += $row['copies']; - $row['home'] = (int) $data['available_count']; - $home_total += $row['home']; - $row['reservations'] = (int) $data['ordered_count']; - $reservations_total += $row['reservations']; - $rows[] = $row; - } - - if(count($rows) >= 1){ - $rows = _clean_up_rows($rows); } - //Adding last row - totals - $row = array(); - $row['data']['Library'] = t('Total'); - $row['data']['Copies'] = $copies_total; - $row['data']['Home'] = $home_total; - $row['data']['Reservations'] = $reservations_total; - $row['class'] = array(drupal_html_class('availability_holdings_last_row')); - $rows[] = $row; - return $rows; -} - /** - * if the same placement exists several times collect them in one line - * @param array - * @return array; - */ -function _clean_up_rows($_rows) { - $rows = array(); - $placements = array(); - - foreach ($_rows as $row) { - $currkey = $row['placement']; - if(!in_array($currkey, $placements)){ - $placements[] = $currkey; - $placementsarr = _get_placements_with_key($_rows, $currkey); - $this_row = _sum_placement($placementsarr); - $rows[] = $this_row; - } - } - return $rows; + return $total; } - /** - * collect materials with the same placement - * @param array $_rows - * @param String $currkey - * @return array $rows; - */ -function _get_placements_with_key($_rows, $currkey){ - $rows = array(); - foreach ($_rows as $key) { - if($key['placement'] == $currkey){ - $rows[] = $key; +/** + * Fill in the issues data, useful for periodical availability. + * + * This method takes into consideration the repeating placements, + * and aggregates them, summing the numeric data. + * + * @param array $input + * Holdings data, as returned from the web-service. + * + * @return array + * An array, with the following keys: + * - Issue year. + * - Issue number. + * - local_id: Periodical identifier. + * - provider: Provider identifier, 'alma' here. + * - placement: Item placement info. + * - location: Actual location string. + * - ordered_count + * - checked_out_count + * - reference_count + * - total_count + * - available_count + * - reservable + */ +function _alma_populate_issues($input) { + $org = alma_get_organisation(); + $output = array(); + $prev_hash = ''; + + // Loop through volumes. + foreach ($input as $year => $volume) { + // Loop through issues. + foreach ($volume as $key => $issues) { + $ordered_count = 0; + $checked_out_count = 0; + $reference_count = 0; + $total_count = 0; + $available_count = 0; + $output[$year][$key]['local_id'] = isset($issues[0]['reservable']) ? $issues[0]['reservable'] : ''; + $output[$year][$key]['provider'] = 'alma'; + $i = 0; + // Loop though placements. + foreach ($issues as $copy) { + $placement = array(); + $branch_id = !empty($copy['branch_id']) ? $copy['branch_id'] : ''; + $department_id = !empty($copy['department_id']) ? $copy['department_id'] : ''; + $location_id = !empty($copy['location_id']) ? $copy['location_id'] : ''; + $sublocation_id = !empty($copy['sublocation_id']) ? $copy['sublocation_id'] : ''; + $shelf_mark = !empty($copy['shelf_mark']) ? $copy['shelf_mark'] : ''; + + if (!empty($branch_id)) { + $placement[] = $org['branch'][$branch_id]; + } + + if (!empty($department_id)) { + $placement[] = $org['department'][$department_id]; + } + + if (!empty($location_id)) { + $placement[] = $org['location'][$location_id]; + } + + if (!empty($sublocation_id)) { + $placement[] = $org['sublocation'][$sublocation_id]; + } + + if (!empty($shelf_mark)) { + $placement[] = $shelf_mark; + } + + $placement_string = implode(' > ', $placement); + + // A hash value, used for recognizing differences in placement. + $hash = md5($branch_id . $department_id . $location_id . $sublocation_id . $shelf_mark); + + // Whether it's a new placement, start a new count and increment the + // row counter. + if ($hash !== $prev_hash) { + $prev_hash = $hash; + $ordered_count = 0; + $checked_out_count = 0; + $reference_count = 0; + $total_count = 0; + $available_count = 0; + $i++; + } + + // The numeric data keeps summing each other, until + // we get a new placement. + $ordered_count += $copy['ordered_count']; + $checked_out_count += $copy['checked_out_count']; + $reference_count += $copy['reference_count']; + $total_count += $copy['total_count']; + $available_count += $copy['available_count']; + + $output[$year][$key]['placement'][$i] = array( + 'location' => $placement_string, + 'ordered_count' => $ordered_count, + 'checked_out_count' => $checked_out_count, + 'reference_count' => $reference_count, + 'total_count' => $total_count, + 'available_count' => $available_count, + 'reservable' => ($copy['show_reservation_button'] === 'yes') ? TRUE : FALSE, + ); + } } } - return $rows; -} - /** - * sum material for same placement in one row - * @param $placementsarr; array with all instances of the same placement - ie. 'Hovedbiblioteket' - * @return array; $row - */ -function _sum_placement($placementsarr){ - $row = $placementsarr[0]; - for($i = 1; $i < count($placementsarr);$i++){ - $next_row = $placementsarr[$i]; - $row['copies'] += $next_row['copies']; - $row['home'] += $next_row['home']; - $row['reservations'] += $next_row['reservations']; - } - return $row; + + return $output; } diff --git a/includes/alma.debt.inc b/includes/alma.debt.inc index c45f65f..ca62dc9 100644 --- a/includes/alma.debt.inc +++ b/includes/alma.debt.inc @@ -9,21 +9,40 @@ * * @param stdClass $account * User object to provide debts for. + * @param bool $reset + * Reset static cache if TRUE else get debts from cache. + * * @return array * DingProviderDebt objects in array, keyed by debt ID. */ -function alma_debt_list($account) { - $data = alma_debt_get_debts($account); - - $debts = array(); +function alma_debt_list($account, $reset = FALSE) { + $creds = ding_user_get_creds($account); + + // Use static cache to speed up communication with Alma. + $results = &drupal_static(__FUNCTION__, FALSE); + if (!$results || $reset) { + // Get debts from Alma. + $debts = alma_client_invoke('get_debts', $creds['name'], $creds['pass']); + + // Create DingProviderDebt instances from Alma's list. + $results = array(); + foreach ($debts['debts'] as $debt) { + // Get the material number from the display name and remove it form it. + preg_match('/^(\w+)\s+(.+)/', $debt['display_name'], $matchs); + if (count($matchs) == 3) { + $debt['display_name'] = $matchs[2]; + $debt['material_number'] = $matchs[1]; + } - // Create DingProviderDebt instances from Alma's list. - foreach ($data['debts'] as $debt) { - $debtObj = new DingProviderDebt($debt['id'], $debt); + // Translate the fee type code into an text string. + $debt['type'] = alma_debt_translate_debt_type($debt['type']); - $debts[$debt['id']] = $debtObj; + $debt_object = new DingProviderDebt($debt['id'], $debt); + $results[$debt['id']] = $debt_object; + } } - return $debts; + + return $results; } /** @@ -35,27 +54,93 @@ function alma_debt_list($account) { * IDs of the paid debts. * @param mixed $order_id * Order ID of the payment transaction, to be recorded in the backend system. + * + * @return array + * Array from ALMA with the results. */ -function alma_debt_payment_received($amount, $params = array(), $order_id = NULL) { - // TODO: We should probably check that $amount adds up to the debts - // we're going to mark paid, since Alma doesn't. - if( !empty($params['order_ids']) ) { - $debt_ids = $params['debt_ids']; - } - elseif( !empty($params['debts']) ) { - $debt_ids = array_keys($params['debts']) ; - } - else { - $debt_ids = array(); - } +function alma_debt_payment_received($amount, $debt_ids = array(), $order_id = NULL) { + // Return result from Alma. return alma_client_invoke('add_payment', implode(',', $debt_ids), $order_id); } /** - * Get list of debts from Alma. + * Translate alma debt types into an human readable string in english. + * + * @param string $debt_type + * The ALMA debt type. + * + * @return string + * English translation of the debt type. It has been */ -function alma_debt_get_debts($account, $reset = FALSE) { - $creds = ding_user_get_creds($account); - - return alma_client_invoke('get_debts', $creds['name'], $creds['pass']); +function alma_debt_translate_debt_type($debt_type) { + // If translation is not found, return the type. So set it as default. + $str = t($debt_type); + + switch ($debt_type) { + case 'overdueFeeInvoiceDebt': + $str = t('Overdue fee invoice'); + break; + + case 'overdueFeeDebt': + $str = t('Overdue fee'); + break; + + case 'loanFeeDebt': + $str = t('Loan fee'); + break; + + case 'reservationPickupFeeDebt': + $str = t('Reservation pick-up fee'); + break; + + case 'reservationFeeDebt': + $str = t('Reservation fee'); + break; + + case 'deleteReservationFeeDebt': + $str = t('Delete reservation fee'); + break; + + case 'illFeeDebt': + $str = t('Interlibrary fee'); + break; + + case 'smsReservationFeeDebt': + $str = t('SMS reservation fee'); + break; + + case 'smsReminderFeeDebt': + $str = t('SMS reminder fee'); + break; + + case 'smsRecall1FeeDebt': + $str = t('SMS first recall fee'); + break; + + case 'smsRecall2FeeDebt': + $str = t('SMS second recall fee'); + break; + + case 'smsRecall3FeeDebt': + $str = t('SMS third recall fee'); + break; + + case 'smsRecall4FeeDebt': + $str = t('SMS fourth recall fee'); + break; + + case 'smsRecall5FeeDebt': + $str = t('SMS fifth recall fee'); + break; + + case 'emailReminderFeeDebt': + $str = t('E-mail reminder fee'); + break; + + case 'otherFeeDebt': + $str = t('Unknown or other fee'); + break; + }; + + return $str; } diff --git a/includes/alma.loan.inc b/includes/alma.loan.inc index c5a0179..a349d9c 100644 --- a/includes/alma.loan.inc +++ b/includes/alma.loan.inc @@ -9,28 +9,47 @@ * * This functions finds all loans for a given user account and returns the loans * as DingProviderLoan objects. - * */ -function alma_loan_list($account) { +function alma_loan_list($account, $reset = FALSE) { + // Get creds is outside cache function as it may throw exception if the user + // is not longer logged in. $creds = ding_user_get_creds($account); - $results = array(); - try { - // Get all loans form alma for the user account given. - $loans = alma_client_invoke('get_loans', $creds['name'], $creds['pass']); - } catch (Exception $e) { - throw new DingProviderLoanUserError($e->getMessage()); - } + $results = &drupal_static(__FUNCTION__, FALSE); + if (!$results || $reset) { + // Check if ding_session_cache is available. + if (module_exists('ding_session_cache') && !$reset) { + $results = ding_session_cache_get('alma', 'loans'); + } - foreach ($loans as $loan) { - $results[$loan['id']] = new DingProviderLoan($loan['id'], array( - 'ding_entity_id' => variable_get('ting_agency', '') . ':' . $loan['record_id'], - 'loan_date' => $loan['loan_date'], - 'expiry' => $loan['due_date'], - 'renewable' => $loan['is_renewable'], - 'materials_number' => $loan['id'], - 'notes' => isset($loan['notes']) ? $loan['notes'] : DingEntityBase::NULL, - )); + // If both static cache and session cache failed, try reloading information + // from alma. + if (empty($results) || $reset) { + try { + // Get all loans form alma for the user account given. + $loans = alma_client_invoke('get_loans', $creds['name'], $creds['pass']); + } + catch (Exception $e) { + throw new DingProviderLoanUserError($e->getMessage()); + } + + $results = array(); + foreach ($loans as $loan) { + $results[$loan['id']] = new DingProviderLoan($loan['id'], array( + 'ding_entity_id' => ding_provider_build_entity_id($loan['record_id']), + 'loan_date' => $loan['loan_date'], + 'expiry' => $loan['due_date'], + 'renewable' => $loan['is_renewable'], + 'materials_number' => $loan['id'], + 'notes' => isset($loan['notes']) ? $loan['notes'] : DingEntityBase::NULL, + )); + } + + // Store the reservations into ding session cache. + if (module_exists('ding_session_cache')) { + ding_session_cache_set('alma', 'loans', $results); + } + } } return $results; @@ -49,13 +68,58 @@ function alma_loan_renew($account, $ids) { foreach ($ids as $id) { if (isset($res[$id]) && $res[$id] === TRUE) { $result[$id] = DingProviderLoan::STATUS_RENEWED; + + // Clear ding session cache. + if (module_exists('ding_session_cache')) { + ding_session_cache_clear('alma', 'loans'); + } } else { - /** - * @todo there are message saying why, the renew failed. - */ $result[$id] = DingProviderLoan::STATUS_NOT_RENEWED; } } + return $result; } + +/** + * Replace entity for the reservation. + * + * Should be used in the case object in not in Ting anymore or the reservation + * is an remote reservation. + * + * @param object $ting_entity + * Provider reservation object. + * + * @return object + * Ting entity object, filled with data from provider service. + */ +function alma_loan_populate_pseudo_entity($ting_entity) { + $alma_object = alma_client_invoke('catalogue_record_detail', $ting_entity->localId); + + if ($alma_object['request_status'] == 'ok' && isset($alma_object['records'][$ting_entity->localId])) { + $source = $alma_object['records'][$ting_entity->localId]; + + $ting_entity->reply->record['dc:title']['dkdcplus:full'] = array($source['titles'][0]); + $ting_entity->reply->record['dc:type']['dkdcplus:BibDK-Type'] = array($source['media_class']); + $ting_entity->reply->record['dc:date'][''] = array($source['publication_year']); + + // If it a ill Alma record authors are not always available. + if (isset($source['authors'])) { + $ting_entity->reply->record['dc:creator']['dkdcplus:aut'] = $source['authors']; + } + + // If it is an inter library loan (ill) Alma record isbn are not always + // available. + if (isset($source['isbns'][0])) { + $ting_entity->reply->record['dc:identifier']['dkdcplus:ISBN'][0] = str_replace(array('-', ' ', 'ISBN'), '', $source['isbns'][0]); + } + + $ting_entity->ting_title = array(LANGUAGE_NONE => array(array('id' => $ting_entity->ding_entity_id))); + $ting_entity->ting_type = array(LANGUAGE_NONE => array(array('id' => $ting_entity->ding_entity_id))); + $ting_entity->ting_author = array(LANGUAGE_NONE => array(array('id' => $ting_entity->ding_entity_id))); + $ting_entity->ting_cover = array(LANGUAGE_NONE => array(array('local_id' => $ting_entity->provider_id))); + } + + return $ting_entity; +} diff --git a/includes/alma.reservation.inc b/includes/alma.reservation.inc index 1692f31..8f1eeae 100644 --- a/includes/alma.reservation.inc +++ b/includes/alma.reservation.inc @@ -1,186 +1,294 @@ field_alma_preferred_branch->value(); + $interest_period = alma_reservation_default_interest_period($profile); + } - -function alma_reservation_options($type, $account, $reservables) { - /* - * While we use ding_reservation for branch handling, we don't want to - * depend on the module, as it would mean that ding_reservation can't be - * disabled. So instead we throw an exception here. - */ - - if (!module_exists('ding_reservation')) { - throw new Exception('Alma reservation options requires ding_reservation.'); - } + // Set default value in the selection box if given else use preferred_branch. + $default = $preferred_branch; + if (!empty($default_value)) { + $default = $default_value; + } $form = array(); - $profile = ding_user_provider_profile($account); - - $branches = alma_reservation_pickup_branches($account); - // @todo; use local branches from issue - some migth not be available in all branches - - if(ding_user_is_provider_user($account)) { - $preferred_branch = $profile->alma_preferred_branch[field_language('profile2', $profile, 'alma_preferred_branch')][0]['value']; - } - else { - $preferred_branch = NULL; - } - - $form += ding_reservation_default_options_branch($type, 'alma_preferred_branch',$preferred_branch, $branches); + $form += ding_reservation_default_options_branch('alma_preferred_branch', $default, $branches); + $form += ding_reservation_interest_period_selector('interest_period', $interest_period, $periods); return $form; } - /** * Validate reservations options. + * + * @param stdClass $account + * Drupal user account object. + * + * @return array + * The interest period and default pick-up branch from the provider profile. */ -function alma_reservation_options_validate($type, $account, $reservables, $values) { - $result = array(); +function alma_reservation_default_options($account) { + // Load profile2 profile. $profile = ding_user_provider_profile($account); - $field_language = field_language('profile2', $profile); - $profile_branch = $profile->alma_preferred_branch[$field_language['alma_preferred_branch']][0]['value']; - return ding_reservation_default_options_branch_validate($type, 'alma_preferred_branch', $profile_branch, $values); + + // Use a metadata wrapper to access the data. + $wrapper = entity_metadata_wrapper('profile2', $profile); + + // Get values. + $preferred_branch = $wrapper->field_alma_preferred_branch->value();; + $interest_period = $wrapper->field_alma_interest_period->value(); + + $result = array( + 'alma_preferred_branch' => $preferred_branch, + 'interest_period' => $interest_period, + ); + + return $result; } /** * Submit handler for reservations options. + * + * @param stdClass $account + * Drupal user account object. + * @param array $values + * The values that should be submitted (@todo needs better description). */ -function alma_reservation_options_submit($type, $account, $reservables, $values) { +function alma_reservation_options_submit($account, $values) { + // Load profile2 profile. $profile = ding_user_provider_profile($account); - $field_language = field_language('profile2', $profile); - $profile_branch = $profile->alma_preferred_branch[$field_language['alma_preferred_branch']][0]['value']; - $update = ding_reservation_default_options_branch_submit($type, 'alma_preferred_branch', $profile_branch, $values); - if (!empty($update['alma_preferred_branch'])) { - $profile->alma_preferred_branch[$field_language['alma_preferred_branch']][0]['value'] = $update['alma_preferred_branch']; + + // Use a metadata wrapper to access the data. + $wrapper = entity_metadata_wrapper('profile2', $profile); + + // Get values. + $preferred_branch = $wrapper->field_alma_preferred_branch->value(); + + // If default branch was not found in the profile, update the profile with the + // one selected. + if (!$preferred_branch) { + $wrapper->field_alma_preferred_branch->set($values['alma_preferred_branch']); $profile->save(); } } /** - * Set preferred pickup branch + * Get list of reserved items index by reservation type. + * + * @param stdClass $account + * Drupal user account object. + * @param string $type + * Reservation type to return. The sting should be one of + * 'DING_RESERVATION_READY', 'DING_RESERVATION_NOT_READY' or + * 'DING_RESERVATION_INTERLIBRARY_LOANS'. + * + * @return array + * An empty array or an array of DingProviderReservation objects. */ -function alma_reservation_set_preferred_branch($account, $branch) { - // Throws an exception if we are not logged in. - $creds = ding_user_get_creds($account); +function alma_reservation_list($account, $type = NULL) { + // Use a static cache to speed up the process of getting reservations from + // alma, when call more than once in a single HTTP request. + $result = &drupal_static(__FUNCTION__); + if (!isset($result)) { + // Check if ding_session_cache is available. + if (module_exists('ding_session_cache')) { + $result = ding_session_cache_get('alma', 'reservations'); + } - /** - * @todo Should call alma an update the branch in the library system (not sure - * if branch has the right format). - */ - //alma_client_invoke('get_reservations', $creds['name'], $creds['pass'], $branch); -} + // If both static cache and session cache failed, try reloading information + // from alma. + if (empty($result)) { + // Set default reservation types. + $result = array( + DING_RESERVATION_READY => array(), + DING_RESERVATION_NOT_READY => array(), + DING_RESERVATION_INTERLIBRARY_LOANS => array(), + ); -/** - * Get list of reserved items. - */ -function alma_reservation_list($account) { - $creds = ding_user_get_creds($account); - $reservations = alma_reservation_get_reservations($account); - $result = array(); - - // Create DingProviderReservation objects into to categories base on pickup - // status. - foreach ($reservations as $reservation) { - if (isset($reservation['pickup_number'])) { - $result[$reservation['id']] = new DingProviderReservation($reservation['id'], array( - 'order_id' => $reservation['id'], - 'ding_entity_id' => variable_get('ting_agency', '') . ':' . $reservation['record_id'], - 'pickup_branch_id' => $reservation['pickup_branch'], - 'pickup_order_id' => $reservation['pickup_number'], - 'pickup_date' => $reservation['pickup_expire_date'], - 'created' => $reservation['create_date'], - 'expiry' => $reservation['valid_to'], - 'queue_number' => $reservation['queue_number'], - 'ready_for_pickup' => 1, - )); + // Get reservations from ALMA for the current account. + $reservations = alma_reservation_get_reservations($account); + + // Create DingProviderReservation objects into three categories. + foreach ($reservations as $reservation) { + // Build standard array which matches all types of reservations. + $data = array( + 'order_id' => $reservation['id'], + 'ding_entity_id' => ding_provider_build_entity_id($reservation['record_id']), + 'pickup_branch_id' => $reservation['pickup_branch'], + 'order_arrived' => NULL, + 'pickup_order_id' => NULL, + 'pickup_date' => NULL, + 'ready_for_pickup' => FALSE, + 'created' => $reservation['create_date'], + 'expiry' => $reservation['valid_to'], + 'queue_number' => $reservation['queue_number'], + 'ill_status' => FALSE, + 'notes' => isset($reservation['notes']) ? $reservation['notes'] : '', + 'reservation_type' => DING_RESERVATION_NOT_READY, + ); + + // If the reservation is ready for pick-up, we fill in that data. + if (isset($reservation['pickup_number'])) { + // Set pick-up information. + $data['pickup_order_id'] = $reservation['pickup_number']; + $data['pickup_date'] = $reservation['pickup_expire_date']; + $data['ready_for_pickup'] = TRUE; + $data['reservation_type'] = DING_RESERVATION_READY; + + // Ready for pick-up can also be a inter-library loan. + if ($reservation['id'] < 0) { + // Inter-library loan reservations have negative IDs (undocumented + // Axiell "feature"). + $data['ill_status'] = TRUE; + } + + // Create reservation object. + $result[DING_RESERVATION_READY][$reservation['id']] = new DingProviderReservation($reservation['id'], $data); + } + elseif ($reservation['id'] < 0) { + // Inter-library loan reservations have negative IDs (undocumented + // Axiell "feature"). + $data['ill_status'] = $reservation['status']; + $data['reservation_type'] = DING_RESERVATION_INTERLIBRARY_LOANS; + + // Create reservation object. + $result[DING_RESERVATION_INTERLIBRARY_LOANS][$reservation['id']] = new DingProviderReservation($reservation['id'], $data); + } + else { + // Default case with, so just create the reservation object. + $result[DING_RESERVATION_NOT_READY][$reservation['id']] = new DingProviderReservation($reservation['id'], $data); + } + } + + // Store the reservations into ding session cache. + if (module_exists('ding_session_cache')) { + ding_session_cache_set('alma', 'reservations', $result); + } + } + } + + if (!is_null($type)) { + if (isset($result[$type])) { + return $result[$type]; } else { - $result[$reservation['id']] = new DingProviderReservation($reservation['id'], array( - 'order_id' => $reservation['id'], - 'ding_entity_id' => variable_get('ting_agency', '') . ':' . $reservation['record_id'], - 'pickup_branch_id' => $reservation['pickup_branch'], - 'created' => $reservation['create_date'], - 'expiry' => $reservation['valid_to'], - 'queue_number' => $reservation['queue_number'], - 'ready_for_pickup' => 0, - )); + watchdog('alma', 'Unknown reservation type (%type) requested', array('%type' => $type), WATCHDOG_ERROR); + return array(); } } return $result; } - /** - * Create a reservation for a given account. +/** + * Create a new reservation in the library system. + * + * @param stdClass $account + * @param string $id + * @param array $options + * @param string $expiry + * + * @return array + * + * @throws DingProviderReservationExists + * @throws DingProviderReservationNotAllowed + * @throws DingProviderReservationNotAvailable */ -function alma_reservation_create($account, $id, $branch, $expiry=null) { +function alma_reservation_create($account, $id, $options = array(), $expiry = NULL) { $creds = ding_user_get_creds($account); + // Check if the users has this reservation and throw exception. - //if (alma_reservation_exists($creds, $id)) { - if( alma_reservation_exists($account, $id) ){ + if (alma_reservation_exists($account, $id)) { throw new DingProviderReservationExists(); } - $profile2 = profile2_load_by_user($account,'provider_alma'); - if( !empty($profile2) ) { - // interest period - if( !isset($expiry) ) { - // get interest period from profile2 - $interest_period = alma_get_interest_period($profile2); - if( $interest_period ){ - $expiry = REQUEST_TIME + ($interest_period['key'] * 24 * 60 * 60 ); - } - } - if( !isset($expiry) ) { - $expiry = REQUEST_TIME + DING_RESERVATION_DEFAULT_INTEREST_PERIOD; + $entity = ding_user_provider_profile($account);; + if (!empty($entity)) { + $wrapper = entity_metadata_wrapper('profile2', $entity); + + // Interest period. + if (!isset($options['interest_period'])) { + if (!isset($expiry)) { + // Use a metadata wrapper to access the data. + $interest_period = $wrapper->field_alma_interest_period->value(); + if ($interest_period) { + // Change it to seconds from days. + $expiry = $interest_period * 86400; + } + } + else { + // The user don't have a default interest period, so use the system wide + // one for alma (which default is 180 days). + $expiry = variable_get('alma_default_interest_period', 180) * 86400; + } + } + else { + $expiry = $options['interest_period'] * 86400; } - // preferred branch - if( empty($branch) ) { - $pref_branch = alma_get_preferred_branch($profile2); - if( $pref_branch ){ - $branches = alma_reservation_pickup_branches(); - foreach($branches as $key => $val){ - if( $val == $pref_branch ) { - $branch = $key; - break; - } - } - } + // Preferred branch. + $branch = $wrapper->field_alma_preferred_branch->value(); + if (isset($options['alma_preferred_branch'])) { + $branch = $options['alma_preferred_branch']; } } // Build the reservation parameters to send. $params = array( 'id' => $id, - 'valid_from' => date('Y-m-d'), - 'valid_to' => alma_reservation_format_date($expiry), + 'valid_from' => date(ALMA_DATE), + 'valid_to' => alma_reservation_format_date(time() + $expiry), 'pickup_branch' => $branch, ); + // Clear the local alma cache. alma_reservation_clear_cache(); + // Try to make the reservation. $result = alma_client_invoke('add_reservation', $creds['name'], $creds['pass'], $params); if ($result === ALMA_AUTH_BLOCKED) { - /** - * @todo return better exception that informs the user about the block - * status. - */ + // @todo return better exception that informs the user about the block + // status. throw new DingProviderReservationNotAllowed(); } if (is_int($result)) { - // Reset session cache + // Reset session cache. alma_reservation_clear_cache(); return array( + 'branch' => $branch, 'queue_number' => $result, ); } @@ -191,13 +299,22 @@ function alma_reservation_create($account, $id, $branch, $expiry=null) { /** * Update order, by defining new expiry date or pickup branch. + * + * @param stdClass $account + * @param array $ids + * @param array $options + * + * @return bool */ function alma_reservation_update($account, $ids, $options) { $creds = ding_user_get_creds($account); $reservations = alma_reservation_get_reservations($account); - foreach($ids as $id) { + $updated = FALSE; + + // Processing IDs. If at least one is updated, return true. + foreach ($ids as $id) { if (isset($reservations[$id])) { - $expiry_date = !empty($options['expiry']) ? alma_reservation_format_date($options['expiry']) : $reservations[$id]['valid_to']; + $expiry_date = !empty($options['interest_period']) ? alma_reservation_format_date(strtotime($reservations[$id]['valid_from']) + $options['interest_period'] * 86400) : $reservations[$id]['valid_to']; $pickup_branch = !empty($options['alma_preferred_branch']) ? $options['alma_preferred_branch'] : $reservations[$id]['pickup_branch']; $changes = array( 'valid_to' => $expiry_date, @@ -205,72 +322,162 @@ function alma_reservation_update($account, $ids, $options) { ); // Alma do not return a status. alma_client_invoke('change_reservation', $creds['name'], $creds['pass'], $reservations[$id], $changes); + $updated = TRUE; } + } + + // Clear cache after all reservations have been updated. + if ($updated) { alma_reservation_clear_cache(); - return TRUE; } - return FALSE; + return $updated; } /** * Delete a reservation for a given account. + * + * @param stdClass $account + * @param string $id + * + * @return type */ function alma_reservation_delete($account, $id) { $creds = ding_user_get_creds($account); $reservations = alma_reservation_get_reservations($account); - + alma_reservation_clear_cache(); - if( isset($reservations[$id]) ) { - return alma_client_invoke('remove_reservation', $creds['name'], $creds['pass'], $reservations[$id]); + if (isset($reservations[(string) $id])) { + return alma_client_invoke('remove_reservation', $creds['name'], $creds['pass'], $reservations[(string) $id]); } } +/** + * Implements hook_default_interest_period(). + * + * Tries to find the users default interest period based on the users profile2 + * provider profile. + * + * @param object $profile + * The users profile2 provider profile. + * + * @return string + * The default interest period selected by the user in his/her profile or the + * default value selected by the site. + */ +function alma_reservation_default_interest_period($profile = NULL) { + // If profile is not given, try loading it for the user. + if (is_null($profile)) { + global $user; + $profile = ding_user_provider_profile($user); + } + + // Get interest period from the profile. + $wrapper = entity_metadata_wrapper('profile2', $profile); + $value = $wrapper->field_alma_interest_period->value(); + + // If no period is selected, try getting default value. + if (is_null($value) || empty($value)) { + $value = variable_get('alma_default_interest_period', 180); + } + + return $value; +} + +/** + * Implements hook_reservation_deletion_enabled(). + * + * Check where reservation deletion have been enabled in the providers settings. + * + * @return bool + * If enabled TRUE else FALSE. + */ +function alma_reservation_reservation_deletion_enabled() { + return variable_get('alma_enable_reservation_deletion', FALSE); +} + /** * Return a branch name for a given branch id. * - * @param $branch_id String - * @return String + * @param string $branch_id + * The identifier for a given pick-up branch (e.g. hb) + * + * @return string + * The human name for the id or NULL if one do not exist. */ function alma_reservation_branch_name($branch_id) { - // Get library organistation from alma. + // Get library organization from alma. $organisation = alma_get_organisation(); - if (isset($organisation['branch'][$branch_id])) { - return $organisation['branch'][$branch_id]; + $branch = (is_array($branch_id) && isset($branch_id['alma_preferred_branch'])) ? $branch_id['alma_preferred_branch'] : $branch_id; + if (isset($organisation['branch'][$branch])) { + return $organisation['branch'][$branch]; } return NULL; } -/********************************** - * Helper functions +/** + * Get all reservation from Alma and store them in the cache. + * + * @param stdClass $account + * Drupal user account object. + * + * @param bool $reset + * If TRUE the cache will be by-passed. + * + * @return mixed + * Alma reservations. */ - function alma_reservation_get_reservations($account, $reset = FALSE) { $creds = ding_user_get_creds($account); - // Try to look in the session for reservation information. - if (!isset($_SESSION['alma_reservations']) || !is_array($_SESSION['alma_reservations']) || $reset) { - $_SESSION['alma_reservations'] = alma_client_invoke('get_reservations', $creds['name'], $creds['pass']); + $reservations = &drupal_static(__FUNCTION__, FALSE); + if (!$reservations || $reset) { + $reservations = alma_client_invoke('get_reservations', $creds['name'], $creds['pass']); } - return $_SESSION['alma_reservations']; + return $reservations; } +/** + * Clear reservations stored in the current session cache. + */ function alma_reservation_clear_cache() { - unset($_SESSION['alma_reservations']); + // Check if ding_session_cache is available. + if (module_exists('ding_session_cache')) { + ding_session_cache_clear('alma', 'reservations'); + } } -function alma_reservation_exists($account, $item_id) { - $reservations = alma_reservation_get_reservations( $account ); +/** + * Check if a reservation exists at the provider (ALMA). + * + * @param stdClass $account + * Drupal user account object. + * @param string $reservation_id + * The id of the reservation to test for. + * + * @return bool + * TRUE if the reservation exists else FALSE. + */ +function alma_reservation_exists($account, $reservation_id) { + $reservations = alma_reservation_get_reservations($account); foreach ($reservations as $res) { - if ($res['record_id'] == $item_id) { + if ($res['record_id'] == $reservation_id) { return TRUE; } - return FALSE; } + return FALSE; } -function alma_reservation_format_date($datetime) { - $timestamp = (!is_int($datetime)) ? strtotime($datetime) : $datetime; - return date('Y-m-d', $timestamp); +/** + * Helper function calculate the date in the feature base on interest period. + * + * @param int $expiry + * The number of seconds into the feature we need at date. + * + * @return string + * The date in the feature in the format 'Y-m-d' (ALMA_DATE). + */ +function alma_reservation_format_date($expiry) { + return date(ALMA_DATE, $expiry); } diff --git a/includes/alma.user.inc b/includes/alma.user.inc index 304a3b6..98addb4 100644 --- a/includes/alma.user.inc +++ b/includes/alma.user.inc @@ -1,10 +1,14 @@ $name - * @param $pass + * @param string $uid + * @param string $pass */ function alma_user_authenticate($uid, $pass) { $return = array( @@ -13,16 +17,16 @@ function alma_user_authenticate($uid, $pass) { try { $res = alma_client_invoke('get_patron_info', $uid, $pass, TRUE); - $return['success'] = TRUE; + if ($res) { + $return['success'] = TRUE; + } } catch (Exception $e) { return $return; } - // @todo Check block status. - // Set creds. - $return['creds'] = array ( + $return['creds'] = array( 'name' => $uid, 'pass' => $pass, ); @@ -54,9 +58,30 @@ function alma_user_authenticate($uid, $pass) { ); } + // Set the users categories. + if (!empty($res['category'])) { + $return['user']['category'] = $res['category']; + } + + $return['user']['blocked'] = FALSE; + if (!empty($res['blocks'])) { + // Send block codes back with the user. + $return['user']['blocks'] = $res['blocks']; + $return['user']['blocked'] = TRUE; + } + return $return; } +/** + * Check if the user creds is set correctly. + * + * @param array $creds + * Array with the user credentials. + * + * @return bool + * TRUE if user is authenticated else FALSE + */ function alma_user_is_authenticated($creds) { return (isset($creds['name']) && isset($creds['pass'])); } @@ -68,78 +93,44 @@ function alma_user_profile_form_validate($form, $form_state) { } - -function alma_user_clear_cache($creds=NULL) { - $status = alma_get_patron(); -} - - /** - * Update profile2 with values from alma patron - */ - -function alma_user_profile_init( $profile2, $auth_res ){ - $creds = ding_user_get_creds($profile2); - $patron = alma_get_patron($creds); - - // reservation pause (absentPeriod) - // apparently alma supports multiple absentPeriods, but for now we handle one only (the first found) - // @todo - check if it's correct to handle the first only - $langs = field_language('profile2', $profile2); - // reservation pause - if( isset($patron->absentPeriods[0]['from_date']) && isset($patron->absentPeriods[0]['to_date'] ) ) { - $profile2->field_alma_reservation_pause[$langs['field_alma_reservation_pause']][0]['value'] = $patron->absentPeriods[0]['from_date']; - $profile2->field_alma_reservation_pause[$langs['field_alma_reservation_pause']][0]['value2'] = $patron->absentPeriods[0]['to_date']; - $profile2->field_absent_id[$langs['field_absent_id']][0]['value'] = $patron->absentPeriods[0]['id']; - } - else { - $profile2->field_reservation_pause[$langs['field_alma_reservation_pause']][0]['value'] = ' '; - $profile2->field_reservation_pause[$langs['field_alma_reservation_pause']][0]['value2'] = ' '; - } - - // preferred_branch - $profile2->field_alma_preferred_branch[$langs['field_alma_preferred_branch']][0]['value'] = $patron->branch; - - //mobile; also here alma supports multiple phones - again we pick the first - $profile2->field_alma_mobile_phone[$langs['field_alma_mobile_phone']][0]['value'] = isset($patron->mobiles[0]['phone']) ? $patron->mobiles[0]['phone'] : ''; - $profile2->field_alma_phone_id[$langs['field_alma_phone_id']][0]['value'] = isset($patron->mobiles[0]['id']) ? $patron->mobiles[0]['id'] : null; - //$profile2->field_alma_phone_id[$langs['field_alma_phone_id']][0]['value'] = isset() .. etc - - // handle init parameter in alma.module/alma_profile2_presave - $profile2->alma_init = TRUE; - $profile2->save(); - unset($profile2->alma_init); -} - -/** - * update provider user; - * @invoked from: ding_user/ding_user_user_presave - * possible changes; email, pincode, preferred_branch + * Update pin code at alma. + * + * @param object $account + * User account object or the user provider profile2. + * @param string $new_pincode + * The users new pin-code. + * + * @return array + * Updated credential array. */ -function alma_user_account_update($account, $changes) { +function alma_user_update_pincode($account, $new_pincode) { $creds = ding_user_get_creds($account); - if( isset($changes['mail']) ) { - // add email - if( empty( $account->mail ) && !empty($changes['mail'] ) ) { - $res = alma_client_invoke('add_email_address', $creds['name'], $creds['pass'], $changes['mail']); - } - // change email - elseif( isset( $account->mail ) && !empty($changes['mail'] ) ){ - $res = alma_client_invoke('change_email_address', $creds['name'], $creds['pass'], $account->mail, $changes['mail']); - } - } - - // change password - if (isset($changes['pass'])) { - $res = alma_client_invoke('change_pin', $creds['name'], $creds['pass'], $changes['pass']); - if( $res ) { + // Change the users pin code.. + if (isset($new_pincode)) { + $res = alma_client_invoke('change_pin', $creds['name'], $creds['pass'], $new_pincode); + if ($res) { // @see ding_user.module/ding_user_user_presave // Set new password. - $creds['pass'] = $changes['pass']; + $creds['pass'] = $new_pincode; + // Update creds. + $result = array(); $result['creds'] = $creds; return $result; } } } + +/** + * Implements clear_cache(). + * + * This hook is only called from ding_dibs after a payment have been accepted. + * + * @param stdClass $account + * Drupal user account object. + */ +function alma_user_clear_cache($account) { + // As the ALMA currently only uses a static cache for debt... do nothing. +} diff --git a/includes/alma.wayf.inc b/includes/alma.wayf.inc new file mode 100644 index 0000000..fa477a4 --- /dev/null +++ b/includes/alma.wayf.inc @@ -0,0 +1,42 @@ + $authentication_attributes['schacPersonalUniqueID'], + 'pass' => $hash, + ); + } + else { + // Set message that hash value was not found. + watchdog('alma', 'The WAYF hash value has not been set in setting.php as $conf[\'wayf_hash\'] and WAYF login will fail.', WATCHDOG_ERROR); + } + + return $credentials; +} + +/** + * Implements hook_wayf_attributes(). + * + * Used to define which attribute to use as login name. + */ +function alma_wayf_attributes() { + return array( + 'schacPersonalUniqueID' => array( + 'field' => 'CPR', + ), + ); +} diff --git a/lib/AlmaClient/AlmaClient.class.php b/lib/AlmaClient/AlmaClient.class.php index b6f77bd..060bcf0 100644 --- a/lib/AlmaClient/AlmaClient.class.php +++ b/lib/AlmaClient/AlmaClient.class.php @@ -26,7 +26,7 @@ class AlmaClient { /** * Constructor, checking if we have a sensible value for $base_url. */ - function __construct($base_url) { + public function __construct($base_url) { if (stripos($base_url, 'http') === 0 && filter_var($base_url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED)) { $this->base_url = $base_url; } @@ -46,28 +46,30 @@ function __construct($base_url) { * are required for all request related to library patrons. * @param array $params * Query string parameters in the form of key => value. - * @param boolean $check_status + * @param bool $check_status * Check the status element, and throw an exception if it is not ok. + * * @return DOMDocument * A DOMDocument object with the response. */ public function request($method, $params = array(), $check_status = TRUE) { - $startTime = explode(' ', microtime()); + $start_time = explode(' ', microtime()); // For use with a non-Drupal-system, we should have a way to swap // the HTTP client out. - $request = drupal_http_request(url($this->base_url . $method, array('query' => $params))); - $stopTime = explode(' ', microtime()); + $request = drupal_http_request(url($this->base_url . $method, array('query' => $params)), array('secure_socket_transport' => 'sslv3')); + $stop_time = explode(' ', microtime()); // For use with a non-Drupal-system, we should have a way to swap // logging and logging preferences out. if (variable_get('alma_enable_logging', FALSE)) { - $seconds = floatval(($stopTime[1]+$stopTime[0]) - ($startTime[1]+$startTime[0])); - - // Filter params to avoid logging sensitive data. - // This can be disabled by setting alma_logging_filter_params = 0. There is no UI for setting this variable + $seconds = floatval(($stop_time[1] + $stop_time[0]) - ($start_time[1] + $start_time[0])); + + // Filter params to avoid logging sensitive data. + // This can be disabled by setting alma_logging_filter_params = 0. There + // is no UI for setting this variable // It is intended for settings.php in development environments only. $params = (variable_get('alma_logging_filter_params', 1)) ? self::filter_request_params($params) : $params; - // Log the request + // Log the request. watchdog('alma', 'Sent request: @url (@seconds s)', array('@url' => url($this->base_url . $method, array('query' => $params)), '@seconds' => $seconds), WATCHDOG_DEBUG); } @@ -82,14 +84,14 @@ public function request($method, $params = array(), $check_status = TRUE) { } else { $message = $doc->getElementsByTagName('status')->item(0)->getAttribute('key'); - switch($message) { + switch ($message) { case '': case 'borrCardNotFound': throw new AlmaClientBorrCardNotFound('Invalid borrower credentials'); - break; + case 'reservationNotFound': throw new AlmaClientReservationNotFound('Reservation not found'); - break; + default: throw new AlmaClientCommunicationError('Status is not okay: ' . $message); } @@ -101,29 +103,37 @@ public function request($method, $params = array(), $check_status = TRUE) { } /** - * Filters sensitive information in request parameters allowing the values to be logged + * Filters sensitive information in request parameters allowing the values to + * be logged. * - * @param array $params An array of request information + * @param array $params + * An array of request information * * @return array - * An array of filtered request information + * An array of filtered request information */ private static function filter_request_params($params) { - // Scramble sensitive information - $sensitive = array('borrCard', 'pinCode','pinCodeChange', 'address', 'emailAddress'); - - $log_params = array(); - foreach ($params as $key => $value) { - if (in_array($key, $sensitive)) { - // Replace the value with a scrambled version generated using md5() and - // the static salt. This way all requests generated by the same page - // load can be grouped - $value = substr(md5($value.self::$salt), 0, strlen($value)); - } - $log_params[$key] = $value; + // Scramble sensitive information + $sensitive = array( + 'borrCard', + 'pinCode', + 'pinCodeChange', + 'address', + 'emailAddress', + ); + + $log_params = array(); + foreach ($params as $key => $value) { + if (in_array($key, $sensitive)) { + // Replace the value with a scrambled version generated using md5() and + // the static salt. This way all requests generated by the same page + // load can be grouped. + $value = substr(md5($value . self::$salt), 0, strlen($value)); } + $log_params[$key] = $value; + } - return $log_params; + return $log_params; } /** @@ -132,7 +142,7 @@ private static function filter_request_params($params) { * Formats the list of branches in an array usable for form API selects. * * @return array - * List of branches, keyed by branch_id + * List of branches, keyed by branch_id. */ public function get_branches() { $branches = array(); @@ -151,7 +161,7 @@ public function get_branches() { * Formats the list of branches in an array usable for form API selects. * * @return array - * List of branches, keyed by branch_id + * List of branches, keyed by branch_id */ public function get_reservation_branches() { $branches = array(); @@ -169,7 +179,7 @@ public function get_reservation_branches() { * Formats the list of branches in an array usable for form API selects. * * @return array - * List of departments, keyed by department id. + * List of departments, keyed by department id. */ public function get_departments() { $departments = array(); @@ -188,7 +198,7 @@ public function get_departments() { * Formats the list of branches in an array usable for form API selects. * * @return array - * List of locations, keyed by location id. + * List of locations, keyed by location id. */ public function get_locations() { $locations = array(); @@ -202,12 +212,12 @@ public function get_locations() { } /** - * Get sublocation names from Alma. + * Get sub location names from Alma. * * Formats the list of branches in an array usable for form API selects. * * @return array - * List of sublocations, keyed by sublocation id. + * List of sub locations, keyed by sub location id. */ public function get_sublocations() { $sublocations = array(); @@ -226,7 +236,7 @@ public function get_sublocations() { * Formats the list of branches in an array usable for form API selects. * * @return array - * List of collections, keyed by collection id. + * List of collections, keyed by collection id. */ public function get_collections() { $collections = array(); @@ -256,6 +266,7 @@ public function get_patron_info($borr_card, $pin_code, $extended = FALSE) { 'addresses' => array(), 'mails' => array(), 'phones' => array(), + 'category' => $info->getAttribute('patronCategory'), ); foreach ($info->getElementsByTagName('address') as $address) { @@ -336,7 +347,7 @@ public function get_reservations($borr_card, $pin_code) { } if ($reservation['status'] == 'fetchable') { - $reservation['pickup_number'] = (integer) $item->getAttribute('pickUpNo'); + $reservation['pickup_number'] = $item->getAttribute('pickUpNo'); $reservation['pickup_expire_date'] = $item->getAttribute('pickUpExpireDate'); } @@ -391,7 +402,7 @@ private static function loan_sort($a, $b) { * Get patron's debts. */ public function get_debts($borr_card, $pin_code) { - + $doc = $this->request('patron/debts', array('borrCard' => $borr_card, 'pinCode' => $pin_code)); $data = array( @@ -402,7 +413,7 @@ public function get_debts($borr_card, $pin_code) { if ($debts_attr = $doc->getElementsByTagName('debts')->item(0)) { $data['total_formatted'] = $debts_attr->getAttribute('totalDebtAmountFormatted'); } - + foreach ($doc->getElementsByTagName('debt') as $item) { $id = $item->getAttribute('debtId'); $data['debts'][$id] = array( @@ -427,7 +438,7 @@ public function add_reservation($borr_card, $pin_code, $reservation) { $params = array( 'borrCard' => $borr_card, 'pinCode' => $pin_code, - 'reservable' => $reservation['id'], + 'reservable' => rawurlencode($reservation['id']), 'reservationPickUpBranch' => $reservation['pickup_branch'], 'reservationValidFrom' => $reservation['valid_from'], 'reservationValidTo' => $reservation['valid_to'], @@ -435,7 +446,7 @@ public function add_reservation($borr_card, $pin_code, $reservation) { // If there's not a validFrom date, set it as today. if (empty($params['reservationValidFrom'])) { - $params['reservationValidFrom'] = date('Y-m-d', $_SERVER['REQUEST_TIME']); + $params['reservationValidFrom'] = date(ALMA_DATE, $_SERVER['REQUEST_TIME']); } // If there's not a validTo date, set it a year in the future. @@ -447,7 +458,7 @@ public function add_reservation($borr_card, $pin_code, $reservation) { $doc = $this->request('patron/reservations/add', $params); $res_status = $doc->getElementsByTagName('reservationStatus')->item(0)->getAttribute('value'); $res_message = $doc->getElementsByTagName('reservationStatus')->item(0)->getAttribute('key'); - $queue_number = (int)$doc->getElementsByTagName('reservation')->item(0)->getAttribute('queueNo'); + $queue_number = (int) $doc->getElementsByTagName('reservation')->item(0)->getAttribute('queueNo'); // Return error code when patron is blocked. if ($res_message == 'reservationPatronBlocked') { @@ -519,9 +530,9 @@ public function renew_loan($borr_card, $pin_code, $loan_ids) { ); $doc = $this->request('patron/loans/renew', $params); - - //Built return array as specified by Ding loan provider. - //See ding_provider_example_loan_renew_loans(). + + // Built return array as specified by Ding loan provider. + // See ding_provider_example_loan_renew_loans(). $reservations = array(); foreach ($doc->getElementsByTagName('loan') as $loan) { $id = $loan->getAttribute('id'); @@ -529,22 +540,28 @@ public function renew_loan($borr_card, $pin_code, $loan_ids) { if ($renewable = $loan->getElementsByTagName('loanIsRenewable')->item(0)) { $message = $renewable->getAttribute('message'); $renewable = $renewable->getAttribute('value'); - //If message is "isRenewedToday" we assumme that the renewal is successful. - //Even if this is not the case any error in the current renewal is irrelevant - //as the loan has previously been renewed so don't report it as such - if ($message == 'isRenewedToday' || $renewable == 'yes') { - $reservations[$id] = TRUE; - } elseif ($message == 'maxNofRenewals') { + // If message is "isRenewedToday" we assume that the renewal is + // successful. Even if this is not the case any error in the current + // renewal is irrelevant as the loan has previously been renewed so + // don't report it as such. + // Also renewalIsDenied marked as 'no' is considered a successful + // renewal. + if ($message == 'isRenewedToday' || $renewable == 'yes' || ($message == 'renewalIsDenied' && $renewable == 'no')) { + $reservations[$id] = TRUE; + } + elseif ($message == 'maxNofRenewals') { $reservations[$id] = t('Maximum number of renewals reached'); - } elseif ($message == 'copyIsReserved') { + } + elseif ($message == 'copyIsReserved') { $reservations[$id] = t('The material is reserved by another loaner'); - } else { + } + else { $reservations[$id] = t('Unable to renew material'); } } } } - + return $reservations; } @@ -656,6 +673,7 @@ public function catalogue_record_detail($alma_ids) { 'request_status' => $doc->getElementsByTagName('status')->item(0)->getAttribute('value'), 'records' => array(), ); + foreach ($doc->getElementsByTagName('detailCatalogueRecord') as $elem) { $record = AlmaClient::process_catalogue_record_details($elem); $data['records'][$record['alma_id']] = $record; @@ -713,13 +731,20 @@ private static function process_catalogue_record_details($elem) { if ($record['media_class'] != 'periodical') { $record['holdings'] = AlmaClient::process_catalogue_record_holdings($elem); } - // Periodicals are nested holdings, which we want to keep that way. else { + // Periodicals are nested holdings, which we want to keep that way. foreach ($elem->getElementsByTagName('compositeHoldings') as $holdings) { foreach ($holdings->childNodes as $year_holdings) { $year = $year_holdings->getAttribute('value'); foreach ($year_holdings->childNodes as $issue_holdings) { $issue = $issue_holdings->getAttribute('value'); + + // If this is a yearly publication it do not have issues. + if (empty($issue)) { + // So we set the issue to index as a single element. + $issue = 0; + } + $holdings = AlmaClient::process_catalogue_record_holdings($issue_holdings); $record['holdings'][$year][$issue] = $holdings; $issue_list = array( @@ -740,7 +765,6 @@ private static function process_catalogue_record_details($elem) { } } } - $record['issues'][$year][$issue] = $issue_list; } } @@ -760,6 +784,7 @@ private static function process_catalogue_record_holdings($elem) { $holdings[] = array( 'reservable' => $item->getAttribute('reservable'), 'status' => $item->getAttribute('status'), + 'show_reservation_button' => $item->getAttribute('showReservationButton'), 'ordered_count' => (int) $item->getAttribute('nofOrdered'), 'checked_out_count' => (int) $item->getAttribute('nofCheckedOut'), 'reference_count' => (int) $item->getAttribute('nofReference'), @@ -776,7 +801,6 @@ private static function process_catalogue_record_holdings($elem) { ); } - return $holdings; } @@ -787,7 +811,10 @@ public function get_availability($alma_ids) { $data = array(); $doc = $this->request('catalogue/availability', array('catalogueRecordKey' => $alma_ids)); foreach ($doc->getElementsByTagName('catalogueRecord') as $record) { - $data[$record->getAttribute('id')] = ($record->getAttribute('isAvailable') == 'yes') ? TRUE : FALSE; + $data[$record->getAttribute('id')] = array( + 'reservable' => ($record->getAttribute('isReservable') == 'true') ? TRUE : FALSE, + 'available' => ($record->getAttribute('isAvailable') == 'yes') ? TRUE : FALSE, + ); } return $data; } @@ -810,12 +837,12 @@ public function add_payment($debt_ids, $order_id = NULL) { * Change user’s preferred branch. * * @param string $borr_card - * Library patron's borrowing card number. Either just an arbitrary - * number printed on their library card or their CPR-code. + * Library patron's borrowing card number. Either just an arbitrary + * number printed on their library card or their CPR-code. * @param string $pin_code - * Library patron's current four digit PIN code. + * Library patron's current four digit PIN code. * @param string $branch_code - * New preferred branch. + * New preferred branch. */ public function change_patron_preferences($borr_card, $pin_code, $branch_code) { $params = array( @@ -832,14 +859,14 @@ public function change_patron_preferences($borr_card, $pin_code, $branch_code) { * Add an Alma absent period. * * @param string $borr_card - * Library patron's borrowing card number. Either just an arbitrary - * number printed on their library card or their CPR-code. + * Library patron's borrowing card number. Either just an arbitrary + * number printed on their library card or their CPR-code. * @param string $pin_code - * Library patron's current four digit PIN code. + * Library patron's current four digit PIN code. * @param string $from_date - * Absent period start date. + * Absent period start date. * @param string $to_date - * Absent period start date. + * Absent period start date. */ public function add_absent_period($borr_card, $pin_code, $from_date, $to_date) { $params = array( @@ -857,27 +884,27 @@ public function add_absent_period($borr_card, $pin_code, $from_date, $to_date) { * Change existing absent period. * * @param string $borr_card - * Library patron's borrowing card number. Either just an arbitrary - * number printed on their library card or their CPR-code. + * Library patron's borrowing card number. Either just an arbitrary + * number printed on their library card or their CPR-code. * @param string $pin_code - * Library patron's current four digit PIN code. + * Library patron's current four digit PIN code. * @param string $absent_id - * ID for existing period. + * ID for existing period. * @param string $from_date - * Absent period start date. + * Absent period start date. * @param string $to_date - * Absent period start date. + * Absent period start date. */ public function change_absent_period($borr_card, $pin_code, $absent_id, $from_date, $to_date) { $params = array( 'borrCard' => $borr_card, 'pinCode' => $pin_code, 'absentId' => $absent_id, - 'absentFromDate' => $from_date, - 'absentToDate' => $to_date, + 'absentFrom' => date_format(date_create($from_date), ALMA_DATE), + 'absentTo' => date_format(date_create($to_date), ALMA_DATE), ); - $doc = $this->request('patron/absentPeriod/change', $params); + $doc = $this->request('patron/absent/change', $params); return TRUE; } @@ -885,12 +912,12 @@ public function change_absent_period($borr_card, $pin_code, $absent_id, $from_da * Remove existing absent period. * * @param string $borr_card - * Library patron's borrowing card number. Either just an arbitrary - * number printed on their library card or their CPR-code. + * Library patron's borrowing card number. Either just an arbitrary + * number printed on their library card or their CPR-code. * @param string $pin_code - * Library patron's current four digit PIN code. + * Library patron's current four digit PIN code. * @param string $absent_id - * ID for existing period. + * ID for existing period. */ public function remove_absent_period($borr_card, $pin_code, $absent_id) { $params = array( @@ -907,14 +934,14 @@ public function remove_absent_period($borr_card, $pin_code, $absent_id) { * Add a messaging service. * * @param string $borr_card - * Library patron's borrowing card number. Either just an arbitrary - * number printed on their library card or their CPR-code. + * Library patron's borrowing card number. Either just an arbitrary + * number printed on their library card or their CPR-code. * @param string $pin_code - * Library patron's current four digit PIN code. + * Library patron's current four digit PIN code. * @param $method - * The method for sending messages e.g. SMS + * The method for sending messages e.g. SMS * @param $type - * The message type e.g. due date alerts + * The message type e.g. due date alerts */ public function add_message_service($borr_card, $pin_code, $method, $type) { $params = array( @@ -932,14 +959,14 @@ public function add_message_service($borr_card, $pin_code, $method, $type) { * Removes a messaging service. * * @param string $borr_card - * Library patron's borrowing card number. Either just an arbitrary - * number printed on their library card or their CPR-code. + * Library patron's borrowing card number. Either just an arbitrary + * number printed on their library card or their CPR-code. * @param string $pin_code - * Library patron's current four digit PIN code. + * Library patron's current four digit PIN code. * @param $method - * The method for sending messages e.g. SMS + * The method for sending messages e.g. SMS * @param $type - * The message type e.g. due date alerts + * The message type e.g. due date alerts */ public function remove_message_service($borr_card, $pin_code, $method, $type) { $params = array( @@ -959,21 +986,16 @@ public function remove_message_service($borr_card, $pin_code, $method, $type) { * Define exceptions for different error conditions inside the Alma client. */ -class AlmaClientInvalidURLError extends Exception { -} +class AlmaClientInvalidURLError extends Exception { } -class AlmaClientHTTPError extends Exception { -} +class AlmaClientHTTPError extends Exception { } -class AlmaClientCommunicationError extends Exception { -} +class AlmaClientCommunicationError extends Exception { } -class AlmaClientBorrCardNotFound extends Exception { -} +class AlmaClientBorrCardNotFound extends Exception { } -class AlmaClientReservationNotFound extends Exception { -} +class AlmaClientReservationNotFound extends Exception { }