/**
 *
 */
function caParseEXIFLatLong($pa_exif)
{
    if (!is_array($pa_exif['GPS'])) {
        return null;
    }
    $vn_lat = '';
    if (is_array($pa_exif['GPS']['GPSLatitude'])) {
        foreach ($pa_exif['GPS']['GPSLatitude'] as $vn_i => $vs_val) {
            $va_tmp = explode('/', $vs_val);
            if ($va_tmp[1] > 0) {
                $vn_lat .= ' ' . $va_tmp[0] / $va_tmp[1];
                switch ($va_tmp[1]) {
                    case 1:
                        $vn_lat .= "°";
                        break;
                    case 100:
                        $vn_lat .= "'";
                        break;
                    default:
                        $vn_lat .= '"';
                        break;
                }
            }
        }
        $vn_lat .= $pa_exif['GPS']['GPSLatitudeRef'];
    }
    $vn_long = '';
    if (is_array($pa_exif['GPS']['GPSLongitude'])) {
        foreach ($pa_exif['GPS']['GPSLongitude'] as $vn_i => $vs_val) {
            $va_tmp = explode('/', $vs_val);
            if ($va_tmp[1] > 0) {
                $vn_long .= ' ' . $va_tmp[0] / $va_tmp[1];
                switch ($va_tmp[1]) {
                    case 1:
                        $vn_long .= "°";
                        break;
                    case 100:
                        $vn_long .= "'";
                        break;
                    default:
                        $vn_long .= '"';
                        break;
                }
            }
        }
        $vn_long .= $pa_exif['GPS']['GPSLongitudeRef'];
    }
    // TODO: extract GPSAltitude, GPSAltitudeRef, GPSImgDirection and GPSImgDirectionRef
    return array('latitude' => caGISminutesToSignedDecimal($vn_lat), 'longitude' => caGISminutesToSignedDecimal($vn_long));
}
 public function parseValue($ps_value, $pa_element_info, $pa_options = null)
 {
     $va_settings = $this->getSettingValuesFromElementArray($pa_element_info, array('mustNotBeBlank'));
     if (is_array($ps_value) && $ps_value['_uploaded_file']) {
         $o_kml = new KmlParser($ps_value['tmp_name']);
         $va_placemarks = $o_kml->getPlacemarks();
         $va_features = array();
         foreach ($va_placemarks as $va_placemark) {
             $va_coords = array();
             switch ($va_placemark['type']) {
                 case 'POINT':
                     $va_coords[] = $va_placemark['latitude'] . ',' . $va_placemark['longitude'];
                     break;
                 case 'PATH':
                     foreach ($va_placemark['coordinates'] as $va_coordinate) {
                         $va_coords[] = $va_coordinate['latitude'] . ',' . $va_coordinate['longitude'];
                     }
                     break;
             }
             if (sizeof($va_coords)) {
                 $va_features[] = join(';', $va_coords);
             }
         }
         if (sizeof($va_features)) {
             $ps_value = '[' . join(':', $va_features) . ']';
         } else {
             $ps_value = '';
         }
     }
     $ps_value = trim(preg_replace("![\t\n\r]+!", ' ', $ps_value));
     if (!trim($ps_value)) {
         if ($va_settings['mustNotBeBlank']) {
             $this->postError(1970, _t('Address or georeference was blank.'), 'GeocodeAttributeValue->parseValue()');
             return false;
         } else {
             return null;
         }
     }
     // is it direct input (decimal lat, decimal long)?
     if (preg_match("!^([^\\[]*)[\\[]{0,1}([\\d,\\-\\.;]+)[\\]]{0,1}\$!", $ps_value, $va_matches) || preg_match("!^([^\\[]*)[\\[]{1}([^\\]]+)[\\]]{1}\$!", $ps_value, $va_matches)) {
         $va_feature_list = preg_split("/[:]+/", $va_matches[2]);
         $va_feature_list_proc = array();
         foreach ($va_feature_list as $vs_feature) {
             $va_point_list = preg_split("/[;]+/", $vs_feature);
             $va_parsed_points = array();
             $vs_first_lat = $vs_first_long = '';
             foreach ($va_point_list as $vs_point) {
                 // is it UTM?
                 if (is_array($va_utm_to_latlong = caGISUTMToSignedDecimals($vs_point))) {
                     $va_parsed_points[] = $va_utm_to_latlong['latitude'] . ',' . $va_utm_to_latlong['longitude'];
                     if (!$vs_first_lat) {
                         $vs_first_lat = $va_utm_to_latlong['latitude'];
                     }
                     if (!$vs_first_long) {
                         $vs_first_long = $va_utm_to_latlong['longitude'];
                     }
                 } else {
                     $va_tmp = preg_split("/[ ]*[,\\/][ ]*/", $vs_point);
                     // convert from degrees minutes seconds to decimal format
                     if (caGISisDMS($va_tmp[0])) {
                         $va_tmp[0] = caGISminutesToSignedDecimal($va_tmp[0]);
                     } else {
                         $va_tmp[0] = caGISDecimalToSignedDecimal($va_tmp[0]);
                     }
                     if (caGISisDMS($va_tmp[1])) {
                         $va_tmp[1] = caGISminutesToSignedDecimal($va_tmp[1]);
                     } else {
                         $va_tmp[1] = caGISDecimalToSignedDecimal($va_tmp[1]);
                     }
                     $va_parsed_points[] = $va_tmp[0] . ',' . $va_tmp[1];
                     if (!$vs_first_lat) {
                         $vs_first_lat = $va_tmp[0];
                     }
                     if (!$vs_first_long) {
                         $vs_first_long = $va_tmp[1];
                     }
                 }
             }
             $va_feature_list_proc[] = join(';', $va_parsed_points);
         }
         return array('value_longtext1' => $va_matches[1], 'value_longtext2' => join(':', $va_feature_list_proc), 'value_decimal1' => $vs_first_lat, 'value_decimal2' => $vs_first_long);
     } else {
         $ps_value = preg_replace("!\\[[\\d,\\-\\.]+\\]!", "", $ps_value);
         if ($ps_value) {
             $vs_google_response = @file_get_contents('https://maps.googleapis.com/maps/api/geocode/json?address=' . urlencode($ps_value) . '&sensor=false');
             if (!($va_google_response = json_decode($vs_google_response, true)) || !isset($va_google_response['status'])) {
                 $this->postError(1970, _t('Could not connect to Google for geocoding'), 'GeocodeAttributeValue->parseValue()');
                 return false;
             }
             if ($va_google_response['status'] != 'OK' || !isset($va_google_response['results']) || sizeof($va_google_response['results']) == 0) {
                 $this->postError(1970, _t('Could not geocode address "%1": [%2]', $ps_value, $va_google_response['status']), 'GeocodeAttributeValue->parseValue()');
                 return false;
             }
             $va_first_result = array_shift($va_google_response['results']);
             if (isset($va_first_result['geometry']['location']) && is_array($va_first_result['geometry']['location'])) {
                 return array('value_longtext1' => $ps_value, 'value_longtext2' => $va_first_result['geometry']['location']['lat'] . ',' . $va_first_result['geometry']['location']['lng'], 'value_decimal1' => $va_first_result['geometry']['location']['lat'], 'value_decimal2' => $va_first_result['geometry']['location']['lng']);
             } else {
                 $this->postError(1970, _t('Could not geocode address "%1"', $ps_value), 'GeocodeAttributeValue->parseValue()');
                 return false;
             }
         }
     }
     return array('value_longtext1' => '', 'value_longtext2' => '', 'value_decimal1' => null, 'value_decimal2' => null);
 }