From 592eac5d8dc4c704bfb34915c0703fc2aecc6d46 Mon Sep 17 00:00:00 2001 From: Aaron Parecki Date: Sun, 6 Jul 2014 18:28:18 -0700 Subject: [PATCH] Adds support for querying your micropub endpoint to check for syndication targets. This changes the value of "in-reply-to" to use hyphens instead of underscore separators!! Also shows you the full request made to your micropub endpoint. --- controllers/auth.php | 4 ++ controllers/controllers.php | 18 ++++++++ lib/helpers.php | 71 +++++++++++++++++++++++++++++- views/dashboard.php | 87 +++++++++++++++++++++++++++++++++++-- views/docs.php | 33 +++++++++++++- 5 files changed, 205 insertions(+), 8 deletions(-) diff --git a/controllers/auth.php b/controllers/auth.php index abbe3b9..13081c4 100644 --- a/controllers/auth.php +++ b/controllers/auth.php @@ -235,6 +235,10 @@ $app->get('/auth/callback', function() use($app) { $user->micropub_response = $token['response']; $user->save(); $_SESSION['user_id'] = $user->id(); + + // Make a request to the micropub endpoint to discover the syndication targets if any. + // Errors are silently ignored here. The user will be able to retry from the new post interface and get feedback. + get_syndication_targets($user); } unset($_SESSION['auth_state']); diff --git a/controllers/controllers.php b/controllers/controllers.php index 5b28bb8..dc18584 100644 --- a/controllers/controllers.php +++ b/controllers/controllers.php @@ -32,6 +32,7 @@ $app->get('/new', function() use($app) { 'micropub_scope' => $user->micropub_scope, 'micropub_access_token' => $user->micropub_access_token, 'response_date' => $user->last_micropub_response_date, + 'syndication_targets' => json_decode($user->syndication_targets, true), 'test_response' => $test_response, 'location_enabled' => $user->location_enabled )); @@ -104,12 +105,28 @@ $app->get('/add-to-home', function() use($app) { } }); +$app->get('/micropub/syndications', function() use($app) { + if($user=require_login($app)) { + $data = get_syndication_targets($user); + $app->response()->body(json_encode(array( + 'targets' => $data['targets'], + 'response' => $data['response'] + ))); + } +}); + $app->post('/micropub/post', function() use($app) { if($user=require_login($app)) { $params = $app->request()->params(); + // Remove any blank params + $params = array_filter($params, function($v){ + return $v !== ''; + }); + // Now send to the micropub endpoint $r = micropub_post($user->micropub_endpoint, $params, $user->micropub_access_token); + $request = $r['request']; $response = $r['response']; $user->last_micropub_response = json_encode($r); @@ -126,6 +143,7 @@ $app->post('/micropub/post', function() use($app) { $user->save(); $app->response()->body(json_encode(array( + 'request' => htmlspecialchars($request), 'response' => htmlspecialchars($response), 'location' => $location, 'error' => $r['error'], diff --git a/lib/helpers.php b/lib/helpers.php index 7748c4e..60eda75 100644 --- a/lib/helpers.php +++ b/lib/helpers.php @@ -73,20 +73,87 @@ function micropub_post($endpoint, $params, $access_token) { 'Authorization: Bearer ' . $access_token )); curl_setopt($ch, CURLOPT_POST, true); - curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array_merge(array( + $post = http_build_query(array_merge(array( 'h' => 'entry' - ), $params))); + ), $params)); + curl_setopt($ch, CURLOPT_POSTFIELDS, $post); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, true); + curl_setopt($ch, CURLINFO_HEADER_OUT, true); $response = curl_exec($ch); $error = curl_error($ch); + $sent_headers = curl_getinfo($ch, CURLINFO_HEADER_OUT); + $request = $sent_headers . $post; return array( + 'request' => $request, 'response' => $response, 'error' => $error, 'curlinfo' => curl_getinfo($ch) ); } +function micropub_get($endpoint, $params, $access_token) { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $endpoint . '?' . http_build_query($params)); + curl_setopt($ch, CURLOPT_HTTPHEADER, array( + 'Authorization: Bearer ' . $access_token + )); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + $response = curl_exec($ch); + $data = array(); + if($response) { + parse_str($response, $data); + } + $error = curl_error($ch); + return array( + 'response' => $response, + 'data' => $data, + 'error' => $error, + 'curlinfo' => curl_getinfo($ch) + ); +} + +function get_syndication_targets(&$user) { + $targets = array(); + + $r = micropub_get($user->micropub_endpoint, array('q'=>'syndicate-to'), $user->micropub_access_token); + if($r['data'] && array_key_exists('syndicate-to', $r['data'])) { + $targetURLs = preg_split('/, ?/', $r['data']['syndicate-to']); + foreach($targetURLs as $t) { + + // If the syndication target doesn't have a scheme, add http + if(!preg_match('/^http/', $t)) + $tmp = 'http://' . $t; + + // Parse the target expecting it to be a URL + $url = parse_url($tmp); + + // If there's a host, and the host contains a . then we can assume there's a favicon + // parse_url will parse strings like http://twitter into an array with a host of twitter, which is not resolvable + if(array_key_exists('host', $url) && strpos($url['host'], '.') !== false) { + $targets[] = array( + 'target' => $t, + 'favicon' => 'http://' . $url['host'] . '/favicon.ico' + ); + } else { + $targets[] = array( + 'target' => $t, + 'favicon' => false + ); + } + } + } + if(count($targets)) { + $user->syndication_targets = json_encode($targets); + $user->save(); + } + + return array( + 'targets' => $targets, + 'response' => $r + ); +} + function static_map($latitude, $longitude, $height=180, $width=700, $zoom=14) { return 'http://static-maps.pdx.esri.com/img.php?marker[]=lat:' . $latitude . ';lng:' . $longitude . ';icon:small-blue-cutout&basemap=gray&width=' . $width . '&height=' . $height . '&zoom=' . $zoom; } diff --git a/views/dashboard.php b/views/dashboard.php index cabeedc..d88a59c 100644 --- a/views/dashboard.php +++ b/views/dashboard.php @@ -23,6 +23,24 @@ +
+ +
+ syndication_targets) { + echo '
    '; + foreach($this->syndication_targets as $syn) { + echo '
  • '; + } + echo '
'; + } else { + ?>
No syndication targets were found on your site. + You can provide a list of supported syndication targets that will appear as checkboxes here.
+
+
+
@@ -45,6 +63,11 @@ + + test_response): ?>

Last response from your Micropub endpoint (response_date) ?>)

@@ -80,17 +103,26 @@ $(function(){ $("#btn_post").click(function(){ + + var syndications = []; + $("#syndication-container button.btn-info").each(function(i,btn){ + syndications.push($(btn).data('syndication')); + }); + $.post("/micropub/post", { content: $("#note_content").val(), - in_reply_to: $("#note_in_reply_to").val(), + 'in-reply-to': $("#note_in_reply_to").val(), location: $("#note_location").val(), category: $("#note_category").val(), - slug: $("#note_slug").val() + slug: $("#note_slug").val(), + 'syndicate-to': syndications.join(',') }, function(data){ var response = JSON.parse(data); if(response.location != false) { - $("#note_form").slideUp(); + $("#note_form").slideUp(200, function(){ + $(window).scrollTop($("#test_success").position().top); + }); $("#test_success").removeClass('hidden'); $("#test_error").addClass('hidden'); @@ -107,8 +139,11 @@ $(function(){ } $("#last_response_date").html("(just now)"); + $("#test_request").html(response.request); + $("#last_request_container").show(); $("#test_response").html(response.response); - }) + }); + return false; }); function location_error(msg) { @@ -174,10 +209,54 @@ $(function(){ fetch_location(); } + bind_syndication_buttons(); }); + +function reload_syndications() { + $.getJSON("/micropub/syndications", function(data){ + if(data.targets) { + $("#syndication-container").html(''); + for(var i in data.targets) { + var target = data.targets[i].target; + var favicon = data.targets[i].favicon; + $("#syndication-container ul").append('
  • '); + } + bind_syndication_buttons(); + } else { + + } + console.log(data); + }); +} + +function bind_syndication_buttons() { + $("#syndication-container button").unbind("click").click(function(){ + $(this).toggleClass('btn-info'); + return false; + }); +} +