<?php

// calendar_data.php - PHProjekt Version 5.0
// copyright  ©  2000-2005 Albrecht Guenther  ag@phprojekt.com
// www.phprojekt.com
// Authors: Albrecht Guenther, $Author: paolo $
// $Id: calendar_data.php,v 1.78 2005/06/24 10:53:52 paolo Exp $


// check whether the lib has been included - authentication!
if (!defined('lib_included')) die('Please use calendar.php!');


include_once($lib_path.'/email_notification.inc.php');
include_once($path_pre.'/calendar/calendar.inc.php');


/**
 * control the submit actions from the event main form
 *
 * @return boolean true on action success
 */
function calendar_action_data() {
    global $ID, $view, $act_for;

    $ret = false;
    if (isset($_REQUEST['action_create'])) {
        unset($_SESSION['calendardata']['current_event']);
        if ($act_for && $view == 4 && !calendar_can_act_for($act_for)) {
            message_stack_in(__('You are not allowed to create an event!'), 'calendar', 'error');
            return false;
        }
        if ($data = calendar_prepare_data()) {
            calendar_add_event($data);
            message_stack_in(__('Event successfully created.'), 'calendar', 'notice');
            $ret = true;
            $mail_title  = __('New Date').':'.$data['event']." ";
            $mail_title .= "(".$data['datum'].', ';
            $mail_title .= $data['anfang'].' - '.$data['ende'].")";
            unset($_SESSION['calendardata']['current_event']);
        }
    }
    else if (isset($_REQUEST['action_update'])) {
        if ( $ID != $_SESSION['calendardata']['current_event']['ID'] ||
             ($act_for && $view == 4 && !calendar_can_act_for($act_for)) ) {
            message_stack_in(__('You are not allowed to edit this event!'), 'calendar', 'error');
            return false;
        }
        if ($data = calendar_prepare_data()) {
            $data['ID'] = $ID;
            if ($_SESSION['calendardata']['current_event']['parent']) {
                // invitee event changed
                calendar_update_event_invitee($data);
            }
            else if ($data['serie_typ'] || $_SESSION['calendardata']['current_event']['serie_typ']) {
                // serial event changed
                calendar_update_event_serial($data);
            }
            else {
                // normal event changed
                calendar_update_event($data);
            }
            message_stack_in(__('Event successfully updated.'), 'calendar', 'notice');
            $ret = true;
            $mail_title  = __('Date changed').':'.$data['event'].": ";
            $mail_title .= "(".$data['datum'].', ';
            $mail_title .= $data['anfang'].' - '.$data['ende'].")";
            unset($_SESSION['calendardata']['current_event']);
        }
    }
    else if (isset($_REQUEST['action_remove_yes'])) {
        if ( $_SESSION['calendardata']['current_event']['parent'] ||
             $ID != $_SESSION['calendardata']['current_event']['ID'] ||
             ($act_for && $view == 4 && !calendar_can_act_for($act_for)) ) {
            message_stack_in(__('You are not allowed to remove this event!'), 'calendar', 'error');
            return false;
        }
        calendar_remove_event($ID);
        $ID = 0;
        message_stack_in(__('Event successfully removed.'), 'calendar', 'notice');
        $ret = true;
        $mail_title  = __('Date deleted').':'.$data['event']." ";
        $mail_title .= "(".$data['datum'].', ';
        $mail_title .= $data['anfang'].' - '.$data['ende'].")";
        unset($_SESSION['calendardata']['current_event']);
    }

    // do this stuff only if the checks and actions above don't went wrong!
    if ($ret) {
        if (!$data) $data = calendar_prepare_data(false);
        // Formdata may only be 0 or 1
        if (!isset($data['send_emailnotification']) ||
            ($data['send_emailnotification'] != '0' && $data['send_emailnotification'] != '1')) {
            $data['send_emailnotification'] = 0;
        }

        // send mail if wanted AND if there are invitees
        if ($data['send_emailnotification'] and count($data['invitees']) > 0 ) {
            // select shortnames for invitees
            $query = "SELECT kurz
                        FROM ".DB_PREFIX.".users
                       WHERE ID IN ('".implode("','", $data['invitees'])."')";
            $res = db_query($query) or db_die();
            $mail_recipient = array();
            while ($row = db_fetch_row($res)) {
                $mail_recipient[] = $row[0];
            }
            email_notification($mail_title, serialize($mail_recipient), '');
        }
    }
    return $ret;
}

/**
 * prepare and check data from form
 *
 * @param  boolean $check
 * @param  array $formdata Optional the data to insert. Defaults to global $formdata
 * @return array modified formdata
 */
function calendar_prepare_data($check=true, $formdata=null) {
    global $view, $user_ID, $act_for;

    // import formdata if needed
    if ($formdata === null) {
        $formdata = $GLOBALS['formdata'];
    }

    if ($view == 4 && $act_for) {
        $formdata['act_for'] = $act_for;
    }

    $formdata['event']  = trim($formdata['event']);
    $formdata['ort']    = trim($formdata['ort']);
    $formdata['remark'] = trim($formdata['remark']);

    if ( !isset($formdata['status']) ||
         ($formdata['status'] != '0' && $formdata['status'] != '1') ) {
        $formdata['status'] = '0';
    }

    if ($check && $formdata['event'] == '') {
        message_stack_in(__('Please give a text!'), 'calendar', 'error');
        return false;
    }

    $d = (int) substr($formdata['datum'], -2);
    $m = (int) substr($formdata['datum'], 5, 2);
    $y = (int) substr($formdata['datum'], 0, 4);

    if ($check && !checkdate($m, $d, $y)) {
        message_stack_in(__('Please check the event date!'), 'calendar', 'error');
        return false;
    }

    if ((!$formdata['anfang'] || $formdata['anfang'] == '----') &&
        (!$formdata['ende'] || $formdata['ende'] == '----')) {
        $formdata['anfang'] = '----';
        $formdata['ende']   = '----';
    }
    else {
        //$formdata['anfang'] = ereg_replace("[.:,;/]", '', $formdata['anfang']);
        //$formdata['ende']   = ereg_replace("[.:,;/]", '', $formdata['ende']);
        $formdata['anfang'] = calendar_format_incomingtime($formdata['anfang']);
        $formdata['ende']   = calendar_format_incomingtime($formdata['ende']);

        if ($check && !ereg("(^[0-9]*$)", $formdata['anfang']) || !ereg("(^[0-9]*$)", $formdata['ende']) ||
            $formdata['anfang'] < 0 || $formdata['ende'] > 2359 ||
            substr($formdata['anfang'], -2) > 59 || substr($formdata['ende'], -2) > 59) {
            message_stack_in(__('Please check your time format!'), 'calendar', 'error');
            return false;
        }

        // begin and end must have 4 digits ...
        $formdata['anfang'] = substr('0000'.$formdata['anfang'], -4);
        $formdata['ende']   = substr('0000'.$formdata['ende'], -4);

        if ($check && $formdata['anfang'] && $formdata['ende'] <= $formdata['anfang']) {
            message_stack_in(__('Please check start and end time!'), 'calendar', 'error');
            return false;
        }
    }

    // check the serial event entries
    if (calendar_serial_date_changed($formdata)) {
        if ($formdata['serie_typ'] && $formdata['serie_bis']) {
            $ds = (int) substr($formdata['serie_bis'], -2);
            $ms = (int) substr($formdata['serie_bis'], 5, 2);
            $ys = (int) substr($formdata['serie_bis'], 0, 4);

            if ($check && !checkdate($ms, $ds, $ys) || $formdata['serie_bis'] <= $formdata['datum']) {
                message_stack_in(__('Please check the serial event date!'), 'calendar', 'error');
                return false;
            }
            $formdata['new_serial_events'] = calendar_calculate_serial_events($formdata);
            if ($check && count($formdata['new_serial_events']) == 0) {
                message_stack_in(__('The serial event data has no result!'), 'calendar', 'error');
                return false;
            }
        }
        else {
            $formdata['serie_typ'] = '';
            $formdata['serie_bis'] = '';
        }
    }

    // add invitees
    $skip = ($act_for) ? $act_for : $user_ID;
    $invitees = array();
    if (is_array($formdata['invitees'])) {
        foreach ($formdata['invitees'] as $tmp_id) {
            $tmp_id = (int) $tmp_id;
            if ($tmp_id == 0 || $tmp_id == $skip) {
                continue;
            }
            $invitees[] = $tmp_id;
        }
    }
    $formdata['invitees'] = $invitees;

    // file upload
    $formdata['uploadfile'] = $_FILES['uploadfile'];

    return $formdata;
}

/**
 * calculate each event depending on the start-, enddate and the stepping
 *
 * @param  array $data
 * @return array
 */
function calendar_calculate_serial_events(&$data) {
    $ret = array();
// TODO: $max_serial_events should be defined as a constant in config.inc.php
    $max_serial_events = 55;
    $d = 0;
    $m = 0;
    $y = 0;

    if      ($data['serie_typ'] == 'd') $d = 1;
    else if ($data['serie_typ'] == 'w') $d = 7;
    else if ($data['serie_typ'] == 'm') $m = 1;
    else if ($data['serie_typ'] == 'y') $y = 1;
    else return $ret;

    $ts = calendar_get_timestamp_from_ymd($data['datum']);
    $te = calendar_get_timestamp_from_ymd($data['serie_bis']);

    // do this to start with the next event in serial
    // (the first one is added as a normal event)
    $ts = mktime(0,0,0, date('m',$ts)+$m, date('d',$ts)+$d, date('Y',$ts)+$y);
    $ii = 1;
    $last = '';
    while ($ts <= $te && $ii < $max_serial_events) {
        $last  = date('Y-m-d', $ts);
        $ret[] = $last;
        $ts = mktime(0,0,0, date('m',$ts)+$m, date('d',$ts)+$d, date('Y',$ts)+$y);
        $ii++;
    }
    // define here the real last date according to $max_serial_events
    if ($last) $data['serie_bis'] = $last;
    return $ret;
}

/**
 * add an event, doing the logical stuff
 *
 * @param  array   $data the checked data from the form
 * @return integer the db id of the new event
 */
function calendar_add_event($data) {
    global $user_ID, $dbIDnull, $dbTSnull;

    $data['ID']       = $dbIDnull;
    $data['parent']   = 0;
    $data['von']      = $user_ID;
    $data['an']       = ($data['act_for']) ? $data['act_for'] : $user_ID;
    $data['event']    = addslashes($data['event']);
    $data['remark']   = addslashes($data['remark']);
    $data['ort']      = addslashes($data['ort']);
    // visi & partstat have been defined in the form
    //$data['visi']     = 0;
    //$data['partstat'] = 2;
    $data['sync1']    = $dbTSnull;
    $data['sync2']    = $dbTSnull;

    if (isset($data['uploadfile']['error'])) {
        $data['upload'] = calendar_get_upload_value($data['uploadfile']['error']);
    }
    else {
        $data['upload'] = '';
    }

    // add this one for the owner..
    calendar_add_event_db($data);
    // get (hopefully) the id of the last added entry
    $id = calendar_get_last_added_id($data);
    if ($id) {
        if (isset($data['invitees']) && count($data['invitees'])) {
            calendar_add_event_invitees($id, $data);
        }
        if ($data['serie_typ']) {
            calendar_add_serial_events($id, $data);
        }
    }
    return $id;
}

/**
 * add invitees to an event
 *
 * @param  array $id the parent db id
 * @param  array $data the checked data from the form
 * @return void
 */
function calendar_add_event_invitees($id, $data) {
    global $dbIDnull, $dbTSnull;

    $data['ID']       = $dbIDnull;
    $data['parent']   = $id;
    $data['sync1']    = $dbTSnull;
    $data['partstat'] = 1;

    // add the events for the invitees
    $values = array();
    foreach ($data['invitees'] as $invitee) {
        $data['an'] = $invitee;
        $values[] = $data;
    }
    calendar_add_event_db($values, true);
}

function calendar_add_serial_events($id, $data) {
    global $dbIDnull, $dbTSnull;

    $data['ID']       = $dbIDnull;
    $data['serie_id'] = $id;

    // add the serial events
    for ($ii=0; $ii<count($data['new_serial_events']); $ii++) {
        $data['datum'] = $data['new_serial_events'][$ii];
        calendar_add_event_db($data);
        $id = calendar_get_last_added_id($data);
        if ($id && isset($data['invitees']) && count($data['invitees'])) {
            calendar_add_event_invitees($id, $data);
        }
    }
}

/**
 * add an event, doing the database stuff
 *
 * @param  array   $event the checked data from the form or an multiple array
 * @param  boolean $multiple
 * @return void
 */
function calendar_add_event_db(&$event, $multiple=false) {
    $data = array();

    if ($multiple) $data    = $event;
    else           $data[0] = $event;

    for ($ii=0; $ii<count($data); $ii++) {
        $values = "(".$data[$ii]['ID'].",          '".$data[$ii]['parent']."',   '".$data[$ii]['von']."',
                    '".$data[$ii]['an']."',        '".$data[$ii]['event']."',    '".$data[$ii]['remark']."',
                    '".$data[$ii]['projekt']."',   '".$data[$ii]['datum']."',    '".$data[$ii]['anfang']."',
                    '".$data[$ii]['ende']."',      '".$data[$ii]['serie_id']."', '".$data[$ii]['serie_typ']."',
                    '".$data[$ii]['serie_bis']."', '".$data[$ii]['ort']."',      '".$data[$ii]['contact']."',
                    '".$data[$ii]['remind']."',    '".$data[$ii]['visi']."',     '".$data[$ii]['partstat']."',
                    '".$data[$ii]['priority']."',  '".$data[$ii]['sync1']."',    '".$data[$ii]['sync2']."',
                    '".$data[$ii]['upload']."',    '".$data[$ii]['status']."')";
        $query = "INSERT INTO ".DB_PREFIX."termine
                              (ID, parent, von, an, event, remark, projekt, datum, anfang, ende,
                               serie_id, serie_typ, serie_bis, ort, contact, remind, visi, partstat,
                               priority, sync1, sync2, upload, status)
                       VALUES ".xss($values);
        $res = db_query($query) or db_die();
    }
}

/**
 * get the db id of the last added event
 *
 * @param  array $data the checked data from the form
 * @return mixed the db id or false on error/not found
 */
function calendar_get_last_added_id(&$data) {
    $ret = false;
    $query = "SELECT ID
                FROM ".DB_PREFIX."termine
               WHERE von      = '".$data['von']."'
                 AND an       = '".$data['an']."'
                 AND projekt  = '".$data['projekt']."'
                 AND datum    = '".$data['datum']."'
                 AND anfang   = '".$data['anfang']."'
                 AND ende     = '".$data['ende']."'
                 AND contact  = '".$data['contact']."'
                 AND priority = '".$data['priority']."'
                 AND visi     = '".$data['visi']."'
                 AND sync1    = '".$data['sync1']."'
                 AND sync2    = '".$data['sync2']."'";
    $res = db_query($query) or db_die();
    $row = db_fetch_row($res);
    if ($row[0]) $ret = $row[0];
    return $ret;
}

/**
 * update an event of an invitee which is only allowed to
 * change some fields..
 *
 * @param  array $data the checked data from the form
 * @return void
 */
function calendar_update_event_invitee($data) {
    global $user_ID, $dbTSnull;

    $act_for_user = "'".implode("','", calendar_get_represented_user('proxy'))."'";

    $data['sync2'] = $dbTSnull;
    $query = "UPDATE ".DB_PREFIX."termine
                 SET partstat = '".$data['partstat']."',
                     sync2    = '".$data['sync2']."'
               WHERE ID = '".$data['ID']."'
                 AND (an = '$user_ID' OR an IN ($act_for_user))";
    $res = db_query(xss($query)) or db_die();
}

/**
 * update an event (and all the stuff of the invitees and serial events)
 *
 * @param  array $data the checked data from the form
 * @return void
 */
function calendar_update_event($data) {
    global $user_ID, $dbTSnull;

    $act_for_user = "'".implode("','", calendar_get_represented_user('proxy'))."'";

    $data['von']      = $user_ID;
    $data['event']    = addslashes($data['event']);
    $data['ort']      = addslashes($data['ort']);
    $data['remark']   = addslashes($data['remark']);
// TODO: should we update this to a new value ?!?! => $data['visi'] = ?;
// TODO: should we update this to a new value ?!?! => $data['priority'] = ?;
    $data['sync2']    = $dbTSnull;

    if (isset($data['uploadfile']['error'])) {
        $data['upload'] = calendar_get_upload_value($data['uploadfile']['error']);
    }
    else {
        $data['upload'] = $_SESSION['calendardata']['current_event']['upload'];
    }

    // remove event entries of no-more-selected invitees..
    calendar_remove_event_invitees($data);

    $serie_id = calendar_get_current_serie_id();
    // update my own data
    $special = array( 'datum'    => $data['datum'],
                      'where'    => "(ID = '".$data['ID']."'",
                      'partstat' => $data['partstat'] );
    if ($serie_id && $serie_id != $data['ID']) {
        $special['datum'] = '';
        $special['where'] .= " OR ID = '$serie_id'";
    }
    $special['where'] .= ") AND (an = '$user_ID' OR an IN ($act_for_user))";
    calendar_update_event_db($data, $special);

    // update the data of invitees
    $special = array( 'datum'    => $data['datum'],
                      'where'    => "parent = '".$data['ID']."'",
                      'partstat' => '' );
    if (calendar_event_date_changed($data)) {
        $special['partstat'] = '1';
    }
    if ($serie_id) {
        $special['datum'] = '';
        $special['where'] .= " OR parent = '$serie_id' OR serie_id = '$serie_id'";
    }
    calendar_update_event_db($data, $special);

    // add new invitees..
    $data2 = $data;
    $data2['invitees'] = array_diff($data2['invitees'], $_SESSION['calendardata']['current_event']['invitees']);
    if (count($data2['invitees'])) {
        if ($serie_id) {
            // for serial events
            calendar_add_serial_event_invitees($data2);
        }
        else {
            // for normal events
            calendar_add_event_invitees($data2['ID'], $data2);
        }
    }
}

/**
 * update a serial event
 *
 * @param  array $data the checked data from the form
 * @return void
 */
function calendar_update_event_serial(&$data) {
    if (calendar_serial_date_changed($data)) {
        // IF this was previously a serial event and it is now switched to a normal one
        // OR this was previously a normal event and it is now switched to a serial one
        // OR the main date data is changed so we have to calculate a completely new
        //    serial event, then ..
        // 1. delete all events in the db with corresponding ids,
        //    but keep the uploaded file, if available
        // 2. create a lonely new one event with the data of the form
// TODO: check if the upload stuff works this way with an already existing upload
// TODO: check also what happens if a new file was uploaded at the same time with this update
        $save_upload = $_SESSION['calendardata']['current_event']['upload'];
        $_SESSION['calendardata']['current_event']['upload'] = '';
        calendar_remove_event($data['ID']);
        $_SESSION['calendardata']['current_event']['upload'] = $save_upload;
        calendar_add_event($data);
    }
    else {
        // the main date data is NOT changed so we have to make the common
        // update routine..
        calendar_update_event($data);
    }
}

function calendar_add_serial_event_invitees($data) {
    global $user_ID, $dbIDnull, $dbTSnull;

    $serie_id = calendar_get_current_serie_id();
    $query = "SELECT DISTINCT parent, serie_id, datum
                FROM ".DB_PREFIX."termine
               WHERE (parent > 0 AND serie_id = '$serie_id')
                  OR parent = '$serie_id'";
    $res = db_query($query) or db_die();
    while ($row = db_fetch_row($res)) {
        $data['serie_id'] = $row[1];
        $data['datum']    = $row[2];
        calendar_add_event_invitees($row[0], $data);
    }
}

/**
 * do the event update on db
 *
 * @param  array  $data the checked data from the form
 * @param  array  $special special control data
 * @return void
 */
function calendar_update_event_db(&$data, &$special) {
    $datum    = ($special['datum'])       ? "datum = '".$special['datum']."'," : '';
    $partstat = ($special['partstat'])    ? "partstat = '".$special['partstat']."'," : '';
    $upload   = (strlen($data['upload'])) ? "upload = '".$data['upload']."'," : '';

    $query = "UPDATE ".DB_PREFIX."termine
                 SET von       = '".$data['von']."',
                     event     = '".$data['event']."',
                     remark    = '".$data['remark']."',
                     projekt   = '".$data['projekt']."',
                     anfang    = '".$data['anfang']."',
                     ende      = '".$data['ende']."',
                     ort       = '".$data['ort']."',
                     contact   = '".$data['contact']."',
                     priority  = '".$data['priority']."',
                     ".$datum."
                     ".$partstat."
                     ".$upload."
                     serie_typ = '".$data['serie_typ']."',
                     serie_bis = '".$data['serie_bis']."',
                     visi      = '".$data['visi']."',
                     sync2     = '".$data['sync2']."',
                     status    = '".$data['status']."'
               WHERE ".$special['where'];
    $res = db_query(xss($query)) or db_die();
}

/**
 * removes an event (and all the stuff of the invitees and serial events)
 *
 * @param  integer $id
 * @return void
 */
function calendar_remove_event($id) {
    global $user_ID, $lib_path;

    $act_for_user = "'".implode("','", calendar_get_represented_user('proxy'))."'";

    // delete an uploaded file, if available
    if ($_SESSION['calendardata']['current_event']['upload']) {
        include_once($lib_path.'/dbman_data.inc.php');
        delete_attached_file('upload', $id, 'calendar');
    }

    if ($serie_id = calendar_get_current_serie_id()) {
        // delete all serial events which belongs to this event
        $where = "((ID = '$id' OR ID = '$serie_id') AND (an = '$user_ID' OR an IN ($act_for_user)))
                  OR parent = '$id' OR parent = '$serie_id' OR serie_id = '$serie_id'";
    }
    else {
        // if this is not a serial event
        $where = "(ID = '$id' AND (an = '$user_ID' OR an IN ($act_for_user))) OR parent = '$id'";
    }

    $query = "DELETE FROM ".DB_PREFIX."termine
                    WHERE $where";
    $res = db_query($query) or db_die();
}

/**
 * removes all events which belongs to the given invitees
 *
 * @param  array $data the checked data from the form
 * @return void
 */
function calendar_remove_event_invitees($data) {
    $data['invitees'][] = 0;
    $where = '';
    // delete also all serial events which belongs to this event
    if ($serie_id = calendar_get_current_serie_id()) {
        $where = "OR parent = '$serie_id' OR (parent > 0 AND serie_id = '$serie_id')";
    }
    $query = "DELETE FROM ".DB_PREFIX."termine
                    WHERE (parent = '".$data['ID']."' $where)
                      AND an NOT IN ('".implode("','", $data['invitees'])."')";
    $res = db_query($query) or db_die();
}

/**
 * check if the event date (form) differs from origin (db)
 *
 * @param  array   $data
 * @return boolean
 */
function calendar_event_date_changed(&$data) {
    if ( isset($_SESSION['calendardata']['current_event']) &&
         $_SESSION['calendardata']['current_event']['datum']  == $data['datum'] &&
         $_SESSION['calendardata']['current_event']['anfang'] == $data['anfang'] &&
         $_SESSION['calendardata']['current_event']['ende']   == $data['ende'] ) {
        return false;
    }
    return true;
}

/**
 * check if the serial date (form) differs from origin (db)
 *
 * @param  array   $data
 * @return boolean
 */
function calendar_serial_date_changed(&$data) {
    if ( isset($_SESSION['calendardata']['current_event']) &&
         $_SESSION['calendardata']['current_event']['datum']     == $data['datum'] &&
         $_SESSION['calendardata']['current_event']['serie_typ'] == $data['serie_typ'] &&
         $_SESSION['calendardata']['current_event']['serie_bis'] == $data['serie_bis'] ) {
        return false;
    }
    return true;
}

/**
 * get the timestamp of a date in the format "yyyy-mm-dd"
 *
 * @param  string  $data
 * @return integer
 */
function calendar_get_timestamp_from_ymd(&$data) {
    $d = (int) substr($data, -2);
    $m = (int) substr($data, 5, 2);
    $y = (int) substr($data, 0, 4);
    return mktime(0,0,0, $m, $d, $y);
}

?>
