/** * adds xref repeats to the database. * * @return bool true on success */ function generaterecurrences($recurrence_id = null) { $db =& JFactory::getDBO(); $nulldate = '0000-00-00'; // generate until limit $params =& JComponentHelper::getParams('com_redevent'); $limit = $params->get('recurrence_limit', 30); $limit_date_int = time() + $limit * 3600 * 24; // get active recurrences $query = ' SELECT MAX(rp.xref_id) as xref_id, r.rrule, r.id as recurrence_id ' . ' FROM #__redevent_repeats AS rp ' . ' INNER JOIN #__redevent_recurrences AS r on r.id = rp.recurrence_id ' . ' INNER JOIN #__redevent_event_venue_xref AS x on x.id = rp.xref_id ' . ' WHERE r.ended = 0 ' . ' AND x.dates > 0 '; if ($recurrence_id) { $query .= ' AND r.id = ' . $db->Quote($recurrence_id); } $query .= ' GROUP BY rp.recurrence_id '; $db->setQuery($query); $recurrences = $db->loadObjectList(); if (empty($recurrences)) { return true; } // get corresponding xrefs $rids = array(); foreach ($recurrences as $r) { $rids[] = $r->xref_id; } $query = ' SELECT x.*, rp.count ' . ' FROM #__redevent_event_venue_xref AS x ' . ' INNER JOIN #__redevent_repeats AS rp ON rp.xref_id = x.id ' . ' WHERE x.id IN (' . implode(",", $rids) . ')'; $db->setQuery($query); $xrefs = $db->loadObjectList('id'); // now, do the job... foreach ($recurrences as $r) { $next = RedeventHelperRecurrence::getnext($r->rrule, $xrefs[$r->xref_id]); while ($next) { if (strtotime($next->dates) > $limit_date_int) { break; } //record xref $object =& JTable::getInstance('RedEvent_eventvenuexref', ''); $object->bind($next); if ($object->store()) { // copy the roles $query = ' INSERT INTO #__redevent_sessions_roles (xref, role_id, user_id) ' . ' SELECT ' . $object->id . ', role_id, user_id ' . ' FROM #__redevent_sessions_roles ' . ' WHERE xref = ' . $db->Quote($r->xref_id); $db->setQuery($query); if (!$db->query()) { RedeventHelperLog::simpleLog('recurrence copying roles error: ' . $db->getErrorMsg()); } // copy the prices $query = ' INSERT INTO #__redevent_sessions_pricegroups (xref, pricegroup_id, price) ' . ' SELECT ' . $object->id . ', pricegroup_id, price ' . ' FROM #__redevent_sessions_pricegroups ' . ' WHERE xref = ' . $db->Quote($r->xref_id); $db->setQuery($query); if (!$db->query()) { RedeventHelperLog::simpleLog('recurrence copying prices error: ' . $db->getErrorMsg()); } // update repeats table $query = ' INSERT INTO #__redevent_repeats ' . ' SET xref_id = ' . $db->Quote($object->id) . ' , recurrence_id = ' . $db->Quote($r->recurrence_id) . ' , count = ' . $db->Quote($next->count); $db->setQuery($query); if (!$db->query()) { RedeventHelperLog::simpleLog('saving repeat error: ' . $db->getErrorMsg()); } // echo "added xref $object->id / count $next->count"; // echo '<br>'; } else { RedeventHelperLog::simpleLog('saving recurrence xref error: ' . $db->getErrorMsg()); } $next = RedeventHelperRecurrence::getnext($r->rrule, $next); } if (!$next) { // no more events to generate, we can disable the rule $query = ' UPDATE #__redevent_recurrences SET ended = 1 WHERE id = ' . $db->Quote($r->recurrence_id); $db->setQuery($query); $db->query(); } } return true; }
function getnext($recurrence, $last_xref, JRegistry $params = null) { $rule = RedeventHelperRecurrence::getRule($recurrence); if ($params === null) { $params =& JComponentHelper::getParams('com_redevent'); } $week_start = $params->get('week_start', 'SU'); // echo '<pre>';print_r($rule); echo '</pre>';exit; // print_r($last_xref); $new = false; // check the count if ($rule->until_type == 'count' && $last_xref->count >= $rule->count) { return false; } $days_name = array('SU' => 'sunday', 'MO' => 'monday', 'TU' => 'tuesday', 'WE' => 'wednesday', 'TH' => 'thursday', 'FR' => 'friday', 'SA' => 'saturday'); $days_number = array('SU' => 0, 'MO' => 1, 'TU' => 2, 'WE' => 3, 'TH' => 4, 'FR' => 5, 'SA' => 6, 'SU' => 7); $xref_start = strtotime($last_xref->dates); // get the next start timestamp switch ($rule->type) { case 'DAILY': $next_start = strtotime($last_xref->dates . " +" . $rule->interval . " day"); break; case 'WEEKLY': // calculate next dates for all set weekdays $next = array(); if (!$rule->weekdays || !count($rule->weekdays)) { // force to the day of previous session $rule->weekdays = array(array_search(date('N', strtotime($last_xref->dates)), $days_number)); } foreach ($rule->weekdays as $d) { if ($week_start == 'SU') { $current = strftime('%w', $xref_start); } else { $current = strftime('%u', $xref_start); } if ($days_number[$d] > $current) { $next[] = strtotime('+1 ' . $days_name[$d], strtotime($last_xref->dates)); } else { if ($days_number[$d] == $current) { // same day, look in next intervall, after this day $next[] = strtotime('+' . $rule->interval . ' ' . $days_name[$d], strtotime($last_xref->dates) + 3600 * 24); } else { // in next intervall $next[] = strtotime('+' . $rule->interval . ' ' . $days_name[$d], strtotime($last_xref->dates)); } } } // the next one is the lowest value $next_start = min($next); break; case 'MONTHLY': if ($rule->monthtype == 'byday') { // first day of this month $first_this = mktime(0, 0, 0, strftime('%m', $xref_start), 1, strftime('%Y', $xref_start)); // last day of this month $last_this = mktime(0, 0, 0, strftime('%m', $xref_start) + 1, 0, strftime('%Y', $xref_start)); // first day of +interval month $first_next_interval = mktime(0, 0, 0, strftime('%m', $xref_start) + $rule->interval, 1, strftime('%Y', $xref_start)); // last day of this month $last_next_interval = mktime(0, 0, 0, strftime('%m', $xref_start) + 1 + $rule->interval, 0, strftime('%Y', $xref_start)); $days = array(); // print_r($rule); foreach ($rule->weeks as $week) { foreach ($rule->weekdays as $day) { $int_day = strtotime($week . ' ' . $days_name[$day], $first_this); if ($int_day > $xref_start && $int_day <= $last_this) { $days[] = $int_day; } $int_day = strtotime($week . ' ' . $days_name[$day], $first_next_interval); if ($int_day > $xref_start && $int_day <= $last_next_interval) { $days[] = $int_day; } } } foreach ($rule->rweeks as $week) { foreach ($rule->rweekdays as $day) { $int_day = strtotime('-' . $week . ' ' . $days_name[$day], $last_this + 24 * 3600); if ($int_day > $xref_start && $int_day >= $first_this) { $days[] = $int_day; } $int_day = strtotime('-' . $week . ' ' . $days_name[$day], $last_next_interval + 24 * 3600); if ($int_day > $xref_start && $int_day >= $first_next_interval) { $days[] = $int_day; } } } $next_start = min($days); } else { $current = strftime('%d', strtotime($last_xref->dates)); if (!$rule->bydays || !count($rule->bydays)) { // force to the day of previous session $rule->bydays = array(date('d', strtotime($last_xref->dates))); } if (!$rule->reverse_bydays) { sort($rule->bydays); $next_day = null; foreach ($rule->bydays as $day) { if ($day > $current) { $next_day = $day; break; } } if ($next_day == null) { $year_month = strftime('%Y-%m', strtotime(date("Y-m-1", strtotime($last_xref->dates)) . ' + ' . $rule->interval . " months")); $next_start = strtotime($year_month . '-' . $rule->bydays[0]); } else { $year_month = strftime('%Y-%m', strtotime($last_xref->dates)); $next_start = strtotime($year_month . '-' . $next_day); } } else { $current_sec = strtotime($last_xref->dates); $next = array(); foreach ($rule->bydays as $day) { // we need to check the dates for this month, and the +interval month $dd = strtotime(date("Y-m-1", strtotime($last_xref->dates)) . ' + 1 months -' . $day . ' day'); if ($dd > $current_sec) { $next[] = $dd; } $dd = strtotime(date("Y-m-1", strtotime($last_xref->dates)) . ' +' . (1 + $rule->interval) . ' months -' . $day . ' days', strtotime($last_xref->dates)); if ($dd > $current_sec) { $next[] = $dd; } } // the next is the closest, lower value $next_start = min($next); } } break; case 'YEARLY': $current = strtotime($last_xref->dates); if (empty($rule->bydays)) { $next_start = mktime(0, 0, 0, strftime('%m', $current), strftime('%d', $current), strftime('%Y', $current) + $rule->interval); } else { if (!$rule->reverse_bydays) { sort($rule->bydays); $next_day = $rule->bydays[0]; foreach ($rule->bydays as $day) { if ($day > $current) { $next_day = $day; break; } } if ($next_day == $rule->bydays[0]) { $next_start = mktime(0, 0, 0, 1, $next_day, strftime('%Y', strtotime($last_xref->dates)) + 1); } else { $next_start = mktime(0, 0, 0, 1, $next_day, strftime('%Y', strtotime($last_xref->dates))); } } else { // total days in this year $total = strftime('%j', mktime(0, 0, 0, 1, 0, strftime('%Y', strtotime($last_xref->dates)) + 1)); $rev_days = array(); // get number in proper order rsort($rule->bydays); foreach ($rule->bydays as $day) { $rev_days[] = $total - $day + 1; } $next_day = null; foreach ($rev_days as $day) { if ($day > $current) { $next_day = $day; break; } } if ($next_day == null) { $next_start = mktime(0, 0, 0, 1, -$rule->bydays[0], strftime('%Y', strtotime($last_xref->dates)) + 1 + $rule->interval); } else { $next_start = mktime(0, 0, 0, 1, $next_day, strftime('%Y', strtotime($last_xref->dates))); } } } break; case 'NONE': default: break; } if (!isset($next_start) || !$next_start) { return false; } // check the until rule if ($rule->until_type == 'until' && strtotime(strftime('%Y-%m-%d', $next_start) . ' ' . $last_xref->times) > strtotime($rule->until)) { return false; } $delta = $next_start - strtotime($last_xref->dates); if (!$delta) { // no delta, so same session... return false; } // return the new occurence $new = clone $last_xref; unset($new->id); $new->dates = strftime('%Y-%m-%d', $next_start); if (strtotime($last_xref->enddates)) { $new->enddates = strftime('%Y-%m-%d', strtotime($last_xref->enddates) + $delta); } if (strtotime($last_xref->registrationend)) { $new->registrationend = strftime('%Y-%m-%d', strtotime($last_xref->registrationend) + $delta); } $new->count++; // echo '<pre>';print_r($new); echo '</pre>';exit; // print_r($new); // exit; return $new; }
/** * Saves xref data * @param array * @return boolean true on success */ function storeXref($data) { $user =& JFactory::getUser(); $settings =& redEVENTHelper::config(); // TODO : check user group access ? $row =& JTable::getInstance('RedEvent_eventvenuexref', ''); if ($data['id']) { if (!$this->canManageXref($data['id'])) { $this->setError('YOU ARE NOT ALLOWED TO EDIT THIS DATE'); return false; } $row->load($data['id']); } else { if (!$this->getCanAddXref()) { $this->setError('YOU ARE NOT ALLOWED TO ADD EVENT DATE'); return false; } } if (!$row->bind($data)) { $this->setError('SUBMIT XREF ERROR BINDING DATA'); RedeventHelperLog::simplelog('SUBMIT XREF ERROR BINDING DATA'); return false; } if (!$row->check()) { $this->setError('SUBMIT XREF ERROR CHECK DATA'); RedeventHelperLog::simplelog('SUBMIT XREF ERROR CHECK DATA'); return false; } if (!$row->store(true)) { $this->setError('SUBMIT XREF ERROR STORE DATA'); RedeventHelperLog::simplelog('SUBMIT XREF ERROR STORE DATA'); return false; } /** roles **/ // first remove current rows $query = ' DELETE FROM #__redevent_sessions_roles ' . ' WHERE xref = ' . $this->_db->Quote($row->id); $this->_db->setQuery($query); if (!$this->_db->query()) { $this->setError($this->_db->getErrorMsg()); return false; } // then recreate them if any foreach ((array) $data['rrole'] as $k => $r) { if (!($data['rrole'][$k] && $data['urole'][$k])) { continue; } $new =& JTable::getInstance('RedEvent_sessions_roles', ''); $new->set('xref', $row->id); $new->set('role_id', $r); $new->set('user_id', $data['urole'][$k]); if (!($new->check() && $new->store())) { $this->setError($new->getError()); return false; } } /** roles END **/ /** prices **/ // first remove current rows $query = ' DELETE FROM #__redevent_sessions_pricegroups ' . ' WHERE xref = ' . $this->_db->Quote($row->id); $this->_db->setQuery($query); if (!$this->_db->query()) { $this->setError($this->_db->getErrorMsg()); return false; } // then recreate them if any foreach ((array) $data['pricegroup'] as $k => $r) { if (!$data['pricegroup'][$k]) { continue; } $new =& JTable::getInstance('RedEvent_sessions_pricegroups', ''); $new->set('xref', $row->id); $new->set('pricegroup_id', $r); $new->set('price', $data['price'][$k]); if (!($new->check() && $new->store())) { $this->setError($new->getError()); return false; } } /** prices END **/ // we need to save the recurrence too $recurrence =& JTable::getInstance('RedEvent_recurrences', ''); if (!isset($data['recurrenceid']) || !$data['recurrenceid']) { $rrule = RedeventHelperRecurrence::parsePost($data); if (!empty($rrule)) { // new recurrence $recurrence->rrule = $rrule; if (!$recurrence->store()) { $this->setError($recurrence->getError()); return false; } // add repeat record $repeat =& JTable::getInstance('RedEvent_repeats', ''); $repeat->set('xref_id', $row->id); $repeat->set('recurrence_id', $recurrence->id); $repeat->set('count', 0); if (!$repeat->store()) { $this->setError($repeat->getError()); return false; } } } else { if ($data['repeat'] == 0) { $recurrence->load($data['recurrenceid']); // reset the status $recurrence->ended = 0; // TODO: maybe add a check to have a choice between updating rrule or not... $rrule = RedeventHelperRecurrence::parsePost($data); $recurrence->rrule = $rrule; if (!$recurrence->store()) { $this->setError($recurrence->getError()); return false; } } } if ($recurrence->id) { redEVENTHelper::generaterecurrences($recurrence->id); } return true; }
/** * save xref data * * @param array $data * @return boolean true on success */ function savexref($data) { $id = (int) $data['id']; $object =& JTable::getInstance('RedEvent_eventvenuexref', ''); if ($id) { $object->load($id); } if (!$object->bind($data)) { $this->setError($object->getError()); return false; } if (!$object->check()) { $this->setError($object->getError()); return false; } if (!$object->store(true)) { $this->setError($object->getError()); return false; } // we need to save the recurrence too $recurrence =& JTable::getInstance('RedEvent_recurrences', ''); if (!$data['recurrenceid']) { $rrule = RedeventHelperRecurrence::parsePost($data); if (!empty($rrule)) { // new recurrence $recurrence->rrule = $rrule; if (!$recurrence->store()) { $this->setError($recurrence->getError()); return false; } // add repeat record $repeat =& JTable::getInstance('RedEvent_repeats', ''); $repeat->set('xref_id', $object->id); $repeat->set('recurrence_id', $recurrence->id); $repeat->set('count', 0); if (!$repeat->store()) { $this->setError($repeat->getError()); return false; } } } else { if ($data['repeat'] == 0) { $recurrence->load($data['recurrenceid']); // reset the status $recurrence->ended = 0; // TODO: maybe add a check to have a choice between updating rrule or not... $rrule = RedeventHelperRecurrence::parsePost($data); $recurrence->rrule = $rrule; if (!$recurrence->store()) { $this->setError($recurrence->getError()); return false; } } } if ($recurrence->id) { redEVENTHelper::generaterecurrences($recurrence->id); } /** roles **/ // first remove current rows $query = ' DELETE FROM #__redevent_sessions_roles ' . ' WHERE xref = ' . $this->_db->Quote($object->id); $this->_db->setQuery($query); if (!$this->_db->query()) { $this->setError($this->_db->getErrorMsg()); return false; } // then recreate them if any foreach ((array) $data['rrole'] as $k => $r) { if (!($data['rrole'][$k] && $data['urole'][$k])) { continue; } $new =& JTable::getInstance('RedEvent_sessions_roles', ''); $new->set('xref', $object->id); $new->set('role_id', $r); $new->set('user_id', $data['urole'][$k]); if (!($new->check() && $new->store())) { $this->setError($new->getError()); return false; } } /** roles END **/ /** prices **/ // first remove current rows $query = ' DELETE FROM #__redevent_sessions_pricegroups ' . ' WHERE xref = ' . $this->_db->Quote($object->id); $this->_db->setQuery($query); if (!$this->_db->query()) { $this->setError($this->_db->getErrorMsg()); return false; } // then recreate them if any foreach ((array) $data['pricegroup'] as $k => $r) { if (!$data['pricegroup'][$k]) { continue; } $new =& JTable::getInstance('RedEvent_sessions_pricegroups', ''); $new->set('xref', $object->id); $new->set('pricegroup_id', $r); $new->set('price', $data['price'][$k]); if (!($new->check() && $new->store())) { $this->setError($new->getError()); return false; } } /** prices END **/ return $object->id; }