forked from GNUsocial/gnu-social
Merge remote-tracking branch 'origin/1.0.x' into 1.0.x
This commit is contained in:
commit
5eba1030ae
@ -161,9 +161,11 @@ abstract class Managed_DataObject extends Memcached_DataObject
|
||||
|
||||
foreach ($table['foreign keys'] as $keyname => $keydef) {
|
||||
if (count($keydef) == 2 && is_string($keydef[0]) && is_array($keydef[1]) && count($keydef[1]) == 1) {
|
||||
if (isset($keydef[1][0])) {
|
||||
$links[$keydef[1][0]] = $keydef[0].':'.$keydef[1][1];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $links;
|
||||
}
|
||||
}
|
@ -1,73 +1,144 @@
|
||||
$(document).ready(function() {
|
||||
|
||||
var today = new Date();
|
||||
// get current time from server
|
||||
var today = new Date($('now').val());
|
||||
|
||||
$("#event-startdate").datepicker({
|
||||
// Don't let the user set a crazy start date
|
||||
// Don't let the user set a start date < before today
|
||||
minDate: today,
|
||||
onClose: function(dateText, picker) {
|
||||
// Don't let the user set a crazy end date
|
||||
var newStartDate = new Date(dateText);
|
||||
var endDate = new Date($("#event-startdate").val());
|
||||
if (endDate < newStartDate) {
|
||||
$("#event-enddate").val(dateText);
|
||||
}
|
||||
if (dateText !== null) {
|
||||
$("#event-enddate").datepicker('option', 'minDate', new Date(dateText));
|
||||
}
|
||||
},
|
||||
onSelect: function() {
|
||||
var startd = $("#event-startdate").val();
|
||||
var endd = $("#event-enddate").val();
|
||||
var sdate = new Date(startd);
|
||||
var edate = new Date(endd);
|
||||
if (sdate !== edate) {
|
||||
updateTimes();
|
||||
}
|
||||
}
|
||||
onClose: onStartDateSelected
|
||||
});
|
||||
|
||||
$("#event-enddate").datepicker({
|
||||
minDate: today,
|
||||
onSelect: function() {
|
||||
var startd = $("#event-startdate").val();
|
||||
var endd = $("#event-enddate").val();
|
||||
var sdate = new Date(startd);
|
||||
var edate = new Date(endd);
|
||||
if (sdate !== edate) {
|
||||
updateTimes();
|
||||
}
|
||||
}
|
||||
onClose: onEndDateSelected
|
||||
});
|
||||
|
||||
function updateTimes() {
|
||||
var startd = $("#event-startdate").val();
|
||||
var endd = $("#event-enddate").val();
|
||||
$("#event-starttime").change(function(e) {
|
||||
var tz = $("#tz").val();
|
||||
|
||||
var startt = $("#event-starttime option:selected").val();
|
||||
var endt = $("#event-endtime option:selected").val();
|
||||
var startDate = $("#event-startdate").val();
|
||||
var startTime = $("#event-starttime option:selected").val().replace(/(pm|am)/, ' $1');
|
||||
var startStr = startDate + ' ' + startTime + ' ' + tz;
|
||||
|
||||
var sdate = new Date(startd + " " + startt);
|
||||
var edate = new Date(endd + " " + endt);
|
||||
var duration = (startd === endd);
|
||||
var endDate = $("#event-enddate").val();
|
||||
var endTime = $("#event-endtime option:selected").val();
|
||||
var endStr = endDate + ' ' + endTime.replace(/(pm|am)/, ' $1') + ' ' + tz;
|
||||
|
||||
$.getJSON($('#timelist_action_url').val(),
|
||||
{ start: startt, ajax: true, duration: duration },
|
||||
function(data) {
|
||||
// just need to compare hours
|
||||
var start = new Date(startStr);
|
||||
var end = new Date(endStr);
|
||||
|
||||
updateTimes(startStr, (startDate === endDate), function (data) {
|
||||
var times = [];
|
||||
$.each(data, function(key, val) {
|
||||
times.push('<option value="' + key + '">' + val + '</option>');
|
||||
});
|
||||
|
||||
$("#event-endtime").html(times.join(''));
|
||||
if (startt < endt) {
|
||||
$("#event-endtime").val(endt).attr("selected", "selected");
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
$("#event-starttime").change(function(e) {
|
||||
updateTimes();
|
||||
if (start > end) {
|
||||
$("#event-endtime").val(startTime).attr("selected", "selected");
|
||||
} else {
|
||||
$("#event-endtime").val(endTime).attr("selected", "selected");
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
$("#event-endtime").change(function(e) {
|
||||
var HOUR = 60 * 60 * 1000;
|
||||
var tz = $("#tz").val();
|
||||
var startDate = $("#event-startdate").val();
|
||||
var endDate = $("#event-enddate").val();
|
||||
var starttime = $("#event-starttime option:selected").val();
|
||||
var endtime = $("#event-endtime option:selected").val();
|
||||
var endtimeText = $("#event-endtime option:selected").text();
|
||||
|
||||
// If the end time is in the next day then update the start date
|
||||
if (startDate === endDate) {
|
||||
var startstr = startDate + ' ' + starttime.replace(/(pm|am)/, ' $1') + ' ' + tz;
|
||||
var start = new Date(startstr);
|
||||
var matches = endtimeText.match(/\(.*\)/);
|
||||
var hours;
|
||||
if (matches) {
|
||||
hours = matches[0].substr(1).split(' ')[0]; // get x from (x hours)
|
||||
if (hours) {
|
||||
if (hours == 30) {
|
||||
hours = .5; // special case: x == 30 from (30 mins)
|
||||
}
|
||||
var end = new Date(start.getTime() + (hours * HOUR));
|
||||
if (end.getDate() > start.getDate()) {
|
||||
$("#event-enddate").datepicker('setDate', end);
|
||||
var endstr = endDate + ' 12:00 am ' + tz;
|
||||
updateTimes(endstr, false, function(data) {
|
||||
var times = [];
|
||||
$.each(data, function(key, val) {
|
||||
times.push('<option value="' + key + '">' + val + '</option>');
|
||||
});
|
||||
$("#event-endtime").html(times.join(''));
|
||||
|
||||
if (start > end) {
|
||||
$("#event-endtime").val(starttime).attr("selected", "selected");
|
||||
} else {
|
||||
$("#event-endtime").val(endtime).attr("selected", "selected");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function onStartDateSelected(dateText, inst) {
|
||||
var tz = $("#tz").val();
|
||||
var startTime = $("#event-starttime option:selected").val();
|
||||
var startDateTime = new Date(dateText + ' ' + startTime.replace(/(pm|am)/, ' $1') + ' ' + tz);
|
||||
|
||||
// When we update the start date and time, we need to update the end date and time
|
||||
// to make sure they are equal or in the future
|
||||
$("#event-enddate").datepicker('option', 'minDate', startDateTime);
|
||||
|
||||
recalculateTimes();
|
||||
}
|
||||
|
||||
function onEndDateSelected(dateText, inst) {
|
||||
recalculateTimes();
|
||||
}
|
||||
|
||||
function recalculateTimes(showDuration) {
|
||||
var tz = $("#tz").val();
|
||||
|
||||
var startDate = $("#event-startdate").val();
|
||||
var startTime = $("#event-starttime option:selected").val();
|
||||
var startStr = startDate + ' ' + startTime.replace(/(pm|am)/, ' $1') + ' ' + tz;
|
||||
var startDateTime = new Date(startStr);
|
||||
|
||||
var endDate = $("#event-enddate").val();
|
||||
var endTime = $("#event-endtime option:selected").val();
|
||||
var endDateTime = new Date(endDate + ' ' + endTime.replace(/(pm|am)/, ' $1') + ' ' + tz);
|
||||
var showDuration = true;
|
||||
|
||||
if (endDateTime.getDate() !== startDateTime.getDate()) {
|
||||
starStr = endDate + ' 12:00 am ' + tz;
|
||||
showDuration = false;
|
||||
}
|
||||
|
||||
updateTimes(startStr, showDuration, function(data) {
|
||||
var times = [];
|
||||
$.each(data, function(key, val) {
|
||||
times.push('<option value="' + key + '">' + val + '</option>');
|
||||
});
|
||||
$("#event-endtime").html(times.join(''));
|
||||
if (startDateTime > endDateTime) {
|
||||
$("#event-endtime").val(startTime).attr("selected", "selected");
|
||||
} else {
|
||||
$("#event-endtime").val(endTime).attr("selected", "selected");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateTimes(start, duration, onSuccess) {
|
||||
$.getJSON($('#timelist_action_url').val(), {start: start, ajax: true, duration: duration}, onSuccess);
|
||||
}
|
||||
|
||||
});
|
||||
|
@ -123,7 +123,9 @@ class EventForm extends Form
|
||||
|
||||
$this->li();
|
||||
|
||||
$times = EventTimeList::getTimes();
|
||||
$times = EventTimeList::getTimes($today->format('m/d/Y 12:00') . ' am ' . $today->format('T'));
|
||||
$start = EventTimeList::nearestHalfHour('@' . $today->getTimestamp());
|
||||
$start->setTimezone(new DateTimeZone(common_timezone()));
|
||||
|
||||
$this->out->dropdown(
|
||||
'event-starttime',
|
||||
@ -131,11 +133,15 @@ class EventForm extends Form
|
||||
_m('LABEL','Start time'),
|
||||
$times,
|
||||
// TRANS: Field title on event form. %s is the abbreviated timezone
|
||||
sprintf(_m("Time the event starts (%s)."), $today->format("T")),
|
||||
sprintf(_m("Time the event starts (%s)."), $today->format('T')),
|
||||
false,
|
||||
null
|
||||
$start->format('g:ia')
|
||||
);
|
||||
|
||||
// Need to keep JavaScript TZ in sync with PHP TZ
|
||||
$this->out->hidden('tz', $today->format('T'));
|
||||
$this->out->hidden('now', $today->format('F d, Y H:i:s T'));
|
||||
|
||||
$this->unli();
|
||||
|
||||
$this->li();
|
||||
@ -150,18 +156,11 @@ class EventForm extends Form
|
||||
|
||||
$this->li();
|
||||
|
||||
// XXX: Initial end time should be at least 30 mins out? We could do
|
||||
// every 15 minute instead -z
|
||||
$keys = array_keys($times);
|
||||
$endStr = date('m/d/y', strtotime('now')) . " {$keys[0]}";
|
||||
$end = new DateTime($endStr);
|
||||
$end->modify('+30');
|
||||
|
||||
$this->out->dropdown(
|
||||
'event-endtime',
|
||||
// TRANS: Field label on event form.
|
||||
_m('LABEL','End time'),
|
||||
EventTimeList::getTimes($end->format('c'), true),
|
||||
EventTimeList::getTimes('@' . $start->getTimestamp(), true),
|
||||
// TRANS: Field title on event form.
|
||||
_m('Time the event ends.'),
|
||||
false,
|
||||
|
@ -39,10 +39,10 @@ class EventTimeList {
|
||||
*/
|
||||
public static function nearestHalfHour($time)
|
||||
{
|
||||
$start = strtotime($time);
|
||||
$startd = new DateTime($time);
|
||||
|
||||
$minutes = date('i', $start);
|
||||
$hour = date('H', $start);
|
||||
$minutes = $startd->format('i');
|
||||
$hour = $startd->format('H');
|
||||
|
||||
if ($minutes >= 30) {
|
||||
$minutes = '00';
|
||||
@ -51,38 +51,33 @@ class EventTimeList {
|
||||
$minutes = '30';
|
||||
}
|
||||
|
||||
$newTimeStr = date('m/d/y', $start) . " {$hour}:{$minutes}:00";
|
||||
return new DateTime($newTimeStr);
|
||||
$startd->setTime($hour, $minutes, 0);
|
||||
|
||||
return $startd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output a list of times in half-hour intervals
|
||||
*
|
||||
* @param string $start Time to start with (date/time string)
|
||||
* @param string $start Time to start with (date string, usually a ts)
|
||||
* @param boolean $duration Whether to include the duration of the event
|
||||
* (from the start)
|
||||
* @return array $times (UTC time string => localized time string)
|
||||
* @return array $times (localized 24 hour time string => fancy time string)
|
||||
*/
|
||||
public static function getTimes($start = 'now', $duration = false)
|
||||
{
|
||||
$newTime = self::nearestHalfHour($start);
|
||||
|
||||
$newTime->setTimezone(new DateTimeZone(common_timezone()));
|
||||
$newTime = new DateTime($start);
|
||||
$times = array();
|
||||
$len = 0;
|
||||
|
||||
for ($i = 0; $i < 48; $i++) {
|
||||
// make sure we store the time as UTC
|
||||
$newTime->setTimezone(new DateTimeZone('UTC'));
|
||||
$utcTime = $newTime->format('H:i:s');
|
||||
|
||||
// localize time for user
|
||||
$newTime->setTimezone(new DateTimeZone(common_timezone()));
|
||||
$localTime = $newTime->format('g:ia');
|
||||
|
||||
for ($i = 0; $i < 47; $i++) {
|
||||
|
||||
$localTime = $newTime->format("g:ia");
|
||||
|
||||
// pretty up the end-time option list a bit
|
||||
if ($duration) {
|
||||
$len += 30;
|
||||
$hours = $len / 60;
|
||||
switch ($hours) {
|
||||
case 0:
|
||||
@ -98,14 +93,18 @@ class EventTimeList {
|
||||
$total = ' ' . _m('(1 hour)');
|
||||
break;
|
||||
default:
|
||||
// TRANS: Number of hours (%d). Used in a list.
|
||||
$total = ' ' . sprintf(_m('(%d hour)','(%d hours)',$hours), $hours);
|
||||
// TRANS: Number of hours (%.1f and %d). Used in a list.
|
||||
$format = is_float($hours)
|
||||
? _m('(%.1f hours)')
|
||||
: _m('(%d hours)');
|
||||
$total = ' ' . sprintf($format, $hours);
|
||||
break;
|
||||
}
|
||||
$localTime .= $total;
|
||||
$len += 30;
|
||||
}
|
||||
|
||||
$times[$utcTime] = $localTime;
|
||||
$times[$newTime->format('g:ia')] = $localTime;
|
||||
$newTime->modify('+30min'); // 30 min intervals
|
||||
}
|
||||
|
||||
|
@ -101,6 +101,7 @@ class NeweventAction extends Action
|
||||
$this->location = $this->trimmed('location');
|
||||
$this->url = $this->trimmed('url');
|
||||
$this->description = $this->trimmed('description');
|
||||
$tz = $this->trimmed('tz');
|
||||
|
||||
$startDate = $this->trimmed('startdate');
|
||||
|
||||
@ -128,13 +129,8 @@ class NeweventAction extends Action
|
||||
$endTime = '00:00';
|
||||
}
|
||||
|
||||
$start = $startDate . ' ' . $startTime;
|
||||
|
||||
common_debug("Event start: '$start'");
|
||||
|
||||
$end = $endDate . ' ' . $endTime;
|
||||
|
||||
common_debug("Event start: '$end'");
|
||||
$start = $startDate . ' ' . $startTime . ' ' . $tz;
|
||||
$end = $endDate . ' ' . $endTime . ' ' . $tz;
|
||||
|
||||
$this->startTime = strtotime($start);
|
||||
$this->endTime = strtotime($end);
|
||||
@ -194,6 +190,7 @@ class NeweventAction extends Action
|
||||
function newEvent()
|
||||
{
|
||||
try {
|
||||
|
||||
if (empty($this->title)) {
|
||||
// TRANS: Client exception thrown when trying to post an event without providing a title.
|
||||
throw new ClientException(_m('Event must have a title.'));
|
||||
@ -209,6 +206,11 @@ class NeweventAction extends Action
|
||||
throw new ClientException(_m('Event must have an end time.'));
|
||||
}
|
||||
|
||||
if (isset($this->url) && Validate::uri($this->url) === false) {
|
||||
// TRANS: Client exception thrown when trying to post an event with an invalid URL.
|
||||
throw new ClientException(_m('URL must be valid.'));
|
||||
}
|
||||
|
||||
$options = array();
|
||||
|
||||
// Does the heavy-lifting for getting "To:" information
|
||||
|
Loading…
Reference in New Issue
Block a user