コード例 #1
0
ファイル: projectbroker.php プロジェクト: nemein/openpsa
 /**
  * Looks for free time slots for a given person for a given task
  *
  * Does the person in question have slots of time available, what
  * are the previous and next events etc
  *
  * @parameter $person person object (alternatively ID, full person will then be loaded from DB)
  * @parameter &$task the task object to search for
  * @return array of slots
  */
 function resolve_person_timeslots($person, &$task)
 {
     $minimum_time_slot = $task->get_parameter('org.openpsa.projects.projectbroker', 'minimum_slot');
     if (empty($minimum_time_slot)) {
         // Default to 15 minutes for minimum time here
         $minimum_time_slot = 0.25;
     }
     midcom::get('componentloader')->load_graceful('org.openpsa.calendar');
     if (!class_exists('org_openpsa_calendar_event_participant_dba')) {
         debug_add('could not load org.openpsa.calendar, aborting', MIDCOM_LOG_WARN);
         return false;
     }
     $slots = org_openpsa_calendar_event_participant_dba::find_free_times($minimum_time_slot * 60, $person, $task->start, $task->end);
     return $slots;
 }
コード例 #2
0
ファイル: member.php プロジェクト: nemein/openpsa
 /**
  * Find amount (seconds) of free
  * time for person between start and end
  */
 public static function find_free_times($amount, $person, $start, $end)
 {
     static $event_cache = array();
     $slots = array();
     if (!is_object($person)) {
         $person = org_openpsa_contacts_person_dba::get_cached($person);
     }
     // Get current events for person
     $qb = org_openpsa_calendar_event_participant_dba::new_query_builder();
     $qb->begin_group('OR');
     $qb->add_constraint('orgOpenpsaObtype', '=', ORG_OPENPSA_OBTYPE_EVENTPARTICIPANT);
     $qb->add_constraint('orgOpenpsaObtype', '=', 0);
     $qb->end_group();
     $qb->add_constraint('uid', '=', $person->id);
     // All events that somehow overlap the given time.
     $qb->begin_group('OR');
     $qb->begin_group('AND');
     $qb->add_constraint('eid.start', '>=', $start);
     $qb->add_constraint('eid.start', '<=', $end);
     $qb->end_group();
     $qb->begin_group('AND');
     $qb->add_constraint('eid.end', '<=', $end);
     $qb->add_constraint('eid.end', '>=', $start);
     $qb->end_group();
     $qb->begin_group('AND');
     $qb->add_constraint('eid.start', '<=', $start);
     $qb->add_constraint('eid.end', '>=', $end);
     $qb->end_group();
     $qb->end_group();
     $qb->add_order('eid.start', 'ASC');
     $qb->add_order('eid.end', 'ASC');
     $eventmembers = $qb->execute();
     if (!is_array($eventmembers)) {
         // QB error
         return $slots;
     }
     $events_by_date = array();
     foreach ($eventmembers as $eventmember) {
         if (!array_key_exists($eventmember->eid, $event_cache)) {
             try {
                 $event_cache[$eventmember->eid] = new org_openpsa_calendar_event_dba($eventmember->eid);
             } catch (midcom_error $e) {
                 continue;
             }
         }
         $event =& $event_cache[$eventmember->eid];
         $ymd = date('Ymd', $event->start);
         if (array_key_exists($ymd, $events_by_date)) {
             $events_by_date[$ymd] = array();
         }
         $events_by_date[$ymd][] = $event;
     }
     // Make sure each date between start and end has at least a dummy event
     $stamp = mktime(0, 0, 1, date('m', $start), date('d', $start), date('Y', $start));
     while ($stamp <= $end) {
         $ymd = date('Ymd', $stamp);
         debug_add("making sure date {$ymd} has at least one event");
         $stamp = mktime(0, 0, 1, date('m', $stamp), date('d', $stamp) + 1, date('Y', $stamp));
         if (array_key_exists($ymd, $events_by_date)) {
             continue;
         }
         debug_add('none found, adding a dummy one');
         $dummy = new org_openpsa_calendar_event_dba();
         $dummy->start = $stamp;
         $dummy->end = $stamp + 1;
         $events_by_date[$ymd] = array($dummy);
     }
     foreach ($events_by_date as $ymd => $events) {
         preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})/', $ymd, $ymd_matches);
         // TODO: get from persons data based on events weekday
         // PONDER: What to do with persons that do not have this data defined ??
         $workday_starts = 8;
         $workday_ends = 16;
         if (empty($workday_starts) || empty($workday_ends)) {
             // No work on that day
             continue;
         }
         $workday_starts_ts = mktime($workday_starts, 0, 0, (int) $ymd_matches[2], (int) $ymd_matches[3], (int) $ymd_matches[1]);
         $workday_ends_ts = mktime($workday_ends, 0, 0, (int) $ymd_matches[2], (int) $ymd_matches[3], (int) $ymd_matches[1]);
         $last_end_time = false;
         $last_event = false;
         foreach ($events as $event_key => $event) {
             if ($event->end <= $workday_starts_ts) {
                 // We need not to consider this event, it ends before we start working
                 unset($events[$event_key]);
                 continue;
             }
             if ($event->start >= $workday_ends_ts) {
                 // We need not to consider this event, it starts after we stop working
                 unset($events[$event_key]);
                 continue;
             }
             debug_add("checking event #{$event->id} ({$event->title})");
             if ($last_end_time === false) {
                 if ($event->start > $workday_starts_ts) {
                     // First event of the day starts after we have started working, use work start time as last end time.
                     $last_end_time = $workday_starts_ts;
                 } else {
                     // Make the first event of the day the last end time and skip rest of the checks
                     $last_end_time = $event->end;
                     // PHP5-TODO: Must be copy by value
                     $last_event = $event;
                     continue;
                 }
             }
             $diff = $event->start - $last_end_time;
             if ($diff >= $amount) {
                 // slot found
                 $slot = array('start' => $last_end_time, 'end' => $event->start, 'previous' => $last_event, 'next' => $event);
                 // PHP5-TODO: This must be copy-by-value
                 $slots[] = $slot;
             }
             $last_end_time = $event->end;
             $last_event = $event;
         }
         // End of day slot
         if ($last_end_time === false) {
             $last_end_time = $workday_starts_ts;
         }
         if ($last_end_time < $workday_ends_ts && $workday_ends_ts - $last_end_time >= $amount) {
             $slot = array('start' => $last_end_time, 'end' => $workday_ends_ts, 'previous' => $last_event, 'next' => false);
             // PHP5-TODO: This must be copy-by-value
             $slots[] = $slot;
         }
     }
     return $slots;
 }
コード例 #3
0
ファイル: event.php プロジェクト: nemein/openpsa
 private function _get_member_by_personid($id, $type = 'participant')
 {
     if (!$this->id) {
         return false;
     }
     $qb = org_openpsa_calendar_event_participant_dba::new_query_builder();
     $qb->add_constraint('eid', '=', $this->id);
     $qb->add_constraint('uid', '=', $id);
     $results = $qb->execute_unchecked();
     if (empty($results)) {
         return false;
     }
     return $results[0];
 }
コード例 #4
0
ファイル: reporthours.php プロジェクト: nemein/openpsa
 /**
  * Search for events withing configured timeframe and if
  * they have confirmed relatedtos to tasks reports hours
  * for each participant (who is task resource) towards
  * said task.
  */
 public function _on_execute()
 {
     debug_add('_on_execute called');
     $root_event = org_openpsa_calendar_interface::find_root_event();
     if (!is_object($root_event)) {
         debug_add('calendar root event not found', MIDCOM_LOG_WARN);
         return;
     }
     if (!class_exists('org_openpsa_relatedto_dba')) {
         debug_add('relatedto library could not be loaded', MIDCOM_LOG_WARN);
         return;
     }
     if (!midcom::get('componentloader')->load_graceful('org.openpsa.projects')) {
         debug_add('org.openpsa.projects could not be loaded', MIDCOM_LOG_WARN);
         return;
     }
     if (!midcom::get('auth')->request_sudo('org.openpsa.calendar')) {
         $msg = "Could not get sudo, aborting operation, see error log for details";
         $this->print_error($msg);
         debug_add($msg, MIDCOM_LOG_ERROR);
         return;
     }
     $qb = org_openpsa_calendar_event_participant_dba::new_query_builder();
     // Event must be directly under openpsa calendar root event
     $qb->add_constraint('eid.up', '=', $root_event->id);
     // Member type must not be resource
     $qb->add_constraint('orgOpenpsaObtype', '<>', ORG_OPENPSA_OBTYPE_EVENTRESOURCE);
     // Event must have ended
     $qb->add_constraint('eid.end', '<', time());
     // Event can be at most week old
     // TODO: make max age configurable
     /* TODO: store a timestamp of last process in root event and use whichever
                 is nearer, though it has the issue with creating events after the fact
                 (which can happen when synchronizing from other systems for example)
        */
     $qb->add_constraint('eid.start', '>', time() - 24 * 3600 * 7);
     // Must not have hours reported already
     $qb->add_constraint('hoursReported', '=', 0);
     $eventmembers = $qb->execute();
     if (!is_array($eventmembers) || count($eventmembers) < 1) {
         midcom::get('auth')->drop_sudo();
         return;
     }
     // keyed by id
     $seen_events = array();
     // keyed by guid
     $seen_tasks = array();
     // keyed by guid
     $event_links = array();
     foreach ($eventmembers as $member) {
         // Bulletproofing: prevent duplicating hour reports
         $member->hoursReported = time();
         if (!$member->update(false)) {
             $msg = "Could not set hoursReported on member #{$member->id} (event #{$member->eid}), errstr: " . midcom_connection::get_error_string() . " skipping this member";
             $this->print_error($msg);
             debug_add($msg, MIDCOM_LOG_ERROR);
             continue;
         }
         //Avoid multiple loads of same event
         if (!isset($seen_events[$member->eid])) {
             $seen_events[$member->eid] = new org_openpsa_calendar_event_dba($member->eid);
         }
         $event =& $seen_events[$member->eid];
         // Avoid multiple queries of events links
         if (!isset($event_links[$event->guid])) {
             $qb2 = org_openpsa_relatedto_dba::new_query_builder();
             $qb2->add_constraint('fromGuid', '=', $event->guid);
             $qb2->add_constraint('fromComponent', '=', 'org.openpsa.calendar');
             $qb2->add_constraint('toComponent', '=', 'org.openpsa.projects');
             $qb2->add_constraint('toClass', '=', 'org_openpsa_projects_task_dba');
             $qb2->add_constraint('status', '=', org_openpsa_relatedto_dba::CONFIRMED);
             $event_links[$event->guid] = $qb2->execute();
         }
         $links =& $event_links[$event->guid];
         // These checks are done here (in stead of few lines above) on purpose
         if (!is_array($links) || count($links) < 1) {
             continue;
         }
         foreach ($links as $link) {
             //Avoid multiple loads of same task
             if (!isset($seen_tasks[$link->toGuid])) {
                 $seen_tasks[$link->toGuid] = new org_openpsa_projects_task_dba($link->toGuid);
             }
             $task =& $seen_tasks[$link->toGuid];
             debug_add("processing task #{$task->id} ({$task->title}) for person #{$member->uid} from event #{$event->id} ({$event->title})");
             // Make sure the person we found is a resource in this particular task
             $task->get_members();
             if (!isset($task->resources[$member->uid])) {
                 debug_add("person #{$member->uid} is not a *resource* in task #{$task->id}, skipping");
                 continue;
             }
             if (!org_openpsa_projects_interface::create_hour_report($task, $member->uid, $event, 'org.openpsa.calendar')) {
                 // MidCOM error log is filled in the method, here we just display error
                 $this->print_error("Failed to create hour_report to task #{$task->id} for person #{$member->uid} from event #{$event->id}");
                 // Failed to create hour_report, unset hoursReported so that we might have better luck next time
                 // PONDER: This might be an issue in case be have multiple tasks linked and only one of them fails... figure out a more granular way to flag reported hours ?
                 $member->hoursReported = 0;
                 if (!$member->update(false)) {
                     $msg = "Could not UNSET hoursReported on member #{$member->id} (event #{$member->eid}), errstr: " . midcom_connection::get_error_string();
                     $this->print_error($msg);
                     debug_add($msg, MIDCOM_LOG_WARN);
                 }
             }
         }
     }
     midcom::get('auth')->drop_sudo();
     debug_add('done');
     return;
 }