Browse Source

properly handle backdated posts with timzone support

pull/10/head
Aaron Parecki 5 years ago
parent
commit
9f83bc0263
4 changed files with 102 additions and 21 deletions
  1. +60
    -13
      controllers/controllers.php
  2. +33
    -3
      lib/helpers.php
  3. +8
    -4
      views/new-post.php
  4. +1
    -1
      views/partials/entry.php

+ 60
- 13
controllers/controllers.php View File

@@ -43,8 +43,26 @@ function generate_login_token() {
$app->get('/new', function() use($app) {
if($user=require_login($app)) {

$entry = false;
$photo_url = false;
// Get the last post and set the timezone offset to match
$date_str = date('Y-m-d');
$time_str = date('H:i:s');
$tz_offset = '+0000';

$last = ORM::for_table('entries')->where('user_id', $user->id)
->order_by_desc('published')->find_one();
if(false && $last) {
$seconds = $last->tz_offset;
$tz_offset = tz_seconds_to_offset($seconds);

// Create a date object in the local timezone given the offset
$date = new DateTime();
if($seconds > 0)
$date->add(new DateInterval('PT'.$seconds.'S'));
elseif($seconds < 0)
$date->sub(new DateInterval('PT'.abs($seconds).'S'));
$date_str = $date->format('Y-m-d');
$time_str = $date->format('H:i:s');
}

// Initially populate the page with the list of options without considering location.
// This way if browser location is disabled or not available, or JS is disabled, there
@@ -59,6 +77,9 @@ $app->get('/new', function() use($app) {
'response_date' => $user->last_micropub_response_date,
'location_enabled' => $user->location_enabled,
'default_options' => get_entry_options($user->id),
'tz_offset' => $tz_offset,
'date_str' => $date_str,
'time_str' => $time_str,
'enable_appcache' => true
));
$app->response()->body($html);
@@ -145,20 +166,20 @@ $app->post('/post', function() use($app) {
// Store the post in the database
$entry = ORM::for_table('entries')->create();
$entry->user_id = $user->id;
$entry->published = date('Y-m-d H:i:s');

$location = false;
if(k($params, 'location') && $location=parse_geo_uri($params['location'])) {
$entry->latitude = $location['latitude'];
$entry->longitude = $location['longitude'];
if($timezone=get_timezone($location['latitude'], $location['longitude'])) {
$entry->timezone = $timezone->getName();
$entry->tz_offset = $timezone->getOffset(new DateTime());
}
} else {
$entry->timezone = 'UTC';
$entry->tz_offset = 0;
}

// The post request is always going to have a date now
$date_string = $params['note_date'] . 'T' . $params['note_time'] . $params['note_tzoffset'];
$entry->published = date('Y-m-d H:i:s', strtotime($date_string));
$entry->tz_offset = tz_offset_to_seconds($params['note_tzoffset']);

$published = $date_string;

if(k($params, 'drank')) {
$entry->content = trim($params['drank']);
$type = 'drink';
@@ -193,6 +214,7 @@ $app->post('/post', function() use($app) {

$mp_request = array(
'h' => 'entry',
'published' => $published,
'p3k-food' => $entry->content,
'p3k-type' => $type,
'location' => k($params, 'location'),
@@ -228,14 +250,39 @@ $app->post('/post', function() use($app) {
}
});

$app->get('/options', function() use($app) {
$app->get('/options.json', function() use($app) {
if($user=require_login($app)) {
$params = $app->request()->params();

$options = get_entry_options($user->id, k($params,'latitude'), k($params,'longitude'));
$html = partial('partials/entry-buttons', ['options'=>$options]);

$app->response()->body($html);
$tz_offset = '+0000';
$date_str = date('Y-m-d');
$time_str = date('H:i:s');
if(k($params,'latitude')) {
if($timezone=get_timezone($params['latitude'], $params['longitude'])) {
$seconds = $timezone->getOffset(new DateTime());
$tz_offset = tz_seconds_to_offset($seconds);

// Create a date object in the local timezone given the offset
$date = new DateTime();
if($seconds > 0)
$date->add(new DateInterval('PT'.$seconds.'S'));
elseif($seconds < 0)
$date->sub(new DateInterval('PT'.abs($seconds).'S'));
$date_str = $date->format('Y-m-d');
$time_str = $date->format('H:i:s');
}
}

$app->response()['Content-type'] = 'application/json';
$app->response()->body(json_encode([
'buttons'=>$html,
'tz_offset'=>$tz_offset,
'date_str'=>$date_str,
'time_str'=>$time_str
]));
}
});

@@ -251,7 +298,7 @@ $app->get('/map.png', function() use($app) {
$app->response()->body($img);
});

$app->get('/teacup.appcache', function() use($app) {
$app->get('/-teacup.appcache', function() use($app) {
$content = partial('appcache');

$app->response()['Content-type'] = 'text/cache-manifest';


+ 33
- 3
lib/helpers.php View File

@@ -192,15 +192,45 @@ function relative_time($date) {
return $rel->timeAgo($date);
}

function date_iso8601($date_string, $tz_offset) {
$date = new DateTime($date_string);
if($tz_offset > 0)
$date->add(new DateInterval('PT'.$tz_offset.'S'));
elseif($tz_offset < 0)
$date->sub(new DateInterval('PT'.abs($tz_offset).'S'));
$tz = tz_seconds_to_offset($tz_offset);
return $date->format('Y-m-d\TH:i:s') . $tz;
}

function tz_seconds_to_offset($seconds) {
return ($seconds < 0 ? '-' : '+') . sprintf('%02d:%02d', abs($seconds/60/60), ($seconds/60)%60);
}

function tz_offset_to_seconds($offset) {
if(preg_match('/([+-])(\d{2}):?(\d{2})/', $offset, $match)) {
$sign = ($match[1] == '-' ? -1 : 1);
return ($match[2] * 60 * 60) + ($match[3] * 60) * $sign;
} else {
return 0;
}
}

function entry_url($entry, $user) {
return $entry->canonical_url ?: Config::$base_url . $user->url . '/' . $entry->id;
}

function entry_date($entry, $user) {
$date = new DateTime($entry->published);
$tz = new DateTimeZone($entry->timezone);
$date->setTimeZone($tz);
return $date;
if($entry->tz_offset > 0)
$date->add(new DateInterval('PT'.$entry->tz_offset.'S'));
elseif($entry->tz_offset < 0)
$date->sub(new DateInterval('PT'.abs($entry->tz_offset).'S'));
$tz = tz_seconds_to_offset($entry->tz_offset);
return new DateTime($date->format('Y-m-d\TH:i:s') . $tz);
// Can switch back to this later if I prompt the user for a named timezone instead of just an offset
// $tz = new DateTimeZone($entry->timezone);
// $date->setTimeZone($tz);
// return $date;
}

function default_drink_options() {


+ 8
- 4
views/new-post.php View File

@@ -23,8 +23,9 @@
<div class="form-group">
<h3>Date</h3>
<input type="date" value="<?= date('Y-m-d') ?>" id="note_date">
<input type="time" value="<?= date('H:i') ?>" id="note_time">
<input type="date" id="note_date" name="note_date" value="<?= $this->date_str ?>">
<input type="text" id="note_time" name="note_time" value="<?= $this->time_str ?>">
<input type="text" id="note_tzoffset" name="note_tzoffset" value="<?= $this->tz_offset ?>">
</div>
</form>

@@ -101,7 +102,7 @@ $(function(){

navigator.geolocation.getCurrentPosition(function(position){

$.get('/options', {
$.getJSON('/options.json', {
latitude: position.coords.latitude,
longitude: position.coords.longitude
}, function(response) {
@@ -117,7 +118,10 @@ $(function(){
selected = '#custom_eat';
}

$("#entry-buttons").html(response);
$("#entry-buttons").html(response.buttons);
$("#note_tzoffset").val(response.tz_offset);
$("#note_date").val(response.date_str);
$("#note_time").val(response.time_str);

// restore the custom values entered
$('#custom_eat').val(custom_eat);


+ 1
- 1
views/partials/entry.php View File

@@ -23,7 +23,7 @@
<?php endif; ?>

<div class="date">
<a href="<?= entry_url($this->entry, $this->user) ?>" class="u-url"><time class="dt-published" datetime="<?= entry_date($this->entry, $this->user)->format('c') ?>"><?= entry_date($this->entry, $this->user)->format('F j, Y g:ia T') ?></time></a>
<a href="<?= entry_url($this->entry, $this->user) ?>" class="u-url"><time class="dt-published" datetime="<?= entry_date($this->entry, $this->user)->format('c') ?>"><?= entry_date($this->entry, $this->user)->format('F j, Y g:ia P') ?></time></a>
</div>
</li>


Loading…
Cancel
Save