diff --git a/pm.css b/pm.css index 44f2331..6bc2c6d 100644 --- a/pm.css +++ b/pm.css @@ -31,37 +31,6 @@ text-align: right; white-space: nowrap; } -div.pm_popup { -display:none; -z-index: 100; -border: 1px solid black; -background-color: #fff; -} - -div.pm_popup_inner { -text-align: center; -} - -div.pm_popup_inner form div div.form-item { -margin: 0; -} - -div.pm_popup_inner form div input.form-submit { -margin: 5px 0 0 0; -} - -div.pm_popup_title { -float: left; -text-align: center; -color: #fff; -width: 100%; -background-color: #5294C1; -} - -div.pm_popup_inner { -clear: both; -} - div.pm_quick_shortcuts { clear: both; } @@ -89,10 +58,6 @@ font-weight: bold; color: #ffffff; } -form.pmcomponent_node_form #edit-preview { - display: none; -} - tr.formgroup { background-color: #ffffff !important; border: none !important; diff --git a/pm.install b/pm.install index 78ee8e0..493ed85 100644 --- a/pm.install +++ b/pm.install @@ -10,8 +10,6 @@ function pm_install() { variable_set('pm_icons_path', drupal_get_path('module', 'pm') . '/icons'); variable_set('pm_organization_nid', 0); - variable_set('pm_yearsrangebegin', 2001); - variable_set('pm_yearsrangeend', 2015); // Set up billing status field. field_create_field(array( @@ -25,6 +23,26 @@ function pm_install() { ), ), )); + + // Set up date fields. + field_create_field(array( + 'type' => 'datetime', + 'field_name' => 'pm_date_range', + 'settings' => array( + 'granularity' => array( + 'year' => 'year', + 'month' => 'month', + 'day' => 'day', + 'hour' => 'hour', + 'minute' => 'minute', + 'second' => 0, + ), + 'tz_handling' => 'none', + 'timezone_db' => '', + 'todate' => 'optional', + ), + 'cardinality' => '1', + )); } /** @@ -33,8 +51,6 @@ function pm_install() { function pm_uninstall() { variable_del('pm_icons_path'); variable_del('pm_organization_nid'); - variable_del('pm_yearsrangebegin'); - variable_del('pm_yearsrangeend'); drupal_uninstall_schema('pm'); } @@ -87,3 +103,32 @@ function pm_update_7101() { ), )); } + +/** + * Make date field available to PM content types. + */ +function pm_update_7102() { + + // Set up date fields. + field_create_field(array( + 'type' => 'datetime', + 'field_name' => 'pm_date_range', + 'settings' => array( + 'granularity' => array( + 'year' => 'year', + 'month' => 'month', + 'day' => 'day', + 'hour' => 'hour', + 'minute' => 'minute', + 'second' => 0, + ), + 'tz_handling' => 'none', + 'timezone_db' => '', + 'todate' => 'optional', + ), + 'cardinality' => '1', + )); + + variable_del('pm_yearsrangebegin'); + variable_del('pm_yearsrangeend'); +} diff --git a/pm.module b/pm.module index f4ab358..8862438 100644 --- a/pm.module +++ b/pm.module @@ -2,15 +2,6 @@ /** * @file * Main module file for the Project Management module. - * Basic Project Management module provides a dashboard and some API functions. - * 1: Hooks (help, perm, init, menu, theme) - * 2: Dashboard - * 3: Admin Settings - * 4: Date / time manipulation - * 5: Taxation functions - * 6: Project Management Icons - * 7: SQL Functions - * 8: Node form theming */ /** @@ -443,34 +434,6 @@ function pm_admin_settings() { '#element_validate' => array('pm_admin_settings_icons_path_validate'), ); - $form['yearsrange'] = array( - '#type' => 'fieldset', - '#title' => t('Years range in dates'), - '#collapsed' => TRUE, - '#collapsible' => TRUE, - '#weight' => $w++, - ); - - $form['yearsrange']['group0'] = array( - '#type' => 'markup', - '#theme' => 'pm_form_group', - '#weight' => $w++, - ); - - $form['yearsrange']['group0']['pm_yearsrangebegin'] = array( - '#type' => 'select', - '#title' => t('Begin'), - '#options' => drupal_map_assoc(range(1970, 2037)), - '#default_value' => variable_get('pm_yearsrangebegin', 2001), - ); - - $form['yearsrange']['group0']['pm_yearsrangeend'] = array( - '#type' => 'select', - '#title' => t('End'), - '#options' => drupal_map_assoc(range(1970, 2037)), - '#default_value' => variable_get('pm_yearsrangeend', 2015), - ); - $form['taxation'] = array( '#type' => 'fieldset', '#title' => t('Taxation defaults'), @@ -672,357 +635,6 @@ function pm_admin_settings_form_submit($form, $form_state) { } /** - * Implements hook_elements(). - */ -function pm_elements() { - $type['datetime'] = array( - '#input' => TRUE, - '#process' => array('pm_datetime_expand'), - '#element_validate' => array('pm_datetime_validate'), - '#default_value' => array( - 'day' => format_date(time(), 'custom', 'j'), - 'month' => format_date(time(), 'custom', 'n'), - 'year' => format_date(time(), 'custom', 'Y'), - 'hour' => format_date(time(), 'custom', 'H'), - 'minute' => format_date(time(), 'custom', 'i'), - ), - ); - $type['dateext'] = array( - '#input' => TRUE, - '#process' => array('pm_dateext_expand'), - '#element_validate' => array('pm_dateext_validate'), - '#default_value' => time(), - '#withnull' => FALSE, - '#disable_date_popup' => FALSE, - ); - return $type; -} - -/** - * Expands a date into individual elements. - */ -function pm_datetime_expand($element) { - if (empty($element['#value'])) { - $element['#value'] = array( - 'day' => format_date(time(), 'custom', 'j'), - 'month' => format_date(time(), 'custom', 'n'), - 'year' => format_date(time(), 'custom', 'Y'), - 'hour' => format_date(time(), 'custom', 'H'), - 'minute' => format_date(time(), 'custom', 'i'), - ); - } - - $element['#tree'] = TRUE; - - // Determine the order of day, month, year in the site's chosen date format. - $format = variable_get('date_format_short', 'm/d/Y - H:i'); - $sort = array(); - $sort['day'] = max(strpos($format, 'd'), strpos($format, 'j')); - $sort['month'] = max(strpos($format, 'm'), strpos($format, 'M')); - $sort['year'] = strpos($format, 'Y'); - $sort['hour'] = strpos($format, 'H'); - $sort['minute'] = strpos($format, 'i'); - asort($sort); - $order = array_keys($sort); - - // Output multi-selector for date. - foreach ($order as $type) { - switch ($type) { - case 'year': - $options = drupal_map_assoc(range(variable_get('pm_yearsrangebegin', 2001), variable_get('pm_yearsrangeend', 2012))); - break; - case 'month': - $options = drupal_map_assoc(range(1, 12), 'map_month'); - break; - case 'day': - $options = drupal_map_assoc(range(1, 31)); - break; - case 'hour': - $options = drupal_map_assoc(range(0, 23)); - break; - case 'minute': - $options = drupal_map_assoc(range(0, 59)); - break; - } - $parents = $element['#parents']; - $parents[] = $type; - $element[$type] = array( - '#type' => 'select', - '#value' => $element['#value'][$type], - '#attributes' => $element['#attributes'], - '#options' => $options, - ); - } - return $element; -} - -/** - * Validate form date elements. - */ -function pm_datetime_validate($form) { - if (!checkdate($form['#value']['month'], $form['#value']['day'], $form['#value']['year'])) { - form_error($form, t('The specified date is invalid.')); - } -} - -/** - * Expand form date elements into day, month, and year. - */ -function pm_dateext_expand($element, $edit, $form_state, $form) { - if (empty($element['#value'])) { - if (!$element['#withnull']) { - $element['#value'] = array( - 'day' => format_date(time(), 'custom', 'j'), - 'month' => format_date(time(), 'custom', 'n'), - 'year' => format_date(time(), 'custom', 'Y'), - ); - } - else { - $element['#value'] = array('day' => -1, 'month' => -1, 'year' => -1); - } - } - - $element['#tree'] = TRUE; - - // If date popup exists, we should use date popup, - // but you can force to disable it by set disable_date_popup to true - if (module_exists('date_popup') && (!isset($element['disable_date_popup']) || !$element['disable_date_popup'])) { - - // value is timestamp - if (is_numeric($element['#value']) && $element['#value'] != 0) { - $element['#value'] = array('popup' => format_date($element['#value'], 'custom', 'Y-m-d')); - } - // value is date array - elseif (is_array($element['#value']) && !isset($element['#value']['popup']) && $element['#value']['day'] != -1) { - $element['#value'] = array('popup' => sprintf("%04d-%02d-%02d", $element['#value']['year'], $element['#value']['month'], $element['#value']['day'])); - } - elseif (is_numeric($element['#value']) || !isset($element['#value']['popup']) || (isset($element['#value']['day']) && $element['#value']['day'] == -1)) { - $element['#value'] = array('popup' => ''); - } - - if (is_array($element['#value']['popup']) && isset($element['#value']['popup']['date'])) { - $value = $element['#value']['popup']['date']; - } - else { - $value = $element['#value']['popup']; - } - - $current_year = date('Y'); - $begin = variable_get('pm_yearsrangebegin', 2001) - $current_year; - if ($begin > 0) { - $begin = '+' . $begin; - } - $end = variable_get('pm_yearsrangeend', 2015) - $current_year; - if ($end > 0) { - $end = '+' . $end; - } - - $parents = $element['#parents']; - $parents[] = 'popup'; - $element['popup'] = array( - '#type' => 'date_popup', - '#date_timezone' => date_default_timezone_name(), - '#date_format' => "Y-m-d", - '#date_year_range' => $begin . ':' . $end, - '#default_value' => $value, - '#attributes' => $element['#attributes'], - '#withnull' => $element['#withnull'], - ); - } - // fallback - use select boxes to choose the date - else { - - // its a timestamp, convert it to a date format - if (is_numeric($element['#value']) && $element['#value'] != 0) { - $element['#value'] = _pm_gmtimestamp_to_date($element['#value']); - } - - // Determine the order of day, month, year in the site's chosen date format. - $format = variable_get('date_format_short', 'm/d/Y - H:i'); - $sort = array(); - $sort['day'] = max(strpos($format, 'd'), strpos($format, 'j')); - $sort['month'] = max(strpos($format, 'm'), strpos($format, 'M')); - $sort['year'] = strpos($format, 'Y'); - asort($sort); - $order = array_keys($sort); - - // Output multi-selector for date. - foreach ($order as $type) { - switch ($type) { - case 'year': - $options = drupal_map_assoc(range(variable_get('pm_yearsrangebegin', 2001), variable_get('pm_yearsrangeend', 2012))); - break; - case 'month': - $options = drupal_map_assoc(range(1, 12), 'map_month'); - break; - case 'day': - $options = drupal_map_assoc(range(1, 31)); - break; - } - if ($element['#withnull']) { - $options = array('-1' => '-') + $options; - } - - if (empty($element['#attributes'])) { - $element['#attributes'] = array(); - } - - $parents = $element['#parents']; - $parents[] = $type; - $element[$type] = array( - '#type' => 'select', - '#value' => isset($element['#value'][$type]) ? $element['#value'][$type] : NULL, - '#options' => $options, - '#attributes' => array_merge(array('onchange' => "pm_datext_tonull(this, '" . $element['#id'] . "')"), $element['#attributes']), - ); - } - } - return $element; -} - -/** - * Validation for the dateext form element. - */ -function pm_dateext_validate($element, &$form_state) { - // value is a string, convert it back to array - if (is_array($element['#value']) && isset($element['#value']['popup'])) { - if (!$element['#withnull'] && empty($element['#value']['popup']['date'])) { - form_set_error($element, t('Field %field is required.', array('%field' => !empty($element['#title']) ? $element['#title'] : ''))); - } - if (preg_match('/(\d{4})-(\d{2})-(\d{2})/', $element['#value']['popup']['date'], $matches)) { - $element['#value'] = array(); - $element['#value']['day'] = (int) $matches[3]; - $element['#value']['month'] = (int) $matches[2]; - $element['#value']['year'] = (int) $matches[1]; - } - else { - if (!$element['#withnull'] && !empty($element['#value']['popup']['date'])) { - form_set_error($element, t('Wrong Format for Field %field. Format should be YYYY-MM-DD.', array('%field' => !empty($element['#title']) ? $element['#title'] : ''))); - } - $element['#value'] = array('day' => -1, 'month' => -1, 'year' => -1); - } - form_set_value($element, $element['#value'], $form_state); - } - - if ($element['#value']['day'] == -1 && !$element['#withnull']) { - form_set_error($element, t('Field %field is required.', array('%field' => !empty($element['#title']) ? $element['#title'] : ''))); - } - if ($element['#value']['day'] != -1 && !checkdate($element['#value']['month'], $element['#value']['day'], $element['#value']['year'])) { - form_error($element, t('The specified date is invalid.')); - } - return $element; -} - -/** - * Converts a local timestamp to GMT. - */ -function _timestamp_to_gm($timestamp, $timezone=NULL) { - if (!isset($timezone)) { - global $user; - if (variable_get('configurable_timezones', 1) && $user->uid && drupal_strlen($user->timezone)) { - $timezone = $user->timezone; - } - else { - $timezone = variable_get('date_default_timezone', 0); - } - } - $timestamp -= $timezone; - return $timestamp; -} - -/** - * Converts a date to a GMT timestamp. - */ -function _pm_date_to_gmtimestamp($date, $timezone=NULL) { - if ($date['month'] == -1 || $date['year'] == -1 || $date['day'] == -1) { - return NULL; - } - else { - $gmttimestamp = gmmktime(0, 0, 0, intval($date['month']), intval($date['day']), intval($date['year'])); - return _timestamp_to_gm($gmttimestamp, $timezone); - } -} - -/** - * Converts a datetime to a GMT timestamp. - */ -function _pm_datetime_to_gmtimestamp($datetime, $timezone=NULL) { - $gmttimestamp = gmmktime(intval($datetime['hour']), intval($datetime['minute']), 0, intval($datetime['month']), - intval($datetime['day']), intval($datetime['year'])); - return _timestamp_to_gm($gmttimestamp, $timezone); -} - -/** - * Converts a GMT timestamp to a datetime. - */ -function _pm_gmtimestamp_to_datetime($timestamp, $timezone=NULL) { - $datetime = array( - 'day' => format_date($timestamp, 'custom', 'j', $timezone), - 'month' => format_date($timestamp, 'custom', 'n', $timezone), - 'year' => format_date($timestamp, 'custom', 'Y', $timezone), - 'hour' => (int)format_date($timestamp, 'custom', 'H', $timezone), - 'minute' => (int)format_date($timestamp, 'custom', 'i', $timezone), - ); - return $datetime; -} - -/** - * Converts a GMT timestamp to a date. - */ -function _pm_gmtimestamp_to_date($timestamp, $timezone=NULL) { - if ($timestamp) { - $date = array( - 'day' => format_date($timestamp, 'custom', 'j', $timezone), - 'month' => format_date($timestamp, 'custom', 'n', $timezone), - 'year' => format_date($timestamp, 'custom', 'Y', $timezone), - ); - } - else { - $date = array( - 'day' => -1, - 'month' => -1, - 'year' => -1, - ); - } - - return $date; -} - -/** - * Converts a GMT Timestamp to a timestamp showing date only. - */ -function _pm_gmtimestamp_without_time($timestamp, $timezone=NULL) { - $date = _pm_gmtimestamp_to_date($timestamp, $timezone); - $gmttimestamp = gmmktime(0, 0, 0, $date['month'], $date['day'], $date['year']); - return _timestamp_to_gm($gmttimestamp, $timezone); -} - -/** - * Converts a string to a time array. - */ -function _pm_strtotime($timestr='') { - $timestr = drupal_substr($timestr, 0, 5); - $time = array(); - $time['hour'] = 0; - $time['minute'] = 0; - - $ar = explode(':', $timestr); - if (is_array($ar)) { - if (array_key_exists(0, $ar)) $time['hour'] = $ar[0]; - if (array_key_exists(1, $ar)) $time['minute'] = $ar[1]; - } - return $time; -} - -/** - * Converts a time array to a string. - */ -function _timetostr($time=array()) { - $timestr = str_pad($time['hour'], 2, "0", STR_PAD_LEFT) . ':' . str_pad($time['minute'], 2, "0", STR_PAD_RIGHT); - return $timestr; -} - -/** * Calculates taxation for Project Management nodes */ function pm_taxation(&$node) { diff --git a/pmexpense/pmexpense.install b/pmexpense/pmexpense.install index 92eafe3..17e0844 100644 --- a/pmexpense/pmexpense.install +++ b/pmexpense/pmexpense.install @@ -11,6 +11,42 @@ function pmexpense_install() { variable_set('node_options_pmexpense', array('status')); variable_set('node_permissions_pmexpense', 0); + // Expense date field. + field_create_field(array( + 'type' => 'datetime', + 'field_name' => 'pmexpense_date', + 'settings' => array( + 'granularity' => array( + 'year' => 'year', + 'month' => 'month', + 'day' => 'day', + 'hour' => 0, + 'minute' => 0, + 'second' => 0, + ), + 'tz_handling' => '', + 'timezone_db' => '', + 'todate' => '', + ), + 'cardinality' => '1', + )); + + field_create_instance(array( + 'field_name' => 'pmexpense_date', + 'bundle' => 'pmexpense', + 'label' => 'Expense Date', + 'required' => 1, + 'entity_type' => 'node', + 'widget' => array( + 'weight' => '-18', + 'type' => 'date_text', + 'active' => 1, + ), + 'settings' => array( + 'default_value' => 'now', + ), + )); + $attributes = array(); $attributes['Expense status'] = array( @@ -60,6 +96,9 @@ function pmexpense_disable() { drupal_set_message(t('Nodes of type "Expense" have not been deleted on disabling Project Management Expense. Please note that they will now have reduced functionality, and will not be protected by Project Management Expense access controls.'), 'warning'); } +/** + * Implements hook_uninstall(). + */ function pmexpense_uninstall() { drupal_uninstall_schema('pmexpense'); @@ -68,6 +107,9 @@ function pmexpense_uninstall() { ->execute(); } +/** + * Implements hook_schema(). + */ function pmexpense_schema() { $schema['pmexpense'] = array( 'fields' => array( @@ -84,7 +126,6 @@ function pmexpense_schema() { 'ticket_title' => array('type' => 'varchar', 'length' => 128), 'provider_nid' => array('type' => 'int'), 'provider_title' => array('type' => 'varchar', 'length' => 128), - 'expensedate' => array('type' => 'int'), 'expensestatus' => array('type' => 'varchar', 'length' => 128), 'amount' => array('type' => 'float'), 'tax1app' => array('type' => 'int'), @@ -112,6 +153,9 @@ function pmexpense_schema() { return $schema; } +/** + * Implements hook_update_last_removed(). + */ function pmexpense_update_last_removed() { return 6202; } @@ -144,3 +188,62 @@ function pmexpense_update_7101() { function pmexpense_update_7102() { node_access_needs_rebuild(TRUE); } + +/** + * Convert Expense Date field to Field API. + */ +function pmexpense_update_7103() { + // Expense date field. + field_create_field(array( + 'type' => 'datetime', + 'field_name' => 'pmexpense_date', + 'settings' => array( + 'granularity' => array( + 'year' => 'year', + 'month' => 'month', + 'day' => 'day', + 'hour' => 0, + 'minute' => 0, + 'second' => 0, + ), + 'tz_handling' => '', + 'timezone_db' => '', + 'todate' => '', + ), + 'cardinality' => '1', + )); + + field_create_instance(array( + 'field_name' => 'pmexpense_date', + 'bundle' => 'pmexpense', + 'label' => 'Expense Date', + 'required' => 1, + 'entity_type' => 'node', + 'widget' => array( + 'weight' => '-18', + 'type' => 'date_text', + 'active' => 1, + ), + 'settings' => array( + 'default_value' => 'now', + ), + )); + + // Migrate data. + $query = db_select('pmexpense', 'pmex'); + $query->join('node', 'n', 'n.vid = pmex.vid'); + $result = $query + ->fields('pmex', array('nid', 'vid', 'expensedate')) + ->execute(); + + foreach ($result as $record) { + $node = node_load($record->nid); + + $node->pmexpense_date[LANGUAGE_NONE][0]['value'] = date('Y-m-d H:i:s', $record->expensedate); + field_attach_presave('node', $node); + field_attach_update('node', $node); + } + + // Delete columns from existing database table. + db_drop_field('pmexpense', 'expensedate'); +} diff --git a/pmexpense/pmexpense.module b/pmexpense/pmexpense.module index 6f4abf3..647e9ea 100644 --- a/pmexpense/pmexpense.module +++ b/pmexpense/pmexpense.module @@ -1,7 +1,7 @@ -20, ), 'group2' => array( - 'label' => 'Date/Provider Group', - 'weight' => -19, + 'label' => 'Provider Group', + 'weight' => -18, ), 'group3' => array( 'label' => 'Amount', - 'weight' => -18, + 'weight' => -17, ), 'group4' => array( 'label' => 'Tax Group', - 'weight' => -17, + 'weight' => -16, ), 'group5' => array( 'label' => 'Billable / Billed Group', - 'weight' => -16, + 'weight' => -15, ), ), ); @@ -254,8 +254,6 @@ function pmexpense_form($node, $form_state) { drupal_set_breadcrumb($breadcrumb); if (arg(1) == 'add') { - $node->expensedate = time(); - if (array_key_exists('organization_nid', $_GET) && !$node->organization_nid) { $node->organization_nid = $_GET['organization_nid']; } @@ -470,12 +468,6 @@ function pmexpense_form($node, $form_state) { '#weight' => $info['group2']['weight'], ); - $form['group2']['expensedate'] = array( - '#type' => 'dateext', - '#title' => t('Date'), - '#default_value' => isset($node->expensedate) ? $node->expensedate : time(), - ); - $form['group2']['provider_title'] = array( '#type' => 'textfield', '#title' => t('Provider'), @@ -620,7 +612,6 @@ function pmexpense_insert($node) { 'ticket_title' => (isset($node->ticket_title)) ? $node->ticket_title : NULL, 'provider_nid' => (isset($node->provider_nid)) ? $node->provider_nid : NULL, 'provider_title' => $node->provider_title, - 'expensedate' => $node->expensedate, 'amount' => $node->amount, 'tax1app' => $node->tax1app, 'tax1percent' => $node->tax1percent, @@ -658,7 +649,6 @@ function pmexpense_update($node) { 'ticket_title' => (isset($node->ticket_title)) ? $node->ticket_title : NULL, 'provider_nid' => (isset($node->provider_nid)) ? $node->provider_nid : NULL, 'provider_title' => $node->provider_title, - 'expensedate' => $node->expensedate, 'amount' => $node->amount, 'tax1app' => $node->tax1app, 'tax1percent' => $node->tax1percent, @@ -687,13 +677,6 @@ function _pmexpense_beforesave(&$node) { $node->tax1percent = str_replace(',', '.', $node->tax1percent); $node->tax2percent = str_replace(',', '.', $node->tax2percent); - if (!!is_numeric($node->expensedate) && is_array($node->expensedate)) { - $node->expensedate = _pm_date_to_gmtimestamp($node->expensedate); - } - elseif (!is_numeric($node->expensedate) && is_string($node->expensedate)) { - $node->expensedate = strtotime($node->expensedate); - } - pm_taxation($node); $org_query = db_select('node', 'n'); diff --git a/pmexpense/pmexpense.theme.inc b/pmexpense/pmexpense.theme.inc index eb1864b..e6a3a91 100644 --- a/pmexpense/pmexpense.theme.inc +++ b/pmexpense/pmexpense.theme.inc @@ -1,7 +1,7 @@ content['links'] = array( '#prefix' => '