diff --git a/okapi/core/OkapiServiceRunner.php b/okapi/core/OkapiServiceRunner.php index 5433e5d9..823c99fe 100644 --- a/okapi/core/OkapiServiceRunner.php +++ b/okapi/core/OkapiServiceRunner.php @@ -43,6 +43,7 @@ class OkapiServiceRunner 'services/caches/formatters/gpx', 'services/caches/formatters/garmin', 'services/caches/formatters/ggz', + 'services/fieldnotes/upload', 'services/caches/map/tile', 'services/logs/capabilities', 'services/logs/delete', diff --git a/okapi/services/fieldnotes/upload/WebService.php b/okapi/services/fieldnotes/upload/WebService.php new file mode 100644 index 00000000..600e5b64 --- /dev/null +++ b/okapi/services/fieldnotes/upload/WebService.php @@ -0,0 +1,170 @@ + 3 + ); + } + + public static function call(OkapiRequest $request) + { + $result = array( + 'success' => false // if the installation doesn't support it + ); + + if (Settings::get('OC_BRANCH') == 'oc.de') + { + + $field_notes = $request->get_parameter('field_notes'); + if (!$field_notes) throw new ParamMissing('field_notes'); + + $result = Okapi::get_submittable_logtype_names(); + $result = json_encode($result, JSON_PRETTY_PRINT); // debug + return Okapi::formatted_response($request, $result); + + $notes = self::parse_notes($field_notes); + if ($notes === false) throw new InvalidParam('field_notes', "Input data not recognized."); + + foreach ($notes as $n) + { + $geocache = OkapiServiceRunner::call( + 'services/caches/geocache', + new OkapiInternalRequest($request->consumer, $request->token, array( + 'cache_code' => $n['code'], + 'fields' => 'internal_id' + )) + ); + $user_id = $request->token->user_id; + $geocache_id = $geocache['internal_id']; + $type = Okapi::logtypename2id($n['type']); + $date = date("Y-m-d H:i:s", strtotime($n['date'])); + $text = $n['log']; + + Db::query(" + insert into field_note ( + user_id, geocache_id, type, date, text + ) values ( + '".Db::escape_string($user_id)."', + '".Db::escape_string($geocache_id)."', + '".Db::escape_string($type)."', + '".Db::escape_string($date)."', + '".Db::escape_string($text)."' + ) + "); + + } + $result = array( + 'success' => true + ); + //$result = json_encode($notes, JSON_PRETTY_PRINT); // debug + } + return Okapi::formatted_response($request, $result); + } + + // ------------------------------------------------------------------ + + private static function parse_notes($field_notes) + { + $decoded_field_notes = base64_decode($field_notes, true); + if ($decoded_field_notes === false) return false; + + $multiline = self::fieldNotesTxtArea2Array($decoded_field_notes); + + $parsed_records = []; + + foreach ($multiline as $line) { + $line = trim($line); + $fields = self::CSVtoArray($line); + + $code = $fields[0]; + $date = $fields[1]; + $type = $fields[2]; + $log = nl2br($fields[3]); + + $parsed_records[] = [ + 'code' => $code, + 'date' => $date, + 'type' => $type, + 'log' => $log, + ]; + } + return $parsed_records; + } + + + // ------------------------------------------------------------------ + + private static function fieldNotesTxtArea2Array($fieldnotes) + { + $output = []; + $buffer = ''; + $start = true; + + $lines = explode("\n", $fieldnotes); + $lines = array_filter($lines); // Drop empty lines + + foreach ($lines as $line) { + if ($start) { + $buffer = $line; + $start = false; + } else { + if (strpos($line, 'OC') !== 0) { + $buffer .= "\n" . $line; + } else { + $output[] = trim($buffer); + $buffer = $line; + } + } + } + + if (!$start) { + $output[] = trim($buffer); + } + + return $output; + } + + // ------------------------------------------------------------------ + + private static function CSVtoArray($text) + { + $ret = ['']; + $i = 0; + $p = ''; + $s = true; + + foreach (str_split($text) as $l) { + if ('"' === $l) { + $s = !$s; + if ('"' === $p) { + $ret[$i] .= '"'; + $l = '-'; + } elseif ('' === $p) { + $l = '-'; + } + } elseif ($s && ',' === $l) { + $l = $ret[++$i] = ''; + } else { + $ret[$i] .= $l; + } + $p = $l; + } + + return $ret; + } +} diff --git a/okapi/services/fieldnotes/upload/docs.xml b/okapi/services/fieldnotes/upload/docs.xml new file mode 100644 index 00000000..acbc4ac0 --- /dev/null +++ b/okapi/services/fieldnotes/upload/docs.xml @@ -0,0 +1,47 @@ + + Upload Fieldnotes + 630 + +

Upload a set of one or more fieldnotes records.

+
+ +

Fieldnotes consist of one or more records in CSV format. Each + record comprises a geocache log consisting of four fields:

+ +

The first three fields are simple entities, the Log Text field is + different and a bit difficult as it may spread over muliple lines + and it may contain quote characters. In order to preserve the structure + of the records, the field_notes parameter must be passed as a + base64 encoded utf8 string. UTF-16LE, UTF-16BE with or without + BOM are not supported. +

+

Since the log type is passed as a string, its value must match the + values supported by the platform (case sensitive!): +

+[
+    "Found it",
+    "Didn't find it",
+    "Comment",
+    "Attended",
+    "Will attend",
+    "Archived",
+    "Ready to search",
+    "Temporarily unavailable"
+]
+        
+

+

Note: This service method is not supported on all installations

+
+ + +

A dictionary of the following structure:

+
    +
  • success - true
  • +
+
+