| 1 |
<?php |
<?php |
| 2 |
// $Id$ |
// $Id: timemap.module,v 1.1 2008/06/02 03:43:49 sethfreach Exp $ |
| 3 |
|
|
| 4 |
/** |
/** |
| 5 |
* @file |
* @file |
| 6 |
* Time module - Track how you spend your day with a simple as possible input interface. |
* Timemap module - Track how you spend your day with a simple as possible input interface. |
| 7 |
*/ |
*/ |
| 8 |
|
|
| 9 |
|
|
| 15 |
'enter tasks', |
'enter tasks', |
| 16 |
'edit own categories', |
'edit own categories', |
| 17 |
'edit global categories', |
'edit global categories', |
| 18 |
|
'edit timemap settings', |
| 19 |
'view own report', |
'view own report', |
| 20 |
'view all reports', |
'view all reports', |
| 21 |
); |
); |
| 22 |
|
|
| 23 |
|
// If CiviCRM is installed, offer more perms that allow people to view subsets of reports |
| 24 |
|
// as defined by CiviCRM relationships. |
| 25 |
|
// |
| 26 |
|
// TODO: Add a civi version check to the if() statement to make sure we use the correct Civi API calls when |
| 27 |
|
// fetching the relationship data. |
| 28 |
|
if (module_exists('civicrm')) { |
| 29 |
|
$perms[] = 'view subordinate reports'; |
| 30 |
|
} |
| 31 |
|
|
| 32 |
return $perms; |
return $perms; |
| 33 |
} |
} |
| 34 |
|
|
| 58 |
'access' => user_access('view own report'), |
'access' => user_access('view own report'), |
| 59 |
); |
); |
| 60 |
$items[] = array( |
$items[] = array( |
| 61 |
|
'title' => t('Time Map Reports'), |
| 62 |
|
'path' => 'timemap/report', |
| 63 |
|
'callback' => 'timemap_report', |
| 64 |
|
'access' => user_access('view own report'), |
| 65 |
|
'type' => MENU_CALLBACK, // technically enable it, but effecively hide it while incomplete. |
| 66 |
|
); |
| 67 |
|
$items[] = array( |
| 68 |
'path' => 'admin/settings/timemap', |
'path' => 'admin/settings/timemap', |
| 69 |
'title' => t('Time Map settings'), |
'title' => t('Time Map Settings'), |
| 70 |
'description' => t('Change some settings and defaults for the timemap module'), |
'description' => t('Change some settings and defaults for the Timemap module'), |
| 71 |
'callback' => 'drupal_get_form', |
'callback' => 'drupal_get_form', |
| 72 |
'callback arguments' => array('timemap_admin_settings'), |
'callback arguments' => array('timemap_admin_settings'), |
| 73 |
'access' => user_access('edit global categories'), |
'access' => (user_access('edit global categories') || user_access('edit timemap settings')), |
| 74 |
); |
); |
| 75 |
|
|
| 76 |
// } else { |
// } else { |
| 161 |
'#colorpicker' => 'color_new', |
'#colorpicker' => 'color_new', |
| 162 |
); |
); |
| 163 |
} |
} |
| 164 |
else { |
else { |
| 165 |
$form['gcats']['color_new_v'] = array( |
$form['gcats']['color_new_v'] = array( |
| 166 |
'#type' => 'textfield', |
'#type' => 'textfield', |
| 167 |
'#size' => '7', |
'#size' => '7', |
| 214 |
); |
); |
| 215 |
} |
} |
| 216 |
} |
} |
| 217 |
|
|
| 218 |
|
$form['gsets'] = array( |
| 219 |
|
'#type' => 'fieldset', |
| 220 |
|
'#access' => user_access('edit timemap settings'), |
| 221 |
|
'#title' => t('Global Settings'), |
| 222 |
|
'#collapsible' => true, |
| 223 |
|
'#collapsed' => false, |
| 224 |
|
'#weight' => -1, |
| 225 |
|
); |
| 226 |
|
$form['gsets']['timemap_report_default_days_to_show'] = array( |
| 227 |
|
'#type' => 'textfield', |
| 228 |
|
'#title' => t('Default number of days to show on reports'), |
| 229 |
|
'#description' => t('Enter the number of days of history to show when viewing reports that utilize this feature. (NOTE: This may be N/A for some reports.)'), |
| 230 |
|
'#default_value' => variable_get('timemap_report_default_days_to_show', 7), |
| 231 |
|
'#size' => 3, |
| 232 |
|
); |
| 233 |
|
if (module_exists('civicrm')) { |
| 234 |
|
$supervisor_role_opts = array(); |
| 235 |
|
// TODO: This is a CiviCRM 1.8 API call. Add logic to determine correct CiviCRM version used and API call!! |
| 236 |
|
foreach(crm_get_relationship_types() as $rel) { |
| 237 |
|
if ( |
| 238 |
|
$rel->contact_type_a == 'Individual' && |
| 239 |
|
$rel->contact_type_b == 'Individual' && |
| 240 |
|
$rel->name_a_b != $rel->name_b_a |
| 241 |
|
) { |
| 242 |
|
$supervisor_role_opts[] = $rel->name_a_b; |
| 243 |
|
$supervisor_role_opts[] = $rel->name_b_a; |
| 244 |
|
} |
| 245 |
|
} |
| 246 |
|
$form['gsets']['timemap_civicrm_subord_rel'] = array( |
| 247 |
|
'#type' => 'select', |
| 248 |
|
'#title' => t('Supervisory Relationship'), |
| 249 |
|
'#description' => t('Select the relationship that defines one CiviCRM user as a Supervisor over others. This relationship will be used to determain the reports seen when a user has permission to view subordinates\' reports.'), |
| 250 |
|
'#options' => $supervisor_role_opts, |
| 251 |
|
'#default_value' => variable_get('timemap_civicrm_subord_rel', null), |
| 252 |
|
); |
| 253 |
|
} |
| 254 |
|
|
| 255 |
return system_settings_form($form); |
return system_settings_form($form); |
| 256 |
} |
} |
| 257 |
|
|
| 258 |
function timemap_admin_settings_validate($id, $values) { |
function timemap_admin_settings_validate($id, $values) { |
| 259 |
if ($values['color_new_v'] && (! preg_match('/^#[0-9A-F]{6}$/i', $values['color_new_v'])) ) { |
if (user_access('edit global categories')) { |
| 260 |
form_set_error('color_new_v'); |
if ($values['color_new_v'] && (! preg_match('/^#[0-9A-F]{6}$/i', $values['color_new_v'])) ) { |
| 261 |
|
form_set_error('color_new_v', t('Please enter a hex value with a preceding \'#\' sign')); |
| 262 |
|
} |
| 263 |
} |
} |
| 264 |
|
|
| 265 |
|
if (user_access('edit timemap settings')) { |
| 266 |
|
if (! is_numeric($values['timemap_report_default_days_to_show'])) { |
| 267 |
|
form_set_error('timemap_report_default_days_to_show', t('Please enter a number')); |
| 268 |
|
} |
| 269 |
|
} |
| 270 |
} |
} |
| 271 |
|
|
| 272 |
function timemap_admin_settings_submit($id, $values) { |
function timemap_admin_settings_submit($id, $values) { |
| 273 |
// enter any new global categories |
// enter any new global categories |
| 274 |
$newgcat = trim($values['newgcat']); |
$newgcat = trim($values['newgcat']); |
| 292 |
} |
} |
| 293 |
} |
} |
| 294 |
} |
} |
| 295 |
|
|
| 296 |
|
//update the variables |
| 297 |
|
if (isset($values['timemap_report_default_days_to_show'])) { |
| 298 |
|
variable_set('timemap_report_default_days_to_show', (int) $values['timemap_report_default_days_to_show']); |
| 299 |
|
} |
| 300 |
|
if (isset($values['timemap_civicrm_subord_rel'])) { |
| 301 |
|
variable_set('timemap_civicrm_subord_rel', $values['timemap_civicrm_subord_rel']); |
| 302 |
|
} |
| 303 |
} |
} |
| 304 |
|
|
| 305 |
function theme_timemap_admin_settings($form) { |
function theme_timemap_admin_settings($form) { |
| 306 |
$out .= drupal_render($form['gcats']); |
//$out .= drupal_render($form['gcats']); |
| 307 |
$out .= '<table border="1"><tr><td>'; |
$out .= '<table border="1"><tr><td>'; |
| 308 |
$out .= drupal_render($form['gcats']['newgcat']); |
$out .= drupal_render($form['gcats']['newgcat']); |
| 309 |
$out .= '</td><td>'; |
$out .= '</td><td>'; |
| 530 |
drupal_add_js(drupal_get_path('module', 'timemap') ."/timemap_simile-timeline.js"); |
drupal_add_js(drupal_get_path('module', 'timemap') ."/timemap_simile-timeline.js"); |
| 531 |
drupal_add_css(drupal_get_path('module', 'timemap') ."/timemap.css"); |
drupal_add_css(drupal_get_path('module', 'timemap') ."/timemap.css"); |
| 532 |
|
|
| 533 |
return $people_chooser .'<div id="time_map" uid="'. $uid .'" offset="'. $user->timezone .'"></div><div class="time_controls" id="time_controls"></div>'; |
return $people_chooser .'<div id="timemap" uid="'. $uid .'" offset="'. $user->timezone .'"></div><div class="timemap_controls" id="timemap_controls"></div>'; |
| 534 |
|
|
| 535 |
} |
} |
| 536 |
|
|
| 589 |
return gmdate('c', $secs); |
return gmdate('c', $secs); |
| 590 |
} |
} |
| 591 |
|
|
| 592 |
|
function timemap_report($uid = null, $report = 'default', $from = null, $numDays = null) { |
| 593 |
|
global $user; |
| 594 |
|
if(! $uid) { |
| 595 |
|
$uid = $user->uid; |
| 596 |
|
} |
| 597 |
|
|
| 598 |
|
$allowed = timemap_viewable_reports_list(); |
| 599 |
|
|
| 600 |
|
if ( ! in_array($uid, array_keys($allowed)) ) { |
| 601 |
|
drupal_access_denied(); |
| 602 |
|
exit(); |
| 603 |
|
} |
| 604 |
|
|
| 605 |
|
$return = ''; |
| 606 |
|
|
| 607 |
|
//are we the only only person who has reports we can view, or are there more to choose from? |
| 608 |
|
if ( ! ((count($allowed) == 1) && isset($allowed[$user->uid])) ) { |
| 609 |
|
$return .= drupal_get_form('timemap_report_choose_person'); |
| 610 |
|
} |
| 611 |
|
|
| 612 |
|
$return .= timemap_draw_report(timemap_get_report_stats($uid, $from, $numDays), $report); |
| 613 |
|
return $return; |
| 614 |
|
} |
| 615 |
|
|
| 616 |
function timemap_report_choose_person() { |
function timemap_report_choose_person() { |
| 617 |
global $user; |
global $user; |
| 618 |
|
|
| 646 |
$userrec = user_load(array('uid' => $row->uid)); |
$userrec = user_load(array('uid' => $row->uid)); |
| 647 |
$names[$userrec->uid] = $userrec->name; |
$names[$userrec->uid] = $userrec->name; |
| 648 |
} |
} |
| 649 |
|
// just return everyone. there's no need to do any further sorting at this point. |
| 650 |
return $names; |
return $names; |
| 651 |
} |
} |
| 652 |
|
|
| 653 |
|
$return = array(); |
| 654 |
|
|
| 655 |
|
// view reports defined by CiviCRM groups? |
| 656 |
|
if (user_access('view subordinate reports')) { |
| 657 |
|
$rel = variable_get('timemap_civicrm_subord_rel'); |
| 658 |
|
$names = crm_get_relationships($user, null, $rel, null, null, 0, 1000); |
| 659 |
|
|
| 660 |
|
$return = array_merge($return, $names); |
| 661 |
|
} |
| 662 |
|
|
| 663 |
// view your own? |
// view your own? |
| 664 |
if (user_access('view own report')) { |
if (user_access('view own report')) { |
| 665 |
return array($user->uid => $user->name); |
$names = array($user->uid => $user->name); |
| 666 |
|
$return = array_merge($return, $names); |
| 667 |
} |
} |
| 668 |
|
|
| 669 |
// no permissions to view reports |
return $return; |
| 670 |
|
} |
| 671 |
|
///////////////////////////////////////// |
| 672 |
|
/** |
| 673 |
|
* Implementation of hook_timemap_report |
| 674 |
|
*/ |
| 675 |
|
function timemap_timemap_report($op = 'list', $delta = 0, $stats = null) { |
| 676 |
|
switch ($op) { |
| 677 |
|
case 'list': |
| 678 |
|
$return[] = array( |
| 679 |
|
'module' => 'timemap', // The module's name that is providing this report!!! |
| 680 |
|
'title' => 'default', |
| 681 |
|
'delta' => 0, |
| 682 |
|
); |
| 683 |
|
return $return; |
| 684 |
|
|
| 685 |
|
case 'view': |
| 686 |
|
switch($delta) { |
| 687 |
|
case 0: |
| 688 |
|
return timemap_get_report_0($stats); |
| 689 |
|
} |
| 690 |
|
break; |
| 691 |
|
} |
| 692 |
|
|
| 693 |
return array(); |
return array(); |
| 694 |
|
} |
| 695 |
|
|
| 696 |
|
function timemap_get_report_0($stats = null) { |
| 697 |
|
return '<pre><code>' . print_r($stats,1) . '</code></pre>'; |
| 698 |
|
} |
| 699 |
|
|
| 700 |
|
function timemap_draw_report($stats, $report = 'default') { |
| 701 |
|
$avail_reports = module_invoke_all('timemap_report', 'list'); |
| 702 |
|
foreach($avail_reports as $rpt) { |
| 703 |
|
if ($rpt['title'] == $report) { |
| 704 |
|
$report_detail = module_invoke($rpt['module'], 'timemap_report', 'view', $rpt['delta'], $stats); |
| 705 |
|
} |
| 706 |
|
} |
| 707 |
|
|
| 708 |
|
// if for some reason we've requested a report that isn't available, kick in our 'default' and notify |
| 709 |
|
if (! isset($report_detail)) { |
| 710 |
|
drupal_set_message("We cannot find a report called <i>$report</i>. Hopefully the following information will be helpful.", 'error'); |
| 711 |
|
$report_detail = module_invoke('timemap', 'timemap_report', 'view', 0, $stats); |
| 712 |
|
} |
| 713 |
|
|
| 714 |
|
return $report_detail; |
| 715 |
|
} |
| 716 |
|
|
| 717 |
|
/** |
| 718 |
|
* Called from timemap_report(). Collect the stats for a given uid and date and return them. |
| 719 |
|
* These stats are then passed to whatever report is being used to draw some pretty pictures. |
| 720 |
|
*/ |
| 721 |
|
function timemap_get_report_stats($uid = null, $from = null, $days_to_show = null) { |
| 722 |
|
global $user; |
| 723 |
|
if (! $uid) { |
| 724 |
|
$uid = $user->uid; |
| 725 |
|
} |
| 726 |
|
|
| 727 |
|
// expect and set variables as days |
| 728 |
|
// we'll default to showing the "default" num of days starting from that many days ago... ie, up to today. |
| 729 |
|
if (! isset($from)) { |
| 730 |
|
$from = variable_get('timemap_report_default_days_to_show', 7); |
| 731 |
|
} |
| 732 |
|
if (! isset($days_to_show)) { |
| 733 |
|
$days_to_show = variable_get('timemap_report_default_days_to_show', 7); |
| 734 |
|
} |
| 735 |
|
|
| 736 |
|
// turn days into unix times relative to now. |
| 737 |
|
// 86400 = 24 * 60 * 60 --> no. secs to "see" |
| 738 |
|
// days-1 because partial today will count as a whole 1 for our purposes |
| 739 |
|
$secs = ($from - 1) * 86400; |
| 740 |
|
|
| 741 |
|
$lastmidnight = strtotime("12 am UTC"); |
| 742 |
|
$from = $lastmidnight - $secs; |
| 743 |
|
$secs_to_show = $from + ($days_to_show * 86400); |
| 744 |
|
|
| 745 |
|
$result = db_query("select d.cid as cid, d.task as task, d.time as time, d.stop as stop, c.category as category |
| 746 |
|
from {timemap_doings} d left join {timemap_categories} c on c.cid=d.cid |
| 747 |
|
where d.uid = %d and d.time between %d and %d |
| 748 |
|
order by d.time", |
| 749 |
|
$uid, $from, $secs_to_show); |
| 750 |
|
$stats_obj['info'] = array( |
| 751 |
|
'days' => $days_to_show, |
| 752 |
|
); |
| 753 |
|
while ($row = db_fetch_object($result)) { |
| 754 |
|
$stats_obj['items'][] = array( |
| 755 |
|
'cid' => $row->cid, |
| 756 |
|
'category' => $row->category, |
| 757 |
|
'task' => $row->task, |
| 758 |
|
'time' => $row->time, |
| 759 |
|
'stop' => $row->stop, |
| 760 |
|
); |
| 761 |
|
} |
| 762 |
|
|
| 763 |
|
return $stats_obj; |
| 764 |
} |
} |