From 63900d009441d8e81714ea56337d5b736806fca1 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sat, 25 Jun 2011 19:39:31 +0530 Subject: [PATCH 01/98] GIS data editor for environments without JavaScript support. GIS data preserved while editing. --- gis_data_editor.php | 271 +++++++++++++++++++ libraries/common.lib.php | 66 +++-- libraries/config.default.php | 1 + libraries/display_tbl.lib.php | 6 +- libraries/gis/pma_gis_geometrycollection.php | 27 ++ libraries/gis/pma_gis_linestring.php | 27 ++ libraries/gis/pma_gis_multilinestring.php | 37 +++ libraries/gis/pma_gis_multipoint.php | 27 ++ libraries/gis/pma_gis_multipolygon.php | 47 ++++ libraries/gis/pma_gis_point.php | 14 + libraries/gis/pma_gis_polygon.php | 37 +++ tbl_change.php | 19 +- tbl_replace.php | 16 ++ themes/original/css/theme_right.css.php | 30 +- themes/pmahomme/css/theme_right.css.php | 30 +- 15 files changed, 622 insertions(+), 33 deletions(-) create mode 100644 gis_data_editor.php diff --git a/gis_data_editor.php b/gis_data_editor.php new file mode 100644 index 0000000000..dd096bbb61 --- /dev/null +++ b/gis_data_editor.php @@ -0,0 +1,271 @@ +generateWkt($gis_data, 0); + +$format = (PMA_USR_BROWSER_AGENT == 'IE' && PMA_USR_BROWSER_VER <= 8) ? 'svg' : 'png'; +$visualizationSettings = array('width' => 400, 'height' => 400,); +$data = array($wkt); +if (! $no_visual) { + $visualization = PMA_GIS_visualization_results($data, $visualizationSettings, $format); +} + +if(isset($_REQUEST['generate']) && $_REQUEST['generate'] == true) { + $extra_data = array( + 'wkt' => $wkt, + 'srid' => $srid, + 'visualization' => $visualization, + ); + PMA_ajaxResponse(null, true, $extra_data); +} +?> + + + + +
+
+

+'); + echo PMA_generate_common_hidden_inputs($url_params); +?> +
+ +
+
+ + " /> + + +
+
+'); + } + for ($a = 0; $a < $geom_count; $a++) { + if ($geom_type == 'GEOMETRYCOLLECTION') { + echo('

'); echo __("Geometry"); echo($a + 1 . ':
'); + if (isset($gis_data[$a]['gis_type'])) { + $type = $gis_data[$a]['gis_type']; + } else { + $type = $gis_types[0]; + } + echo(''); + echo(''); + } else { + $type = $geom_type; + } + + if ($type == 'POINT') { + echo('
'); echo __("Point"); +?> + + + +'); + + for ($i = 0; $i < $no_of_points; $i++) { + echo('
'); echo __("Point"); echo($i + 1 . ':'); +?> + + + + + "> +'); + + for ($i = 0; $i < $no_of_lines; $i++) { + echo('
'); + if ($type == 'MULTILINESTRING') { + echo __("Linestring"); echo($i + 1 . ':'); + } else { + if ($i == 0) { + echo __("Outer Ring:"); + } else { + echo __("Inner Ring"); echo($i . ':'); + } + } + + $no_of_points = isset($gis_data[$a][$type][$i]['no_of_points']) ? $gis_data[$a][$type][$i]['no_of_points'] : 2; + if ($type == 'MULTILINESTRING' && $no_of_points < 2) { + $no_of_points = 2; + } + if ($type == 'POLYGON' && $no_of_points < 3) { + $no_of_points = 3; + } + if (isset($gis_data[$a][$type][$i]['add_point'])) { + $no_of_points++; + } + echo(''); + + for ($j = 0; $j < $no_of_points; $j++) { + echo('
'); echo __("Point"); echo($j + 1 . ':'); +?> + + + + "> +
+'); + + for ($k = 0; $k < $no_of_polygons; $k++) { + echo('
'); echo __("Polygon"); echo($k + 1 . ':'); + $no_of_lines = isset($gis_data[$a][$type][$k]['no_of_lines']) ? $gis_data[$a][$type][$k]['no_of_lines'] : 1; + if ($no_of_lines < 1) { + $no_of_lines = 1; + } + if (isset($gis_data[$a][$type][$k]['add_line'])) { + $no_of_lines++; + } + echo(''); + + for ($i = 0; $i < $no_of_lines; $i++) { + echo('

'); + if ($i == 0) { + echo __("Outer Ring:"); + } else { + echo __("Inner Ring"); echo($i . ':'); + } + + $no_of_points = isset($gis_data[$a][$type][$k][$i]['no_of_points']) ? $gis_data[$a][$type][$k][$i]['no_of_points'] : 3; + if ($no_of_points < 3) { + $no_of_points = 3; + } + if (isset($gis_data[$a][$type][$k][$i]['add_point'])) { + $no_of_points++; + } + echo(''); + + for ($j = 0; $j < $no_of_points; $j++) { + echo('
'); echo __("Point"); echo($j + 1 . ':'); +?> + " value="" /> + + " value="" /> + " value=""> +
" value=""> +

" value=""> +

" /> + +
+
+
+

+

+ +
+
+
+ + \ No newline at end of file diff --git a/libraries/common.lib.php b/libraries/common.lib.php index a9b87f99e7..633af50d24 100644 --- a/libraries/common.lib.php +++ b/libraries/common.lib.php @@ -1397,7 +1397,7 @@ function PMA_localizeNumber($value) * @param integer $digits_left number of digits left of the comma * @param integer $digits_right number of digits right of the comma * @param boolean $only_down do not reformat numbers below 1 - * @param boolean $noTrailingZero removes trailing zeros right of the comma (default: true) + * @param boolean $noTrailingZero removes trailing zeros right of the comma (default: true) * * @return string the formatted value and its unit * @@ -1408,13 +1408,13 @@ function PMA_localizeNumber($value) function PMA_formatNumber($value, $digits_left = 3, $digits_right = 0, $only_down = false, $noTrailingZero = true) { if($value==0) return '0'; - + $originalValue = $value; //number_format is not multibyte safe, str_replace is safe if ($digits_left === 0) { $value = number_format($value, $digits_right); if($originalValue!=0 && floatval($value) == 0) $value = ' <'.(1/PMA_pow(10,$digits_right)); - + return PMA_localizeNumber($value); } @@ -1448,7 +1448,7 @@ function PMA_formatNumber($value, $digits_left = 3, $digits_right = 0, $only_dow } $dh = PMA_pow(10, $digits_right); - + // This gives us the right SI prefix already, but $digits_left parameter not incorporated $d = floor(log10($value) / 3); // Lowering the SI prefix by 1 gives us an additional 3 zeros @@ -1457,18 +1457,18 @@ function PMA_formatNumber($value, $digits_left = 3, $digits_right = 0, $only_dow if($digits_left > $cur_digits) { $d-= floor(($digits_left - $cur_digits)/3); } - + if($d<0 && $only_down) $d=0; - + $value = round($value / (PMA_pow(1000, $d, 'pow') / $dh)) /$dh; $unit = $units[$d]; - + // If we dont want any zeros after the comma just add the thousand seperator if($noTrailingZero) $value = PMA_localizeNumber(preg_replace("/(?<=\d)(?=(\d{3})+(?!\d))/",",",$value)); else $value = PMA_localizeNumber(number_format($value, $digits_right)); //number_format is not multibyte safe, str_replace is safe - + if($originalValue!=0 && floatval($value) == 0) return ' <'.(1/PMA_pow(10,$digits_right)).' '.$unit; return $sign . $value . ' ' . $unit; @@ -2731,6 +2731,31 @@ function PMA_replace_binary_contents($content) { return $result; } +/** + * Converts GIS data to Well Known Text format + * + * @param $data GIS data + * @param $includeSRID Add SRID to the WKT + * @return GIS data in Well Know Text format + */ +function PMA_asWKT($data, $includeSRID = false) { + // Convert to WKT format + $hex = bin2hex($data); + $wktsql = "SELECT ASTEXT(x'" . $hex . "')"; + if ($includeSRID) { + $wktsql .= ", SRID(x'" . $hex . "')"; + } + $wktresult = PMA_DBI_try_query($wktsql, null, PMA_DBI_QUERY_STORE); + $wktarr = PMA_DBI_fetch_row($wktresult, 0); + $wktval = $wktarr[0]; + if ($includeSRID) { + $srid = $wktarr[1]; + $wktval = "'" . $wktval . "'," . $srid; + } + @PMA_DBI_free_result($wktresult); + return $wktval; +} + /** * If the string starts with a \r\n pair (0x0d0a) add an extra \n * @@ -3039,20 +3064,23 @@ function PMA_getSupportedDatatypes($html = false, $selected = '') */ function PMA_unsupportedDatatypes() { - // These GIS data types are not yet supported. - $no_support_types = array('geometry', - 'point', - 'linestring', - 'polygon', - 'multipoint', - 'multilinestring', - 'multipolygon', - 'geometrycollection' - ); - + $no_support_types = array(); return $no_support_types; } +function PMA_getGISDatatypes() { + $gis_data_types = array('geometry', + 'point', + 'linestring', + 'polygon', + 'multipoint', + 'multilinestring', + 'multipolygon', + 'geometrycollection' + ); + + return $gis_data_types; +} /** * Creates a dropdown box with MySQL functions for a particular column. * diff --git a/libraries/config.default.php b/libraries/config.default.php index 1a478b7874..7525994fd3 100644 --- a/libraries/config.default.php +++ b/libraries/config.default.php @@ -3049,6 +3049,7 @@ if ($cfg['ShowFunctionFields']) { 'FUNC_CHAR' => '', 'FUNC_DATE' => '', 'FUNC_NUMBER' => '', + 'FUNC_SPATIAL' => 'GeomFromText', 'first_timestamp' => 'NOW', 'pk_char36' => 'UUID', ); diff --git a/libraries/display_tbl.lib.php b/libraries/display_tbl.lib.php index d41e2452c5..cc517d358d 100644 --- a/libraries/display_tbl.lib.php +++ b/libraries/display_tbl.lib.php @@ -1514,11 +1514,7 @@ function PMA_displayTableBody(&$dt_result, &$is_display, $map, $analyzed_sql) { // Display in Well Known Text(WKT) format. } elseif ('WKT' == $_SESSION['tmp_user_values']['geometry_display']) { // Convert to WKT format - $wktsql = "SELECT ASTEXT (GeomFromWKB(x'" . PMA_substr(bin2hex($row[$i]), 8) . "'))"; - $wktresult = PMA_DBI_try_query($wktsql, null, PMA_DBI_QUERY_STORE); - $wktarr = PMA_DBI_fetch_row($wktresult, 0); - $wktval = $wktarr[0]; - @PMA_DBI_free_result($wktresult); + $wktval = PMA_asWKT($row[$i]); if (PMA_strlen($wktval) > $GLOBALS['cfg']['LimitChars'] && $_SESSION['tmp_user_values']['display_text'] == 'P' diff --git a/libraries/gis/pma_gis_geometrycollection.php b/libraries/gis/pma_gis_geometrycollection.php index 43a7cf4d14..2fcb62441d 100644 --- a/libraries/gis/pma_gis_geometrycollection.php +++ b/libraries/gis/pma_gis_geometrycollection.php @@ -221,5 +221,32 @@ class PMA_GIS_Geometrycollection extends PMA_GIS_Geometry } return $sub_parts; } + + /** + * Generate the WKT with the set of parameters passed by the GIS editor. + * + * @param array $gis_data GIS data + * @param int $index Index into the parameter object + * + * @return WKT with the set of parameters passed by the GIS editor + */ + public function generateWkt($gis_data, $index) + { + $geom_count = (isset($gis_data['GEOMETRYCOLLECTION']['geom_count'])) + ? $gis_data['GEOMETRYCOLLECTION']['geom_count'] : 1; + $wkt = 'GEOMETRYCOLLECTION('; + for ($i = 0; $i < $geom_count; $i++) { + if (isset($gis_data[$i]['gis_type'])) { + $type = $gis_data[$i]['gis_type']; + $gis_obj = PMA_GIS_Factory::factory($type); + $wkt .= $gis_obj->generateWkt($gis_data, $i) . ','; + } + } + if (isset($gis_data[0]['gis_type'])) { + $wkt = substr($wkt, 0, strlen($wkt) - 1); + } + $wkt .= ')'; + return $wkt; + } } ?> diff --git a/libraries/gis/pma_gis_linestring.php b/libraries/gis/pma_gis_linestring.php index 05483be736..fca3d017d0 100644 --- a/libraries/gis/pma_gis_linestring.php +++ b/libraries/gis/pma_gis_linestring.php @@ -194,5 +194,32 @@ class PMA_GIS_Linestring extends PMA_GIS_Geometry . json_encode($style_options) . '));'; return $result; } + + /** + * Generate the WKT with the set of parameters passed by the GIS editor. + * + * @param array $gis_data GIS data + * @param int $index Index into the parameter object + * + * @return WKT with the set of parameters passed by the GIS editor + */ + public function generateWkt($gis_data, $index) + { + $no_of_points = isset($gis_data[$index]['LINESTRING']['no_of_points']) + ? $gis_data[$index]['LINESTRING']['no_of_points'] : 2; + if ($no_of_points < 2) { + $no_of_points = 2; + } + $wkt = 'LINESTRING('; + for ($i = 0; $i < $no_of_points; $i++) { + $wkt .= (isset($gis_data[$index]['LINESTRING'][$i]['x']) + ? $gis_data[$index]['LINESTRING'][$i]['x'] : '') + . ' ' . (isset($gis_data[$index]['LINESTRING'][$i]['y']) + ? $gis_data[$index]['LINESTRING'][$i]['y'] : '') .','; + } + $wkt = substr($wkt, 0, strlen($wkt) - 1); + $wkt .= ')'; + return $wkt; + } } ?> diff --git a/libraries/gis/pma_gis_multilinestring.php b/libraries/gis/pma_gis_multilinestring.php index 9291202b69..050ec2a169 100644 --- a/libraries/gis/pma_gis_multilinestring.php +++ b/libraries/gis/pma_gis_multilinestring.php @@ -223,5 +223,42 @@ class PMA_GIS_Multilinestring extends PMA_GIS_Geometry $row .= ')), null, ' . json_encode($style_options) . '));'; return $row; } + + /** + * Generate the WKT with the set of parameters passed by the GIS editor. + * + * @param array $gis_data GIS data + * @param int $index Index into the parameter object + * + * @return WKT with the set of parameters passed by the GIS editor + */ + public function generateWkt($gis_data, $index) + { + $no_of_lines = isset($gis_data[$index]['MULTILINESTRING']['no_of_lines']) + ? $gis_data[$index]['MULTILINESTRING']['no_of_lines'] : 1; + if ($no_of_lines < 1) { + $no_of_lines = 1; + } + $wkt = 'MULTILINESTRING('; + for ($i = 0; $i < $no_of_lines; $i++) { + $no_of_points = isset($gis_data[$index]['MULTILINESTRING'][$i]['no_of_points']) + ? $gis_data[$index]['MULTILINESTRING'][$i]['no_of_points'] : 2; + if ($no_of_points < 2) { + $no_of_points = 2; + } + $wkt .= '('; + for ($j = 0; $j < $no_of_points; $j++) { + $wkt .= (isset($gis_data[$index]['MULTILINESTRING'][$i][$j]['x']) + ? $gis_data[$index]['MULTILINESTRING'][$i][$j]['x'] : '') + . ' ' . (isset($gis_data[$index]['MULTILINESTRING'][$i][$j]['y']) + ? $gis_data[$index]['MULTILINESTRING'][$i][$j]['y'] : '') .','; + } + $wkt = substr($wkt, 0, strlen($wkt) - 1); + $wkt .= '),'; + } + $wkt = substr($wkt, 0, strlen($wkt) - 1); + $wkt .= ')'; + return $wkt; + } } ?> diff --git a/libraries/gis/pma_gis_multipoint.php b/libraries/gis/pma_gis_multipoint.php index 8b66022dfb..e749760a4c 100644 --- a/libraries/gis/pma_gis_multipoint.php +++ b/libraries/gis/pma_gis_multipoint.php @@ -186,5 +186,32 @@ class PMA_GIS_Multipoint extends PMA_GIS_Geometry . json_encode($style_options) . '));'; return $result; } + + /** + * Generate the WKT with the set of parameters passed by the GIS editor. + * + * @param array $gis_data GIS data + * @param int $index Index into the parameter object + * + * @return WKT with the set of parameters passed by the GIS editor + */ + public function generateWkt($gis_data, $index) + { + $no_of_points = isset($gis_data[$index]['MULTIPOINT']['no_of_points']) + ? $gis_data[$index]['MULTIPOINT']['no_of_points'] : 1; + if ($no_of_points < 1) { + $no_of_points = 1; + } + $wkt = 'MULTIPOINT('; + for ($i = 0; $i < $no_of_points; $i++) { + $wkt .= (isset($gis_data[$index]['MULTIPOINT'][$i]['x']) + ? $gis_data[$index]['MULTIPOINT'][$i]['x'] : '') + . ' ' . (isset($gis_data[$index]['MULTIPOINT'][$i]['y']) + ? $gis_data[$index]['MULTIPOINT'][$i]['y'] : '') .','; + } + $wkt = substr($wkt, 0, strlen($wkt) - 1); + $wkt .= ')'; + return $wkt; + } } ?> diff --git a/libraries/gis/pma_gis_multipolygon.php b/libraries/gis/pma_gis_multipolygon.php index c0adcd10d7..5fa3148a96 100644 --- a/libraries/gis/pma_gis_multipolygon.php +++ b/libraries/gis/pma_gis_multipolygon.php @@ -311,5 +311,52 @@ class PMA_GIS_Multipolygon extends PMA_GIS_Geometry return $row; } + + /** + * Generate the WKT with the set of parameters passed by the GIS editor. + * + * @param array $gis_data GIS data + * @param int $index Index into the parameter object + * + * @return WKT with the set of parameters passed by the GIS editor + */ + public function generateWkt($gis_data, $index) + { + $no_of_polygons = isset($gis_data[$index]['MULTIPOLYGON']['no_of_polygons']) + ? $gis_data[$index]['MULTIPOLYGON']['no_of_polygons'] : 1; + if ($no_of_polygons < 1) { + $no_of_polygons = 1; + } + $wkt = 'MULTIPOLYGON('; + for ($k = 0; $k < $no_of_polygons; $k++) { + $no_of_lines = isset($gis_data[$index]['MULTIPOLYGON'][$k]['no_of_lines']) + ? $gis_data[$index]['MULTIPOLYGON'][$k]['no_of_lines'] : 1; + if ($no_of_lines < 1) { + $no_of_lines = 1; + } + $wkt .= '('; + for ($i = 0; $i < $no_of_lines; $i++) { + $no_of_points = isset($gis_data[$index]['MULTIPOLYGON'][$k][$i]['no_of_points']) + ? $gis_data[$index]['MULTIPOLYGON'][$k][$i]['no_of_points'] : 3; + if ($no_of_points < 3) { + $no_of_points = 3; + } + $wkt .= '('; + for ($j = 0; $j < $no_of_points; $j++) { + $wkt .= (isset($gis_data[$index]['MULTIPOLYGON'][$k][$i][$j]['x']) + ? $gis_data[$index]['MULTIPOLYGON'][$k][$i][$j]['x'] : '') + . ' ' . (isset($gis_data[$index]['MULTIPOLYGON'][$k][$i][$j]['y']) + ? $gis_data[$index]['MULTIPOLYGON'][$k][$i][$j]['y'] : '') .','; + } + $wkt = substr($wkt, 0, strlen($wkt) - 1); + $wkt .= '),'; + } + $wkt = substr($wkt, 0, strlen($wkt) - 1); + $wkt .= '),'; + } + $wkt = substr($wkt, 0, strlen($wkt) - 1); + $wkt .= ')'; + return $wkt; + } } ?> diff --git a/libraries/gis/pma_gis_point.php b/libraries/gis/pma_gis_point.php index 365eae4191..a63c5689f6 100644 --- a/libraries/gis/pma_gis_point.php +++ b/libraries/gis/pma_gis_point.php @@ -172,5 +172,19 @@ class PMA_GIS_Point extends PMA_GIS_Geometry . ' null, ' . json_encode($style_options) . '));'; return $result; } + + /** + * Generate the WKT with the set of parameters passed by the GIS editor. + * + * @param array $gis_data GIS data + * @param int $index Index into the parameter object + * + * @return WKT with the set of parameters passed by the GIS editor + */ + public function generateWkt($gis_data, $index) + { + return 'POINT(' . (isset($gis_data[$index]['POINT']['x']) ? $gis_data[$index]['POINT']['x'] : '') + . ' ' . (isset($gis_data[$index]['POINT']['y']) ? $gis_data[$index]['POINT']['y'] : '') . ')'; + } } ?> diff --git a/libraries/gis/pma_gis_polygon.php b/libraries/gis/pma_gis_polygon.php index 5da0d2545c..0497a7593d 100644 --- a/libraries/gis/pma_gis_polygon.php +++ b/libraries/gis/pma_gis_polygon.php @@ -286,5 +286,42 @@ class PMA_GIS_Polygon extends PMA_GIS_Geometry return $row; } + + /** + * Generate the WKT with the set of parameters passed by the GIS editor. + * + * @param array $gis_data GIS data + * @param int $index Index into the parameter object + * + * @return WKT with the set of parameters passed by the GIS editor + */ + public function generateWkt($gis_data, $index) + { + $no_of_lines = isset($gis_data[$index]['POLYGON']['no_of_lines']) + ? $gis_data[$index]['POLYGON']['no_of_lines'] : 1; + if ($no_of_lines < 1) { + $no_of_lines = 1; + } + $wkt = 'POLYGON('; + for ($i = 0; $i < $no_of_lines; $i++) { + $no_of_points = isset($gis_data[$index]['POLYGON'][$i]['no_of_points']) + ? $gis_data[$index]['POLYGON'][$i]['no_of_points'] : 3; + if ($no_of_points < 3) { + $no_of_points = 3; + } + $wkt .= '('; + for ($j = 0; $j < $no_of_points; $j++) { + $wkt .= (isset($gis_data[$index]['POLYGON'][$i][$j]['x']) + ? $gis_data[$index]['POLYGON'][$i][$j]['x'] : '') + . ' ' . (isset($gis_data[$index]['POLYGON'][$i][$j]['y']) + ? $gis_data[$index]['POLYGON'][$i][$j]['y'] : '') .','; + } + $wkt = substr($wkt, 0, strlen($wkt) - 1); + $wkt .= '),'; + } + $wkt = substr($wkt, 0, strlen($wkt) - 1); + $wkt .= ')'; + return $wkt; + } } ?> diff --git a/tbl_change.php b/tbl_change.php index 94c7da078d..a3e485a2c9 100644 --- a/tbl_change.php +++ b/tbl_change.php @@ -469,6 +469,9 @@ foreach ($rows as $row_id => $vrow) { $vrow) { $data = $vrow[$field['Field']]; } elseif ($field['True_Type'] == 'bit') { $special_chars = PMA_printable_bit_value($vrow[$field['Field']], $extracted_fieldspec['spec_in_brackets']); + } elseif (in_array($field['True_Type'], $gis_data_types)) { + // Convert gis data to Well Know Text format + $vrow[$field['Field']] = PMA_asWKT($vrow[$field['Field']], true); + $special_chars = htmlspecialchars($vrow[$field['Field']]); } else { // special binary "characters" if ($field['is_binary'] || ($field['is_blob'] && ! $cfg['ProtectBinary'])) { @@ -892,7 +899,6 @@ foreach ($rows as $row_id => $vrow) { } } // end if (web-server upload directory) } // end elseif (binary or blob) - elseif (in_array($field['pma_type'], $no_support_types)) { // ignore this column to avoid changing it } @@ -953,6 +959,17 @@ foreach ($rows as $row_id => $vrow) { } } } + if (in_array($field['pma_type'], $gis_data_types)) { + echo(''); + $_url_params = array('field' => $field['Field_title']); + if ($field['pma_type'] != 'geometry') { + $_url_params = $_url_params + array('gis_data[gis_type]' => strtoupper($field['pma_type'])); + } + $edit_url = 'gis_data_editor.php' . PMA_generate_common_url($_url_params); + $edit_str = PMA_getIcon('b_edit.png', __('Edit/Insert'), true); + echo(PMA_linkOrButton($edit_url, $edit_str, array(), false, false, '_blank')); + echo(''); + } ?> diff --git a/tbl_replace.php b/tbl_replace.php index e08dafb09d..6dd46bb283 100644 --- a/tbl_replace.php +++ b/tbl_replace.php @@ -171,6 +171,17 @@ $func_no_param = array( 'CURRENT_USER', ); +$gis_from_text_functions = array( + 'GeomFromText', + 'GeomCollFromText', + 'LineFromText', + 'MLineFromText', + 'PointFromText', + 'MPointFromText', + 'PolyFromText', + 'MPolyFromText', +); + foreach ($loop_array as $rownumber => $where_clause) { // skip fields to be ignored if (! $using_key && isset($_REQUEST['insert_ignore_' . $where_clause])) { @@ -260,6 +271,11 @@ foreach ($loop_array as $rownumber => $where_clause) { $cur_value = "'" . $uuid . "'"; } elseif (in_array($me_funcs[$key], $func_no_param)) { $cur_value = $me_funcs[$key] . '()'; + } elseif (in_array($me_funcs[$key], $gis_from_text_functions) && substr($val, 0, 3) == "'''") { + // Converting $val of the form '''POINT(12 15)'',145' to 'POINT(12 15)',145 + $val = str_replace("''", "'", $val); + $val = substr($val, 1, strlen($val) - 2); + $cur_value = $me_funcs[$key] . '(' . $val . ')'; } else { $cur_value = $me_funcs[$key] . '(' . $val . ')'; } diff --git a/themes/original/css/theme_right.css.php b/themes/original/css/theme_right.css.php index cd0a2fd55f..e4fd194ee9 100644 --- a/themes/original/css/theme_right.css.php +++ b/themes/original/css/theme_right.css.php @@ -965,7 +965,7 @@ img.sortableIcon { } h3#serverstatusqueries span { - font-size:60%; + font-size:60%; display:inline; } @@ -1048,9 +1048,9 @@ div#serverstatus table .tblFooters a:after { } div.liveChart { - clear:both; - min-width:500px; - height:400px; + clear:both; + min-width:500px; + height:400px; padding-bottom:80px; } @@ -1962,6 +1962,28 @@ fieldset .disabled-field td { display:none; } +#gis_data_editor { + display: none; + position: fixed; + _position: absolute; /* hack for IE */ + z-index: 101; + overflow-y: auto; + overflow-x: hidden; +} + +#gis_data_editor_no_js { + margin: auto auto; +} + +#gis_data_editor, #gis_data_editor_no_js { + background: #D0DCE0; + padding: 15px; +} + +#gis_data_textarea { + height: 6em; +} + .CodeMirror { line-height: 1em; font-family: monospace; diff --git a/themes/pmahomme/css/theme_right.css.php b/themes/pmahomme/css/theme_right.css.php index bba0bcb46d..96f49b69c0 100644 --- a/themes/pmahomme/css/theme_right.css.php +++ b/themes/pmahomme/css/theme_right.css.php @@ -1171,7 +1171,7 @@ img.sortableIcon { } h3#serverstatusqueries span { - font-size:60%; + font-size:60%; display:inline; } @@ -1238,9 +1238,9 @@ div#serverstatus table .tblFooters a { } div.liveChart { - clear:both; - min-width:500px; - height:400px; + clear:both; + min-width:500px; + height:400px; padding-bottom:80px; } /* end serverstatus */ @@ -2320,6 +2320,28 @@ fieldset .disabled-field td { display: none; } +#gis_data_editor { + display: none; + position: fixed; + _position: absolute; /* hack for IE */ + z-index: 101; + overflow-y: auto; + overflow-x: hidden; +} + +#gis_data_editor_no_js { + margin: auto auto; +} + +#gis_data_editor, #gis_data_editor_no_js { + background: #D0DCE0; + padding: 15px; +} + +#gis_data_textarea { + height: 6em; +} + .CodeMirror { line-height: 1em; font-family: monospace; From da6fe46a4d34c650e3d7f0b70d04ea22730f8e19 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sat, 25 Jun 2011 21:24:07 +0530 Subject: [PATCH 02/98] GISFromWKB functions in data insert/edit window fixed. --- tbl_replace.php | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/tbl_replace.php b/tbl_replace.php index 6dd46bb283..fad6b07429 100644 --- a/tbl_replace.php +++ b/tbl_replace.php @@ -182,6 +182,17 @@ $gis_from_text_functions = array( 'MPolyFromText', ); +$gis_from_wkb_functions = array( + 'GeomFromWKB', + 'GeomCollFromWKB', + 'LineFromWKB', + 'MLineFromWKB', + 'PointFromWKB', + 'MPointFromWKB', + 'PolyFromWKB', + 'MPolyFromWKB', +); + foreach ($loop_array as $rownumber => $where_clause) { // skip fields to be ignored if (! $using_key && isset($_REQUEST['insert_ignore_' . $where_clause])) { @@ -271,10 +282,14 @@ foreach ($loop_array as $rownumber => $where_clause) { $cur_value = "'" . $uuid . "'"; } elseif (in_array($me_funcs[$key], $func_no_param)) { $cur_value = $me_funcs[$key] . '()'; - } elseif (in_array($me_funcs[$key], $gis_from_text_functions) && substr($val, 0, 3) == "'''") { - // Converting $val of the form '''POINT(12 15)'',145' to 'POINT(12 15)',145 - $val = str_replace("''", "'", $val); + } elseif ((in_array($me_funcs[$key], $gis_from_text_functions) + && substr($val, 0, 3) == "'''") + || in_array($me_funcs[$key], $gis_from_wkb_functions) + ) { + // Remove enclosing apostrophes $val = substr($val, 1, strlen($val) - 2); + // Remove escaping apostrophes + $val = str_replace("''", "'", $val); $cur_value = $me_funcs[$key] . '(' . $val . ')'; } else { $cur_value = $me_funcs[$key] . '(' . $val . ')'; From 5ac3f567c454764152631c26a9dafec7bf7eef0a Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sat, 25 Jun 2011 23:01:48 +0530 Subject: [PATCH 03/98] GIS data editing for POINT --- gis_data_editor.php | 13 ++++++++++--- libraries/gis/pma_gis_point.php | 25 +++++++++++++++++++++++++ tbl_change.php | 5 ++++- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/gis_data_editor.php b/gis_data_editor.php index dd096bbb61..37d46c5f7d 100644 --- a/gis_data_editor.php +++ b/gis_data_editor.php @@ -24,13 +24,20 @@ $gis_types = array( $no_visual = true; if (! isset($gis_data['gis_type'])) { - $gis_data['gis_type'] = $gis_types[0]; - $no_visual = true; + if (isset($_REQUEST['value'])) { + $gis_data['gis_type'] = substr($_REQUEST['value'], 1, strpos($_REQUEST['value'], "(") - 1); + } else { + $gis_data['gis_type'] = $gis_types[0]; + $no_visual = true; + } } - $geom_type = $gis_data['gis_type']; $gis_obj = PMA_GIS_Factory::factory($geom_type); +if (isset($_REQUEST['value'])) { + $gis_data = array_merge($gis_data, $gis_obj->generateParams($_REQUEST['value'])); +} + $srid = isset($gis_data['srid']) ? htmlspecialchars($gis_data['srid']) : ''; $wkt = $gis_obj->generateWkt($gis_data, 0); diff --git a/libraries/gis/pma_gis_point.php b/libraries/gis/pma_gis_point.php index a63c5689f6..50b70a1438 100644 --- a/libraries/gis/pma_gis_point.php +++ b/libraries/gis/pma_gis_point.php @@ -186,5 +186,30 @@ class PMA_GIS_Point extends PMA_GIS_Geometry return 'POINT(' . (isset($gis_data[$index]['POINT']['x']) ? $gis_data[$index]['POINT']['x'] : '') . ' ' . (isset($gis_data[$index]['POINT']['y']) ? $gis_data[$index]['POINT']['y'] : '') . ')'; } + + /** + * Generate parameters for the GIS data editor from the value of the gis column. + * + * @param string $value of the gis column + * @param index $index of the geometry + * + * @return parameters for the GIS data editor from the value of the gis column + */ + public function generateParams($value, $index = 0) + { + $params = array(); + $lastComma = strripos($value, ","); + $params['srid'] = trim(substr($value, $lastComma + 1)); + $wkt = trim(substr($value, 1, $lastComma - 2)); + + // Trim to remove leading 'POINT(' and trailing ')' + $point = substr($wkt, 6, (strlen($wkt) - 7)); + $points_arr = $this->extractPoints($point, null); + + $params[$index]['POINT']['x'] = $points_arr[0][0]; + $params[$index]['POINT']['y'] = $points_arr[0][1]; + + return $params; + } } ?> diff --git a/tbl_change.php b/tbl_change.php index a3e485a2c9..66ee5cf408 100644 --- a/tbl_change.php +++ b/tbl_change.php @@ -961,7 +961,10 @@ foreach ($rows as $row_id => $vrow) { } if (in_array($field['pma_type'], $gis_data_types)) { echo(''); - $_url_params = array('field' => $field['Field_title']); + $_url_params = array( + 'field' => $field['Field_title'], + 'value' => $vrow[$field['Field']], + ); if ($field['pma_type'] != 'geometry') { $_url_params = $_url_params + array('gis_data[gis_type]' => strtoupper($field['pma_type'])); } From ff3efd4b7d3ac7b00117d7ef78f239972e3f9d50 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sun, 26 Jun 2011 17:57:12 +0530 Subject: [PATCH 04/98] Editing geometry data using GIS data editor. --- libraries/gis/pma_gis_geometrycollection.php | 32 +++++++++++ libraries/gis/pma_gis_linestring.php | 35 ++++++++++++ libraries/gis/pma_gis_multilinestring.php | 41 ++++++++++++++ libraries/gis/pma_gis_multipoint.php | 35 ++++++++++++ libraries/gis/pma_gis_multipolygon.php | 59 ++++++++++++++++++++ libraries/gis/pma_gis_point.php | 22 +++++--- libraries/gis/pma_gis_polygon.php | 40 +++++++++++++ 7 files changed, 256 insertions(+), 8 deletions(-) diff --git a/libraries/gis/pma_gis_geometrycollection.php b/libraries/gis/pma_gis_geometrycollection.php index 2fcb62441d..d8c17b3aaa 100644 --- a/libraries/gis/pma_gis_geometrycollection.php +++ b/libraries/gis/pma_gis_geometrycollection.php @@ -248,5 +248,37 @@ class PMA_GIS_Geometrycollection extends PMA_GIS_Geometry $wkt .= ')'; return $wkt; } + + /** Generate parameters for the GIS data editor from the value of the GIS column. + * + * @param string $value of the GIS column + * @param index $index of the geometry + * + * @return parameters for the GIS data editor from the value of the GIS column + */ + public function generateParams($value) + { + $params = array(); + $last_comma = strripos($value, ","); + $params['srid'] = trim(substr($value, $last_comma + 1)); + $wkt = trim(substr($value, 1, $last_comma - 2)); + + // Trim to remove leading 'GEOMETRYCOLLECTION(' and trailing ')' + $goem_col = substr($wkt, 19, (strlen($wkt) - 20)); + // Split the geometry collection object to get its constituents. + $sub_parts = $this->_explodeGeomCol($goem_col); + $params['GEOMETRYCOLLECTION']['geom_count'] = count($sub_parts); + + $i = 0; + foreach ($sub_parts as $sub_part) { + $type_pos = stripos($sub_part, '('); + $type = substr($sub_part, 0, $type_pos); + + $gis_obj = PMA_GIS_Factory::factory($type); + $params = array_merge($params, $gis_obj->generateParams($sub_part, $i)); + $i++; + } + return $params; + } } ?> diff --git a/libraries/gis/pma_gis_linestring.php b/libraries/gis/pma_gis_linestring.php index fca3d017d0..8114451ae0 100644 --- a/libraries/gis/pma_gis_linestring.php +++ b/libraries/gis/pma_gis_linestring.php @@ -221,5 +221,40 @@ class PMA_GIS_Linestring extends PMA_GIS_Geometry $wkt .= ')'; return $wkt; } + + /** + * Generate parameters for the GIS data editor from the value of the GIS column. + * + * @param string $value of the GIS column + * @param index $index of the geometry + * + * @return parameters for the GIS data editor from the value of the GIS column + */ + public function generateParams($value, $index = -1) + { + if ($index == -1) { + $index = 0; + $params = array(); + $last_comma = strripos($value, ","); + $params['srid'] = trim(substr($value, $last_comma + 1)); + $wkt = trim(substr($value, 1, $last_comma - 2)); + } else { + $params[$index]['gis_type'] = 'LINESTRING'; + $wkt = $value; + } + + // Trim to remove leading 'LINESTRING(' and trailing ')' + $linestring = substr($wkt, 11, (strlen($wkt) - 12)); + $points_arr = $this->extractPoints($linestring, null); + + $no_of_points = count($points_arr); + $params[$index]['LINESTRING']['no_of_points'] = $no_of_points; + for ($i = 0; $i < $no_of_points; $i++) { + $params[$index]['LINESTRING'][$i]['x'] = $points_arr[$i][0]; + $params[$index]['LINESTRING'][$i]['y'] = $points_arr[$i][1]; + } + + return $params; + } } ?> diff --git a/libraries/gis/pma_gis_multilinestring.php b/libraries/gis/pma_gis_multilinestring.php index 050ec2a169..f80dbc17bd 100644 --- a/libraries/gis/pma_gis_multilinestring.php +++ b/libraries/gis/pma_gis_multilinestring.php @@ -260,5 +260,46 @@ class PMA_GIS_Multilinestring extends PMA_GIS_Geometry $wkt .= ')'; return $wkt; } + + /** + * Generate parameters for the GIS data editor from the value of the GIS column. + * + * @param string $value of the GIS column + * @param index $index of the geometry + * + * @return parameters for the GIS data editor from the value of the GIS column + */ + public function generateParams($value, $index = -1) + { + if ($index == -1) { + $index = 0; + $params = array(); + $last_comma = strripos($value, ","); + $params['srid'] = trim(substr($value, $last_comma + 1)); + $wkt = trim(substr($value, 1, $last_comma - 2)); + } else { + $params[$index]['gis_type'] = 'MULTILINESTRING'; + $wkt = $value; + } + + // Trim to remove leading 'MULTILINESTRING((' and trailing '))' + $multilinestirng = substr($wkt, 17, (strlen($wkt) - 19)); + // Seperate each linestring + $linestirngs = explode("),(", $multilinestirng); + $params[$index]['MULTILINESTRING']['no_of_lines'] = count($linestirngs); + + $j = 0; + foreach ($linestirngs as $linestring) { + $points_arr = $this->extractPoints($linestring, null); + $no_of_points = count($points_arr); + $params[$index]['MULTILINESTRING'][$j]['no_of_points'] = $no_of_points; + for ($i = 0; $i < $no_of_points; $i++) { + $params[$index]['MULTILINESTRING'][$j][$i]['x'] = $points_arr[$i][0]; + $params[$index]['MULTILINESTRING'][$j][$i]['y'] = $points_arr[$i][1]; + } + $j++; + } + return $params; + } } ?> diff --git a/libraries/gis/pma_gis_multipoint.php b/libraries/gis/pma_gis_multipoint.php index e749760a4c..c97813a66e 100644 --- a/libraries/gis/pma_gis_multipoint.php +++ b/libraries/gis/pma_gis_multipoint.php @@ -213,5 +213,40 @@ class PMA_GIS_Multipoint extends PMA_GIS_Geometry $wkt .= ')'; return $wkt; } + + /** + * Generate parameters for the GIS data editor from the value of the GIS column. + * + * @param string $value of the GIS column + * @param index $index of the geometry + * + * @return parameters for the GIS data editor from the value of the GIS column + */ + public function generateParams($value, $index = -1) + { + if ($index == -1) { + $index = 0; + $params = array(); + $last_comma = strripos($value, ","); + $params['srid'] = trim(substr($value, $last_comma + 1)); + $wkt = trim(substr($value, 1, $last_comma - 2)); + } else { + $params[$index]['gis_type'] = 'MULTIPOINT'; + $wkt = $value; + } + + // Trim to remove leading 'MULTIPOINT(' and trailing ')' + $points = substr($wkt, 11, (strlen($wkt) - 12)); + $points_arr = $this->extractPoints($points, null); + + $no_of_points = count($points_arr); + $params[$index]['MULTIPOINT']['no_of_points'] = $no_of_points; + for ($i = 0; $i < $no_of_points; $i++) { + $params[$index]['MULTIPOINT'][$i]['x'] = $points_arr[$i][0]; + $params[$index]['MULTIPOINT'][$i]['y'] = $points_arr[$i][1]; + } + + return $params; + } } ?> diff --git a/libraries/gis/pma_gis_multipolygon.php b/libraries/gis/pma_gis_multipolygon.php index 5fa3148a96..03be3bc3c6 100644 --- a/libraries/gis/pma_gis_multipolygon.php +++ b/libraries/gis/pma_gis_multipolygon.php @@ -358,5 +358,64 @@ class PMA_GIS_Multipolygon extends PMA_GIS_Geometry $wkt .= ')'; return $wkt; } + + /** Generate parameters for the GIS data editor from the value of the GIS column. + * + * @param string $value of the GIS column + * @param index $index of the geometry + * + * @return parameters for the GIS data editor from the value of the GIS column + */ + public function generateParams($value, $index = -1) + { + if ($index == -1) { + $index = 0; + $params = array(); + $last_comma = strripos($value, ","); + $params['srid'] = trim(substr($value, $last_comma + 1)); + $wkt = trim(substr($value, 1, $last_comma - 2)); + } else { + $params[$index]['gis_type'] = 'MULTIPOLYGON'; + $wkt = $value; + } + + // Trim to remove leading 'MULTIPOLYGON(((' and trailing ')))' + $multipolygon = substr($wkt, 15, (strlen($wkt) - 18)); + // Seperate each polygon + $polygons = explode(")),((", $multipolygon); + $params[$index]['MULTIPOLYGON']['no_of_polygons'] = count($polygons); + + $k = 0; + foreach ($polygons as $polygon) { + // If the polygon doesnt have an inner polygon + if (strpos($polygon, "),(") === false) { + $params[$index]['MULTIPOLYGON'][$k]['no_of_lines'] = 1; + $points_arr = $this->extractPoints($polygon, null); + $no_of_points = count($points_arr); + $params[$index]['MULTIPOLYGON'][$k][0]['no_of_points'] = $no_of_points; + for ($i = 0; $i < $no_of_points; $i++) { + $params[$index]['MULTIPOLYGON'][$k][0][$i]['x'] = $points_arr[$i][0]; + $params[$index]['MULTIPOLYGON'][$k][0][$i]['y'] = $points_arr[$i][1]; + } + } else { + // Seperate outer and inner polygons + $parts = explode("),(", $polygon); + $params[$index]['MULTIPOLYGON'][$k]['no_of_lines'] = count($parts); + $j = 0; + foreach ($parts as $ring) { + $points_arr = $this->extractPoints($ring, null); + $no_of_points = count($points_arr); + $params[$index]['MULTIPOLYGON'][$k][$j]['no_of_points'] = $no_of_points; + for ($i = 0; $i < $no_of_points; $i++) { + $params[$index]['MULTIPOLYGON'][$k][$j][$i]['x'] = $points_arr[$i][0]; + $params[$index]['MULTIPOLYGON'][$k][$j][$i]['y'] = $points_arr[$i][1]; + } + $j++; + } + } + $k++; + } + return $params; + } } ?> diff --git a/libraries/gis/pma_gis_point.php b/libraries/gis/pma_gis_point.php index 50b70a1438..d5db147aa2 100644 --- a/libraries/gis/pma_gis_point.php +++ b/libraries/gis/pma_gis_point.php @@ -188,19 +188,25 @@ class PMA_GIS_Point extends PMA_GIS_Geometry } /** - * Generate parameters for the GIS data editor from the value of the gis column. + * Generate parameters for the GIS data editor from the value of the GIS column. * - * @param string $value of the gis column + * @param string $value of the GIS column * @param index $index of the geometry * - * @return parameters for the GIS data editor from the value of the gis column + * @return parameters for the GIS data editor from the value of the GIS column */ - public function generateParams($value, $index = 0) + public function generateParams($value, $index = -1) { - $params = array(); - $lastComma = strripos($value, ","); - $params['srid'] = trim(substr($value, $lastComma + 1)); - $wkt = trim(substr($value, 1, $lastComma - 2)); + if ($index == -1) { + $index = 0; + $params = array(); + $last_comma = strripos($value, ","); + $params['srid'] = trim(substr($value, $last_comma + 1)); + $wkt = trim(substr($value, 1, $last_comma - 2)); + } else { + $params[$index]['gis_type'] = 'POINT'; + $wkt = $value; + } // Trim to remove leading 'POINT(' and trailing ')' $point = substr($wkt, 6, (strlen($wkt) - 7)); diff --git a/libraries/gis/pma_gis_polygon.php b/libraries/gis/pma_gis_polygon.php index 0497a7593d..3bef784e5c 100644 --- a/libraries/gis/pma_gis_polygon.php +++ b/libraries/gis/pma_gis_polygon.php @@ -323,5 +323,45 @@ class PMA_GIS_Polygon extends PMA_GIS_Geometry $wkt .= ')'; return $wkt; } + + /** Generate parameters for the GIS data editor from the value of the GIS column. + * + * @param string $value of the GIS column + * @param index $index of the geometry + * + * @return parameters for the GIS data editor from the value of the GIS column + */ + public function generateParams($value, $index = -1) + { + if ($index == -1) { + $index = 0; + $params = array(); + $last_comma = strripos($value, ","); + $params['srid'] = trim(substr($value, $last_comma + 1)); + $wkt = trim(substr($value, 1, $last_comma - 2)); + } else { + $params[$index]['gis_type'] = 'POLYGON'; + $wkt = $value; + } + + // Trim to remove leading 'POLYGON((' and trailing '))' + $polygon = substr($wkt, 9, (strlen($wkt) - 11)); + // Seperate each linestring + $linerings = explode("),(", $polygon); + $params[$index]['POLYGON']['no_of_lines'] = count($linerings); + + $j = 0; + foreach ($linerings as $linering) { + $points_arr = $this->extractPoints($linering, null); + $no_of_points = count($points_arr); + $params[$index]['POLYGON'][$j]['no_of_points'] = $no_of_points; + for ($i = 0; $i < $no_of_points; $i++) { + $params[$index]['POLYGON'][$j][$i]['x'] = $points_arr[$i][0]; + $params[$index]['POLYGON'][$j][$i]['y'] = $points_arr[$i][1]; + } + $j++; + } + return $params; + } } ?> From 67ef96d1f6d6bbf6b7d906a02c4c79898a11ee66 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Thu, 30 Jun 2011 09:58:09 +0530 Subject: [PATCH 05/98] Check whether the variable is set before accessing it. --- libraries/gis_visualization.lib.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/gis_visualization.lib.php b/libraries/gis_visualization.lib.php index cc15dc984a..388d1830e9 100644 --- a/libraries/gis_visualization.lib.php +++ b/libraries/gis_visualization.lib.php @@ -75,7 +75,9 @@ function PMA_GIS_modify_query($sql_query, $visualizationSettings) // If select cluase is * } else { // If label column is chosen add it to the query - if ($visualizationSettings['labelColumn'] != '') { + if (isset($visualizationSettings['labelColumn']) + && $visualizationSettings['labelColumn'] != '' + ) { $modified_query .= '`' . $visualizationSettings['labelColumn'] .'`, '; } From c4faafdc792abb3b2bef62b70ab7f32fd85aa143 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sun, 3 Jul 2011 22:12:02 +0530 Subject: [PATCH 06/98] Import GIS data from ESRI shape files --- libraries/bfShapeFiles/ShapeFile.lib.php | 649 ++++++++++++++++++++++ libraries/gis/pma_gis_multilinestring.php | 24 +- libraries/gis/pma_gis_multipoint.php | 19 +- libraries/gis/pma_gis_point.php | 12 + libraries/import.lib.php | 45 +- libraries/import/shp.php | 344 ++++++++++++ 6 files changed, 1075 insertions(+), 18 deletions(-) create mode 100644 libraries/bfShapeFiles/ShapeFile.lib.php create mode 100644 libraries/import/shp.php diff --git a/libraries/bfShapeFiles/ShapeFile.lib.php b/libraries/bfShapeFiles/ShapeFile.lib.php new file mode 100644 index 0000000000..0680708c05 --- /dev/null +++ b/libraries/bfShapeFiles/ShapeFile.lib.php @@ -0,0 +1,649 @@ += 0 ; $i--) { + $result .= $binValue{$i}; + } + + return $result; + } + + function packDouble($value, $mode = 'LE') { + $value = (double)$value; + $bin = pack("d", $value); + + //We test if the conversion of an integer (1) is done as LE or BE by default + switch (pack ('L', 1)) { + case pack ('V', 1): //Little Endian + $result = ($mode == 'LE') ? $bin : swap($bin); + break; + case pack ('N', 1): //Big Endian + $result = ($mode == 'BE') ? $bin : swap($bin); + break; + default: //Some other thing, we just return false + $result = FALSE; + } + + return $result; + } + + class ShapeFile { + var $FileName; + + var $SHPFile; + var $SHXFile; + var $DBFFile; + + var $DBFHeader; + + var $lastError = ""; + + var $boundingBox = array("xmin" => 0.0, "ymin" => 0.0, "xmax" => 0.0, "ymax" => 0.0); + var $fileLength = 0; + var $shapeType = 0; + + var $records; + + function ShapeFile($shapeType, $boundingBox = array("xmin" => 0.0, "ymin" => 0.0, "xmax" => 0.0, "ymax" => 0.0), $FileName = NULL) { + $this->shapeType = $shapeType; + $this->boundingBox = $boundingBox; + $this->FileName = $FileName; + $this->fileLength = 50; + } + + function loadFromFile($FileName) { + $this->FileName = $FileName; + + if (($this->_openSHPFile()) && ($this->_openDBFFile())) { + $this->_loadHeaders(); + $this->_loadRecords(); + $this->_closeSHPFile(); + $this->_closeDBFFile(); + } else { + return false; + } + } + + function saveToFile($FileName = NULL) { + if ($FileName != NULL) $this->FileName = $FileName; + + if (($this->_openSHPFile(TRUE)) && ($this->_openSHXFile(TRUE)) && ($this->_openDBFFile(TRUE))) { + $this->_saveHeaders(); + $this->_saveRecords(); + $this->_closeSHPFile(); + $this->_closeSHXFile(); + $this->_closeDBFFile(); + } else { + return false; + } + } + + function addRecord($record) { + if ((isset($this->DBFHeader)) && (is_array($this->DBFHeader))) { + $record->updateDBFInfo($this->DBFHeader); + } + + $this->fileLength += ($record->getContentLength() + 4); + $this->records[] = $record; + $this->records[count($this->records) - 1]->recordNumber = count($this->records); + + return (count($this->records) - 1); + } + + function deleteRecord($index) { + if (isset($this->records[$index])) { + $this->fileLength -= ($this->records[$index]->getContentLength() + 4); + for ($i = $index; $i < (count($this->records) - 1); $i++) { + $this->records[$i] = $this->records[$i + 1]; + } + unset($this->records[count($this->records) - 1]); + $this->_deleteRecordFromDBF($index); + } + } + + function getDBFHeader() { + return $this->DBFHeader; + } + + function setDBFHeader($header) { + $this->DBFHeader = $header; + + for ($i = 0; $i < count($this->records); $i++) { + $this->records[$i]->updateDBFInfo($header); + } + } + + function getIndexFromDBFData($field, $value) { + $result = -1; + for ($i = 0; $i < (count($this->records) - 1); $i++) { + if (isset($this->records[$i]->DBFData[$field]) && (strtoupper($this->records[$i]->DBFData[$field]) == strtoupper($value))) { + $result = $i; + } + } + + return $result; + } + + function _loadDBFHeader() { + $DBFFile = fopen(str_replace('.*', '.dbf', $this->FileName), 'r'); + + $result = array(); + $buff32 = array(); + $i = 1; + $inHeader = true; + + while ($inHeader) { + if (!feof($DBFFile)) { + $buff32 = fread($DBFFile, 32); + if ($i > 1) { + if (substr($buff32, 0, 1) == chr(13)) { + $inHeader = false; + } else { + $pos = strpos(substr($buff32, 0, 10), chr(0)); + $pos = ($pos == 0 ? 10 : $pos); + + $fieldName = substr($buff32, 0, $pos); + $fieldType = substr($buff32, 11, 1); + $fieldLen = ord(substr($buff32, 16, 1)); + $fieldDec = ord(substr($buff32, 17, 1)); + + array_push($result, array($fieldName, $fieldType, $fieldLen, $fieldDec)); + } + } + $i++; + } else { + $inHeader = false; + } + } + + fclose($DBFFile); + return($result); + } + + function _deleteRecordFromDBF($index) { + if (@dbase_delete_record($this->DBFFile, $index)) { + @dbase_pack($this->DBFFile); + } + } + + function _loadHeaders() { + fseek($this->SHPFile, 24, SEEK_SET); + $this->fileLength = loadData("N", fread($this->SHPFile, 4)); + + fseek($this->SHPFile, 32, SEEK_SET); + $this->shapeType = loadData("V", fread($this->SHPFile, 4)); + + $this->boundingBox = array(); + $this->boundingBox["xmin"] = loadData("d", fread($this->SHPFile, 8)); + $this->boundingBox["ymin"] = loadData("d", fread($this->SHPFile, 8)); + $this->boundingBox["xmax"] = loadData("d", fread($this->SHPFile, 8)); + $this->boundingBox["ymax"] = loadData("d", fread($this->SHPFile, 8)); + + $this->DBFHeader = $this->_loadDBFHeader(); + } + + function _saveHeaders() { + fwrite($this->SHPFile, pack("NNNNNN", 9994, 0, 0, 0, 0, 0)); + fwrite($this->SHPFile, pack("N", $this->fileLength)); + fwrite($this->SHPFile, pack("V", 1000)); + fwrite($this->SHPFile, pack("V", $this->shapeType)); + fwrite($this->SHPFile, packDouble($this->boundingBox['xmin'])); + fwrite($this->SHPFile, packDouble($this->boundingBox['ymin'])); + fwrite($this->SHPFile, packDouble($this->boundingBox['xmax'])); + fwrite($this->SHPFile, packDouble($this->boundingBox['ymax'])); + fwrite($this->SHPFile, pack("dddd", 0, 0, 0, 0)); + + fwrite($this->SHXFile, pack("NNNNNN", 9994, 0, 0, 0, 0, 0)); + fwrite($this->SHXFile, pack("N", 50 + 4*count($this->records))); + fwrite($this->SHXFile, pack("V", 1000)); + fwrite($this->SHXFile, pack("V", $this->shapeType)); + fwrite($this->SHXFile, packDouble($this->boundingBox['xmin'])); + fwrite($this->SHXFile, packDouble($this->boundingBox['ymin'])); + fwrite($this->SHXFile, packDouble($this->boundingBox['xmax'])); + fwrite($this->SHXFile, packDouble($this->boundingBox['ymax'])); + fwrite($this->SHXFile, pack("dddd", 0, 0, 0, 0)); + } + + function _loadRecords() { + fseek($this->SHPFile, 100); + while (!feof($this->SHPFile)) { + $bByte = ftell($this->SHPFile); + $record = new ShapeRecord(-1); + $record->loadFromFile($this->SHPFile, $this->DBFFile); + $eByte = ftell($this->SHPFile); + if (($eByte <= $bByte) || ($record->lastError != "")) { + return false; + } + + $this->records[] = $record; + } + } + + function _saveRecords() { + if (file_exists(str_replace('.*', '.dbf', $this->FileName))) { + @unlink(str_replace('.*', '.dbf', $this->FileName)); + } + if (!($this->DBFFile = @dbase_create(str_replace('.*', '.dbf', $this->FileName), $this->DBFHeader))) { + return $this->setError(sprintf("It wasn't possible to create the DBase file '%s'", str_replace('.*', '.dbf', $this->FileName))); + } + + $offset = 50; + if (is_array($this->records) && (count($this->records) > 0)) { + reset($this->records); + while (list($index, $record) = each($this->records)) { + //Save the record to the .shp file + $record->saveToFile($this->SHPFile, $this->DBFFile, $index + 1); + + //Save the record to the .shx file + fwrite($this->SHXFile, pack("N", $offset)); + fwrite($this->SHXFile, pack("N", $record->getContentLength())); + $offset += (4 + $record->getContentLength()); + } + } + @dbase_pack($this->DBFFile); + } + + function _openSHPFile($toWrite = false) { + $this->SHPFile = @fopen(str_replace('.*', '.shp', $this->FileName), ($toWrite ? "wb+" : "rb")); + if (!$this->SHPFile) { + return $this->setError(sprintf("It wasn't possible to open the Shape file '%s'", str_replace('.*', '.shp', $this->FileName))); + } + + return TRUE; + } + + function _closeSHPFile() { + if ($this->SHPFile) { + fclose($this->SHPFile); + $this->SHPFile = NULL; + } + } + + function _openSHXFile($toWrite = false) { + $this->SHXFile = @fopen(str_replace('.*', '.shx', $this->FileName), ($toWrite ? "wb+" : "rb")); + if (!$this->SHXFile) { + return $this->setError(sprintf("It wasn't possible to open the Index file '%s'", str_replace('.*', '.shx', $this->FileName))); + } + + return TRUE; + } + + function _closeSHXFile() { + if ($this->SHXFile) { + fclose($this->SHXFile); + $this->SHXFile = NULL; + } + } + + function _openDBFFile($toWrite = false) { + $checkFunction = $toWrite ? "is_writable" : "is_readable"; + if (($toWrite) && (!file_exists(str_replace('.*', '.dbf', $this->FileName)))) { + if (!@dbase_create(str_replace('.*', '.dbf', $this->FileName), $this->DBFHeader)) { + return $this->setError(sprintf("It wasn't possible to create the DBase file '%s'", str_replace('.*', '.dbf', $this->FileName))); + } + } + if ($checkFunction(str_replace('.*', '.dbf', $this->FileName))) { + $this->DBFFile = dbase_open(str_replace('.*', '.dbf', $this->FileName), ($toWrite ? 2 : 0)); + if (!$this->DBFFile) { + return $this->setError(sprintf("It wasn't possible to open the DBase file '%s'", str_replace('.*', '.dbf', $this->FileName))); + } + } else { + return $this->setError(sprintf("It wasn't possible to find the DBase file '%s'", str_replace('.*', '.dbf', $this->FileName))); + } + return TRUE; + } + + function _closeDBFFile() { + if ($this->DBFFile) { + dbase_close($this->DBFFile); + $this->DBFFile = NULL; + } + } + + function setError($error) { + $this->lastError = $error; + return false; + } + } + + class ShapeRecord { + var $SHPFile = NULL; + var $DBFFile = NULL; + + var $recordNumber = NULL; + var $shapeType = NULL; + + var $lastError = ""; + + var $SHPData = array(); + var $DBFData = array(); + + function ShapeRecord($shapeType) { + $this->shapeType = $shapeType; + } + + function loadFromFile(&$SHPFile, &$DBFFile) { + $this->SHPFile = $SHPFile; + $this->DBFFile = $DBFFile; + $this->_loadHeaders(); + + switch ($this->shapeType) { + case 0: + $this->_loadNullRecord(); + break; + case 1: + $this->_loadPointRecord(); + break; + case 3: + $this->_loadPolyLineRecord(); + break; + case 5: + $this->_loadPolygonRecord(); + break; + case 8: + $this->_loadMultiPointRecord(); + break; + default: + $this->setError(sprintf("The Shape Type '%s' is not supported.", $this->shapeType)); + break; + } + $this->_loadDBFData(); + } + + function saveToFile(&$SHPFile, &$DBFFile, $recordNumber) { + $this->SHPFile = $SHPFile; + $this->DBFFile = $DBFFile; + $this->recordNumber = $recordNumber; + $this->_saveHeaders(); + + switch ($this->shapeType) { + case 0: + $this->_saveNullRecord(); + break; + case 1: + $this->_savePointRecord(); + break; + case 3: + $this->_savePolyLineRecord(); + break; + case 5: + $this->_savePolygonRecord(); + break; + case 8: + $this->_saveMultiPointRecord(); + break; + default: + $this->setError(sprintf("The Shape Type '%s' is not supported.", $this->shapeType)); + break; + } + $this->_saveDBFData(); + } + + function updateDBFInfo($header) { + $tmp = $this->DBFData; + unset($this->DBFData); + $this->DBFData = array(); + reset($header); + while (list($key, $value) = each($header)) { + $this->DBFData[$value[0]] = (isset($tmp[$value[0]])) ? $tmp[$value[0]] : ""; + } + } + + function _loadHeaders() { + $this->recordNumber = loadData("N", fread($this->SHPFile, 4)); + $tmp = loadData("N", fread($this->SHPFile, 4)); //We read the length of the record + $this->shapeType = loadData("V", fread($this->SHPFile, 4)); + } + + function _saveHeaders() { + fwrite($this->SHPFile, pack("N", $this->recordNumber)); + fwrite($this->SHPFile, pack("N", $this->getContentLength())); + fwrite($this->SHPFile, pack("V", $this->shapeType)); + } + + function _loadPoint() { + $data = array(); + + $data["x"] = loadData("d", fread($this->SHPFile, 8)); + $data["y"] = loadData("d", fread($this->SHPFile, 8)); + + return $data; + } + + function _savePoint($data) { + fwrite($this->SHPFile, packDouble($data["x"])); + fwrite($this->SHPFile, packDouble($data["y"])); + } + + function _loadNullRecord() { + $this->SHPData = array(); + } + + function _saveNullRecord() { + //Don't save anything + } + + function _loadPointRecord() { + $this->SHPData = $this->_loadPoint(); + } + + function _savePointRecord() { + $this->_savePoint($this->SHPData); + } + + function _loadMultiPointRecord() { + $this->SHPData = array(); + $this->SHPData["xmin"] = loadData("d", fread($this->SHPFile, 8)); + $this->SHPData["ymin"] = loadData("d", fread($this->SHPFile, 8)); + $this->SHPData["xmax"] = loadData("d", fread($this->SHPFile, 8)); + $this->SHPData["ymax"] = loadData("d", fread($this->SHPFile, 8)); + + $this->SHPData["numpoints"] = loadData("V", fread($this->SHPFile, 4)); + + for ($i = 0; $i <= $this->SHPData["numpoints"]; $i++) { + $this->SHPData["points"][] = $this->_loadPoint(); + } + } + + function _saveMultiPointRecord() { + fwrite($this->SHPFile, pack("dddd", $this->SHPData["xmin"], $this->SHPData["ymin"], $this->SHPData["xmax"], $this->SHPData["ymax"])); + + fwrite($this->SHPFile, pack("V", $this->SHPData["numpoints"])); + + for ($i = 0; $i <= $this->SHPData["numpoints"]; $i++) { + $this->_savePoint($this->SHPData["points"][$i]); + } + } + + function _loadPolyLineRecord() { + $this->SHPData = array(); + $this->SHPData["xmin"] = loadData("d", fread($this->SHPFile, 8)); + $this->SHPData["ymin"] = loadData("d", fread($this->SHPFile, 8)); + $this->SHPData["xmax"] = loadData("d", fread($this->SHPFile, 8)); + $this->SHPData["ymax"] = loadData("d", fread($this->SHPFile, 8)); + + $this->SHPData["numparts"] = loadData("V", fread($this->SHPFile, 4)); + $this->SHPData["numpoints"] = loadData("V", fread($this->SHPFile, 4)); + + for ($i = 0; $i < $this->SHPData["numparts"]; $i++) { + $this->SHPData["parts"][$i] = loadData("V", fread($this->SHPFile, 4)); + } + + $firstIndex = ftell($this->SHPFile); + $readPoints = 0; + reset($this->SHPData["parts"]); + while (list($partIndex, $partData) = each($this->SHPData["parts"])) { + if (!isset($this->SHPData["parts"][$partIndex]["points"]) || !is_array($this->SHPData["parts"][$partIndex]["points"])) { + $this->SHPData["parts"][$partIndex] = array(); + $this->SHPData["parts"][$partIndex]["points"] = array(); + } + while (!in_array($readPoints, $this->SHPData["parts"]) && ($readPoints < ($this->SHPData["numpoints"])) && !feof($this->SHPFile)) { + $this->SHPData["parts"][$partIndex]["points"][] = $this->_loadPoint(); + $readPoints++; + } + } + + fseek($this->SHPFile, $firstIndex + ($readPoints*16)); + } + + function _savePolyLineRecord() { + fwrite($this->SHPFile, pack("dddd", $this->SHPData["xmin"], $this->SHPData["ymin"], $this->SHPData["xmax"], $this->SHPData["ymax"])); + + fwrite($this->SHPFile, pack("VV", $this->SHPData["numparts"], $this->SHPData["numpoints"])); + + for ($i = 0; $i < $this->SHPData["numparts"]; $i++) { + fwrite($this->SHPFile, pack("V", count($this->SHPData["parts"][$i]))); + } + + reset($this->SHPData["parts"]); + foreach ($this->SHPData["parts"] as $partData){ + reset($partData["points"]); + while (list($pointIndex, $pointData) = each($partData["points"])) { + $this->_savePoint($pointData); + } + } + } + + function _loadPolygonRecord() { + $this->_loadPolyLineRecord(); + } + + function _savePolygonRecord() { + $this->_savePolyLineRecord(); + } + + function addPoint($point, $partIndex = 0) { + switch ($this->shapeType) { + case 0: + //Don't add anything + break; + case 1: + //Substitutes the value of the current point + $this->SHPData = $point; + break; + case 3: + case 5: + //Adds a new point to the selected part + if (!isset($this->SHPData["xmin"]) || ($this->SHPData["xmin"] > $point["x"])) $this->SHPData["xmin"] = $point["x"]; + if (!isset($this->SHPData["ymin"]) || ($this->SHPData["ymin"] > $point["y"])) $this->SHPData["ymin"] = $point["y"]; + if (!isset($this->SHPData["xmax"]) || ($this->SHPData["xmax"] < $point["x"])) $this->SHPData["xmax"] = $point["x"]; + if (!isset($this->SHPData["ymax"]) || ($this->SHPData["ymax"] < $point["y"])) $this->SHPData["ymax"] = $point["y"]; + + $this->SHPData["parts"][$partIndex]["points"][] = $point; + + $this->SHPData["numparts"] = count($this->SHPData["parts"]); + $this->SHPData["numpoints"]++; + break; + case 8: + //Adds a new point + if (!isset($this->SHPData["xmin"]) || ($this->SHPData["xmin"] > $point["x"])) $this->SHPData["xmin"] = $point["x"]; + if (!isset($this->SHPData["ymin"]) || ($this->SHPData["ymin"] > $point["y"])) $this->SHPData["ymin"] = $point["y"]; + if (!isset($this->SHPData["xmax"]) || ($this->SHPData["xmax"] < $point["x"])) $this->SHPData["xmax"] = $point["x"]; + if (!isset($this->SHPData["ymax"]) || ($this->SHPData["ymax"] < $point["y"])) $this->SHPData["ymax"] = $point["y"]; + + $this->SHPData["points"][] = $point; + $this->SHPData["numpoints"]++; + break; + default: + $this->setError(sprintf("The Shape Type '%s' is not supported.", $this->shapeType)); + break; + } + } + + function deletePoint($pointIndex = 0, $partIndex = 0) { + switch ($this->shapeType) { + case 0: + //Don't delete anything + break; + case 1: + //Sets the value of the point to zero + $this->SHPData["x"] = 0.0; + $this->SHPData["y"] = 0.0; + break; + case 3: + case 5: + //Deletes the point from the selected part, if exists + if (isset($this->SHPData["parts"][$partIndex]) && isset($this->SHPData["parts"][$partIndex]["points"][$pointIndex])) { + for ($i = $pointIndex; $i < (count($this->SHPData["parts"][$partIndex]["points"]) - 1); $i++) { + $this->SHPData["parts"][$partIndex]["points"][$i] = $this->SHPData["parts"][$partIndex]["points"][$i + 1]; + } + unset($this->SHPData["parts"][$partIndex]["points"][count($this->SHPData["parts"][$partIndex]["points"]) - 1]); + + $this->SHPData["numparts"] = count($this->SHPData["parts"]); + $this->SHPData["numpoints"]--; + } + break; + case 8: + //Deletes the point, if exists + if (isset($this->SHPData["points"][$pointIndex])) { + for ($i = $pointIndex; $i < (count($this->SHPData["points"]) - 1); $i++) { + $this->SHPData["points"][$i] = $this->SHPData["points"][$i + 1]; + } + unset($this->SHPData["points"][count($this->SHPData["points"]) - 1]); + + $this->SHPData["numpoints"]--; + } + break; + default: + $this->setError(sprintf("The Shape Type '%s' is not supported.", $this->shapeType)); + break; + } + } + + function getContentLength() { + switch ($this->shapeType) { + case 0: + $result = 0; + break; + case 1: + $result = 10; + break; + case 3: + case 5: + $result = 22 + 2*count($this->SHPData["parts"]); + for ($i = 0; $i < count($this->SHPData["parts"]); $i++) { + $result += 8*count($this->SHPData["parts"][$i]["points"]); + } + break; + case 8: + $result = 20 + 8*count($this->SHPData["points"]); + break; + default: + $result = false; + $this->setError(sprintf("The Shape Type '%s' is not supported.", $this->shapeType)); + break; + } + return $result; + } + + function _loadDBFData() { + $this->DBFData = @dbase_get_record_with_names($this->DBFFile, $this->recordNumber); + unset($this->DBFData["deleted"]); + } + + function _saveDBFData() { + unset($this->DBFData["deleted"]); + if ($this->recordNumber <= dbase_numrecords($this->DBFFile)) { + if (!dbase_replace_record($this->DBFFile, array_values($this->DBFData), $this->recordNumber)) { + $this->setError("I wasn't possible to update the information in the DBF file."); + } + } else { + if (!dbase_add_record($this->DBFFile, array_values($this->DBFData))) { + $this->setError("I wasn't possible to add the information to the DBF file."); + } + } + } + + function setError($error) { + $this->lastError = $error; + return false; + } + } + +?> diff --git a/libraries/gis/pma_gis_multilinestring.php b/libraries/gis/pma_gis_multilinestring.php index f80dbc17bd..0ac845244a 100644 --- a/libraries/gis/pma_gis_multilinestring.php +++ b/libraries/gis/pma_gis_multilinestring.php @@ -251,7 +251,29 @@ class PMA_GIS_Multilinestring extends PMA_GIS_Geometry $wkt .= (isset($gis_data[$index]['MULTILINESTRING'][$i][$j]['x']) ? $gis_data[$index]['MULTILINESTRING'][$i][$j]['x'] : '') . ' ' . (isset($gis_data[$index]['MULTILINESTRING'][$i][$j]['y']) - ? $gis_data[$index]['MULTILINESTRING'][$i][$j]['y'] : '') .','; + ? $gis_data[$index]['MULTILINESTRING'][$i][$j]['y'] : '') . ','; + } + $wkt = substr($wkt, 0, strlen($wkt) - 1); + $wkt .= '),'; + } + $wkt = substr($wkt, 0, strlen($wkt) - 1); + $wkt .= ')'; + return $wkt; + } + + /** + * Generate the WKT for the data from ESRI shape files. + * + * @param array $row_data GIS data + * + * @return the WKT for the data from ESRI shape files + */ + public function getShape($row_data) { + $wkt = 'MULTILINESTRING('; + for ($i = 0; $i < $row_data['numparts']; $i++) { + $wkt .= '('; + foreach($row_data['parts'][$i]['points'] as $point) { + $wkt .= $point['x'] . ' ' . $point['y'] . ','; } $wkt = substr($wkt, 0, strlen($wkt) - 1); $wkt .= '),'; diff --git a/libraries/gis/pma_gis_multipoint.php b/libraries/gis/pma_gis_multipoint.php index c97813a66e..086c2c7cd3 100644 --- a/libraries/gis/pma_gis_multipoint.php +++ b/libraries/gis/pma_gis_multipoint.php @@ -207,7 +207,24 @@ class PMA_GIS_Multipoint extends PMA_GIS_Geometry $wkt .= (isset($gis_data[$index]['MULTIPOINT'][$i]['x']) ? $gis_data[$index]['MULTIPOINT'][$i]['x'] : '') . ' ' . (isset($gis_data[$index]['MULTIPOINT'][$i]['y']) - ? $gis_data[$index]['MULTIPOINT'][$i]['y'] : '') .','; + ? $gis_data[$index]['MULTIPOINT'][$i]['y'] : '') . ','; + } + $wkt = substr($wkt, 0, strlen($wkt) - 1); + $wkt .= ')'; + return $wkt; + } + + /** + * Generate the WKT for the data from ESRI shape files. + * + * @param array $row_data GIS data + * + * @return the WKT for the data from ESRI shape files + */ + public function getShape($row_data) { + $wkt = 'MULTIPOINT('; + for ($i = 0; $i < $row_data['numpoints']; $i++) { + $wkt .= $row_data['points'][$i]['x'] . ' ' . $row_data['points'][$i]['y'] . ','; } $wkt = substr($wkt, 0, strlen($wkt) - 1); $wkt .= ')'; diff --git a/libraries/gis/pma_gis_point.php b/libraries/gis/pma_gis_point.php index d5db147aa2..2cade89e57 100644 --- a/libraries/gis/pma_gis_point.php +++ b/libraries/gis/pma_gis_point.php @@ -187,6 +187,18 @@ class PMA_GIS_Point extends PMA_GIS_Geometry . ' ' . (isset($gis_data[$index]['POINT']['y']) ? $gis_data[$index]['POINT']['y'] : '') . ')'; } + /** + * Generate the WKT for the data from ESRI shape files. + * + * @param array $row_data GIS data + * + * @return the WKT for the data from ESRI shape files + */ + public function getShape($row_data) { + $gis_data = array(array('POINT' => array('x' => $row_data['x'], 'y' => $row_data['y']))); + return $this->generateWkt($gis_data, 0); + } + /** * Generate parameters for the GIS data editor from the value of the GIS column. * diff --git a/libraries/import.lib.php b/libraries/import.lib.php index e2cbdd201f..ba2995bdf5 100644 --- a/libraries/import.lib.php +++ b/libraries/import.lib.php @@ -418,6 +418,7 @@ define("VARCHAR", 1); define("INT", 2); define("DECIMAL", 3); define("BIGINT", 4); +define("GEOMETRY", 5); /* Decimal size defs */ define("M", 0); @@ -430,8 +431,9 @@ define("COL_NAMES", 1); define("ROWS", 2); /* Analysis array defs */ -define("TYPES", 0); -define("SIZES", 1); +define("TYPES", 0); +define("SIZES", 1); +define("FORMATTEDSQL", 2); /** * Obtains the precision (total # of digits) from a size of type decimal @@ -911,7 +913,7 @@ function PMA_buildSQL($db_name, &$tables, &$analyses = NULL, &$additional_sql = } if ($analyses != NULL) { - $type_array = array(NONE => "NULL", VARCHAR => "varchar", INT => "int", DECIMAL => "decimal", BIGINT => "bigint"); + $type_array = array(NONE => "NULL", VARCHAR => "varchar", INT => "int", DECIMAL => "decimal", BIGINT => "bigint", GEOMETRY => 'geometry'); /* TODO: Do more checking here to make sure they really are matched */ if (count($tables) != count($analyses)) { @@ -930,7 +932,10 @@ function PMA_buildSQL($db_name, &$tables, &$analyses = NULL, &$additional_sql = $size = 10; } - $tempSQLStr .= PMA_backquote($tables[$i][COL_NAMES][$j]) . " " . $type_array[$analyses[$i][TYPES][$j]] . "(" . $size . ")"; + $tempSQLStr .= PMA_backquote($tables[$i][COL_NAMES][$j]) . " " . $type_array[$analyses[$i][TYPES][$j]]; + if ($analyses[$i][TYPES][$j] != GEOMETRY) { + $tempSQLStr .= "(" . $size . ")"; + } if ($j != (count($tables[$i][COL_NAMES]) - 1)) { $tempSQLStr .= ", "; @@ -974,21 +979,29 @@ function PMA_buildSQL($db_name, &$tables, &$analyses = NULL, &$additional_sql = for ($j = 0; $j < $num_rows; ++$j) { $tempSQLStr .= "("; - for ($k = 0; $k < $num_cols; ++$k) { - if ($analyses != NULL) { - $is_varchar = ($analyses[$i][TYPES][$col_count] === VARCHAR); + for ($k = 0; $k < $num_cols; ++$k) { + // If fully formatted SQL, no need to enclose with aphostrophes, add shalshes etc. + if ($analyses != null + && isset($analyses[$i][FORMATTEDSQL][$col_count]) + && $analyses[$i][FORMATTEDSQL][$col_count] == true + ) { + $tempSQLStr .= (string) $tables[$i][ROWS][$j][$k]; } else { - $is_varchar = !is_numeric($tables[$i][ROWS][$j][$k]); - } + if ($analyses != null) { + $is_varchar = ($analyses[$i][TYPES][$col_count] === VARCHAR); + } else { + $is_varchar = !is_numeric($tables[$i][ROWS][$j][$k]); + } - /* Don't put quotes around NULL fields */ - if (! strcmp($tables[$i][ROWS][$j][$k], 'NULL')) { - $is_varchar = false; - } + /* Don't put quotes around NULL fields */ + if (! strcmp($tables[$i][ROWS][$j][$k], 'NULL')) { + $is_varchar = false; + } - $tempSQLStr .= (($is_varchar) ? "'" : ""); - $tempSQLStr .= PMA_sqlAddSlashes((string)$tables[$i][ROWS][$j][$k]); - $tempSQLStr .= (($is_varchar) ? "'" : ""); + $tempSQLStr .= (($is_varchar) ? "'" : ""); + $tempSQLStr .= PMA_sqlAddSlashes((string)$tables[$i][ROWS][$j][$k]); + $tempSQLStr .= (($is_varchar) ? "'" : ""); + } if ($k != ($num_cols - 1)) { $tempSQLStr .= ", "; diff --git a/libraries/import/shp.php b/libraries/import/shp.php new file mode 100644 index 0000000000..77d9f09ecc --- /dev/null +++ b/libraries/import/shp.php @@ -0,0 +1,344 @@ + __('ESRI Shape File'), + 'extension' => 'shp', + 'options' => array(), + 'options_text' => __('Options'), + ); +} else { + + // Append the bfShapeFiles directory to the include path variable + set_include_path(get_include_path() . PATH_SEPARATOR . getcwd() . '/libraries/bfShapeFiles/'); + require_once './libraries/bfShapeFiles/ShapeFile.lib.php'; + + $GLOBALS['finished'] = false; + $buffer = ''; + $eof = false; + + // Returns specified number of bytes from the buffer. + // Buffer automatically fetch next chunk of data when the buffer falls short. + // Sets $eof when $GLOBALS['finished'] is set and the buffer is falls short. + function readFromBuffer($length){ + global $buffer, $eof; + + if (strlen($buffer) < $length) { + if ($GLOBALS['finished']) { + $eof = true; + } else { + $buffer .= PMA_importGetNextChunk(); + } + } + $result = substr($buffer, 0, $length); + $buffer = substr($buffer, $length); + return $result; + } + + /** + * This class extends from ShapeFile class to cater following phpMyAdmin specific requirements. + * 1) To loads data from .dbf file only when the dBase extension is availble. + * 2) To use PMA_importGetNextChunk() functionality to read data, rather than reading directly from a file. + * Using readFromBuffer() inplace of fread(). This makes it possible to use compressions. + */ + class PMA_ShapeFile extends ShapeFile { + + function _isDbaseLoaded() + { + return extension_loaded('dbase'); + } + + function loadFromFile($FileName) + { + $this->_loadHeaders(); + $this->_loadRecords(); + if ($this->_isDbaseLoaded()) { + $this->_closeDBFFile(); + } + } + + function _loadHeaders() + { + readFromBuffer(24); + $this->fileLength = loadData("N", readFromBuffer(4)); + + readFromBuffer(4); + $this->shapeType = loadData("V", readFromBuffer(4)); + + $this->boundingBox = array(); + $this->boundingBox["xmin"] = loadData("d", readFromBuffer(8)); + $this->boundingBox["ymin"] = loadData("d", readFromBuffer(8)); + $this->boundingBox["xmax"] = loadData("d", readFromBuffer(8)); + $this->boundingBox["ymax"] = loadData("d", readFromBuffer(8)); + + if ($this->_isDbaseLoaded() && $this->_openDBFFile()) { + $this->DBFHeader = $this->_loadDBFHeader(); + } + } + + function _loadRecords() + { + global $eof; + readFromBuffer(32); + while (true) { + $record = new PMA_ShapeRecord(-1); + $record->loadFromFile($this->SHPFile, $this->DBFFile); + if ($record->lastError != "") { + return false; + } + if ($eof) { + break; + } + + $this->records[] = $record; + } + } + } + + /** + * This class extends from ShapeRecord class to cater following phpMyAdmin specific requirements. + * 1) To loads data from .dbf file only when the dBase extension is availble. + * 2) To use PMA_importGetNextChunk() functionality to read data, rather than reading directly from a file. + * Using readFromBuffer() inplace of fread(). This makes it possible to use compressions. + */ + class PMA_ShapeRecord extends ShapeRecord { + + function loadFromFile(&$SHPFile, &$DBFFile) + { + $this->DBFFile = $DBFFile; + $this->_loadHeaders(); + + switch ($this->shapeType) { + case 0: + $this->_loadNullRecord(); + break; + case 1: + $this->_loadPointRecord(); + break; + case 3: + $this->_loadPolyLineRecord(); + break; + case 5: + $this->_loadPolygonRecord(); + break; + case 8: + $this->_loadMultiPointRecord(); + break; + default: + $this->setError(sprintf("The Shape Type '%s' is not supported.", $this->shapeType)); + break; + } + if (extension_loaded('dbase') && isset($this->DBFFile)) { + $this->_loadDBFData(); + } + } + + function _loadHeaders() + { + $this->recordNumber = loadData("N", readFromBuffer(4)); + $tmp = loadData("N", readFromBuffer(4)); //We read the length of the record + $this->shapeType = loadData("V", readFromBuffer(4)); + } + + function _loadPoint() + { + $data = array(); + + $data["x"] = loadData("d", readFromBuffer(8)); + $data["y"] = loadData("d", readFromBuffer(8)); + + return $data; + } + + function _loadMultiPointRecord() + { + $this->SHPData = array(); + $this->SHPData["xmin"] = loadData("d", readFromBuffer(8)); + $this->SHPData["ymin"] = loadData("d", readFromBuffer(8)); + $this->SHPData["xmax"] = loadData("d", readFromBuffer(8)); + $this->SHPData["ymax"] = loadData("d", readFromBuffer(8)); + + $this->SHPData["numpoints"] = loadData("V", readFromBuffer(4)); + + for ($i = 0; $i <= $this->SHPData["numpoints"]; $i++) { + $this->SHPData["points"][] = $this->_loadPoint(); + } + } + + function _loadPolyLineRecord() + { + $this->SHPData = array(); + $this->SHPData["xmin"] = loadData("d", readFromBuffer(8)); + $this->SHPData["ymin"] = loadData("d", readFromBuffer(8)); + $this->SHPData["xmax"] = loadData("d", readFromBuffer(8)); + $this->SHPData["ymax"] = loadData("d", readFromBuffer(8)); + + $this->SHPData["numparts"] = loadData("V", readFromBuffer(4)); + $this->SHPData["numpoints"] = loadData("V", readFromBuffer(4)); + + for ($i = 0; $i < $this->SHPData["numparts"]; $i++) { + $this->SHPData["parts"][$i] = loadData("V", readFromBuffer(4)); + } + + $readPoints = 0; + reset($this->SHPData["parts"]); + while (list($partIndex, $partData) = each($this->SHPData["parts"])) { + if (!isset($this->SHPData["parts"][$partIndex]["points"]) || !is_array($this->SHPData["parts"][$partIndex]["points"])) { + $this->SHPData["parts"][$partIndex] = array(); + $this->SHPData["parts"][$partIndex]["points"] = array(); + } + while (!in_array($readPoints, $this->SHPData["parts"]) && ($readPoints < ($this->SHPData["numpoints"]))) { + $this->SHPData["parts"][$partIndex]["points"][] = $this->_loadPoint(); + $readPoints++; + } + } + } + } + + $shp = new PMA_ShapeFile(1); + if (extension_loaded('dbase')) { + // If file is in UploadDir, use .dbf file in the same UploadDir to load extra data. + if (! empty($local_import_file) && ! empty($cfg['UploadDir']) && $compression == 'none') { + // Replace the .shp with .*, so the bsShapeFiles library correctly locates .dbf file. + $file_name = substr($import_file, 0, strlen($import_file) - 4) . '.*'; + $shp->FileName = $file_name; + } + } + $shp->loadFromFile(''); + + $esri_types = array( + 0 => 'Null Shape', + 1 => 'Point', + 3 => 'PolyLine', + 5 => 'Polygon', + 8 => 'MultiPoint', + 11 => 'PointZ', + 13 => 'PolyLineZ', + 15 => 'PolygonZ', + 18 => 'MultiPointZ', + 21 => 'PointM', + 23 => 'PolyLineM', + 25 => 'PolygonM', + 28 => 'MultiPointM', + 31 => 'MultiPatch', + ); + + require_once './libraries/gis/pma_gis_geometry.php'; + switch ($shp->shapeType) { + // Esri Null Shape + case 0: + $gis_obj = null; + break; + // Esri Point + case 1: + require_once './libraries/gis/pma_gis_point.php'; + $gis_obj = PMA_GIS_Point::singleton(); + break; + // Esri PolyLine + case 3: + require_once './libraries/gis/pma_gis_multilinestring.php'; + $gis_obj = PMA_GIS_Multilinestring::singleton(); + break; + // Esri Polygon + case 5: + require_once './libraries/gis/pma_gis_multipolygon.php'; + $gis_obj = PMA_GIS_Multipolygon::singleton(); + break; + // Esri MultiPoint + case 8: + require_once './libraries/gis/pma_gis_multipoint.php'; + $gis_obj = PMA_GIS_Multipoint::singleton(); + break; + default: + $error = true; + $err = PMA_Message::error(__('MySQL Spatial Extention does not support ESRI type "%s".')); + $param = isset($esri_types[$shp->shapeType]) ? $esri_types[$shp->shapeType] : __('Unkown Type'); + $err->addParam($param); + PMA_mysqlDie($err->getMessage(), '', '', $err_url); + } + + $num_rows = count($shp->records); + // If .dbf file is loaded, the number of extra data columns + $num_data_cols = isset($shp->DBFHeader) ? count($shp->DBFHeader) : 0; + + $rows = array(); + $col_names = array(); + if ($num_rows != 0) { + foreach($shp->records as $record){ + $tempRow = array(); + if ($gis_obj == null) { + $tempRow[] = null; + } else { + $tempRow[] = "GeomFromText('" . $gis_obj->getShape($record->SHPData) . "')"; + } + + if (isset($shp->DBFHeader)) { + foreach ($shp->DBFHeader as $c) { + $cell = trim($record->DBFData[$c[0]]); + + if (! strcmp($cell, '')) { + $cell = 'NULL'; + } + + $tempRow[] = $cell; + } + } + $rows[] = $tempRow; + } + } + + // Column names for spatial column and the rest of the columns, if they are available + $col_names[] = 'SPATIAL'; + for ($n = 0; $n < $num_data_cols; $n++) { + $col_names[] = $shp->DBFHeader[$n][0]; + } + + // Set table name based on the number of tables + if (strlen($db)) { + $result = PMA_DBI_fetch_result('SHOW TABLES'); + $table_name = 'TABLE '.(count($result) + 1); + } else { + $table_name = 'TBL_NAME'; + } + $tables = array(array($table_name, $col_names, $rows)); + + // Use data from shape file to chose best-fit MySQL types for each column + $analyses = array(); + $analyses[] = PMA_analyzeTable($tables[0]); + + $table_no = 0; $spatial_col = 0; + $analyses[$table_no][TYPES][$spatial_col] = GEOMETRY; + $analyses[$table_no][FORMATTEDSQL][$spatial_col] = true; + + // Set database name to the currently selected one, if applicable + if (strlen($db)) { + $db_name = $db; + $options = array('create_db' => false); + } else { + $db_name = 'SHP_DB'; + $options = null; + } + + // Created and execute necessary SQL statements from data + $null_param = null; + PMA_buildSQL($db_name, $tables, $analyses, $null_param, $options); + + unset($tables); + unset($analyses); + + $finished = true; + $error = false; + + // Commit any possible data in buffers + PMA_importRunQuery(); +} +?> From ae88c2e758de107313e8a8cfaa192c42984a9fb8 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sun, 3 Jul 2011 22:14:14 +0530 Subject: [PATCH 07/98] Tabs replaced with spaces --- libraries/import.lib.php | 332 +++++++++++++++++++-------------------- 1 file changed, 166 insertions(+), 166 deletions(-) diff --git a/libraries/import.lib.php b/libraries/import.lib.php index ba2995bdf5..5cc5b01559 100644 --- a/libraries/import.lib.php +++ b/libraries/import.lib.php @@ -337,35 +337,35 @@ function PMA_importGetNextChunk($size = 32768) */ function PMA_getColumnAlphaName($num) { - $A = 65; // ASCII value for capital "A" - $col_name = ""; + $A = 65; // ASCII value for capital "A" + $col_name = ""; - if ($num > 26) { - $div = (int)($num / 26); - $remain = (int)($num % 26); + if ($num > 26) { + $div = (int)($num / 26); + $remain = (int)($num % 26); - // subtract 1 of divided value in case the modulus is 0, - // this is necessary because A-Z has no 'zero' - if ($remain == 0) { - $div--; - } + // subtract 1 of divided value in case the modulus is 0, + // this is necessary because A-Z has no 'zero' + if ($remain == 0) { + $div--; + } - // recursive function call - $col_name = PMA_getColumnAlphaName($div); - // use modulus as new column number - $num = $remain; - } + // recursive function call + $col_name = PMA_getColumnAlphaName($div); + // use modulus as new column number + $num = $remain; + } - if ($num == 0) { - // use 'Z' if column number is 0, - // this is necessary because A-Z has no 'zero' - $col_name .= chr(($A + 26) - 1); - } else { - // convert column number to ASCII character - $col_name .= chr(($A + $num) - 1); - } + if ($num == 0) { + // use 'Z' if column number is 0, + // this is necessary because A-Z has no 'zero' + $col_name .= chr(($A + 26) - 1); + } else { + // convert column number to ASCII character + $col_name .= chr(($A + $num) - 1); + } - return $col_name; + return $col_name; } /** @@ -388,19 +388,19 @@ function PMA_getColumnNumberFromName($name) { $num_chars = strlen($name); $column_number = 0; for ($i = 0; $i < $num_chars; ++$i) { - // read string from back to front - $char_pos = ($num_chars - 1) - $i; + // read string from back to front + $char_pos = ($num_chars - 1) - $i; - // convert capital character to ASCII value - // and subtract 64 to get corresponding decimal value - // ASCII value of "A" is 65, "B" is 66, etc. - // Decimal equivalent of "A" is 1, "B" is 2, etc. - $number = (ord($name[$char_pos]) - 64); + // convert capital character to ASCII value + // and subtract 64 to get corresponding decimal value + // ASCII value of "A" is 65, "B" is 66, etc. + // Decimal equivalent of "A" is 1, "B" is 2, etc. + $number = (ord($name[$char_pos]) - 64); - // base26 to base10 conversion : multiply each number - // with corresponding value of the position, in this case - // $i=0 : 1; $i=1 : 26; $i=2 : 676; ... - $column_number += $number * pow(26,$i); + // base26 to base10 conversion : multiply each number + // with corresponding value of the position, in this case + // $i=0 : 1; $i=1 : 26; $i=2 : 676; ... + $column_number += $number * pow(26,$i); } return $column_number; } else { @@ -458,7 +458,7 @@ function PMA_getM($last_cumulative_size) { * @return int Scale of the given decimal size notation */ function PMA_getD($last_cumulative_size) { - return (int)substr($last_cumulative_size, (strpos($last_cumulative_size, ",") + 1), (strlen($last_cumulative_size) - strpos($last_cumulative_size, ","))); + return (int)substr($last_cumulative_size, (strpos($last_cumulative_size, ",") + 1), (strlen($last_cumulative_size) - strpos($last_cumulative_size, ","))); } /** @@ -496,7 +496,7 @@ function PMA_getDecimalSize(&$cell) { * @return string Size of the given cell in the type-appropriate format */ function PMA_detectSize($last_cumulative_size, $last_cumulative_type, $curr_type, &$cell) { - $curr_size = strlen((string)$cell); + $curr_size = strlen((string)$cell); /** * If the cell is NULL, don't treat it as a varchar @@ -507,17 +507,17 @@ function PMA_detectSize($last_cumulative_size, $last_cumulative_type, $curr_type /** * What to do if the current cell is of type VARCHAR */ - elseif ($curr_type == VARCHAR) { + elseif ($curr_type == VARCHAR) { /** * The last cumulative type was VARCHAR */ - if ($last_cumulative_type == VARCHAR) { - if ($curr_size >= $last_cumulative_size) { - return $curr_size; + if ($last_cumulative_type == VARCHAR) { + if ($curr_size >= $last_cumulative_size) { + return $curr_size; } else { - return $last_cumulative_size; + return $last_cumulative_size; } - } + } /** * The last cumulative type was DECIMAL */ @@ -529,7 +529,7 @@ function PMA_detectSize($last_cumulative_size, $last_cumulative_type, $curr_type } else { return $oldM; } - } + } /** * The last cumulative type was BIGINT or INT */ @@ -539,7 +539,7 @@ function PMA_detectSize($last_cumulative_size, $last_cumulative_type, $curr_type } else { return $last_cumulative_size; } - } + } /** * This is the first row to be analyzed */ @@ -556,7 +556,7 @@ function PMA_detectSize($last_cumulative_size, $last_cumulative_type, $curr_type return -1; } - } + } /** * What to do if the current cell is of type DECIMAL */ @@ -564,66 +564,66 @@ function PMA_detectSize($last_cumulative_size, $last_cumulative_type, $curr_type /** * The last cumulative type was VARCHAR */ - if ($last_cumulative_type == VARCHAR) { + if ($last_cumulative_type == VARCHAR) { /* Convert $last_cumulative_size from varchar to decimal format */ - $size = PMA_getDecimalSize($cell); + $size = PMA_getDecimalSize($cell); - if ($size[M] >= $last_cumulative_size) { - return $size[M]; + if ($size[M] >= $last_cumulative_size) { + return $size[M]; } else { - return $last_cumulative_size; + return $last_cumulative_size; } - } + } /** * The last cumulative type was DECIMAL */ elseif ($last_cumulative_type == DECIMAL) { - $size = PMA_getDecimalSize($cell); + $size = PMA_getDecimalSize($cell); - $oldM = PMA_getM($last_cumulative_size); - $oldD = PMA_getD($last_cumulative_size); + $oldM = PMA_getM($last_cumulative_size); + $oldD = PMA_getD($last_cumulative_size); - /* New val if M or D is greater than current largest */ - if ($size[M] > $oldM || $size[D] > $oldD) { - /* Take the largest of both types */ - return (string)((($size[M] > $oldM) ? $size[M] : $oldM) . "," . (($size[D] > $oldD) ? $size[D] : $oldD)); + /* New val if M or D is greater than current largest */ + if ($size[M] > $oldM || $size[D] > $oldD) { + /* Take the largest of both types */ + return (string)((($size[M] > $oldM) ? $size[M] : $oldM) . "," . (($size[D] > $oldD) ? $size[D] : $oldD)); } else { - return $last_cumulative_size; + return $last_cumulative_size; } - } + } /** * The last cumulative type was BIGINT or INT */ elseif ($last_cumulative_type == BIGINT || $last_cumulative_type == INT) { - /* Convert $last_cumulative_size from int to decimal format */ - $size = PMA_getDecimalSize($cell); + /* Convert $last_cumulative_size from int to decimal format */ + $size = PMA_getDecimalSize($cell); - if ($size[M] >= $last_cumulative_size) { - return $size[FULL]; + if ($size[M] >= $last_cumulative_size) { + return $size[FULL]; } else { - return ($last_cumulative_size.",".$size[D]); + return ($last_cumulative_size.",".$size[D]); } - } + } /** * This is the first row to be analyzed */ elseif (! isset($last_cumulative_type) || $last_cumulative_type == NONE) { /* First row of the column */ - $size = PMA_getDecimalSize($cell); + $size = PMA_getDecimalSize($cell); - return $size[FULL]; - } + return $size[FULL]; + } /** * An error has DEFINITELY occurred */ - else { + else { /** * TODO: Handle this MUCH more elegantly */ return -1; } - } + } /** * What to do if the current cell is of type BIGINT or INT */ @@ -631,41 +631,41 @@ function PMA_detectSize($last_cumulative_size, $last_cumulative_type, $curr_type /** * The last cumulative type was VARCHAR */ - if ($last_cumulative_type == VARCHAR) { - if ($curr_size >= $last_cumulative_size) { - return $curr_size; + if ($last_cumulative_type == VARCHAR) { + if ($curr_size >= $last_cumulative_size) { + return $curr_size; } else { - return $last_cumulative_size; + return $last_cumulative_size; } - } + } /** * The last cumulative type was DECIMAL */ elseif ($last_cumulative_type == DECIMAL) { $oldM = PMA_getM($last_cumulative_size); - $oldD = PMA_getD($last_cumulative_size); - $oldInt = $oldM - $oldD; - $newInt = strlen((string)$cell); + $oldD = PMA_getD($last_cumulative_size); + $oldInt = $oldM - $oldD; + $newInt = strlen((string)$cell); - /* See which has the larger integer length */ - if ($oldInt >= $newInt) { - /* Use old decimal size */ - return $last_cumulative_size; + /* See which has the larger integer length */ + if ($oldInt >= $newInt) { + /* Use old decimal size */ + return $last_cumulative_size; } else { - /* Use $newInt + $oldD as new M */ - return (($newInt + $oldD) . "," . $oldD); + /* Use $newInt + $oldD as new M */ + return (($newInt + $oldD) . "," . $oldD); } - } + } /** * The last cumulative type was BIGINT or INT */ elseif ($last_cumulative_type == BIGINT || $last_cumulative_type == INT) { - if ($curr_size >= $last_cumulative_size) { - return $curr_size; + if ($curr_size >= $last_cumulative_size) { + return $curr_size; } else { - return $last_cumulative_size; + return $last_cumulative_size; } - } + } /** * This is the first row to be analyzed */ @@ -675,18 +675,18 @@ function PMA_detectSize($last_cumulative_size, $last_cumulative_type, $curr_type /** * An error has DEFINITELY occurred */ - else { + else { /** * TODO: Handle this MUCH more elegantly */ return -1; } - } + } /** * An error has DEFINITELY occurred */ - else { + else { /** * TODO: Handle this MUCH more elegantly */ @@ -721,11 +721,11 @@ function PMA_detectType($last_cumulative_type, &$cell) { if ($cell == (string)(float)$cell && strpos($cell, ".") !== false && substr_count($cell, ".") == 1) { return DECIMAL; } else { - if (abs($cell) > 2147483647) { - return BIGINT; - } else { - return INT; - } + if (abs($cell) > 2147483647) { + return BIGINT; + } else { + return INT; + } } } else { return VARCHAR; @@ -746,62 +746,62 @@ function PMA_detectType($last_cumulative_type, &$cell) { * @return array array(array $types, array $sizes) */ function PMA_analyzeTable(&$table) { - /* Get number of rows in table */ - $numRows = count($table[ROWS]); - /* Get number of columns */ - $numCols = count($table[COL_NAMES]); - /* Current type for each column */ - $types = array(); - $sizes = array(); + /* Get number of rows in table */ + $numRows = count($table[ROWS]); + /* Get number of columns */ + $numCols = count($table[COL_NAMES]); + /* Current type for each column */ + $types = array(); + $sizes = array(); - /* Initialize $sizes to all 0's */ - for ($i = 0; $i < $numCols; ++$i) { - $sizes[$i] = 0; - } + /* Initialize $sizes to all 0's */ + for ($i = 0; $i < $numCols; ++$i) { + $sizes[$i] = 0; + } /* Initialize $types to NONE */ for ($i = 0; $i < $numCols; ++$i) { $types[$i] = NONE; } - /* Temp vars */ - $curr_type = NONE; - $curr_size = 0; + /* Temp vars */ + $curr_type = NONE; + $curr_size = 0; - /* If the passed array is not of the correct form, do not process it */ - if (is_array($table) && ! is_array($table[TBL_NAME]) && is_array($table[COL_NAMES]) && is_array($table[ROWS])) { - /* Analyze each column */ - for ($i = 0; $i < $numCols; ++$i) { - /* Analyze the column in each row */ - for ($j = 0; $j < $numRows; ++$j) { - /* Determine type of the current cell */ - $curr_type = PMA_detectType($types[$i], $table[ROWS][$j][$i]); - /* Determine size of the current cell */ - $sizes[$i] = PMA_detectSize($sizes[$i], $types[$i], $curr_type, $table[ROWS][$j][$i]); + /* If the passed array is not of the correct form, do not process it */ + if (is_array($table) && ! is_array($table[TBL_NAME]) && is_array($table[COL_NAMES]) && is_array($table[ROWS])) { + /* Analyze each column */ + for ($i = 0; $i < $numCols; ++$i) { + /* Analyze the column in each row */ + for ($j = 0; $j < $numRows; ++$j) { + /* Determine type of the current cell */ + $curr_type = PMA_detectType($types[$i], $table[ROWS][$j][$i]); + /* Determine size of the current cell */ + $sizes[$i] = PMA_detectSize($sizes[$i], $types[$i], $curr_type, $table[ROWS][$j][$i]); - /** - * If a type for this column has already been declared, - * only alter it if it was a number and a varchar was found - */ - if ($curr_type != NONE) { - if ($curr_type == VARCHAR) { - $types[$i] = VARCHAR; - } else if ($curr_type == DECIMAL) { - if ($types[$i] != VARCHAR) { - $types[$i] = DECIMAL; - } - } else if ($curr_type == BIGINT) { - if ($types[$i] != VARCHAR && $types[$i] != DECIMAL) { - $types[$i] = BIGINT; - } - } else if ($curr_type == INT) { - if ($types[$i] != VARCHAR && $types[$i] != DECIMAL && $types[$i] != BIGINT) { - $types[$i] = INT; - } - } - } - } - } + /** + * If a type for this column has already been declared, + * only alter it if it was a number and a varchar was found + */ + if ($curr_type != NONE) { + if ($curr_type == VARCHAR) { + $types[$i] = VARCHAR; + } else if ($curr_type == DECIMAL) { + if ($types[$i] != VARCHAR) { + $types[$i] = DECIMAL; + } + } else if ($curr_type == BIGINT) { + if ($types[$i] != VARCHAR && $types[$i] != DECIMAL) { + $types[$i] = BIGINT; + } + } else if ($curr_type == INT) { + if ($types[$i] != VARCHAR && $types[$i] != DECIMAL && $types[$i] != BIGINT) { + $types[$i] = INT; + } + } + } + } + } /* Check to ensure that all types are valid */ $len = count($types); @@ -812,16 +812,16 @@ function PMA_analyzeTable(&$table) { } } - return array($types, $sizes); - } - else - { + return array($types, $sizes); + } + else + { /** * TODO: Handle this better */ - return false; - } + return false; + } } /* Needed to quell the beast that is PMA_Message */ @@ -957,10 +957,10 @@ function PMA_buildSQL($db_name, &$tables, &$analyses = NULL, &$additional_sql = * * Only one insert query is formed for each table */ - $tempSQLStr = ""; - $col_count = 0; + $tempSQLStr = ""; + $col_count = 0; $num_tables = count($tables); - for ($i = 0; $i < $num_tables; ++$i) { + for ($i = 0; $i < $num_tables; ++$i) { $num_cols = count($tables[$i][COL_NAMES]); $num_rows = count($tables[$i][ROWS]); @@ -976,7 +976,7 @@ function PMA_buildSQL($db_name, &$tables, &$analyses = NULL, &$additional_sql = $tempSQLStr .= ") VALUES "; - for ($j = 0; $j < $num_rows; ++$j) { + for ($j = 0; $j < $num_rows; ++$j) { $tempSQLStr .= "("; for ($k = 0; $k < $num_cols; ++$k) { @@ -1003,19 +1003,19 @@ function PMA_buildSQL($db_name, &$tables, &$analyses = NULL, &$additional_sql = $tempSQLStr .= (($is_varchar) ? "'" : ""); } - if ($k != ($num_cols - 1)) { - $tempSQLStr .= ", "; + if ($k != ($num_cols - 1)) { + $tempSQLStr .= ", "; } - if ($col_count == ($num_cols - 1)) { - $col_count = 0; - } else { - $col_count++; + if ($col_count == ($num_cols - 1)) { + $col_count = 0; + } else { + $col_count++; } /* Delete the cell after we are done with it */ unset($tables[$i][ROWS][$j][$k]); - } + } $tempSQLStr .= ")"; @@ -1023,10 +1023,10 @@ function PMA_buildSQL($db_name, &$tables, &$analyses = NULL, &$additional_sql = $tempSQLStr .= ",\n "; } - $col_count = 0; + $col_count = 0; /* Delete the row after we are done with it */ unset($tables[$i][ROWS][$j]); - } + } $tempSQLStr .= ";"; @@ -1036,7 +1036,7 @@ function PMA_buildSQL($db_name, &$tables, &$analyses = NULL, &$additional_sql = * to store them in a (possibly large) buffer */ PMA_importRunQuery($tempSQLStr, $tempSQLStr); - } + } /* No longer needed */ unset($tempSQLStr); From cfeb031d1f8d7c31cb3fdf6b376ba7b7ea757a59 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sun, 3 Jul 2011 22:36:34 +0530 Subject: [PATCH 08/98] A polygon needs to have atleast 4 points. --- gis_data_editor.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gis_data_editor.php b/gis_data_editor.php index 37d46c5f7d..21cafc8cdd 100644 --- a/gis_data_editor.php +++ b/gis_data_editor.php @@ -178,8 +178,8 @@ if(isset($_REQUEST['generate']) && $_REQUEST['generate'] == true) { if ($type == 'MULTILINESTRING' && $no_of_points < 2) { $no_of_points = 2; } - if ($type == 'POLYGON' && $no_of_points < 3) { - $no_of_points = 3; + if ($type == 'POLYGON' && $no_of_points < 4) { + $no_of_points = 4; } if (isset($gis_data[$a][$type][$i]['add_point'])) { $no_of_points++; From 93ab68dd131616369dccd0a6a62ff5f1a1a710d2 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sun, 3 Jul 2011 22:41:52 +0530 Subject: [PATCH 09/98] A polygon needs to have atleast 4 points - more instances --- gis_data_editor.php | 4 ++-- libraries/gis/pma_gis_multipolygon.php | 4 ++-- libraries/gis/pma_gis_polygon.php | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gis_data_editor.php b/gis_data_editor.php index 21cafc8cdd..3fd077256d 100644 --- a/gis_data_editor.php +++ b/gis_data_editor.php @@ -228,8 +228,8 @@ if(isset($_REQUEST['generate']) && $_REQUEST['generate'] == true) { } $no_of_points = isset($gis_data[$a][$type][$k][$i]['no_of_points']) ? $gis_data[$a][$type][$k][$i]['no_of_points'] : 3; - if ($no_of_points < 3) { - $no_of_points = 3; + if ($no_of_points < 4) { + $no_of_points = 4; } if (isset($gis_data[$a][$type][$k][$i]['add_point'])) { $no_of_points++; diff --git a/libraries/gis/pma_gis_multipolygon.php b/libraries/gis/pma_gis_multipolygon.php index 03be3bc3c6..d9aeec67f6 100644 --- a/libraries/gis/pma_gis_multipolygon.php +++ b/libraries/gis/pma_gis_multipolygon.php @@ -338,8 +338,8 @@ class PMA_GIS_Multipolygon extends PMA_GIS_Geometry for ($i = 0; $i < $no_of_lines; $i++) { $no_of_points = isset($gis_data[$index]['MULTIPOLYGON'][$k][$i]['no_of_points']) ? $gis_data[$index]['MULTIPOLYGON'][$k][$i]['no_of_points'] : 3; - if ($no_of_points < 3) { - $no_of_points = 3; + if ($no_of_points < 4) { + $no_of_points = 4; } $wkt .= '('; for ($j = 0; $j < $no_of_points; $j++) { diff --git a/libraries/gis/pma_gis_polygon.php b/libraries/gis/pma_gis_polygon.php index 3bef784e5c..0098ee62ee 100644 --- a/libraries/gis/pma_gis_polygon.php +++ b/libraries/gis/pma_gis_polygon.php @@ -306,8 +306,8 @@ class PMA_GIS_Polygon extends PMA_GIS_Geometry for ($i = 0; $i < $no_of_lines; $i++) { $no_of_points = isset($gis_data[$index]['POLYGON'][$i]['no_of_points']) ? $gis_data[$index]['POLYGON'][$i]['no_of_points'] : 3; - if ($no_of_points < 3) { - $no_of_points = 3; + if ($no_of_points < 4) { + $no_of_points = 4; } $wkt .= '('; for ($j = 0; $j < $no_of_points; $j++) { From 4d111205b1dfb1ef220b052f8ba96b8b1c47af0d Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sun, 3 Jul 2011 22:46:48 +0530 Subject: [PATCH 10/98] A polygon needs to have atleast 4 points - more instances --- gis_data_editor.php | 2 +- libraries/gis/pma_gis_multipolygon.php | 2 +- libraries/gis/pma_gis_polygon.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gis_data_editor.php b/gis_data_editor.php index 3fd077256d..3bc74847a7 100644 --- a/gis_data_editor.php +++ b/gis_data_editor.php @@ -227,7 +227,7 @@ if(isset($_REQUEST['generate']) && $_REQUEST['generate'] == true) { echo __("Inner Ring"); echo($i . ':'); } - $no_of_points = isset($gis_data[$a][$type][$k][$i]['no_of_points']) ? $gis_data[$a][$type][$k][$i]['no_of_points'] : 3; + $no_of_points = isset($gis_data[$a][$type][$k][$i]['no_of_points']) ? $gis_data[$a][$type][$k][$i]['no_of_points'] : 4; if ($no_of_points < 4) { $no_of_points = 4; } diff --git a/libraries/gis/pma_gis_multipolygon.php b/libraries/gis/pma_gis_multipolygon.php index d9aeec67f6..96c144374c 100644 --- a/libraries/gis/pma_gis_multipolygon.php +++ b/libraries/gis/pma_gis_multipolygon.php @@ -337,7 +337,7 @@ class PMA_GIS_Multipolygon extends PMA_GIS_Geometry $wkt .= '('; for ($i = 0; $i < $no_of_lines; $i++) { $no_of_points = isset($gis_data[$index]['MULTIPOLYGON'][$k][$i]['no_of_points']) - ? $gis_data[$index]['MULTIPOLYGON'][$k][$i]['no_of_points'] : 3; + ? $gis_data[$index]['MULTIPOLYGON'][$k][$i]['no_of_points'] : 4; if ($no_of_points < 4) { $no_of_points = 4; } diff --git a/libraries/gis/pma_gis_polygon.php b/libraries/gis/pma_gis_polygon.php index 0098ee62ee..239e219b65 100644 --- a/libraries/gis/pma_gis_polygon.php +++ b/libraries/gis/pma_gis_polygon.php @@ -305,7 +305,7 @@ class PMA_GIS_Polygon extends PMA_GIS_Geometry $wkt = 'POLYGON('; for ($i = 0; $i < $no_of_lines; $i++) { $no_of_points = isset($gis_data[$index]['POLYGON'][$i]['no_of_points']) - ? $gis_data[$index]['POLYGON'][$i]['no_of_points'] : 3; + ? $gis_data[$index]['POLYGON'][$i]['no_of_points'] : 4; if ($no_of_points < 4) { $no_of_points = 4; } From 5a1018fc43c63c12c8ba8787e83ce4d48f91ff6e Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sun, 3 Jul 2011 23:56:47 +0530 Subject: [PATCH 11/98] Increase memory limit and time limit --- libraries/import/shp.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/import/shp.php b/libraries/import/shp.php index 77d9f09ecc..73cc0c4f3d 100644 --- a/libraries/import/shp.php +++ b/libraries/import/shp.php @@ -18,6 +18,9 @@ if (isset($plugin_list)) { ); } else { + ini_set('memory_limit', '128M'); + set_time_limit(120); + // Append the bfShapeFiles directory to the include path variable set_include_path(get_include_path() . PATH_SEPARATOR . getcwd() . '/libraries/bfShapeFiles/'); require_once './libraries/bfShapeFiles/ShapeFile.lib.php'; From c6a8098239bac87d105525173e14cf1d1cbc0afa Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Mon, 4 Jul 2011 00:31:24 +0530 Subject: [PATCH 12/98] Typo --- libraries/import/shp.php | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/libraries/import/shp.php b/libraries/import/shp.php index 73cc0c4f3d..e6f97e0635 100644 --- a/libraries/import/shp.php +++ b/libraries/import/shp.php @@ -30,8 +30,8 @@ if (isset($plugin_list)) { $eof = false; // Returns specified number of bytes from the buffer. - // Buffer automatically fetch next chunk of data when the buffer falls short. - // Sets $eof when $GLOBALS['finished'] is set and the buffer is falls short. + // Buffer automatically fetches next chunk of data when the buffer falls short. + // Sets $eof when $GLOBALS['finished'] is set and the buffer falls short. function readFromBuffer($length){ global $buffer, $eof; @@ -48,10 +48,10 @@ if (isset($plugin_list)) { } /** - * This class extends from ShapeFile class to cater following phpMyAdmin specific requirements. - * 1) To loads data from .dbf file only when the dBase extension is availble. + * This class extends ShapeFile class to cater following phpMyAdmin specific requirements. + * 1) To load data from .dbf file only when the dBase extension is available. * 2) To use PMA_importGetNextChunk() functionality to read data, rather than reading directly from a file. - * Using readFromBuffer() inplace of fread(). This makes it possible to use compressions. + * Using readFromBuffer() in place of fread(). This makes it possible to use compressions. */ class PMA_ShapeFile extends ShapeFile { @@ -108,10 +108,10 @@ if (isset($plugin_list)) { } /** - * This class extends from ShapeRecord class to cater following phpMyAdmin specific requirements. - * 1) To loads data from .dbf file only when the dBase extension is availble. + * This class extends ShapeRecord class to cater following phpMyAdmin specific requirements. + * 1) To load data from .dbf file only when the dBase extension is available. * 2) To use PMA_importGetNextChunk() functionality to read data, rather than reading directly from a file. - * Using readFromBuffer() inplace of fread(). This makes it possible to use compressions. + * Using readFromBuffer() in place of fread(). This makes it possible to use compressions. */ class PMA_ShapeRecord extends ShapeRecord { @@ -237,33 +237,33 @@ if (isset($plugin_list)) { require_once './libraries/gis/pma_gis_geometry.php'; switch ($shp->shapeType) { - // Esri Null Shape + // ESRI Null Shape case 0: $gis_obj = null; break; - // Esri Point + // ESRI Point case 1: require_once './libraries/gis/pma_gis_point.php'; $gis_obj = PMA_GIS_Point::singleton(); break; - // Esri PolyLine + // ESRI PolyLine case 3: require_once './libraries/gis/pma_gis_multilinestring.php'; $gis_obj = PMA_GIS_Multilinestring::singleton(); break; - // Esri Polygon + // ESRI Polygon case 5: require_once './libraries/gis/pma_gis_multipolygon.php'; $gis_obj = PMA_GIS_Multipolygon::singleton(); break; - // Esri MultiPoint + // ESRI MultiPoint case 8: require_once './libraries/gis/pma_gis_multipoint.php'; $gis_obj = PMA_GIS_Multipoint::singleton(); break; default: $error = true; - $err = PMA_Message::error(__('MySQL Spatial Extention does not support ESRI type "%s".')); + $err = PMA_Message::error(__('MySQL Spatial Extension does not support ESRI type "%s".')); $param = isset($esri_types[$shp->shapeType]) ? $esri_types[$shp->shapeType] : __('Unkown Type'); $err->addParam($param); PMA_mysqlDie($err->getMessage(), '', '', $err_url); From 28519cf25befaba56aa677d38af2847c2a7febcb Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Fri, 8 Jul 2011 18:31:19 +0530 Subject: [PATCH 13/98] ESRI shape files imported from a zip archive --- libraries/import/shp.php | 35 ++++++++++++++- libraries/zip_extension.lib.php | 78 ++++++++++++++++++++++++++++++--- 2 files changed, 107 insertions(+), 6 deletions(-) diff --git a/libraries/import/shp.php b/libraries/import/shp.php index e6f97e0635..4bfdf4d3db 100644 --- a/libraries/import/shp.php +++ b/libraries/import/shp.php @@ -208,16 +208,49 @@ if (isset($plugin_list)) { } $shp = new PMA_ShapeFile(1); + // If the zip archive has more than one file, get the content to the buffer from .shp file. + if ($compression == 'application/zip' && PMA_getNoOfFilesInZip($import_file) > 1) { + $zip_content = PMA_getZipContents($import_file, '/^.*\.shp$/i'); + $GLOBALS['import_text'] = $zip_content['data']; + } + + // We need dbase extension to handle .dbf file if (extension_loaded('dbase')) { + // If we can extract the zip archive to 'TempDir' and use the files in it for import + if ($compression == 'application/zip' + && ! empty($cfg['TempDir']) + && is_writable($cfg['TempDir']) + ) { + $dbf_file_name = PMA_findFileFromZipArchive('/^.*\.dbf$/i', $import_file); + // If the corresponding .dbf file is in the zip archive + if ($dbf_file_name) { + // Extract the .dbf file and point to it. + $extracted = PMA_zipExtract($import_file, realpath($cfg['TempDir']), array($dbf_file_name)); + if ($extracted) { + $dbf_file_path = realpath($cfg['TempDir']) . '/' . $dbf_file_name; + $temp_dbf_file = true; + // Replace the .dbf with .*, as required by the bsShapeFiles library. + $file_name = substr($dbf_file_path, 0, strlen($dbf_file_path) - 4) . '.*'; + $shp->FileName = $file_name; + } + } + } // If file is in UploadDir, use .dbf file in the same UploadDir to load extra data. - if (! empty($local_import_file) && ! empty($cfg['UploadDir']) && $compression == 'none') { + elseif (! empty($local_import_file) && ! empty($cfg['UploadDir']) && $compression == 'none') { // Replace the .shp with .*, so the bsShapeFiles library correctly locates .dbf file. $file_name = substr($import_file, 0, strlen($import_file) - 4) . '.*'; $shp->FileName = $file_name; } } + + // Load data $shp->loadFromFile(''); + // Delete the .dbf file extracted to 'TempDir' + if ($temp_dbf_file) { + unlink($dbf_file_path); + } + $esri_types = array( 0 => 'Null Shape', 1 => 'Point', diff --git a/libraries/zip_extension.lib.php b/libraries/zip_extension.lib.php index 05279118e1..3153a962c3 100644 --- a/libraries/zip_extension.lib.php +++ b/libraries/zip_extension.lib.php @@ -10,11 +10,12 @@ * Gets zip file contents * * @param string $file + * @param string $specific_entry regular expression to match a file * @return array ($error_message, $file_data); $error_message * is empty if no error */ -function PMA_getZipContents($file) +function PMA_getZipContents($file, $specific_entry = null) { $error_message = ''; $file_data = ''; @@ -28,11 +29,15 @@ function PMA_getZipContents($file) $read = zip_entry_read($first_zip_entry); $ods_mime = 'application/vnd.oasis.opendocument.spreadsheet'; if (!strcmp($ods_mime, $read)) { + $specific_entry = '/^content\.xml$/'; + } + + if (isset($specific_entry)) { /* Return the correct contents, not just the first entry */ for ( ; ; ) { $entry = zip_read($zip_handle); if (is_resource($entry)) { - if (!strcmp('content.xml', zip_entry_name($entry))) { + if (preg_match($specific_entry, zip_entry_name($entry))) { zip_entry_open($zip_handle, $entry, 'r'); $file_data = zip_entry_read($entry, zip_entry_filesize($entry)); zip_entry_close($entry); @@ -41,15 +46,15 @@ function PMA_getZipContents($file) } else { /** * Either we have reached the end of the zip and still - * haven't found 'content.xml' or there was a parsing + * haven't found $specific_entry or there was a parsing * error that we must display */ if ($entry === false) { - $error_message = __('Error in ZIP archive:') . ' Could not find "content.xml"'; + $error_message = __('Error in ZIP archive:') . ' Could not find "' . $specific_entry . '"'; } else { $error_message = __('Error in ZIP archive:') . ' ' . PMA_getZipError($zip_handle); } - + break; } } @@ -68,6 +73,69 @@ function PMA_getZipContents($file) return (array('error' => $error_message, 'data' => $file_data)); } +/** + * Returns the file name of the first file that matches the given $file_regexp. + * + * @param string $file_regexp regular expression for the file name to match + * @param string $file zip archive + */ +function PMA_findFileFromZipArchive ($file_regexp, $file) +{ + $zip_handle = zip_open($file); + $found = false; + if (is_resource($zip_handle)) { + $entry = zip_read($zip_handle); + while (is_resource($entry)) { + if (preg_match($file_regexp, zip_entry_name($entry))) { + $file_name = zip_entry_name($entry); + zip_close($zip_handle); + return $file_name; + } + $entry = zip_read($zip_handle); + } + } + zip_close($zip_handle); + return false; +} + +/** + * Returns the number of files in the zip archive. + * + * @param string $file + */ +function PMA_getNoOfFilesInZip($file) +{ + $count = 0; + $zip_handle = zip_open($file); + $found = false; + if (is_resource($zip_handle)) { + $entry = zip_read($zip_handle); + while (is_resource($entry)) { + $count++; + $entry = zip_read($zip_handle); + } + } + zip_close($zip_handle); + return $count; +} + +/** + * Extracts a set of files from the given zip archive to a given destinations. + * + * @param string $zip_path + * @param string $destination + * @param array $entries + */ +function PMA_zipExtract($zip_path, $destination, $entries) { + $zip = new ZipArchive; + if ($zip->open($zip_path) === true) { + $zip->extractTo($destination, $entries); + $zip->close(); + return true; + } + return false; +} + /** * Gets zip error message * From a58bb10e1839d0740cb634112f36462d52d4ac6f Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Fri, 8 Jul 2011 18:32:35 +0530 Subject: [PATCH 14/98] Correctly import multipolygons from ESRI shape files --- libraries/gis/pma_gis_multipolygon.php | 110 ++++++++++++++++++++++++- libraries/gis/pma_gis_polygon.php | 94 +++++++++++++++++++++ libraries/import/shp.php | 11 ++- 3 files changed, 210 insertions(+), 5 deletions(-) diff --git a/libraries/gis/pma_gis_multipolygon.php b/libraries/gis/pma_gis_multipolygon.php index 96c144374c..31b9ce5729 100644 --- a/libraries/gis/pma_gis_multipolygon.php +++ b/libraries/gis/pma_gis_multipolygon.php @@ -359,7 +359,115 @@ class PMA_GIS_Multipolygon extends PMA_GIS_Geometry return $wkt; } - /** Generate parameters for the GIS data editor from the value of the GIS column. + /** + * Generate the WKT for the data from ESRI shape files. + * + * @param array $row_data GIS data + * + * @return the WKT for the data from ESRI shape files + */ + public function getShape($row_data) + { + // Determines whether each line ring is an inner ring or an outer ring. + // If it's an inner ring get a point on the surface which can be used to + // correctly classify inner rings to their respective outer rings. + require_once './libraries/gis/pma_gis_polygon.php'; + foreach ($row_data['parts'] as $i => $ring) { + $row_data['parts'][$i]['isOuter'] = PMA_GIS_Polygon::isOuterRing($ring['points']); + } + + $this->getPointsOnSurface($row_data['parts']); + + // Classify inner rings to their respective outer rings. + foreach ($row_data['parts'] as $j => $ring1) { + if (! $ring1['isOuter']) { + foreach ($row_data['parts'] as $k => $ring2) { + if ($ring2['isOuter']) { + // If the pointOnSurface of the inner ring is also inside the outer ring + if (PMA_GIS_Polygon::isPointInsidePolygon($ring1['pointOnSurface'], $ring2['points'])) { + if (! isset($ring2['inner'])) { + $row_data['parts'][$k]['inner'] = array(); + } + $row_data['parts'][$k]['inner'][] = $j; + } + } + } + } + } + + $wkt = 'MULTIPOLYGON('; + // for each polygon + foreach ($row_data['parts'] as $ring) { + if ($ring['isOuter']) { + $wkt .= '('; // start of polygon + + $wkt .= '('; // start of outer ring + foreach($ring['points'] as $point) { + $wkt .= $point['x'] . ' ' . $point['y'] . ','; + } + $wkt = substr($wkt, 0, strlen($wkt) - 1); + $wkt .= ')'; // end of outer ring + + // inner rings if any + if (isset($ring['inner'])) { + foreach ($ring['inner'] as $j) { + $wkt .= ',('; // start of inner ring + foreach ($row_data['parts'][$j]['points'] as $innerPoint) { + $wkt .= $innerPoint['x'] . ' ' . $innerPoint['y'] . ','; + } + $wkt = substr($wkt, 0, strlen($wkt) - 1); + $wkt .= ')'; // end of inner ring + } + } + + $wkt .= '),'; // end of polygon + } + } + $wkt = substr($wkt, 0, strlen($wkt) - 1); + + $wkt .= ')'; // end of multipolygon + return $wkt; + } + + /** + * Attach to each ring a point on its surface. + * + * @param array $rings + */ + private function getPointsOnSurface(&$rings) + { + $sql = 'SELECT '; + $inner_rings = false; + + foreach ($rings as $i => $ring) { + if (! $ring['isOuter']) { + $inner_rings = true; + // gis_data[0]['MULTIPOLYGON'][0][0] will have $ring + $gis_data = array(array('MULTIPOLYGON' => array(array($ring['points'])))); + $gis_data[0]['MULTIPOLYGON'][0][0]['no_of_points'] = count($ring['points']); + $geom = $this->generateWkt($gis_data, 0); + $sql .= 'AsText(PointOnSurface(GeomFromText("' . $geom . '"))) as `P' . $i . '`, '; + } + } + if (! $inner_rings) { + return; + } + + $sql = substr($sql, 0, strlen($sql) - 2); + $result = PMA_DBI_fetch_result($sql); + + require_once './libraries/gis/pma_gis_point.php'; + $point = PMA_GIS_Point::singleton(); + foreach ($rings as $i => $ring) { + if (! $ring['isOuter']) { + $param = $point->generateParams($result[0]['P' . $i], 0); + $rings[$i]['pointOnSurface'] = $param[0]['POINT']; + } + } + } + + /** + * Generate parameters for the GIS data editor from the value of the GIS column. * * @param string $value of the GIS column * @param index $index of the geometry diff --git a/libraries/gis/pma_gis_polygon.php b/libraries/gis/pma_gis_polygon.php index 239e219b65..f1c051ec40 100644 --- a/libraries/gis/pma_gis_polygon.php +++ b/libraries/gis/pma_gis_polygon.php @@ -324,6 +324,100 @@ class PMA_GIS_Polygon extends PMA_GIS_Geometry return $wkt; } + /** + * Calculates the area of a closed simple polygon. + * + * @param array $ring array of points forming the ring + * + * @return the area of a closed simple polygon. + */ + public static function area($ring) { + + $no_of_points = count($ring); + + // If the last point is same as the first point ignore it + $last = count($ring) - 1; + if (($ring[0]['x'] == $ring[$last]['x']) && ($ring[0]['y'] == $ring[$last]['y'])) { + $no_of_points--; + } + + // _n-1 + // A = _1_ \ (X(i) * Y(i+1)) - (Y(i) * X(i+1)) + // 2 /__ + // i=0 + $area = 0; + for ($i = 0; $i < $no_of_points; $i++) { + $j = ($i + 1) % $no_of_points; + $area += $ring[$i]['x'] * $ring[$j]['y']; + $area -= $ring[$i]['y'] * $ring[$j]['x']; + } + $area /= 2.0; + + return $area; + } + + /** + * Determines whether a set of points represents an outer ring. + * If points are in clockwise orientation then, they form an outer ring. + * + * @param array $ring array of points forming the ring + * + * @return whether a set of points represents an outer ring. + */ + public static function isOuterRing($ring) + { + // If area is negative then it's in clockwise orientation, i.e. it's an outer ring + if (PMA_GIS_Polygon::area($ring) < 0) { + return true; + } + return false; + } + + /** + * Determines whether a given point is inside a given polygon. + * + * @param array $point x, y coordinates of the point + * @param array $ring array of points forming the ring + * + * @return whether a given point is inside a given polygon + */ + public static function isPointInsidePolygon($point, $polygon) + { + // If first point is repeated at the end remove it + $last = count($polygon) - 1; + if (($polygon[0]['x'] == $polygon[$last]['x']) && ($polygon[0]['y'] == $polygon[$last]['y'])) { + $polygon = array_slice($polygon, 0, $last); + } + + $no_of_points = count($polygon); + $counter = 0; + + // Use ray casting algorithm + $p1 = $polygon[0]; + for ($i = 1; $i <= $no_of_points; $i++) { + $p2 = $polygon[$i % $no_of_points]; + if ($point['y'] > min(array($p1['y'], $p2['y']))) { + if ($point['y'] <= max(array($p1['y'], $p2['y']))) { + if ($point['x'] <= max(array($p1['x'], $p2['x']))) { + if ($p1['y'] != $p2['y']) { + $xinters = ($point['y'] - $p1['y']) * ($p2['x'] - $p1['x']) / ($p2['y'] - $p1['y']) + $p1['x']; + if ($p1['x'] == $p2['x'] || $point['x'] <= $xinters) { + $counter++; + } + } + } + } + } + $p1 = $p2; + } + + if ($counter % 2 == 0) { + return false; + } else { + return true; + } + } + /** Generate parameters for the GIS data editor from the value of the GIS column. * * @param string $value of the GIS column diff --git a/libraries/import/shp.php b/libraries/import/shp.php index 4bfdf4d3db..abee9632f2 100644 --- a/libraries/import/shp.php +++ b/libraries/import/shp.php @@ -18,8 +18,11 @@ if (isset($plugin_list)) { ); } else { - ini_set('memory_limit', '128M'); - set_time_limit(120); + if ((int) ini_get('memory_limit') < 512) { + ini_set('memory_limit', '512M'); + } + set_time_limit(300); + // Append the bfShapeFiles directory to the include path variable set_include_path(get_include_path() . PATH_SEPARATOR . getcwd() . '/libraries/bfShapeFiles/'); @@ -208,7 +211,7 @@ if (isset($plugin_list)) { } $shp = new PMA_ShapeFile(1); - // If the zip archive has more than one file, get the content to the buffer from .shp file. + // If the zip archive has more than one file, get the correct content to the buffer from .shp file. if ($compression == 'application/zip' && PMA_getNoOfFilesInZip($import_file) > 1) { $zip_content = PMA_getZipContents($import_file, '/^.*\.shp$/i'); $GLOBALS['import_text'] = $zip_content['data']; @@ -227,7 +230,7 @@ if (isset($plugin_list)) { // Extract the .dbf file and point to it. $extracted = PMA_zipExtract($import_file, realpath($cfg['TempDir']), array($dbf_file_name)); if ($extracted) { - $dbf_file_path = realpath($cfg['TempDir']) . '/' . $dbf_file_name; + $dbf_file_path = realpath($cfg['TempDir']) . (PMA_IS_WINDOWS ? '\\' : '/') . $dbf_file_name; $temp_dbf_file = true; // Replace the .dbf with .*, as required by the bsShapeFiles library. $file_name = substr($dbf_file_path, 0, strlen($dbf_file_path) - 4) . '.*'; From c81db372d79bf96acc8a4a2cdb2fe7f0430b57e4 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sat, 9 Jul 2011 19:18:03 +0530 Subject: [PATCH 15/98] Manually implemented PointOnSurface() function as it is not yet implemented in MySQL --- libraries/gis/pma_gis_multipolygon.php | 44 +++----------------- libraries/gis/pma_gis_polygon.php | 57 ++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 38 deletions(-) diff --git a/libraries/gis/pma_gis_multipolygon.php b/libraries/gis/pma_gis_multipolygon.php index 31b9ce5729..4f57c1db59 100644 --- a/libraries/gis/pma_gis_multipolygon.php +++ b/libraries/gis/pma_gis_multipolygon.php @@ -376,7 +376,12 @@ class PMA_GIS_Multipolygon extends PMA_GIS_Geometry $row_data['parts'][$i]['isOuter'] = PMA_GIS_Polygon::isOuterRing($ring['points']); } - $this->getPointsOnSurface($row_data['parts']); + // Find points on surface for inner rings + foreach ($row_data['parts'] as $i => $ring) { + if (! $ring['isOuter']) { + $row_data['parts'][$i]['pointOnSurface'] = PMA_GIS_Polygon::getPointOnSurface($ring['points']); + } + } // Classify inner rings to their respective outer rings. foreach ($row_data['parts'] as $j => $ring1) { @@ -429,43 +434,6 @@ class PMA_GIS_Multipolygon extends PMA_GIS_Geometry return $wkt; } - /** - * Attach to each ring a point on its surface. - * - * @param array $rings - */ - private function getPointsOnSurface(&$rings) - { - $sql = 'SELECT '; - $inner_rings = false; - - foreach ($rings as $i => $ring) { - if (! $ring['isOuter']) { - $inner_rings = true; - // gis_data[0]['MULTIPOLYGON'][0][0] will have $ring - $gis_data = array(array('MULTIPOLYGON' => array(array($ring['points'])))); - $gis_data[0]['MULTIPOLYGON'][0][0]['no_of_points'] = count($ring['points']); - $geom = $this->generateWkt($gis_data, 0); - $sql .= 'AsText(PointOnSurface(GeomFromText("' . $geom . '"))) as `P' . $i . '`, '; - } - } - if (! $inner_rings) { - return; - } - - $sql = substr($sql, 0, strlen($sql) - 2); - $result = PMA_DBI_fetch_result($sql); - - require_once './libraries/gis/pma_gis_point.php'; - $point = PMA_GIS_Point::singleton(); - foreach ($rings as $i => $ring) { - if (! $ring['isOuter']) { - $param = $point->generateParams($result[0]['P' . $i], 0); - $rings[$i]['pointOnSurface'] = $param[0]['POINT']; - } - } - } - /** * Generate parameters for the GIS data editor from the value of the GIS column. * diff --git a/libraries/gis/pma_gis_polygon.php b/libraries/gis/pma_gis_polygon.php index f1c051ec40..19e2f53ad0 100644 --- a/libraries/gis/pma_gis_polygon.php +++ b/libraries/gis/pma_gis_polygon.php @@ -418,6 +418,63 @@ class PMA_GIS_Polygon extends PMA_GIS_Geometry } } + /** + * Returns a point that is guaranteed to be on the surface of the ring. + * (for simple closed rings) + * + * @param array $ring array of points forming the ring + */ + public static function getPointOnSurface($ring) + { + // Find two consecutive distinct points. + for ($i = 0; $i < count($ring) - 1; $i++) { + if (($ring[$i]['x'] != $ring[$i + 1]['x']) + || ($ring[$i]['y'] != $ring[$i + 1]['y']) + ) { + $x0 = $ring[$i]['x']; + $x1 = $ring[$i + 1]['x']; + $y0 = $ring[$i]['y']; + $y1 = $ring[$i + 1]['y']; + } + } + + if (! isset($x0)) { + return false; + } + + // Find the mid point + $x2 = ($x0 + $x1) / 2; + $y2 = ($y0 + $y1) / 2; + + // Always keep $epsilon < 1 to go with the reduction logic found later in this method + $epsilon = 0.1; + $denominator = sqrt(pow(($y1 - $y0), 2) + pow(($x0 - $x1), 2)); + $pointA = array(); $pointB = array(); + + while (true) { + // Get the points on either sides of the line with a distance of epsilon to the mid point + $pointA['x'] = $x2 + ($epsilon * ($y1 - $y0)) / $denominator; + $pointA['y'] = $y2 + ($pointA['x'] - $x2) * ($x0 - $x1) / ($y1 - $y0); + + $pointB['x'] = $x2 + ($epsilon * ($y1 - $y0)) / (0 - $denominator); + $pointB['y'] = $y2 + ($pointB['x'] - $x2) * ($x0 - $x1) / ($y1 - $y0); + + // One of the points should be inside the polygon, unless epcilon chosen is too large + if (PMA_GIS_Polygon::isPointInsidePolygon($pointA, $ring)) { + return $pointA; + } else if (PMA_GIS_Polygon::isPointInsidePolygon($pointB, $ring)) { + return $pointB; + } + + // If both are outside the polygon reduce the epsilon and recalculate the points + // (reduce exponentially for faster convergance) + else { + $epsilon = pow($epsilon, 2); + } + + } + } + /** Generate parameters for the GIS data editor from the value of the GIS column. * * @param string $value of the GIS column From 2795a9061ca0a2c4f344303b686c64dbbc7032cd Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sun, 10 Jul 2011 22:13:50 +0530 Subject: [PATCH 16/98] Resolve problems due to merge commit --- tbl_replace.php | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/tbl_replace.php b/tbl_replace.php index b2f8d97f2f..04ac9314f0 100644 --- a/tbl_replace.php +++ b/tbl_replace.php @@ -153,7 +153,29 @@ $func_optional_param = array( 'UNIX_TIMESTAMP', ); -$gis_from_text_functions = array( 'GeomFromText', 'GeomCollFromText', 'LineFromText', 'MLineFromText', 'PointFromText', 'MPointFromText', 'PolyFromText', 'MPolyFromText',);$gis_from_wkb_functions = array( 'GeomFromWKB', 'GeomCollFromWKB', 'LineFromWKB', 'MLineFromWKB', 'PointFromWKB', 'MPointFromWKB', 'PolyFromWKB', 'MPolyFromWKB',);foreach ($loop_array as $rownumber => $where_clause) { +$gis_from_text_functions = array( + 'GeomFromText', + 'GeomCollFromText', + 'LineFromText', + 'MLineFromText', + 'PointFromText', + 'MPointFromText', + 'PolyFromText', + 'MPolyFromText', +); + +$gis_from_wkb_functions = array( + 'GeomFromWKB', + 'GeomCollFromWKB', + 'LineFromWKB', + 'MLineFromWKB', + 'PointFromWKB', + 'MPointFromWKB', + 'PolyFromWKB', + 'MPolyFromWKB', +); + +foreach ($loop_array as $rownumber => $where_clause) { // skip fields to be ignored if (! $using_key && isset($_REQUEST['insert_ignore_' . $where_clause])) { continue; @@ -238,11 +260,6 @@ $gis_from_text_functions = array( 'GeomFromText', 'GeomCollFromText', ' /* This way user will know what UUID new row has */ $uuid = PMA_DBI_fetch_value('SELECT UUID()'); $cur_value = "'" . $uuid . "'"; - } elseif (!in_array($me_funcs[$key], $func_no_param) - || ($val != "''" && in_array($me_funcs[$key], $func_optional_param))) { - $cur_value = $me_funcs[$key] . '(' . $val . ')'; - } else { - $cur_value = $me_funcs[$key] . '()'; } elseif ((in_array($me_funcs[$key], $gis_from_text_functions) && substr($val, 0, 3) == "'''") || in_array($me_funcs[$key], $gis_from_wkb_functions) @@ -252,8 +269,11 @@ $gis_from_text_functions = array( 'GeomFromText', 'GeomCollFromText', ' // Remove escaping apostrophes $val = str_replace("''", "'", $val); $cur_value = $me_funcs[$key] . '(' . $val . ')'; - } else { + } elseif (! in_array($me_funcs[$key], $func_no_param) + || ($val != "''" && in_array($me_funcs[$key], $func_optional_param))) { $cur_value = $me_funcs[$key] . '(' . $val . ')'; + } else { + $cur_value = $me_funcs[$key] . '()'; } // i n s e r t From 4e8cc7dc97871ba757517d0791488d57abee71a1 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sun, 10 Jul 2011 23:29:05 +0530 Subject: [PATCH 17/98] Avoid accessing undefined variables --- tbl_change.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tbl_change.php b/tbl_change.php index 7ecca885dd..e3363aa884 100644 --- a/tbl_change.php +++ b/tbl_change.php @@ -964,9 +964,10 @@ foreach ($rows as $row_id => $vrow) { } if (in_array($field['pma_type'], $gis_data_types)) { echo(''); + $data_val = isset($vrow[$field['Field']]) ? $vrow[$field['Field']] : ''; $_url_params = array( 'field' => $field['Field_title'], - 'value' => $vrow[$field['Field']], + 'value' => $data_val, ); if ($field['pma_type'] != 'geometry') { $_url_params = $_url_params + array('gis_data[gis_type]' => strtoupper($field['pma_type'])); From 3ca86a3929e201898e692ab3608d0dcf1a8a4bf2 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Mon, 11 Jul 2011 21:29:48 +0530 Subject: [PATCH 18/98] Protection against malformed WKT and null --- libraries/gis/pma_gis_factory.php | 7 +++++-- libraries/gis/pma_gis_geometrycollection.php | 21 ++++++++++++++++++++ libraries/gis/pma_gis_visualization.php | 6 ++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/libraries/gis/pma_gis_factory.php b/libraries/gis/pma_gis_factory.php index 7dd1daee95..1ba966910c 100644 --- a/libraries/gis/pma_gis_factory.php +++ b/libraries/gis/pma_gis_factory.php @@ -20,6 +20,9 @@ class PMA_GIS_Factory include_once './libraries/gis/pma_gis_geometry.php'; $type_lower = strtolower($type); + if (! file_exists('./libraries/gis/pma_gis_' . $type_lower . '.php')) { + return false; + } if (include_once './libraries/gis/pma_gis_' . $type_lower . '.php') { switch($type) { case 'MULTIPOLYGON' : @@ -37,10 +40,10 @@ class PMA_GIS_Factory case 'GEOMETRYCOLLECTION' : return PMA_GIS_Geometrycollection::singleton(); default : - throw new Exception('Unknown GIS data type'); + return false; } } else { - throw new Exception('File not found'); + return false; } } } diff --git a/libraries/gis/pma_gis_geometrycollection.php b/libraries/gis/pma_gis_geometrycollection.php index d8c17b3aaa..dd4621dad0 100644 --- a/libraries/gis/pma_gis_geometrycollection.php +++ b/libraries/gis/pma_gis_geometrycollection.php @@ -53,6 +53,9 @@ class PMA_GIS_Geometrycollection extends PMA_GIS_Geometry $type = substr($sub_part, 0, $type_pos); $gis_obj = PMA_GIS_Factory::factory($type); + if (! $gis_obj) { + continue; + } $scale_data = $gis_obj->scaleRow($sub_part); // Upadate minimum/maximum values for x and y cordinates. @@ -102,6 +105,9 @@ class PMA_GIS_Geometrycollection extends PMA_GIS_Geometry $type = substr($sub_part, 0, $type_pos); $gis_obj = PMA_GIS_Factory::factory($type); + if (! $gis_obj) { + continue; + } $image = $gis_obj->prepareRowAsPng($sub_part, $label, $color, $scale_data, $image); } return $image; @@ -130,6 +136,9 @@ class PMA_GIS_Geometrycollection extends PMA_GIS_Geometry $type = substr($sub_part, 0, $type_pos); $gis_obj = PMA_GIS_Factory::factory($type); + if (! $gis_obj) { + continue; + } $image = $gis_obj->prepareRowAsPdf($sub_part, $label, $color, $scale_data, $pdf); } return $pdf; @@ -159,6 +168,9 @@ class PMA_GIS_Geometrycollection extends PMA_GIS_Geometry $type = substr($sub_part, 0, $type_pos); $gis_obj = PMA_GIS_Factory::factory($type); + if (! $gis_obj) { + continue; + } $row .= $gis_obj->prepareRowAsSvg($sub_part, $label, $color, $scale_data); } return $row; @@ -189,6 +201,9 @@ class PMA_GIS_Geometrycollection extends PMA_GIS_Geometry $type = substr($sub_part, 0, $type_pos); $gis_obj = PMA_GIS_Factory::factory($type); + if (! $gis_obj) { + continue; + } $row .= $gis_obj->prepareRowAsOl($sub_part, $srid, $label, $color, $scale_data); } return $row; @@ -239,6 +254,9 @@ class PMA_GIS_Geometrycollection extends PMA_GIS_Geometry if (isset($gis_data[$i]['gis_type'])) { $type = $gis_data[$i]['gis_type']; $gis_obj = PMA_GIS_Factory::factory($type); + if (! $gis_obj) { + continue; + } $wkt .= $gis_obj->generateWkt($gis_data, $i) . ','; } } @@ -275,6 +293,9 @@ class PMA_GIS_Geometrycollection extends PMA_GIS_Geometry $type = substr($sub_part, 0, $type_pos); $gis_obj = PMA_GIS_Factory::factory($type); + if (! $gis_obj) { + continue; + } $params = array_merge($params, $gis_obj->generateParams($sub_part, $i)); $i++; } diff --git a/libraries/gis/pma_gis_visualization.php b/libraries/gis/pma_gis_visualization.php index 7c368570b2..31a20bbed7 100644 --- a/libraries/gis/pma_gis_visualization.php +++ b/libraries/gis/pma_gis_visualization.php @@ -313,6 +313,9 @@ class PMA_GIS_Visualization $type = substr($ref_data, 0, $type_pos); $gis_obj = PMA_GIS_Factory::factory($type); + if (! $gis_obj) { + continue; + } $scale_data = $gis_obj->scaleRow($row[$this->_settings['spatialColumn']]); // Upadate minimum/maximum values for x and y cordinates. @@ -392,6 +395,9 @@ class PMA_GIS_Visualization $type = substr($ref_data, 0, $type_pos); $gis_obj = PMA_GIS_Factory::factory($type); + if (! $gis_obj) { + continue; + } $label = ''; if (isset($this->_settings['labelColumn']) && isset($row[$this->_settings['labelColumn']]) From b9e5125870e8d6575f679d59d46e1fddec2f9e0c Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Mon, 11 Jul 2011 22:25:45 +0530 Subject: [PATCH 19/98] Correctly display null and empty values in geometry columns --- libraries/display_tbl.lib.php | 92 +++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/libraries/display_tbl.lib.php b/libraries/display_tbl.lib.php index 77ce26c8ad..1eb3872117 100644 --- a/libraries/display_tbl.lib.php +++ b/libraries/display_tbl.lib.php @@ -1519,61 +1519,67 @@ function PMA_displayTableBody(&$dt_result, &$is_display, $map, $analyzed_sql) { // Remove 'inline_edit' from $class as we do not allow to inline-edit geometry data. $class = str_replace('inline_edit', '', $class); - // Display as [GEOMETRY - (size)] - if ('GEOM' == $_SESSION['tmp_user_values']['geometry_display']) { - $geometry_text = PMA_handle_non_printable_contents( - 'GEOMETRY', (isset($row[$i]) ? $row[$i] : ''), $transform_function, - $transform_options, $default_function, $meta - ); - $vertical_display['data'][$row_no][$i] = PMA_buildValueDisplay( - $class, $condition_field, $geometry_text - ); + if (! isset($row[$i]) || is_null($row[$i])) { + $vertical_display['data'][$row_no][$i] = PMA_buildNullDisplay($class, $condition_field); + } elseif ($row[$i] != '') { + // Display as [GEOMETRY - (size)] + if ('GEOM' == $_SESSION['tmp_user_values']['geometry_display']) { + $geometry_text = PMA_handle_non_printable_contents( + 'GEOMETRY', (isset($row[$i]) ? $row[$i] : ''), $transform_function, + $transform_options, $default_function, $meta + ); + $vertical_display['data'][$row_no][$i] = PMA_buildValueDisplay( + $class, $condition_field, $geometry_text + ); - // Display in Well Known Text(WKT) format. - } elseif ('WKT' == $_SESSION['tmp_user_values']['geometry_display']) { - // Convert to WKT format - $wktval = PMA_asWKT($row[$i]); + // Display in Well Known Text(WKT) format. + } elseif ('WKT' == $_SESSION['tmp_user_values']['geometry_display']) { + // Convert to WKT format + $wktval = PMA_asWKT($row[$i]); - if (PMA_strlen($wktval) > $GLOBALS['cfg']['LimitChars'] - && $_SESSION['tmp_user_values']['display_text'] == 'P' - ) { - $wktval = PMA_substr($wktval, 0, $GLOBALS['cfg']['LimitChars']) . '...'; - $is_field_truncated = true; - } - - $vertical_display['data'][$row_no][$i] = ' $GLOBALS['cfg']['LimitChars'] + if (PMA_strlen($wktval) > $GLOBALS['cfg']['LimitChars'] && $_SESSION['tmp_user_values']['display_text'] == 'P' ) { - $wkbval = PMA_substr($wkbval, 0, $GLOBALS['cfg']['LimitChars']) . '...'; + $wktval = PMA_substr($wktval, 0, $GLOBALS['cfg']['LimitChars']) . '...'; $is_field_truncated = true; } $vertical_display['data'][$row_no][$i] = ' $GLOBALS['cfg']['LimitChars'] + && $_SESSION['tmp_user_values']['display_text'] == 'P' + ) { + $wkbval = PMA_substr($wkbval, 0, $GLOBALS['cfg']['LimitChars']) . '...'; + $is_field_truncated = true; + } + + $vertical_display['data'][$row_no][$i] = ' Date: Tue, 12 Jul 2011 14:21:48 +0530 Subject: [PATCH 20/98] Trim the name before being displayed as the tooltip. --- js/tbl_gis_visualization.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/tbl_gis_visualization.js b/js/tbl_gis_visualization.js index 81a86c480a..0668e56899 100644 --- a/js/tbl_gis_visualization.js +++ b/js/tbl_gis_visualization.js @@ -224,7 +224,7 @@ $(document).ready(function() { */ $('.polygon, .multipolygon, .point, .multipoint, .linestring, .multilinestring, ' + '.geometrycollection').live('mousemove', function(event) { - contents = $(this).attr('name'); + contents = $.trim($(this).attr('name')); $("#tooltip").remove(); if (contents != '') { $('
' + contents + '
').css({ From 242534a78ad3d26334cd97dcf8346c7cd327179b Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Wed, 13 Jul 2011 00:17:09 +0530 Subject: [PATCH 21/98] Avoid divide by zero error --- libraries/gis/pma_gis_polygon.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libraries/gis/pma_gis_polygon.php b/libraries/gis/pma_gis_polygon.php index 19e2f53ad0..1f077727a8 100644 --- a/libraries/gis/pma_gis_polygon.php +++ b/libraries/gis/pma_gis_polygon.php @@ -428,13 +428,12 @@ class PMA_GIS_Polygon extends PMA_GIS_Geometry { // Find two consecutive distinct points. for ($i = 0; $i < count($ring) - 1; $i++) { - if (($ring[$i]['x'] != $ring[$i + 1]['x']) - || ($ring[$i]['y'] != $ring[$i + 1]['y']) - ) { + if ($ring[$i]['y'] != $ring[$i + 1]['y']) { $x0 = $ring[$i]['x']; $x1 = $ring[$i + 1]['x']; $y0 = $ring[$i]['y']; $y1 = $ring[$i + 1]['y']; + break; } } @@ -462,7 +461,7 @@ class PMA_GIS_Polygon extends PMA_GIS_Geometry // One of the points should be inside the polygon, unless epcilon chosen is too large if (PMA_GIS_Polygon::isPointInsidePolygon($pointA, $ring)) { return $pointA; - } else if (PMA_GIS_Polygon::isPointInsidePolygon($pointB, $ring)) { + } elseif (PMA_GIS_Polygon::isPointInsidePolygon($pointB, $ring)) { return $pointB; } @@ -470,6 +469,9 @@ class PMA_GIS_Polygon extends PMA_GIS_Geometry // (reduce exponentially for faster convergance) else { $epsilon = pow($epsilon, 2); + if ($epsilon == 0) { + return false; + } } } From 2bf70868bbd9c69036470b4a9cbfe2fe29e1a8fc Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Wed, 13 Jul 2011 00:19:11 +0530 Subject: [PATCH 22/98] Avoid undefined variables --- libraries/import/shp.php | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/import/shp.php b/libraries/import/shp.php index abee9632f2..bd9fc50d98 100644 --- a/libraries/import/shp.php +++ b/libraries/import/shp.php @@ -217,6 +217,7 @@ if (isset($plugin_list)) { $GLOBALS['import_text'] = $zip_content['data']; } + $temp_dbf_file = false; // We need dbase extension to handle .dbf file if (extension_loaded('dbase')) { // If we can extract the zip archive to 'TempDir' and use the files in it for import From a1e6b187c60999d1934ed5f7428c95f0a5d3820d Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Wed, 13 Jul 2011 23:51:25 +0530 Subject: [PATCH 23/98] Correctly display error message for zero data. --- libraries/import/shp.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libraries/import/shp.php b/libraries/import/shp.php index bd9fc50d98..900eb75902 100644 --- a/libraries/import/shp.php +++ b/libraries/import/shp.php @@ -336,6 +336,12 @@ if (isset($plugin_list)) { } } + if(count($rows) == 0) { + $error = true; + $err = PMA_Message::error(__('The imported file does not cantain any data')); + PMA_mysqlDie($err->getMessage(), '', '', $err_url); + } + // Column names for spatial column and the rest of the columns, if they are available $col_names[] = 'SPATIAL'; for ($n = 0; $n < $num_data_cols; $n++) { From e0e0dea09b25da67f60d787b0c2312dbbc5a7660 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Thu, 14 Jul 2011 00:09:25 +0530 Subject: [PATCH 24/98] 1) Better error handling. 2)Typo --- libraries/import/shp.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libraries/import/shp.php b/libraries/import/shp.php index 900eb75902..a92cfda4ed 100644 --- a/libraries/import/shp.php +++ b/libraries/import/shp.php @@ -300,9 +300,12 @@ if (isset($plugin_list)) { break; default: $error = true; - $err = PMA_Message::error(__('MySQL Spatial Extension does not support ESRI type "%s".')); - $param = isset($esri_types[$shp->shapeType]) ? $esri_types[$shp->shapeType] : __('Unkown Type'); - $err->addParam($param); + if (! isset($esri_types[$shp->shapeType])) { + $err = PMA_Message::error(__('You tried to import an invalid file or the imported file contains invalid data')); + } else { + $err = PMA_Message::error(__('MySQL Spatial Extension does not support ESRI type "%s".')); + $err->addParam($param); + } PMA_mysqlDie($err->getMessage(), '', '', $err_url); } @@ -338,7 +341,7 @@ if (isset($plugin_list)) { if(count($rows) == 0) { $error = true; - $err = PMA_Message::error(__('The imported file does not cantain any data')); + $err = PMA_Message::error(__('The imported file does not contain any data')); PMA_mysqlDie($err->getMessage(), '', '', $err_url); } From 66f73b4114bf8e60496fe052ec86b33c65c3137e Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Thu, 14 Jul 2011 09:59:35 +0530 Subject: [PATCH 25/98] Better error handling. --- libraries/import/shp.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libraries/import/shp.php b/libraries/import/shp.php index a92cfda4ed..14195214ec 100644 --- a/libraries/import/shp.php +++ b/libraries/import/shp.php @@ -249,6 +249,12 @@ if (isset($plugin_list)) { // Load data $shp->loadFromFile(''); + if ($shp->lastError != "") { + $error = true; + $err = PMA_Message::error(__('There was an error importing the ESRI shape file: "%s".')); + $err->addParam($shp->lastError); + PMA_mysqlDie($err->getMessage(), '', '', $err_url); + } // Delete the .dbf file extracted to 'TempDir' if ($temp_dbf_file) { From b1634f80fd598d67130b7fccd29f7bc8dbc726b4 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Thu, 14 Jul 2011 19:39:39 +0530 Subject: [PATCH 26/98] GIS data editor extended for JS enabled browsers --- gis_data_editor.php | 67 +++++++----- js/messages.php | 1 + js/tbl_change.js | 131 ++++++++++++++++++++++++ tbl_change.php | 7 +- themes/original/css/theme_right.css.php | 7 ++ themes/pmahomme/css/theme_right.css.php | 9 +- 6 files changed, 194 insertions(+), 28 deletions(-) diff --git a/gis_data_editor.php b/gis_data_editor.php index 3bc74847a7..cc53722989 100644 --- a/gis_data_editor.php +++ b/gis_data_editor.php @@ -1,8 +1,9 @@ $wkt, - 'srid' => $srid, + 'result' => $result, 'visualization' => $visualization, ); PMA_ajaxResponse(null, true, $extra_data); } + +if(isset($_REQUEST['get_gis_editor']) && $_REQUEST['get_gis_editor'] == true) { + ob_start(); +} else { ?> - - -
+ +

'); - echo PMA_generate_common_hidden_inputs($url_params); + echo(''); + echo(''); + echo PMA_generate_common_hidden_inputs(); ?>
- - " /> + " />
@@ -104,7 +116,7 @@ if(isset($_REQUEST['generate']) && $_REQUEST['generate'] == true) { } else { $type = $gis_types[0]; } - echo(''); foreach (array_slice($gis_types, 0, 6) as $gis_type) { echo(''); } echo(''); - echo(''); + echo(''); } else { $type = $geom_type; } @@ -149,7 +161,7 @@ if(isset($_REQUEST['generate']) && $_REQUEST['generate'] == true) { - "> + "> "> +?> ">
+?>
" value="" /> " value=""> +?> " class="add" value="">
" value=""> +?>
" class= "add" value="">

" value=""> +?>

" class= "add" value="">

" /> +?>

" />
@@ -260,15 +272,20 @@ if(isset($_REQUEST['generate']) && $_REQUEST['generate'] == true) {

+ +
'); + + // Add close and cancel links + $('#gis_data_editor_no_js') + .prepend('' + PMA_messages['strClose'] + ''); + $(' ' + PMA_messages['strCancel'] + '') + .insertAfter($("input[name='gis_data[save]']")); + + // Remove the unnecessary text + $('div#gis_data_output p').remove(); + + // Remove 'add' buttons and add links + $('.add').each(function(e) { + $button = $(this); + text = $button.attr('value'); + name = $button.attr('name'); + $button.after('+ ' + text + '').remove(); + }); +} + /** * Ajax handlers for Change Table page * @@ -221,6 +260,98 @@ function verificationsAfterFieldChange(urlField, multi_edit, theType){ */ $(document).ready(function() { + $('.open_gis_editor').live('click', function(event) { + event.preventDefault(); + + // Center the popup + var $span = $(this); + var windowWidth = document.documentElement.clientWidth; + var windowHeight = document.documentElement.clientHeight; + var popupWidth = windowWidth * 0.9; + var popupHeight = windowHeight * 0.8; + var popupOffsetTop = windowHeight / 2 - popupHeight / 2; + var popupOffsetLeft = windowWidth / 2 - popupWidth / 2; + var $gis_editor = $("#gis_editor"); + $gis_editor.css({"position":"absolute", "top": popupOffsetTop, "left": popupOffsetLeft, "width": popupWidth, "height": popupHeight}); + + // Current value + var value = $span.parent('td').children("input[type='text']").val(); + // Field name + var field = $span.parents('tr').children('td:first').find("input[type='hidden']").val(); + // Names of input field and null checkbox + var input_name = $span.parents('tr').children('td:nth-child(5)').find('input:nth-child(3)').attr('name'); + var null_checkbox_name = $span.parents('tr').children('td:nth-child(4)').find('.checkbox_null').attr('name'); + + $.post('gis_data_editor.php', { + 'field' : field, + 'value' : value, + 'input_name' : input_name, + 'null_checkbox_name' : null_checkbox_name, + 'get_gis_editor' : true, + 'token' : window.parent.token + }, function(data) { + if(data.success == true) { + $gis_editor.html(data.gis_editor); + prepareJSVersion(); + $('').appendTo($gis_editor); + } else { + PMA_ajaxShowMessage(data.error); + } + }) + + // Make it appear + $("#popup_background").css({"opacity":"0.7"}); + $("#popup_background").fadeIn("fast"); + $gis_editor.fadeIn("fast"); + }) + + /** + * Prepare and insert the GIS data in Well Known Text format + * to the input field. + */ + $("input[name='gis_data[save]']").live('click', function(event) { + event.preventDefault(); + + var $form = $('form#gis_data_editor_form'); + var input_name = $form.find("input[name='input_name']").val(); + var null_checkbox_name = $form.find("input[name='null_checkbox_name']").val(); + + $.post('gis_data_editor.php', $form.serialize() + "&generate=true", function(data) { + if(data.success == true) { + $("input[name='" + null_checkbox_name + "']").attr('checked', false); + $("input[name='" + input_name + "']").val(data.result); + } else { + PMA_ajaxShowMessage(data.error); + } + }); + closeGISEditor(); + }); + + /** + * Update the form on change of the GIS type. + */ + $(".gis_type").live('change', function(event) { + var $gis_editor = $("#gis_editor"); + var $form = $('form#gis_data_editor_form'); + + $.post('gis_data_editor.php', $form.serialize() + "&get_gis_editor=true", function(data) { + if(data.success == true) { + $gis_editor.html(data.gis_editor); + prepareJSVersion(); + $('').appendTo($gis_editor); + } else { + PMA_ajaxShowMessage(data.error); + } + }); + }); + + /** + * Handles closing of the GIS data editor. + */ + $('.close_gis_editor, .cancel_gis_editor').live('click', function() { + closeGISEditor(); + }) + // these were hidden via the "hide" class $('.foreign_values_anchor').show(); diff --git a/tbl_change.php b/tbl_change.php index e3363aa884..afbf2dd6e9 100644 --- a/tbl_change.php +++ b/tbl_change.php @@ -963,19 +963,22 @@ foreach ($rows as $row_id => $vrow) { } } if (in_array($field['pma_type'], $gis_data_types)) { - echo(''); $data_val = isset($vrow[$field['Field']]) ? $vrow[$field['Field']] : ''; $_url_params = array( 'field' => $field['Field_title'], 'value' => $data_val, - ); + 'input_name' => 'fields' + $field_name_appendix, + 'null_checkbox_name' => 'fields_null' + $field_name_appendix, + ); if ($field['pma_type'] != 'geometry') { $_url_params = $_url_params + array('gis_data[gis_type]' => strtoupper($field['pma_type'])); } $edit_url = 'gis_data_editor.php' . PMA_generate_common_url($_url_params); $edit_str = PMA_getIcon('b_edit.png', __('Edit/Insert'), true); + echo(''); echo(PMA_linkOrButton($edit_url, $edit_str, array(), false, false, '_blank')); echo(''); + echo('
'); } ?> diff --git a/themes/original/css/theme_right.css.php b/themes/original/css/theme_right.css.php index 9acbbcbe8f..d2e9b4dc37 100644 --- a/themes/original/css/theme_right.css.php +++ b/themes/original/css/theme_right.css.php @@ -1553,6 +1553,13 @@ input#input_import_file { margin: 5px 0px 5px 0px; } +/** + * GIS data editor styles + */ +a.close_gis_editor { + float: right; +} + /** * ENUM/SET editor styles */ diff --git a/themes/pmahomme/css/theme_right.css.php b/themes/pmahomme/css/theme_right.css.php index 69a3b941e3..9e8bc09def 100644 --- a/themes/pmahomme/css/theme_right.css.php +++ b/themes/pmahomme/css/theme_right.css.php @@ -1897,6 +1897,13 @@ input#input_import_file { margin: 5px 0px 5px 0px; } +/** + * GIS data editor styles + */ +a.close_gis_editor { + float: right; +} + /** * ENUM/SET editor styles */ @@ -2595,7 +2602,7 @@ span.mysql-number { border-radius: 5px; -webkit-border-radius: 5px; -moz-border-radius: 5px; - + background-image: url(./themes/svg_gradient.php?from=eeeeee&to=cccccc); background-size: 100% 100%; background: -webkit-gradient(linear, left top, left bottom, from(#eeeeee), to(#cccccc)); From fd0cb076c0c415c321edf8e811c9691d6f2ca06f Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Fri, 15 Jul 2011 00:03:48 +0530 Subject: [PATCH 27/98] Better styling for GIS data editor. --- js/tbl_change.js | 8 ++--- tbl_change.php | 2 +- themes/original/css/theme_right.css.php | 40 +++++++++++-------------- themes/pmahomme/css/theme_right.css.php | 40 +++++++++++-------------- 4 files changed, 41 insertions(+), 49 deletions(-) diff --git a/js/tbl_change.js b/js/tbl_change.js index d1c262fbe3..7ab6141169 100644 --- a/js/tbl_change.js +++ b/js/tbl_change.js @@ -216,7 +216,9 @@ function verificationsAfterFieldChange(urlField, multi_edit, theType){ * Closes the GIS data editor and perform necessary clean up work. */ function closeGISEditor(){ - $("#gis_editor").html('').attr('hidden', true); + $("#popup_background").fadeOut("fast"); + $("#gis_editor").fadeOut("fast"); + $("#gis_editor").html(''); } /** @@ -229,13 +231,11 @@ function prepareJSVersion() { // Change the text on the submit button $("input[name='gis_data[save]']") .attr('value', PMA_messages['strCopy']) - .remove() .insertAfter($('#gis_data_textarea')) .before('

'); // Add close and cancel links - $('#gis_data_editor_no_js') - .prepend('' + PMA_messages['strClose'] + ''); + $('#gis_data_editor').prepend('' + PMA_messages['strClose'] + ''); $(' ' + PMA_messages['strCancel'] + '') .insertAfter($("input[name='gis_data[save]']")); diff --git a/tbl_change.php b/tbl_change.php index afbf2dd6e9..4696a03fc4 100644 --- a/tbl_change.php +++ b/tbl_change.php @@ -978,7 +978,7 @@ foreach ($rows as $row_id => $vrow) { echo(''); echo(PMA_linkOrButton($edit_url, $edit_str, array(), false, false, '_blank')); echo(''); - echo('
'); + echo('
'); } ?> diff --git a/themes/original/css/theme_right.css.php b/themes/original/css/theme_right.css.php index a193c1ed02..dbad0c740a 100644 --- a/themes/original/css/theme_right.css.php +++ b/themes/original/css/theme_right.css.php @@ -1560,6 +1560,24 @@ a.close_gis_editor { float: right; } +#gis_editor { + display: none; + position: fixed; + _position: absolute; /* hack for IE */ + z-index: 101; + overflow-y: auto; + overflow-x: hidden; +} + +#gis_data_textarea { + height: 6em; +} + +#gis_data_editor { + background: #D0DCE0; + padding: 15px; +} + /** * ENUM/SET editor styles */ @@ -2026,28 +2044,6 @@ fieldset .disabled-field td { display:none; } -#gis_data_editor { - display: none; - position: fixed; - _position: absolute; /* hack for IE */ - z-index: 101; - overflow-y: auto; - overflow-x: hidden; -} - -#gis_data_editor_no_js { - margin: auto auto; -} - -#gis_data_editor, #gis_data_editor_no_js { - background: #D0DCE0; - padding: 15px; -} - -#gis_data_textarea { - height: 6em; -} - .CodeMirror { line-height: 1em; font-family: monospace; diff --git a/themes/pmahomme/css/theme_right.css.php b/themes/pmahomme/css/theme_right.css.php index ba457ead71..3114904f46 100644 --- a/themes/pmahomme/css/theme_right.css.php +++ b/themes/pmahomme/css/theme_right.css.php @@ -1904,6 +1904,24 @@ a.close_gis_editor { float: right; } +#gis_editor { + display: none; + position: fixed; + _position: absolute; /* hack for IE */ + z-index: 101; + overflow-y: auto; + overflow-x: hidden; +} + +#gis_data_textarea { + height: 6em; +} + +#gis_data_editor { + background: #D0DCE0; + padding: 15px; +} + /** * ENUM/SET editor styles */ @@ -2393,28 +2411,6 @@ fieldset .disabled-field td { display: none; } -#gis_data_editor { - display: none; - position: fixed; - _position: absolute; /* hack for IE */ - z-index: 101; - overflow-y: auto; - overflow-x: hidden; -} - -#gis_data_editor_no_js { - margin: auto auto; -} - -#gis_data_editor, #gis_data_editor_no_js { - background: #D0DCE0; - padding: 15px; -} - -#gis_data_textarea { - height: 6em; -} - .CodeMirror { line-height: 1em; font-family: monospace; From 0c9301f7dbc88ee49021f708d9004e0b57975fd8 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Fri, 15 Jul 2011 00:04:32 +0530 Subject: [PATCH 28/98] Corrected order of includes. --- gis_data_editor.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gis_data_editor.php b/gis_data_editor.php index cc53722989..da5e5795f6 100644 --- a/gis_data_editor.php +++ b/gis_data_editor.php @@ -1,9 +1,9 @@
-
+

'); echo(''); From 6e7c3adbc15eb1f4b822a083b954cbc39a02bc13 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Fri, 15 Jul 2011 00:27:31 +0530 Subject: [PATCH 29/98] Trigger AJAX calls on data change and update the output --- js/tbl_change.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/js/tbl_change.js b/js/tbl_change.js index 7ab6141169..bd331ccc4d 100644 --- a/js/tbl_change.js +++ b/js/tbl_change.js @@ -327,6 +327,20 @@ $(document).ready(function() { closeGISEditor(); }); + /** + * Trigger asynchronous calls on data change and update the output. + */ + $('#gis_editor').find("input[type='text']").live('change', function() { + var $form = $('form#gis_data_editor_form'); + $.post('gis_data_editor.php', $form.serialize() + "&generate=true", function(data) { + if(data.success == true) { + $('#gis_data_textarea').val(data.result); + } else { + PMA_ajaxShowMessage(data.error); + } + }); + }); + /** * Update the form on change of the GIS type. */ From c18ef53b57ba72a6b35e479b3510d855cc636aa7 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Fri, 15 Jul 2011 18:30:28 +0530 Subject: [PATCH 30/98] Do not use PMA_mysqlDie() to handle these errors. --- libraries/import/shp.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libraries/import/shp.php b/libraries/import/shp.php index 14195214ec..7ee62fdce3 100644 --- a/libraries/import/shp.php +++ b/libraries/import/shp.php @@ -251,9 +251,9 @@ if (isset($plugin_list)) { $shp->loadFromFile(''); if ($shp->lastError != "") { $error = true; - $err = PMA_Message::error(__('There was an error importing the ESRI shape file: "%s".')); - $err->addParam($shp->lastError); - PMA_mysqlDie($err->getMessage(), '', '', $err_url); + $message = PMA_Message::error(__('There was an error importing the ESRI shape file: "%s".')); + $message->addParam($shp->lastError); + return; } // Delete the .dbf file extracted to 'TempDir' @@ -307,12 +307,12 @@ if (isset($plugin_list)) { default: $error = true; if (! isset($esri_types[$shp->shapeType])) { - $err = PMA_Message::error(__('You tried to import an invalid file or the imported file contains invalid data')); + $message = PMA_Message::error(__('You tried to import an invalid file or the imported file contains invalid data')); } else { - $err = PMA_Message::error(__('MySQL Spatial Extension does not support ESRI type "%s".')); - $err->addParam($param); + $message = PMA_Message::error(__('MySQL Spatial Extension does not support ESRI type "%s".')); + $message->addParam($param); } - PMA_mysqlDie($err->getMessage(), '', '', $err_url); + return; } $num_rows = count($shp->records); @@ -347,8 +347,8 @@ if (isset($plugin_list)) { if(count($rows) == 0) { $error = true; - $err = PMA_Message::error(__('The imported file does not contain any data')); - PMA_mysqlDie($err->getMessage(), '', '', $err_url); + $message = PMA_Message::error(__('The imported file does not contain any data')); + return; } // Column names for spatial column and the rest of the columns, if they are available From f5bd53fae03e41c2b26f3769ce891270d00d39e9 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Fri, 15 Jul 2011 18:31:15 +0530 Subject: [PATCH 31/98] Remove hidden fields not used. --- js/tbl_change.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/js/tbl_change.js b/js/tbl_change.js index bd331ccc4d..620d6600ff 100644 --- a/js/tbl_change.js +++ b/js/tbl_change.js @@ -293,7 +293,6 @@ $(document).ready(function() { if(data.success == true) { $gis_editor.html(data.gis_editor); prepareJSVersion(); - $('').appendTo($gis_editor); } else { PMA_ajaxShowMessage(data.error); } @@ -352,7 +351,6 @@ $(document).ready(function() { if(data.success == true) { $gis_editor.html(data.gis_editor); prepareJSVersion(); - $('').appendTo($gis_editor); } else { PMA_ajaxShowMessage(data.error); } From 166b571964d6c3513359512b8eef83584f2f9ddf Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Fri, 15 Jul 2011 23:13:00 +0530 Subject: [PATCH 32/98] Non JS version does not need this parameters. --- gis_data_editor.php | 8 ++++++-- js/tbl_change.js | 3 ++- tbl_change.php | 2 -- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/gis_data_editor.php b/gis_data_editor.php index da5e5795f6..e86abb735e 100644 --- a/gis_data_editor.php +++ b/gis_data_editor.php @@ -75,8 +75,12 @@ if(isset($_REQUEST['get_gis_editor']) && $_REQUEST['get_gis_editor'] == true) {

'); - echo(''); - echo(''); + if (isset($_REQUEST['input_name'])) { + echo(''); + } + if (isset($_REQUEST['null_checkbox_name'])) { + echo(''); + } echo PMA_generate_common_hidden_inputs(); ?>
diff --git a/js/tbl_change.js b/js/tbl_change.js index 620d6600ff..3218fafdba 100644 --- a/js/tbl_change.js +++ b/js/tbl_change.js @@ -255,7 +255,8 @@ function prepareJSVersion() { * Ajax handlers for Change Table page * * Actions Ajaxified here: - * Submit Data to be inserted into the table + * GIS data editor. + * Submit Data to be inserted into the table. * Restart insertion with 'N' rows. */ $(document).ready(function() { diff --git a/tbl_change.php b/tbl_change.php index 4696a03fc4..d520737135 100644 --- a/tbl_change.php +++ b/tbl_change.php @@ -967,8 +967,6 @@ foreach ($rows as $row_id => $vrow) { $_url_params = array( 'field' => $field['Field_title'], 'value' => $data_val, - 'input_name' => 'fields' + $field_name_appendix, - 'null_checkbox_name' => 'fields_null' + $field_name_appendix, ); if ($field['pma_type'] != 'geometry') { $_url_params = $_url_params + array('gis_data[gis_type]' => strtoupper($field['pma_type'])); From b2d703dbea2077c9ff48686ee230d7a7ff224318 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sat, 16 Jul 2011 00:29:00 +0530 Subject: [PATCH 33/98] Add points with JavaScript --- gis_data_editor.php | 6 +++--- js/tbl_change.js | 30 ++++++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/gis_data_editor.php b/gis_data_editor.php index e86abb735e..3aadc58bea 100644 --- a/gis_data_editor.php +++ b/gis_data_editor.php @@ -165,7 +165,7 @@ if(isset($_REQUEST['get_gis_editor']) && $_REQUEST['get_gis_editor'] == true) { - "> + "> "> +?> ">
@@ -259,7 +259,7 @@ if(isset($_REQUEST['get_gis_editor']) && $_REQUEST['get_gis_editor'] == true) { " value="" /> " class="add" value=""> +?> " class="add point" value="">
" class= "add" value=""> + ' + text + '').remove(); + var $button = $(this); + $button.addClass('addJs').removeClass('add'); + var classes = $button.attr('class'); + $button + .after('+ ' + $button.attr('value') + '') + .remove(); }); } @@ -365,6 +368,25 @@ $(document).ready(function() { closeGISEditor(); }) + /** + * Handle adding data points + */ + $('.addJs.point').live('click', function() { + var $a = $(this); + var name = $a.attr('name'); + var prefix = name.substr(0, name.length - 11); + var $noOfPointsInput = $("input[name='" + prefix + "[no_of_points]" + "']"); + var noOfPoints = parseInt($noOfPointsInput.attr('value')); + var html = '
' + + 'Point' + (noOfPoints + 1) + ':' + + '' + + '' + + '' + + ''; + $a.before(html); + $noOfPointsInput.attr('value', noOfPoints + 1); + }); + // these were hidden via the "hide" class $('.foreign_values_anchor').show(); From 83d8d3a8ed3043f52b1f1ef42af33fccfead1e87 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sat, 16 Jul 2011 02:11:18 +0530 Subject: [PATCH 34/98] Handle adding linestrings and inner rings. Better comments --- gis_data_editor.php | 2 +- js/tbl_change.js | 63 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/gis_data_editor.php b/gis_data_editor.php index 3aadc58bea..59f9f1bfad 100644 --- a/gis_data_editor.php +++ b/gis_data_editor.php @@ -212,7 +212,7 @@ if(isset($_REQUEST['get_gis_editor']) && $_REQUEST['get_gis_editor'] == true) { ?> ">
+?>
Point' + (pointNumber + 1) + ':' + + '' + + '' + + '' + + ''; +} + /** * Ajax handlers for Change Table page * @@ -369,24 +384,56 @@ $(document).ready(function() { }) /** - * Handle adding data points + * Handles adding data points */ $('.addJs.point').live('click', function() { var $a = $(this); var name = $a.attr('name'); + // Eg. name = gis_data[0][MULTIPOINT][add_point] => prefix = gis_data[0][MULTIPOINT] var prefix = name.substr(0, name.length - 11); + // Find the number of points var $noOfPointsInput = $("input[name='" + prefix + "[no_of_points]" + "']"); var noOfPoints = parseInt($noOfPointsInput.attr('value')); - var html = '
' - + 'Point' + (noOfPoints + 1) + ':' - + '' - + '' - + '' - + ''; + // Add the new data point + var html = addDataPoint(noOfPoints, prefix); $a.before(html); - $noOfPointsInput.attr('value', noOfPoints + 1); + $noOfPointsInput.attr('value', noOfPoints + 1); }); + /** + * Handles adding linestrings and inner rings + */ + $('.line.addJs').live('click', function() { + var $a = $(this); + var name = $a.attr('name'); + + // Eg. name = gis_data[0][MULTILINESTRING][add_line] => prefix = gis_data[0][MULTILINESTRING] + var prefix = name.substr(0, name.length - 10); + var type = prefix.slice(prefix.lastIndexOf('[') + 1, prefix.lastIndexOf(']')); + + // Find the number of lines + var $noOfLinesInput = $("input[name='" + prefix + "[no_of_lines]" + "']"); + var noOfLines = parseInt($noOfLinesInput.attr('value')); + + // Add the new linesting of inner ring based on the type + var html = '
'; + if (type == 'MULTILINESTRING') { + html += 'Linestring' + (noOfLines + 1) + ':'; + var noOfPoints = 2; + } else { + html += 'Inner Ring' + noOfLines + ':'; + var noOfPoints = 4; + } + html += ''; + for (i = 0; i < noOfPoints; i++) { + html += addDataPoint(i, (prefix + '[' + noOfLines + ']')); + } + html += '+ Add a point
'; + + $a.before(html); + $noOfLinesInput.attr('value', noOfLines + 1); + }); + // these were hidden via the "hide" class $('.foreign_values_anchor').show(); From ed23518a44fdd62c5394c785e515d65f7c4910eb Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sat, 16 Jul 2011 10:50:22 +0530 Subject: [PATCH 35/98] Handle adding polygons and geometry objects --- gis_data_editor.php | 12 +++++------ js/tbl_change.js | 51 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/gis_data_editor.php b/gis_data_editor.php index 59f9f1bfad..9d2b112b47 100644 --- a/gis_data_editor.php +++ b/gis_data_editor.php @@ -135,10 +135,10 @@ if(isset($_REQUEST['get_gis_editor']) && $_REQUEST['get_gis_editor'] == true) { } if ($type == 'POINT') { - echo('
'); echo __("Point"); -?> + echo('
'); echo __("Point"); echo(' :'); +?> - + " class="add point" value="">
" class= "add" value=""> +?>
" class="add line" value="">

" class= "add" value=""> +?>

" class="add polygon" value="">

" /> +?>

" />
diff --git a/js/tbl_change.js b/js/tbl_change.js index b589f548b9..dab6de5d33 100644 --- a/js/tbl_change.js +++ b/js/tbl_change.js @@ -434,6 +434,57 @@ $(document).ready(function() { $noOfLinesInput.attr('value', noOfLines + 1); }); + /** + * Handles adding polygons + */ + $('.addJs.polygon').live('click', function() { + var $a = $(this); + var name = $a.attr('name'); + // Eg. name = gis_data[0][MULTIPOLYGON][add_polygon] => prefix = gis_data[0][MULTIPOLYGON] + var prefix = name.substr(0, name.length - 13); + // Find the number of polygons + var $noOfPolygonsInput = $("input[name='" + prefix + "[no_of_polygons]" + "']"); + var noOfPolygons = parseInt($noOfPolygonsInput.attr('value')); + + // Add the new polygon + var html = 'Polygon' + (noOfPolygons + 1) + ':
'; + html += ''; + + '
' + 'Outer Ring' + ':'; + + ''; + for (i = 0; i < 4; i++) { + html += addDataPoint(i, (prefix + '[' + noOfPolygons + '][0]')); + } + html += '+ Add a point
'; + + '+ Add an inner ring

'; + + $a.before(html); + $noOfPolygonsInput.attr('value', noOfPolygons + 1); + }); + + /** + * Handles adding geoms + */ + $('.addJs.geom').live('click', function() { + var $a = $(this); + var prefix = 'gis_data[GEOMETRYCOLLECTION]'; + // Find the number of geoms + var $noOfGeomsInput = $("input[name='" + prefix + "[geom_count]" + "']"); + var noOfGeoms = parseInt($noOfGeomsInput.attr('value')); + + var html1 = 'Geometry' + (noOfGeoms + 1) + ':
'; + var $geomType = $("select[name='gis_data[" + (noOfGeoms - 1) + "][gis_type]']").clone(); + $geomType.attr('name', 'gis_data[' + noOfGeoms + '][gis_type]').val('POINT'); + var html2 = '
' + 'Point' + ' :' + + '' + + '' + + '' + + '' + + '

'; + + $a.before(html1); $geomType.insertBefore($a); $a.before(html2); + $noOfGeomsInput.attr('value', noOfGeoms + 1); + }); + // these were hidden via the "hide" class $('.foreign_values_anchor').show(); From 7af88c04c75641fc3aba7e26935c0ef8f9e2dcbe Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sat, 16 Jul 2011 11:05:53 +0530 Subject: [PATCH 36/98] Cleanup spaces --- js/tbl_change.js | 72 ++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/js/tbl_change.js b/js/tbl_change.js index dab6de5d33..fd8916b0be 100644 --- a/js/tbl_change.js +++ b/js/tbl_change.js @@ -227,21 +227,21 @@ function closeGISEditor(){ function prepareJSVersion() { // Hide 'Go' buttons associated with the dropdowns $('.go').hide(); - + // Change the text on the submit button $("input[name='gis_data[save]']") .attr('value', PMA_messages['strCopy']) .insertAfter($('#gis_data_textarea')) .before('

'); - + // Add close and cancel links $('#gis_data_editor').prepend('' + PMA_messages['strClose'] + ''); $(' ' + PMA_messages['strCancel'] + '') .insertAfter($("input[name='gis_data[save]']")); - + // Remove the unnecessary text $('div#gis_data_output p').remove(); - + // Remove 'add' buttons and add links $('.add').each(function(e) { var $button = $(this); @@ -279,9 +279,9 @@ function addDataPoint(pointNumber, prefix) { */ $(document).ready(function() { - $('.open_gis_editor').live('click', function(event) { + $('.open_gis_editor').live('click', function(event) { event.preventDefault(); - + // Center the popup var $span = $(this); var windowWidth = document.documentElement.clientWidth; @@ -300,10 +300,10 @@ $(document).ready(function() { // Names of input field and null checkbox var input_name = $span.parents('tr').children('td:nth-child(5)').find('input:nth-child(3)').attr('name'); var null_checkbox_name = $span.parents('tr').children('td:nth-child(4)').find('.checkbox_null').attr('name'); - + $.post('gis_data_editor.php', { - 'field' : field, - 'value' : value, + 'field' : field, + 'value' : value, 'input_name' : input_name, 'null_checkbox_name' : null_checkbox_name, 'get_gis_editor' : true, @@ -316,24 +316,24 @@ $(document).ready(function() { PMA_ajaxShowMessage(data.error); } }) - + // Make it appear $("#popup_background").css({"opacity":"0.7"}); $("#popup_background").fadeIn("fast"); $gis_editor.fadeIn("fast"); }) - + /** * Prepare and insert the GIS data in Well Known Text format * to the input field. */ $("input[name='gis_data[save]']").live('click', function(event) { - event.preventDefault(); - + event.preventDefault(); + var $form = $('form#gis_data_editor_form'); var input_name = $form.find("input[name='input_name']").val(); var null_checkbox_name = $form.find("input[name='null_checkbox_name']").val(); - + $.post('gis_data_editor.php', $form.serialize() + "&generate=true", function(data) { if(data.success == true) { $("input[name='" + null_checkbox_name + "']").attr('checked', false); @@ -342,9 +342,9 @@ $(document).ready(function() { PMA_ajaxShowMessage(data.error); } }); - closeGISEditor(); + closeGISEditor(); }); - + /** * Trigger asynchronous calls on data change and update the output. */ @@ -358,14 +358,14 @@ $(document).ready(function() { } }); }); - + /** * Update the form on change of the GIS type. */ $(".gis_type").live('change', function(event) { var $gis_editor = $("#gis_editor"); var $form = $('form#gis_data_editor_form'); - + $.post('gis_data_editor.php', $form.serialize() + "&get_gis_editor=true", function(data) { if(data.success == true) { $gis_editor.html(data.gis_editor); @@ -375,14 +375,14 @@ $(document).ready(function() { } }); }); - + /** * Handles closing of the GIS data editor. */ $('.close_gis_editor, .cancel_gis_editor').live('click', function() { closeGISEditor(); }) - + /** * Handles adding data points */ @@ -399,7 +399,7 @@ $(document).ready(function() { $a.before(html); $noOfPointsInput.attr('value', noOfPoints + 1); }); - + /** * Handles adding linestrings and inner rings */ @@ -429,7 +429,7 @@ $(document).ready(function() { html += addDataPoint(i, (prefix + '[' + noOfLines + ']')); } html += '+ Add a point
'; - + $a.before(html); $noOfLinesInput.attr('value', noOfLines + 1); }); @@ -490,23 +490,23 @@ $(document).ready(function() { /** * Handles all current checkboxes for Null; this only takes care of the - * checkboxes on currently displayed rows as the rows generated by - * "Continue insertion" are handled in the "Continue insertion" code - * + * checkboxes on currently displayed rows as the rows generated by + * "Continue insertion" are handled in the "Continue insertion" code + * */ $('.checkbox_null').bind('click', function(e) { nullify( // use hidden fields populated by tbl_change.php $(this).siblings('.nullify_code').val(), - $(this).closest('tr').find('input:hidden').first().val(), + $(this).closest('tr').find('input:hidden').first().val(), $(this).siblings('.hashed_field').val(), $(this).siblings('.multi_edit').val() ); }); /** - * Submission of data to be inserted or updated - * + * Submission of data to be inserted or updated + * * @uses PMA_ajaxShowMessage() * * This section has been deactivated. Here are the problems that I've @@ -521,9 +521,9 @@ $(document).ready(function() { * 2. This code can be called if we are editing or inserting. If editing, * the "and then" action can be "go back to this page" or "edit next * row", in which cases it makes sense to use AJAX. But the "go back - * to previous page" and "insert another new row" actions, using AJAX + * to previous page" and "insert another new row" actions, using AJAX * has no obvious advantage. If inserting, the "go back to previous" - * action needs a page refresh anyway. + * action needs a page refresh anyway. */ $("#insertFormDEACTIVATED").live('submit', function(event) { @@ -652,8 +652,8 @@ $(document).ready(function() { .bind('change', function(e) { var $changed_element = $(this); verificationsAfterFieldChange( - $changed_element.data('hashed_field'), - $changed_element.data('new_row_index'), + $changed_element.data('hashed_field'), + $changed_element.data('new_row_index'), $changed_element.closest('tr').find('span.column_type').html() ); }); @@ -665,15 +665,15 @@ $(document).ready(function() { // to the original row, not the cloned one, so unbind() .unbind('click') // Keep these values to be used when the element - // will be clicked + // will be clicked .data('hashed_field', hashed_field) .data('new_row_index', new_row_index) .bind('click', function(e) { var $changed_element = $(this); nullify( $changed_element.siblings('.nullify_code').val(), - $this_element.closest('tr').find('input:hidden').first().val(), - $changed_element.data('hashed_field'), + $this_element.closest('tr').find('input:hidden').first().val(), + $changed_element.data('hashed_field'), '[multi_edit][' + $changed_element.data('new_row_index') + ']' ); }); @@ -725,7 +725,7 @@ $(document).ready(function() { // IMO it's not really important to handle the tabindex for // function and Null var tabindex = 0; - $('.textfield') + $('.textfield') .each(function() { tabindex++; $(this).attr('tabindex', tabindex); From ba93a625b9de49fc10c1d65a880768258497459c Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sat, 16 Jul 2011 13:14:29 +0530 Subject: [PATCH 37/98] Make JS messages translatable. --- js/messages.php | 13 ++++++++++++- js/tbl_change.js | 31 +++++++++++++++++-------------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/js/messages.php b/js/messages.php index e433384bef..b2c987123a 100644 --- a/js/messages.php +++ b/js/messages.php @@ -142,7 +142,18 @@ $js_messages['strShowSearchCriteria'] = __('Show search criteria'); /* For tbl_change.js */ $js_messages['strIgnore'] = __('Ignore'); -$js_messages['strCopy']= __('Copy'); +$js_messages['strCopy'] = __('Copy'); +$js_messages['strX'] = __('X'); +$js_messages['strY'] = __('Y'); +$js_messages['strPoint'] = __('Point'); +$js_messages['strLineString'] = __('Linestring'); +$js_messages['strPolygon'] = __('Polygon'); +$js_messages['strGeometry'] = __('Geometry'); +$js_messages['strInnerRing'] = __('Inner Ring'); +$js_messages['strOuterRing'] = __('Outer Ring'); +$js_messages['strAddPoint'] = __('Add a point'); +$js_messages['strAddInnerRing'] = __('Add an inner ring'); +$js_messages['strAddPolygon'] = __('Add a polygon'); /* Designer (pmd/scripts/move.js) */ $js_messages['strSelectReferencedKey'] = __('Select referenced key'); diff --git a/js/tbl_change.js b/js/tbl_change.js index fd8916b0be..8a517bd029 100644 --- a/js/tbl_change.js +++ b/js/tbl_change.js @@ -262,10 +262,10 @@ function prepareJSVersion() { * @returns the HTML for a data point */ function addDataPoint(pointNumber, prefix) { - return '
Point' + (pointNumber + 1) + ':' - + '' + return '
' + $js_messages['strPoint'] + (pointNumber + 1) + ':' + + '' + '' - + '' + + '' + ''; } @@ -418,17 +418,18 @@ $(document).ready(function() { // Add the new linesting of inner ring based on the type var html = '
'; if (type == 'MULTILINESTRING') { - html += 'Linestring' + (noOfLines + 1) + ':'; + html += $js_messages['strLineString'] + (noOfLines + 1) + ':'; var noOfPoints = 2; } else { - html += 'Inner Ring' + noOfLines + ':'; + html += $js_messages['strInnerRing'] + noOfLines + ':'; var noOfPoints = 4; } html += ''; for (i = 0; i < noOfPoints; i++) { html += addDataPoint(i, (prefix + '[' + noOfLines + ']')); } - html += '+ Add a point
'; + html += '+ ' + + $js_messages['strAddPoint'] + '
'; $a.before(html); $noOfLinesInput.attr('value', noOfLines + 1); @@ -447,15 +448,17 @@ $(document).ready(function() { var noOfPolygons = parseInt($noOfPolygonsInput.attr('value')); // Add the new polygon - var html = 'Polygon' + (noOfPolygons + 1) + ':
'; + var html = $js_messages['strPolygon'] + (noOfPolygons + 1) + ':
'; html += ''; - + '
' + 'Outer Ring' + ':'; + + '
' + $js_messages['strOuterRing'] + ':'; + ''; for (i = 0; i < 4; i++) { html += addDataPoint(i, (prefix + '[' + noOfPolygons + '][0]')); } - html += '+ Add a point
'; - + '+ Add an inner ring

'; + html += '+ ' + + $js_messages['strAddPoint'] + '
'; + + '+ ' + + $js_messages['strAddInnerRing'] + '

'; $a.before(html); $noOfPolygonsInput.attr('value', noOfPolygons + 1); @@ -471,13 +474,13 @@ $(document).ready(function() { var $noOfGeomsInput = $("input[name='" + prefix + "[geom_count]" + "']"); var noOfGeoms = parseInt($noOfGeomsInput.attr('value')); - var html1 = 'Geometry' + (noOfGeoms + 1) + ':
'; + var html1 = $js_messages['strGeometry'] + (noOfGeoms + 1) + ':
'; var $geomType = $("select[name='gis_data[" + (noOfGeoms - 1) + "][gis_type]']").clone(); $geomType.attr('name', 'gis_data[' + noOfGeoms + '][gis_type]').val('POINT'); - var html2 = '
' + 'Point' + ' :' - + '' + var html2 = '
' + $js_messages['strPoint'] + ' :' + + '' + '' - + '' + + '' + '' + '

'; From 1b9ddd2efa71971ef1b78356cc878af437cdf5dd Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sat, 16 Jul 2011 13:23:11 +0530 Subject: [PATCH 38/98] These should be PMA_messages[] --- js/tbl_change.js | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/js/tbl_change.js b/js/tbl_change.js index 8a517bd029..737859db35 100644 --- a/js/tbl_change.js +++ b/js/tbl_change.js @@ -262,10 +262,10 @@ function prepareJSVersion() { * @returns the HTML for a data point */ function addDataPoint(pointNumber, prefix) { - return '
' + $js_messages['strPoint'] + (pointNumber + 1) + ':' - + '' + return '
' + PMA_messages['strPoint'] + (pointNumber + 1) + ':' + + '' + '' - + '' + + '' + ''; } @@ -418,10 +418,10 @@ $(document).ready(function() { // Add the new linesting of inner ring based on the type var html = '
'; if (type == 'MULTILINESTRING') { - html += $js_messages['strLineString'] + (noOfLines + 1) + ':'; + html += PMA_messages['strLineString'] + (noOfLines + 1) + ':'; var noOfPoints = 2; } else { - html += $js_messages['strInnerRing'] + noOfLines + ':'; + html += PMA_messages['strInnerRing'] + noOfLines + ':'; var noOfPoints = 4; } html += ''; @@ -429,7 +429,7 @@ $(document).ready(function() { html += addDataPoint(i, (prefix + '[' + noOfLines + ']')); } html += '+ ' - + $js_messages['strAddPoint'] + '
'; + + PMA_messages['strAddPoint'] + '
'; $a.before(html); $noOfLinesInput.attr('value', noOfLines + 1); @@ -448,17 +448,17 @@ $(document).ready(function() { var noOfPolygons = parseInt($noOfPolygonsInput.attr('value')); // Add the new polygon - var html = $js_messages['strPolygon'] + (noOfPolygons + 1) + ':
'; + var html = PMA_messages['strPolygon'] + (noOfPolygons + 1) + ':
'; html += ''; - + '
' + $js_messages['strOuterRing'] + ':'; + + '
' + PMA_messages['strOuterRing'] + ':'; + ''; for (i = 0; i < 4; i++) { html += addDataPoint(i, (prefix + '[' + noOfPolygons + '][0]')); } html += '+ ' - + $js_messages['strAddPoint'] + '
'; + + PMA_messages['strAddPoint'] + '
'; + '+ ' - + $js_messages['strAddInnerRing'] + '

'; + + PMA_messages['strAddInnerRing'] + '

'; $a.before(html); $noOfPolygonsInput.attr('value', noOfPolygons + 1); @@ -474,13 +474,13 @@ $(document).ready(function() { var $noOfGeomsInput = $("input[name='" + prefix + "[geom_count]" + "']"); var noOfGeoms = parseInt($noOfGeomsInput.attr('value')); - var html1 = $js_messages['strGeometry'] + (noOfGeoms + 1) + ':
'; + var html1 = PMA_messages['strGeometry'] + (noOfGeoms + 1) + ':
'; var $geomType = $("select[name='gis_data[" + (noOfGeoms - 1) + "][gis_type]']").clone(); $geomType.attr('name', 'gis_data[' + noOfGeoms + '][gis_type]').val('POINT'); - var html2 = '
' + $js_messages['strPoint'] + ' :' - + '' + var html2 = '
' + PMA_messages['strPoint'] + ' :' + + '' + '' - + '' + + '' + '' + '

'; From d85c777c78a854d56d39cb6420624e22eedc6586 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sat, 16 Jul 2011 14:17:17 +0530 Subject: [PATCH 39/98] Chose the correct GIS type --- gis_data_editor.php | 4 +++- js/tbl_change.js | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/gis_data_editor.php b/gis_data_editor.php index 9d2b112b47..f93e7f4112 100644 --- a/gis_data_editor.php +++ b/gis_data_editor.php @@ -25,7 +25,9 @@ $gis_types = array( $no_visual = true; if (! isset($gis_data['gis_type'])) { - if (isset($_REQUEST['value'])) { + if (isset($_REQUEST['type']) && $_REQUEST['type'] != '') { + $gis_data['gis_type'] = strtoupper($_REQUEST['type']); + } elseif (isset($_REQUEST['value'])) { $gis_data['gis_type'] = substr($_REQUEST['value'], 1, strpos($_REQUEST['value'], "(") - 1); } if(! in_array($gis_data['gis_type'], $gis_types)) { diff --git a/js/tbl_change.js b/js/tbl_change.js index 737859db35..2abcf06ad4 100644 --- a/js/tbl_change.js +++ b/js/tbl_change.js @@ -297,13 +297,16 @@ $(document).ready(function() { var value = $span.parent('td').children("input[type='text']").val(); // Field name var field = $span.parents('tr').children('td:first').find("input[type='hidden']").val(); + // Column type + var type = $span.parents('tr').find('span.column_type').text(); // Names of input field and null checkbox - var input_name = $span.parents('tr').children('td:nth-child(5)').find('input:nth-child(3)').attr('name'); - var null_checkbox_name = $span.parents('tr').children('td:nth-child(4)').find('.checkbox_null').attr('name'); + var input_name = $span.parent('td').children("input[type='text']").attr('name'); + var null_checkbox_name = $span.parents('tr').find('.checkbox_null').attr('name'); $.post('gis_data_editor.php', { 'field' : field, 'value' : value, + 'type' : type, 'input_name' : input_name, 'null_checkbox_name' : null_checkbox_name, 'get_gis_editor' : true, From 5a6379f93e97a4535a3a78b56ddc6a5cbe3901e8 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sun, 17 Jul 2011 16:59:25 +0530 Subject: [PATCH 40/98] SVG based data visualization for GIS data editor --- gis_data_editor.php | 70 ++++++++++++++++++------- js/tbl_change.js | 22 +++++++- js/tbl_gis_visualization.js | 66 +++++++++++++---------- libraries/gis/pma_gis_visualization.php | 3 +- tbl_change.php | 4 ++ themes/original/css/theme_right.css.php | 13 +++++ themes/pmahomme/css/theme_right.css.php | 13 +++++ 7 files changed, 138 insertions(+), 53 deletions(-) diff --git a/gis_data_editor.php b/gis_data_editor.php index f93e7f4112..80928f96e2 100644 --- a/gis_data_editor.php +++ b/gis_data_editor.php @@ -23,39 +23,39 @@ $gis_types = array( 'GEOMETRYCOLLECTION' ); -$no_visual = true; +// Extract type from the initial call and make sure that it's a valid one. +// Extract from field's values if availbale, if not use the column type passed. if (! isset($gis_data['gis_type'])) { if (isset($_REQUEST['type']) && $_REQUEST['type'] != '') { $gis_data['gis_type'] = strtoupper($_REQUEST['type']); - } elseif (isset($_REQUEST['value'])) { + } + if (isset($_REQUEST['value'])) { $gis_data['gis_type'] = substr($_REQUEST['value'], 1, strpos($_REQUEST['value'], "(") - 1); } if(! in_array($gis_data['gis_type'], $gis_types)) { $gis_data['gis_type'] = $gis_types[0]; - $no_visual = true; } } $geom_type = $gis_data['gis_type']; +// Generate parameters from value passed. $gis_obj = PMA_GIS_Factory::factory($geom_type); if (isset($_REQUEST['value'])) { $gis_data = array_merge($gis_data, $gis_obj->generateParams($_REQUEST['value'])); } -$srid = isset($gis_data['srid']) ? htmlspecialchars($gis_data['srid']) : ''; +// Generate Well Known Text +$srid = (isset($gis_data['srid']) && $gis_data['srid'] != '') ? htmlspecialchars($gis_data['srid']) : 0; $wkt = $gis_obj->generateWkt($gis_data, 0); +$result = "'" . $wkt . "'," . $srid; -$format = (PMA_USR_BROWSER_AGENT == 'IE' && PMA_USR_BROWSER_VER <= 8) ? 'svg' : 'png'; -$visualizationSettings = array('width' => 400, 'height' => 400,); -$data = array($wkt); -if (! $no_visual) { - $visualization = PMA_GIS_visualization_results($data, $visualizationSettings, $format); -} +// Gererate PNG or SVG based visualization +$format = (PMA_USR_BROWSER_AGENT == 'IE' && PMA_USR_BROWSER_VER <= 8) ? 'png' : 'svg'; +$visualizationSettings = array('width' => 450, 'height' => 300, 'spatialColumn' => 'wkt'); +$data = array(array('wkt' => $wkt, 'srid' => $srid)); +$visualization = PMA_GIS_visualization_results($data, $visualizationSettings, $format); -$result = "'" . $wkt . "'"; -if ($srid != '') { - $result .= ',' . $srid; -} +// If the call is to update the WKT and visualization make an AJAX response if(isset($_REQUEST['generate']) && $_REQUEST['generate'] == true) { $extra_data = array( 'result' => $result, @@ -64,6 +64,7 @@ if(isset($_REQUEST['generate']) && $_REQUEST['generate'] == true) { PMA_ajaxResponse(null, true, $extra_data); } +// If the call is to get the whole content, start buffering, skipping and tags if(isset($_REQUEST['get_gis_editor']) && $_REQUEST['get_gis_editor'] == true) { ob_start(); } else { @@ -74,9 +75,12 @@ if(isset($_REQUEST['get_gis_editor']) && $_REQUEST['get_gis_editor'] == true) { } ?> +

+ '); + // The input field to which the final result should be added and corresponding null checkbox if (isset($_REQUEST['input_name'])) { echo(''); } @@ -85,9 +89,31 @@ if(isset($_REQUEST['get_gis_editor']) && $_REQUEST['get_gis_editor'] == true) { } echo PMA_generate_common_hidden_inputs(); ?> -
- + +
+
+
+
+ /> + +
+ + +
+ + +
-

" /> -
+?>
+ +

@@ -285,6 +314,7 @@ if(isset($_REQUEST['get_gis_editor']) && $_REQUEST['get_gis_editor'] == true) { 0) { var pmaThemeImage = $('#pmaThemeImage').attr('value'); @@ -113,6 +93,34 @@ $(document).ready(function() { $('').appendTo($placeholder); } + $('.choice').show(); +} + +/** + * Ajax handlers for GIS visualization page + * + * Actions Ajaxified here: + * + * Zooming in and zooming out on mousewheel movement. + * Panning the visualization on dragging. + * Zooming in on double clicking. + * Zooming out on clicking the zoom out button. + * Panning on clicking the arrow buttons. + * Displaying tooltips for GIS objects. + */ +$(document).ready(function() { + initVisualization(); + + $('#choice').live('click', function() { + if ($(this).prop('checked') == false) { + $('#placeholder').show(); + $('#openlayersmap').hide(); + } else { + $('#placeholder').hide(); + $('#openlayersmap').show(); + } + }); + $('#placeholder').live('mousewheel', function(event, delta) { if (delta > 0) { //zoom in @@ -134,13 +142,13 @@ $(document).ready(function() { var dragX = 0; var dragY = 0; $('svg').live('dragstart', function(event, dd) { - $placeholder.addClass('placeholderDrag'); + $('#placeholder').addClass('placeholderDrag'); dragX = Math.round(dd.offsetX); dragY = Math.round(dd.offsetY); }); $('svg').live('mouseup', function(event) { - $placeholder.removeClass('placeholderDrag'); + $('#placeholder').removeClass('placeholderDrag'); }); $('svg').live('drag', function(event, dd) { diff --git a/libraries/gis/pma_gis_visualization.php b/libraries/gis/pma_gis_visualization.php index 31a20bbed7..0df2a43487 100644 --- a/libraries/gis/pma_gis_visualization.php +++ b/libraries/gis/pma_gis_visualization.php @@ -431,5 +431,4 @@ class PMA_GIS_Visualization return $results; } } -?> - +?> \ No newline at end of file diff --git a/tbl_change.php b/tbl_change.php index d520737135..cdb9c2f73a 100644 --- a/tbl_change.php +++ b/tbl_change.php @@ -116,6 +116,10 @@ if ($GLOBALS['cfg']['ShowPropertyComments']) { */ $GLOBALS['js_include'][] = 'functions.js'; $GLOBALS['js_include'][] = 'tbl_change.js'; +$GLOBALS['js_include'][] = 'jquery/jquery.svg.js'; +$GLOBALS['js_include'][] = 'jquery/jquery.mousewheel.js'; +$GLOBALS['js_include'][] = 'jquery/jquery.event.drag-2.0.min.js'; +$GLOBALS['js_include'][] = 'tbl_gis_visualization.js'; $GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js'; $GLOBALS['js_include'][] = 'jquery/timepicker.js'; /** diff --git a/themes/original/css/theme_right.css.php b/themes/original/css/theme_right.css.php index dbad0c740a..de07493169 100644 --- a/themes/original/css/theme_right.css.php +++ b/themes/original/css/theme_right.css.php @@ -1569,6 +1569,10 @@ a.close_gis_editor { overflow-x: hidden; } +#gis_data { + min-height: 230px; +} + #gis_data_textarea { height: 6em; } @@ -1576,6 +1580,15 @@ a.close_gis_editor { #gis_data_editor { background: #D0DCE0; padding: 15px; + min-height: 500px; +} + +#gis_data_editor .choice { + display: none; +} + +#gis_data_editor input[type="text"] { + width: 75px; } /** diff --git a/themes/pmahomme/css/theme_right.css.php b/themes/pmahomme/css/theme_right.css.php index 3114904f46..c72cdf5003 100644 --- a/themes/pmahomme/css/theme_right.css.php +++ b/themes/pmahomme/css/theme_right.css.php @@ -1913,6 +1913,10 @@ a.close_gis_editor { overflow-x: hidden; } +#gis_data { + min-height: 230px; +} + #gis_data_textarea { height: 6em; } @@ -1920,6 +1924,15 @@ a.close_gis_editor { #gis_data_editor { background: #D0DCE0; padding: 15px; + min-height: 500px; +} + +#gis_data_editor .choice { + display: none; +} + +#gis_data_editor input[type="text"] { + width: 75px; } /** From 2a402a3103c5a12e6c9d2fd2515d7695da2942ff Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Mon, 18 Jul 2011 13:43:46 +0530 Subject: [PATCH 41/98] OpenStreetMaps based data visualization for GIS data editor --- gis_data_editor.php | 8 +++++- js/tbl_change.js | 22 ++++----------- js/tbl_gis_visualization.js | 4 ++- libraries/gis/pma_gis_geometrycollection.php | 9 +++--- libraries/gis/pma_gis_linestring.php | 17 +++++++----- libraries/gis/pma_gis_multilinestring.php | 13 +++++---- libraries/gis/pma_gis_multipoint.php | 17 +++++++----- libraries/gis/pma_gis_multipolygon.php | 17 +++++++----- libraries/gis/pma_gis_point.php | 18 +++++++----- libraries/gis/pma_gis_polygon.php | 17 +++++++----- libraries/gis/pma_gis_visualization.php | 28 ++++++++++++++++++- tbl_change.php | 8 +++++- tbl_gis_visualization.php | 29 -------------------- 13 files changed, 114 insertions(+), 93 deletions(-) diff --git a/gis_data_editor.php b/gis_data_editor.php index 80928f96e2..6b35fc6018 100644 --- a/gis_data_editor.php +++ b/gis_data_editor.php @@ -47,19 +47,22 @@ if (isset($_REQUEST['value'])) { // Generate Well Known Text $srid = (isset($gis_data['srid']) && $gis_data['srid'] != '') ? htmlspecialchars($gis_data['srid']) : 0; $wkt = $gis_obj->generateWkt($gis_data, 0); +$wkt_with_zero = $gis_obj->generateWkt($gis_data, 0, '0'); $result = "'" . $wkt . "'," . $srid; // Gererate PNG or SVG based visualization $format = (PMA_USR_BROWSER_AGENT == 'IE' && PMA_USR_BROWSER_VER <= 8) ? 'png' : 'svg'; $visualizationSettings = array('width' => 450, 'height' => 300, 'spatialColumn' => 'wkt'); -$data = array(array('wkt' => $wkt, 'srid' => $srid)); +$data = array(array('wkt' => $wkt_with_zero, 'srid' => $srid)); $visualization = PMA_GIS_visualization_results($data, $visualizationSettings, $format); +$open_layers = PMA_GIS_visualization_results($data, $visualizationSettings, 'ol'); // If the call is to update the WKT and visualization make an AJAX response if(isset($_REQUEST['generate']) && $_REQUEST['generate'] == true) { $extra_data = array( 'result' => $result, 'visualization' => $visualization, + 'openLayers' => $open_layers, ); PMA_ajaxResponse(null, true, $extra_data); } @@ -111,6 +114,9 @@ if(isset($_REQUEST['get_gis_editor']) && $_REQUEST['get_gis_editor'] == true) { ?> />
+ diff --git a/js/tbl_change.js b/js/tbl_change.js index 8d9963a7c2..183e309212 100644 --- a/js/tbl_change.js +++ b/js/tbl_change.js @@ -314,9 +314,6 @@ $(document).ready(function() { 'get_gis_editor' : true, 'token' : token }, function(data) { - if (! $.isPlainObject(data)) { - data = $.parseJSON(data); - } if(data.success == true) { $gis_editor.html(data.gis_editor); initVisualization(); @@ -324,7 +321,7 @@ $(document).ready(function() { } else { PMA_ajaxShowMessage(data.error); } - }) + }, 'json') // Make it appear $("#popup_background").css({"opacity":"0.7"}); @@ -344,16 +341,13 @@ $(document).ready(function() { var null_checkbox_name = $form.find("input[name='null_checkbox_name']").val(); $.post('gis_data_editor.php', $form.serialize() + "&generate=true", function(data) { - if (! $.isPlainObject(data)) { - data = $.parseJSON(data); - } if(data.success == true) { $("input[name='" + null_checkbox_name + "']").attr('checked', false); $("input[name='" + input_name + "']").val(data.result); } else { PMA_ajaxShowMessage(data.error); } - }); + }, 'json'); closeGISEditor(); }); @@ -363,17 +357,16 @@ $(document).ready(function() { $('#gis_editor').find("input[type='text']").live('change', function() { var $form = $('form#gis_data_editor_form'); $.post('gis_data_editor.php', $form.serialize() + "&generate=true", function(data) { - if (! $.isPlainObject(data)) { - data = $.parseJSON(data); - } if(data.success == true) { $('#gis_data_textarea').val(data.result); $('#placeholder').empty().removeClass('hasSVG').html(data.visualization); + $('#openlayersmap').empty(); + eval(data.openLayers); initVisualization(); } else { PMA_ajaxShowMessage(data.error); } - }); + }, 'json'); }); /** @@ -384,9 +377,6 @@ $(document).ready(function() { var $form = $('form#gis_data_editor_form'); $.post('gis_data_editor.php', $form.serialize() + "&get_gis_editor=true", function(data) { - if (! $.isPlainObject(data)) { - data = $.parseJSON(data); - } if(data.success == true) { $gis_editor.html(data.gis_editor); initVisualization(); @@ -394,7 +384,7 @@ $(document).ready(function() { } else { PMA_ajaxShowMessage(data.error); } - }); + }, 'json'); }); /** diff --git a/js/tbl_gis_visualization.js b/js/tbl_gis_visualization.js index 0135f30043..6cde8fe474 100644 --- a/js/tbl_gis_visualization.js +++ b/js/tbl_gis_visualization.js @@ -69,7 +69,9 @@ function initVisualization() { 'float' : 'right' }; $openlayersmap.css(cssObj); - drawOpenLayers(); + if (typeof drawOpenLayers == 'function') { + drawOpenLayers(); + } $placeholder.svg({ onLoad: function(svg_ref) { diff --git a/libraries/gis/pma_gis_geometrycollection.php b/libraries/gis/pma_gis_geometrycollection.php index dd4621dad0..331692dd9b 100644 --- a/libraries/gis/pma_gis_geometrycollection.php +++ b/libraries/gis/pma_gis_geometrycollection.php @@ -240,12 +240,13 @@ class PMA_GIS_Geometrycollection extends PMA_GIS_Geometry /** * Generate the WKT with the set of parameters passed by the GIS editor. * - * @param array $gis_data GIS data - * @param int $index Index into the parameter object + * @param array $gis_data GIS data + * @param int $index Index into the parameter object + * @param string $empty Value for empty points * * @return WKT with the set of parameters passed by the GIS editor */ - public function generateWkt($gis_data, $index) + public function generateWkt($gis_data, $index, $empty = '') { $geom_count = (isset($gis_data['GEOMETRYCOLLECTION']['geom_count'])) ? $gis_data['GEOMETRYCOLLECTION']['geom_count'] : 1; @@ -257,7 +258,7 @@ class PMA_GIS_Geometrycollection extends PMA_GIS_Geometry if (! $gis_obj) { continue; } - $wkt .= $gis_obj->generateWkt($gis_data, $i) . ','; + $wkt .= $gis_obj->generateWkt($gis_data, $i, $empty) . ','; } } if (isset($gis_data[0]['gis_type'])) { diff --git a/libraries/gis/pma_gis_linestring.php b/libraries/gis/pma_gis_linestring.php index 8114451ae0..152aa7b420 100644 --- a/libraries/gis/pma_gis_linestring.php +++ b/libraries/gis/pma_gis_linestring.php @@ -198,12 +198,13 @@ class PMA_GIS_Linestring extends PMA_GIS_Geometry /** * Generate the WKT with the set of parameters passed by the GIS editor. * - * @param array $gis_data GIS data - * @param int $index Index into the parameter object + * @param array $gis_data GIS data + * @param int $index Index into the parameter object + * @param string $empty Value for empty points * * @return WKT with the set of parameters passed by the GIS editor */ - public function generateWkt($gis_data, $index) + public function generateWkt($gis_data, $index, $empty = '') { $no_of_points = isset($gis_data[$index]['LINESTRING']['no_of_points']) ? $gis_data[$index]['LINESTRING']['no_of_points'] : 2; @@ -212,10 +213,12 @@ class PMA_GIS_Linestring extends PMA_GIS_Geometry } $wkt = 'LINESTRING('; for ($i = 0; $i < $no_of_points; $i++) { - $wkt .= (isset($gis_data[$index]['LINESTRING'][$i]['x']) - ? $gis_data[$index]['LINESTRING'][$i]['x'] : '') - . ' ' . (isset($gis_data[$index]['LINESTRING'][$i]['y']) - ? $gis_data[$index]['LINESTRING'][$i]['y'] : '') .','; + $wkt .= ((isset($gis_data[$index]['LINESTRING'][$i]['x']) + && trim($gis_data[$index]['LINESTRING'][$i]['x']) != '') + ? $gis_data[$index]['LINESTRING'][$i]['x'] : $empty) + . ' ' . ((isset($gis_data[$index]['LINESTRING'][$i]['y']) + && trim($gis_data[$index]['LINESTRING'][$i]['y']) != '') + ? $gis_data[$index]['LINESTRING'][$i]['y'] : $empty) .','; } $wkt = substr($wkt, 0, strlen($wkt) - 1); $wkt .= ')'; diff --git a/libraries/gis/pma_gis_multilinestring.php b/libraries/gis/pma_gis_multilinestring.php index 0ac845244a..098f442c10 100644 --- a/libraries/gis/pma_gis_multilinestring.php +++ b/libraries/gis/pma_gis_multilinestring.php @@ -229,10 +229,11 @@ class PMA_GIS_Multilinestring extends PMA_GIS_Geometry * * @param array $gis_data GIS data * @param int $index Index into the parameter object + * @param string $empty Value for empty points * * @return WKT with the set of parameters passed by the GIS editor */ - public function generateWkt($gis_data, $index) + public function generateWkt($gis_data, $index, $empty = '') { $no_of_lines = isset($gis_data[$index]['MULTILINESTRING']['no_of_lines']) ? $gis_data[$index]['MULTILINESTRING']['no_of_lines'] : 1; @@ -248,10 +249,12 @@ class PMA_GIS_Multilinestring extends PMA_GIS_Geometry } $wkt .= '('; for ($j = 0; $j < $no_of_points; $j++) { - $wkt .= (isset($gis_data[$index]['MULTILINESTRING'][$i][$j]['x']) - ? $gis_data[$index]['MULTILINESTRING'][$i][$j]['x'] : '') - . ' ' . (isset($gis_data[$index]['MULTILINESTRING'][$i][$j]['y']) - ? $gis_data[$index]['MULTILINESTRING'][$i][$j]['y'] : '') . ','; + $wkt .= ((isset($gis_data[$index]['MULTILINESTRING'][$i][$j]['x']) + && trim($gis_data[$index]['MULTILINESTRING'][$i][$j]['x']) != '') + ? $gis_data[$index]['MULTILINESTRING'][$i][$j]['x'] : $empty) + . ' ' . ((isset($gis_data[$index]['MULTILINESTRING'][$i][$j]['y']) + && trim($gis_data[$index]['MULTILINESTRING'][$i][$j]['y']) != '') + ? $gis_data[$index]['MULTILINESTRING'][$i][$j]['y'] : $empty) . ','; } $wkt = substr($wkt, 0, strlen($wkt) - 1); $wkt .= '),'; diff --git a/libraries/gis/pma_gis_multipoint.php b/libraries/gis/pma_gis_multipoint.php index 086c2c7cd3..7d14c1e625 100644 --- a/libraries/gis/pma_gis_multipoint.php +++ b/libraries/gis/pma_gis_multipoint.php @@ -190,12 +190,13 @@ class PMA_GIS_Multipoint extends PMA_GIS_Geometry /** * Generate the WKT with the set of parameters passed by the GIS editor. * - * @param array $gis_data GIS data - * @param int $index Index into the parameter object + * @param array $gis_data GIS data + * @param int $index Index into the parameter object + * @param string $empty Value for empty points * * @return WKT with the set of parameters passed by the GIS editor */ - public function generateWkt($gis_data, $index) + public function generateWkt($gis_data, $index, $empty = '') { $no_of_points = isset($gis_data[$index]['MULTIPOINT']['no_of_points']) ? $gis_data[$index]['MULTIPOINT']['no_of_points'] : 1; @@ -204,10 +205,12 @@ class PMA_GIS_Multipoint extends PMA_GIS_Geometry } $wkt = 'MULTIPOINT('; for ($i = 0; $i < $no_of_points; $i++) { - $wkt .= (isset($gis_data[$index]['MULTIPOINT'][$i]['x']) - ? $gis_data[$index]['MULTIPOINT'][$i]['x'] : '') - . ' ' . (isset($gis_data[$index]['MULTIPOINT'][$i]['y']) - ? $gis_data[$index]['MULTIPOINT'][$i]['y'] : '') . ','; + $wkt .= ((isset($gis_data[$index]['MULTIPOINT'][$i]['x']) + && trim($gis_data[$index]['MULTIPOINT'][$i]['x']) != '') + ? $gis_data[$index]['MULTIPOINT'][$i]['x'] : $empty) + . ' ' . ((isset($gis_data[$index]['MULTIPOINT'][$i]['y']) + && trim($gis_data[$index]['MULTIPOINT'][$i]['y']) != '') + ? $gis_data[$index]['MULTIPOINT'][$i]['y'] : $empty) . ','; } $wkt = substr($wkt, 0, strlen($wkt) - 1); $wkt .= ')'; diff --git a/libraries/gis/pma_gis_multipolygon.php b/libraries/gis/pma_gis_multipolygon.php index 4f57c1db59..345ed59d65 100644 --- a/libraries/gis/pma_gis_multipolygon.php +++ b/libraries/gis/pma_gis_multipolygon.php @@ -315,12 +315,13 @@ class PMA_GIS_Multipolygon extends PMA_GIS_Geometry /** * Generate the WKT with the set of parameters passed by the GIS editor. * - * @param array $gis_data GIS data - * @param int $index Index into the parameter object + * @param array $gis_data GIS data + * @param int $index Index into the parameter object + * @param string $empty Value for empty points * * @return WKT with the set of parameters passed by the GIS editor */ - public function generateWkt($gis_data, $index) + public function generateWkt($gis_data, $index, $empty = '') { $no_of_polygons = isset($gis_data[$index]['MULTIPOLYGON']['no_of_polygons']) ? $gis_data[$index]['MULTIPOLYGON']['no_of_polygons'] : 1; @@ -343,10 +344,12 @@ class PMA_GIS_Multipolygon extends PMA_GIS_Geometry } $wkt .= '('; for ($j = 0; $j < $no_of_points; $j++) { - $wkt .= (isset($gis_data[$index]['MULTIPOLYGON'][$k][$i][$j]['x']) - ? $gis_data[$index]['MULTIPOLYGON'][$k][$i][$j]['x'] : '') - . ' ' . (isset($gis_data[$index]['MULTIPOLYGON'][$k][$i][$j]['y']) - ? $gis_data[$index]['MULTIPOLYGON'][$k][$i][$j]['y'] : '') .','; + $wkt .= ((isset($gis_data[$index]['MULTIPOLYGON'][$k][$i][$j]['x']) + && trim($gis_data[$index]['MULTIPOLYGON'][$k][$i][$j]['x']) != '') + ? $gis_data[$index]['MULTIPOLYGON'][$k][$i][$j]['x'] : $empty) + . ' ' . ((isset($gis_data[$index]['MULTIPOLYGON'][$k][$i][$j]['y']) + && trim($gis_data[$index]['MULTIPOLYGON'][$k][$i][$j]['y']) != '') + ? $gis_data[$index]['MULTIPOLYGON'][$k][$i][$j]['y'] : $empty) .','; } $wkt = substr($wkt, 0, strlen($wkt) - 1); $wkt .= '),'; diff --git a/libraries/gis/pma_gis_point.php b/libraries/gis/pma_gis_point.php index 2cade89e57..a1acc0fd80 100644 --- a/libraries/gis/pma_gis_point.php +++ b/libraries/gis/pma_gis_point.php @@ -176,15 +176,19 @@ class PMA_GIS_Point extends PMA_GIS_Geometry /** * Generate the WKT with the set of parameters passed by the GIS editor. * - * @param array $gis_data GIS data - * @param int $index Index into the parameter object + * @param array $gis_data GIS data + * @param int $index Index into the parameter object + * @param string $empty Value for empty points * * @return WKT with the set of parameters passed by the GIS editor */ - public function generateWkt($gis_data, $index) + public function generateWkt($gis_data, $index, $empty = '') { - return 'POINT(' . (isset($gis_data[$index]['POINT']['x']) ? $gis_data[$index]['POINT']['x'] : '') - . ' ' . (isset($gis_data[$index]['POINT']['y']) ? $gis_data[$index]['POINT']['y'] : '') . ')'; + return 'POINT(' + . ((isset($gis_data[$index]['POINT']['x']) && trim($gis_data[$index]['POINT']['x']) != '') + ? $gis_data[$index]['POINT']['x'] : $empty) . ' ' + . ((isset($gis_data[$index]['POINT']['y']) && trim($gis_data[$index]['POINT']['y']) != '') + ? $gis_data[$index]['POINT']['y'] : $empty) . ')'; } /** @@ -195,8 +199,8 @@ class PMA_GIS_Point extends PMA_GIS_Geometry * @return the WKT for the data from ESRI shape files */ public function getShape($row_data) { - $gis_data = array(array('POINT' => array('x' => $row_data['x'], 'y' => $row_data['y']))); - return $this->generateWkt($gis_data, 0); + return 'POINT(' . (isset($row_data['x']) ? $row_data['x'] : '') + . ' ' . (isset($row_data['y']) ? $row_data['y'] : '') . ')'; } /** diff --git a/libraries/gis/pma_gis_polygon.php b/libraries/gis/pma_gis_polygon.php index 1f077727a8..17665fdd27 100644 --- a/libraries/gis/pma_gis_polygon.php +++ b/libraries/gis/pma_gis_polygon.php @@ -290,12 +290,13 @@ class PMA_GIS_Polygon extends PMA_GIS_Geometry /** * Generate the WKT with the set of parameters passed by the GIS editor. * - * @param array $gis_data GIS data - * @param int $index Index into the parameter object + * @param array $gis_data GIS data + * @param int $index Index into the parameter object + * @param string $empty Value for empty points * * @return WKT with the set of parameters passed by the GIS editor */ - public function generateWkt($gis_data, $index) + public function generateWkt($gis_data, $index, $empty = '') { $no_of_lines = isset($gis_data[$index]['POLYGON']['no_of_lines']) ? $gis_data[$index]['POLYGON']['no_of_lines'] : 1; @@ -311,10 +312,12 @@ class PMA_GIS_Polygon extends PMA_GIS_Geometry } $wkt .= '('; for ($j = 0; $j < $no_of_points; $j++) { - $wkt .= (isset($gis_data[$index]['POLYGON'][$i][$j]['x']) - ? $gis_data[$index]['POLYGON'][$i][$j]['x'] : '') - . ' ' . (isset($gis_data[$index]['POLYGON'][$i][$j]['y']) - ? $gis_data[$index]['POLYGON'][$i][$j]['y'] : '') .','; + $wkt .= ((isset($gis_data[$index]['POLYGON'][$i][$j]['x']) + && trim($gis_data[$index]['POLYGON'][$i][$j]['x']) != '') + ? $gis_data[$index]['POLYGON'][$i][$j]['x'] : $empty) + . ' ' . ((isset($gis_data[$index]['POLYGON'][$i][$j]['y']) + && trim($gis_data[$index]['POLYGON'][$i][$j]['y']) != '') + ? $gis_data[$index]['POLYGON'][$i][$j]['y'] : $empty) .','; } $wkt = substr($wkt, 0, strlen($wkt) - 1); $wkt .= '),'; diff --git a/libraries/gis/pma_gis_visualization.php b/libraries/gis/pma_gis_visualization.php index 0df2a43487..b86f8527a6 100644 --- a/libraries/gis/pma_gis_visualization.php +++ b/libraries/gis/pma_gis_visualization.php @@ -252,7 +252,33 @@ class PMA_GIS_Visualization { $this->init(); $scale_data = $this->_scaleDataSet($this->_data); - $output = $this->_prepareDataSet($this->_data, 0, $scale_data, 'ol', ''); + $output = + 'var options = {' + . 'projection: new OpenLayers.Projection("EPSG:900913"),' + . 'displayProjection: new OpenLayers.Projection("EPSG:4326"),' + . 'units: "m",' + . 'numZoomLevels: 18,' + . 'maxResolution: 156543.0339,' + . 'maxExtent: new OpenLayers.Bounds(-20037508, -20037508, 20037508, 20037508),' + . 'restrictedExtent: new OpenLayers.Bounds(-20037508, -20037508, 20037508, 20037508)' + . '};' + . 'var map = new OpenLayers.Map("openlayersmap", options);' + . 'var layerNone = new OpenLayers.Layer.Boxes("None", {isBaseLayer: true});' + . 'var layerMapnik = new OpenLayers.Layer.OSM.Mapnik("Mapnik");' + . 'var layerOsmarender = new OpenLayers.Layer.OSM.Osmarender("Osmarender");' + . 'var layerCycleMap = new OpenLayers.Layer.OSM.CycleMap("CycleMap");' + . 'map.addLayers([layerMapnik, layerOsmarender, layerCycleMap, layerNone]);' + . 'var vectorLayer = new OpenLayers.Layer.Vector("Data");' + . 'var bound;'; + $output .= $this->_prepareDataSet($this->_data, 0, $scale_data, 'ol', ''); + $output .= + 'map.addLayer(vectorLayer);' + . 'map.zoomToExtent(bound);' + . 'if (map.getZoom() < 2) {' + . 'map.zoomTo(2);' + . '}' + . 'map.addControl(new OpenLayers.Control.LayerSwitcher());' + . 'map.addControl(new OpenLayers.Control.MousePosition());'; return $output; } diff --git a/tbl_change.php b/tbl_change.php index cdb9c2f73a..86589dd9dc 100644 --- a/tbl_change.php +++ b/tbl_change.php @@ -120,6 +120,7 @@ $GLOBALS['js_include'][] = 'jquery/jquery.svg.js'; $GLOBALS['js_include'][] = 'jquery/jquery.mousewheel.js'; $GLOBALS['js_include'][] = 'jquery/jquery.event.drag-2.0.min.js'; $GLOBALS['js_include'][] = 'tbl_gis_visualization.js'; +$GLOBALS['js_include'][] = 'openlayers/OpenLayers.js'; $GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js'; $GLOBALS['js_include'][] = 'jquery/timepicker.js'; /** @@ -967,6 +968,7 @@ foreach ($rows as $row_id => $vrow) { } } if (in_array($field['pma_type'], $gis_data_types)) { + $gis_exists = true; $data_val = isset($vrow[$field['Field']]) ? $vrow[$field['Field']] : ''; $_url_params = array( 'field' => $field['Field_title'], @@ -991,9 +993,13 @@ foreach ($rows as $row_id => $vrow) { $o_rows++; echo '
'; } // end foreach on multi-edit + +// Conditionally add OpenStreetMap.js if geometry columns exist +if (isset($gis_exists) && $gis_exists == true) { + echo(' From 0e4435266b588de8788b01bb92bf8261c3762ab5 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Mon, 18 Jul 2011 14:03:21 +0530 Subject: [PATCH 42/98] Change of classes to avoid conflicts with classes used in tbl_gis_visualization.js --- gis_data_editor.php | 14 +++++++------- js/tbl_change.js | 16 ++++++++-------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/gis_data_editor.php b/gis_data_editor.php index 6b35fc6018..77a6e7adef 100644 --- a/gis_data_editor.php +++ b/gis_data_editor.php @@ -201,7 +201,7 @@ if(isset($_REQUEST['get_gis_editor']) && $_REQUEST['get_gis_editor'] == true) { - "> + "> "> +?> ">
+?>
" value="" /> " class="add point" value=""> +?> " class="add addPoint" value="">
" class="add line" value=""> +?>
" class="add addLine" value="">

" class="add polygon" value=""> +?>

" class="add addPolygon" value="">

" /> +?>

" />
diff --git a/js/tbl_change.js b/js/tbl_change.js index 183e309212..cd68a01ce1 100644 --- a/js/tbl_change.js +++ b/js/tbl_change.js @@ -397,7 +397,7 @@ $(document).ready(function() { /** * Handles adding data points */ - $('.addJs.point').live('click', function() { + $('.addJs.addPoint').live('click', function() { var $a = $(this); var name = $a.attr('name'); // Eg. name = gis_data[0][MULTIPOINT][add_point] => prefix = gis_data[0][MULTIPOINT] @@ -414,7 +414,7 @@ $(document).ready(function() { /** * Handles adding linestrings and inner rings */ - $('.line.addJs').live('click', function() { + $('.addLine.addJs').live('click', function() { var $a = $(this); var name = $a.attr('name'); @@ -439,7 +439,7 @@ $(document).ready(function() { for (i = 0; i < noOfPoints; i++) { html += addDataPoint(i, (prefix + '[' + noOfLines + ']')); } - html += '+ ' + html += '+ ' + PMA_messages['strAddPoint'] + '
'; $a.before(html); @@ -449,7 +449,7 @@ $(document).ready(function() { /** * Handles adding polygons */ - $('.addJs.polygon').live('click', function() { + $('.addJs.addPolygon').live('click', function() { var $a = $(this); var name = $a.attr('name'); // Eg. name = gis_data[0][MULTIPOLYGON][add_polygon] => prefix = gis_data[0][MULTIPOLYGON] @@ -466,9 +466,9 @@ $(document).ready(function() { for (i = 0; i < 4; i++) { html += addDataPoint(i, (prefix + '[' + noOfPolygons + '][0]')); } - html += '+ ' - + PMA_messages['strAddPoint'] + '
'; - + '+ ' + html += '+ ' + + PMA_messages['strAddPoint'] + '
' + + '+ ' + PMA_messages['strAddInnerRing'] + '

'; $a.before(html); @@ -478,7 +478,7 @@ $(document).ready(function() { /** * Handles adding geoms */ - $('.addJs.geom').live('click', function() { + $('.addJs.addGeom').live('click', function() { var $a = $(this); var prefix = 'gis_data[GEOMETRYCOLLECTION]'; // Find the number of geoms From 015ad8968008284f565ecd1274f37ddcd89ca06e Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Wed, 20 Jul 2011 15:41:35 +0530 Subject: [PATCH 43/98] Size of GIS visualization auto adjusted to fit the available space --- js/tbl_gis_visualization.js | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/js/tbl_gis_visualization.js b/js/tbl_gis_visualization.js index 6cde8fe474..c022961e9e 100644 --- a/js/tbl_gis_visualization.js +++ b/js/tbl_gis_visualization.js @@ -8,7 +8,9 @@ */ var x = 0; +var default_x = 0; var y = 0; +var default_y = 0; var scale = 1; var svg; @@ -61,7 +63,26 @@ function initVisualization() { } else { $placeholder.hide(); } - + + // Resizing the visualization + if ($('.gis_table').length > 0) { // If we are in GIS data visualization + // Hide inputs for width and height + $("input[name='visualizationSettings[width]']").parents('tr').remove(); + $("input[name='visualizationSettings[height]']").parents('tr').remove(); + + var old_width = $placeholder.width(); + var extra = 100; + var leftWidth = $('.gis_table').width(); + var windowWidth = document.documentElement.clientWidth; + var visWidth = windowWidth - extra - leftWidth; + // assign new value for width + $placeholder.width(visWidth); + $('svg').attr('width', visWidth); + // assign the offset created due to resizing to default_x and center the svg. + default_x = (visWidth - old_width) / 2; + x = default_x; + } + var cssObj = { 'border' : '1px solid #aaa', 'width' : $placeholder.width(), @@ -96,6 +117,7 @@ function initVisualization() { } $('.choice').show(); + zoomAndPan(); } /** @@ -111,7 +133,10 @@ function initVisualization() { * Displaying tooltips for GIS objects. */ $(document).ready(function() { - initVisualization(); + // If we are in GIS data visualization + if ($('.gis_table').length > 0) { + initVisualization(); + } $('#choice').live('click', function() { if ($(this).prop('checked') == false) { @@ -187,8 +212,8 @@ $(document).ready(function() { $('#zoom_world').live('click', function(e) { e.preventDefault(); scale = 1; - x = 0; - y = 0; + x = default_x; + y = default_y; zoomAndPan(); }); From 47762d7b14815296256dea277647f152c1c5c2fc Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Wed, 20 Jul 2011 23:07:53 +0530 Subject: [PATCH 44/98] Better organized JS code --- gis_data_editor.php | 4 +- js/tbl_change.js | 21 ++++++-- js/tbl_gis_visualization.js | 105 ++++++++++++++++++++++++------------ 3 files changed, 91 insertions(+), 39 deletions(-) diff --git a/gis_data_editor.php b/gis_data_editor.php index 77a6e7adef..11d606a01d 100644 --- a/gis_data_editor.php +++ b/gis_data_editor.php @@ -297,9 +297,9 @@ if(isset($_REQUEST['get_gis_editor']) && $_REQUEST['get_gis_editor'] == true) { " class="add addPoint" value="">
" class="add addLine" value=""> +?>
" class="add addLine" value="">


" class="add addPolygon" value=""> +?>
" class="add addPolygon" value=""> '; } +/** + * Initialize the visualization in the GIS data editor. + */ +function initGISEditorVisualization() { + // Loads either SVG or OSM visualization based on the choice + selectVisualization(); + // Adds necessary styles to the div that coontains the openStreetMap + styleOSM(); + // Loads the SVG element and make a reference to it + loadSVG(); + // Adds controllers for zooming and panning + addZoomPanControllers(); + zoomAndPan(); +} + /** * Ajax handlers for Change Table page * @@ -316,7 +331,7 @@ $(document).ready(function() { }, function(data) { if(data.success == true) { $gis_editor.html(data.gis_editor); - initVisualization(); + initGISEditorVisualization(); prepareJSVersion(); } else { PMA_ajaxShowMessage(data.error); @@ -362,7 +377,7 @@ $(document).ready(function() { $('#placeholder').empty().removeClass('hasSVG').html(data.visualization); $('#openlayersmap').empty(); eval(data.openLayers); - initVisualization(); + initGISEditorVisualization(); } else { PMA_ajaxShowMessage(data.error); } @@ -379,7 +394,7 @@ $(document).ready(function() { $.post('gis_data_editor.php', $form.serialize() + "&get_gis_editor=true", function(data) { if(data.success == true) { $gis_editor.html(data.gis_editor); - initVisualization(); + initGISEditorVisualization(); prepareJSVersion(); } else { PMA_ajaxShowMessage(data.error); diff --git a/js/tbl_gis_visualization.js b/js/tbl_gis_visualization.js index c022961e9e..c31ad8f6b0 100644 --- a/js/tbl_gis_visualization.js +++ b/js/tbl_gis_visualization.js @@ -52,47 +52,36 @@ function zoomAndPan() { } /** - * Initialize the visualization. + * Initially loads either SVG or OSM visualization based on the choice. */ -function initVisualization() { - var $placeholder = $('#placeholder'); - var $openlayersmap = $('#openlayersmap'); - +function selectVisualization() { if ($('#choice').prop('checked') != true) { - $openlayersmap.hide(); + $('#openlayersmap').hide(); } else { - $placeholder.hide(); - } - - // Resizing the visualization - if ($('.gis_table').length > 0) { // If we are in GIS data visualization - // Hide inputs for width and height - $("input[name='visualizationSettings[width]']").parents('tr').remove(); - $("input[name='visualizationSettings[height]']").parents('tr').remove(); - - var old_width = $placeholder.width(); - var extra = 100; - var leftWidth = $('.gis_table').width(); - var windowWidth = document.documentElement.clientWidth; - var visWidth = windowWidth - extra - leftWidth; - // assign new value for width - $placeholder.width(visWidth); - $('svg').attr('width', visWidth); - // assign the offset created due to resizing to default_x and center the svg. - default_x = (visWidth - old_width) / 2; - x = default_x; + $('#placeholder').hide(); } + $('.choice').show(); +} +/** + * Adds necessary styles to the div that coontains the openStreetMap. + */ +function styleOSM() { + var $placeholder = $('#placeholder'); var cssObj = { 'border' : '1px solid #aaa', 'width' : $placeholder.width(), 'height' : $placeholder.height(), 'float' : 'right' }; - $openlayersmap.css(cssObj); - if (typeof drawOpenLayers == 'function') { - drawOpenLayers(); - } + $('#openlayersmap').css(cssObj); +} + +/** + * Loads the SVG element and make a reference to it. + */ +function loadSVG() { + var $placeholder = $('#placeholder'); $placeholder.svg({ onLoad: function(svg_ref) { @@ -100,9 +89,15 @@ function initVisualization() { } }); - // Removes the second SVG element unnecessarily added due to the above command. + // Removes the second SVG element unnecessarily added due to the above command $placeholder.find('svg:nth-child(2)').remove(); +} +/** + * Adds controllers for zooming and panning. + */ +function addZoomPanControllers() { + var $placeholder = $('#placeholder'); if ($("#placeholder svg").length > 0) { var pmaThemeImage = $('#pmaThemeImage').attr('value'); // add panning arrows @@ -115,8 +110,49 @@ function initVisualization() { $('').appendTo($placeholder); $('').appendTo($placeholder); } +} - $('.choice').show(); +/** + * Resizes the GIS visualization to fit into the space available. + */ +function resizeGISVisualization() { + var $placeholder = $('#placeholder'); + + // Hide inputs for width and height + $("input[name='visualizationSettings[width]']").parents('tr').remove(); + $("input[name='visualizationSettings[height]']").parents('tr').remove(); + + var old_width = $placeholder.width(); + var extraPadding = 100; + var leftWidth = $('.gis_table').width(); + var windowWidth = document.documentElement.clientWidth; + var visWidth = windowWidth - extraPadding - leftWidth; + + // Assign new value for width + $placeholder.width(visWidth); + $('svg').attr('width', visWidth); + + // Assign the offset created due to resizing to default_x and center the svg. + default_x = (visWidth - old_width) / 2; + x = default_x; +} + +/** + * Initialize the GIS visualization. + */ +function initGISVisualization() { + // Loads either SVG or OSM visualization based on the choice + selectVisualization(); + // Resizes the GIS visualization to fit into the space available + resizeGISVisualization(); + // Adds necessary styles to the div that coontains the openStreetMap + styleOSM(); + // Draws openStreetMap with openLayers + drawOpenLayers(); + // Loads the SVG element and make a reference to it + loadSVG(); + // Adds controllers for zooming and panning + addZoomPanControllers(); zoomAndPan(); } @@ -133,9 +169,10 @@ function initVisualization() { * Displaying tooltips for GIS objects. */ $(document).ready(function() { - // If we are in GIS data visualization + + // If we are in GIS visualization, initialize it if ($('.gis_table').length > 0) { - initVisualization(); + initGISVisualization(); } $('#choice').live('click', function() { From 1f2ba4e9cc51c2bf2b1c1b96f78f29143e033e36 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sun, 24 Jul 2011 22:17:03 +0530 Subject: [PATCH 45/98] Resolves problems with point and multipoint visualizations due to the assumption of empty values as zeros --- libraries/gis/pma_gis_geometry.php | 13 +++++++--- libraries/gis/pma_gis_multipoint.php | 38 ++++++++++++++++++---------- libraries/gis/pma_gis_point.php | 36 ++++++++++++++++---------- 3 files changed, 55 insertions(+), 32 deletions(-) diff --git a/libraries/gis/pma_gis_geometry.php b/libraries/gis/pma_gis_geometry.php index 787eaf3e23..075f77808b 100644 --- a/libraries/gis/pma_gis_geometry.php +++ b/libraries/gis/pma_gis_geometry.php @@ -142,11 +142,16 @@ abstract class PMA_GIS_Geometry $cordinates = explode(" ", $point); if ($scale_data != null) { - $x = ($cordinates[0] - $scale_data['x']) * $scale_data['scale']; - $y = $scale_data['height'] - ($cordinates[1] - $scale_data['y']) * $scale_data['scale']; + if (trim($cordinates[0]) != '' && trim($cordinates[1]) != '') { + $x = ($cordinates[0] - $scale_data['x']) * $scale_data['scale']; + $y = $scale_data['height'] - ($cordinates[1] - $scale_data['y']) * $scale_data['scale']; + } else { + $x = ''; + $y = ''; + } } else { - $x = $cordinates[0]; - $y = $cordinates[1]; + $x = trim($cordinates[0]); + $y = trim($cordinates[1]); } if (! $linear) { diff --git a/libraries/gis/pma_gis_multipoint.php b/libraries/gis/pma_gis_multipoint.php index bbec0f6f51..4c9b3aae49 100644 --- a/libraries/gis/pma_gis_multipoint.php +++ b/libraries/gis/pma_gis_multipoint.php @@ -70,7 +70,9 @@ class PMA_GIS_Multipoint extends PMA_GIS_Geometry foreach ($points_arr as $point) { // draw a small circle to mark the point - imagearc($image, $point[0], $point[1], 7, 7, 0, 360, $color); + if ($point[0] != '' && $point[1] != '') { + imagearc($image, $point[0], $point[1], 7, 7, 0, 360, $color); + } } return $image; } @@ -100,7 +102,9 @@ class PMA_GIS_Multipoint extends PMA_GIS_Geometry foreach ($points_arr as $point) { // draw a small circle to mark the point - $pdf->Circle($point[0], $point[1], 2, 0, 360, 'D', $line); + if ($point[0] != '' && $point[1] != '') { + $pdf->Circle($point[0], $point[1], 2, 0, 360, 'D', $line); + } } return $pdf; } @@ -131,12 +135,14 @@ class PMA_GIS_Multipoint extends PMA_GIS_Geometry $row = ''; foreach ($points_arr as $point) { - $row .= ' $val) { - $row .= ' ' . $option . '="' . trim($val) . '"'; + if ($point[0] != '' && $point[1] != '') { + $row .= ' $val) { + $row .= ' ' . $option . '="' . trim($val) . '"'; + } + $row .= '/>'; } - $row .= '/>'; } return $row; @@ -176,11 +182,15 @@ class PMA_GIS_Multipoint extends PMA_GIS_Geometry $row = 'new Array('; foreach ($points_arr as $point) { - $row .= '(new OpenLayers.Geometry.Point(' . $point[0] . ', ' . $point[1] - . ')).transform(new OpenLayers.Projection("EPSG:' . $srid - . '"), map.getProjectionObject()), '; + if ($point[0] != '' && $point[1] != '') { + $row .= '(new OpenLayers.Geometry.Point(' . $point[0] . ', ' . $point[1] + . ')).transform(new OpenLayers.Projection("EPSG:' . $srid + . '"), map.getProjectionObject()), '; + } + } + if (substr($row, strlen($row) - 2) == ', ') { + $row = substr($row, 0, strlen($row) - 2); } - $row = substr($row, 0, strlen($row) - 2); $row .= ')'; $result .= 'vectorLayer.addFeatures(new OpenLayers.Feature.Vector(' @@ -194,7 +204,7 @@ class PMA_GIS_Multipoint extends PMA_GIS_Geometry * * @param array $gis_data GIS data * @param int $index Index into the parameter object - * @param string $empty Value for empty points + * @param string $empty Multipoint does not adhere to this * * @return WKT with the set of parameters passed by the GIS editor */ @@ -209,10 +219,10 @@ class PMA_GIS_Multipoint extends PMA_GIS_Geometry for ($i = 0; $i < $no_of_points; $i++) { $wkt .= ((isset($gis_data[$index]['MULTIPOINT'][$i]['x']) && trim($gis_data[$index]['MULTIPOINT'][$i]['x']) != '') - ? $gis_data[$index]['MULTIPOINT'][$i]['x'] : $empty) + ? $gis_data[$index]['MULTIPOINT'][$i]['x'] : '') . ' ' . ((isset($gis_data[$index]['MULTIPOINT'][$i]['y']) && trim($gis_data[$index]['MULTIPOINT'][$i]['y']) != '') - ? $gis_data[$index]['MULTIPOINT'][$i]['y'] : $empty) . ','; + ? $gis_data[$index]['MULTIPOINT'][$i]['y'] : '') . ','; } $wkt = substr($wkt, 0, strlen($wkt) - 1); $wkt .= ')'; diff --git a/libraries/gis/pma_gis_point.php b/libraries/gis/pma_gis_point.php index 0b4bff15aa..bca3843c5e 100644 --- a/libraries/gis/pma_gis_point.php +++ b/libraries/gis/pma_gis_point.php @@ -69,7 +69,9 @@ class PMA_GIS_Point extends PMA_GIS_Geometry $points_arr = $this->extractPoints($point, $scale_data); // draw a small circle to mark the point - imagearc($image, $points_arr[0][0], $points_arr[0][1], 7, 7, 0, 360, $color); + if ($points_arr[0][0] != '' && $points_arr[0][1] != '') { + imagearc($image, $points_arr[0][0], $points_arr[0][1], 7, 7, 0, 360, $color); + } return $image; } @@ -97,7 +99,9 @@ class PMA_GIS_Point extends PMA_GIS_Geometry $points_arr = $this->extractPoints($point, $scale_data); // draw a small circle to mark the point - $pdf->Circle($points_arr[0][0], $points_arr[0][1], 2, 0, 360, 'D', $line); + if ($points_arr[0][0] != '' && $points_arr[0][1] != '') { + $pdf->Circle($points_arr[0][0], $points_arr[0][1], 2, 0, 360, 'D', $line); + } return $pdf; } @@ -126,11 +130,13 @@ class PMA_GIS_Point extends PMA_GIS_Geometry $point = substr($spatial, 6, (strlen($spatial) - 7)); $points_arr = $this->extractPoints($point, $scale_data); - $row = ' $val) { - $row .= ' ' . $option . '="' . trim($val) . '"'; + if ($points_arr[0][0] != '' && $points_arr[0][1] != '') { + $row = ' $val) { + $row .= ' ' . $option . '="' . trim($val) . '"'; + } + $row .= '/>'; } - $row .= '/>'; return $row; } @@ -167,11 +173,13 @@ class PMA_GIS_Point extends PMA_GIS_Geometry $point = substr($spatial, 6, (strlen($spatial) - 7)); $points_arr = $this->extractPoints($point, null); - $result .= 'vectorLayer.addFeatures(new OpenLayers.Feature.Vector((' - . 'new OpenLayers.Geometry.Point(' . $points_arr[0][0] . ', ' - . $points_arr[0][1] . ').transform(new OpenLayers.Projection("EPSG:' - . $srid . '"), map.getProjectionObject())), null, ' - . json_encode($style_options) . '));'; + if ($points_arr[0][0] != '' && $points_arr[0][1] != '') { + $result .= 'vectorLayer.addFeatures(new OpenLayers.Feature.Vector((' + . 'new OpenLayers.Geometry.Point(' . $points_arr[0][0] . ', ' + . $points_arr[0][1] . ').transform(new OpenLayers.Projection("EPSG:' + . $srid . '"), map.getProjectionObject())), null, ' + . json_encode($style_options) . '));'; + } return $result; } @@ -180,7 +188,7 @@ class PMA_GIS_Point extends PMA_GIS_Geometry * * @param array $gis_data GIS data * @param int $index Index into the parameter object - * @param string $empty Value for empty points + * @param string $empty Point deos not adhere to this parameter * * @return WKT with the set of parameters passed by the GIS editor */ @@ -188,9 +196,9 @@ class PMA_GIS_Point extends PMA_GIS_Geometry { return 'POINT(' . ((isset($gis_data[$index]['POINT']['x']) && trim($gis_data[$index]['POINT']['x']) != '') - ? $gis_data[$index]['POINT']['x'] : $empty) . ' ' + ? $gis_data[$index]['POINT']['x'] : '') . ' ' . ((isset($gis_data[$index]['POINT']['y']) && trim($gis_data[$index]['POINT']['y']) != '') - ? $gis_data[$index]['POINT']['y'] : $empty) . ')'; + ? $gis_data[$index]['POINT']['y'] : '') . ')'; } /** From 11ca5daa412c0338d63020f94f74530e95463ce9 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sun, 24 Jul 2011 22:30:52 +0530 Subject: [PATCH 46/98] Change of color --- libraries/gis/pma_gis_visualization.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/gis/pma_gis_visualization.php b/libraries/gis/pma_gis_visualization.php index 87bd281232..b6f1e95587 100644 --- a/libraries/gis/pma_gis_visualization.php +++ b/libraries/gis/pma_gis_visualization.php @@ -18,11 +18,11 @@ class PMA_GIS_Visualization // Array of colors to be used for GIS visualizations. 'colors' => array( - '#BCE02E', + '#B02EE0', '#E0642E', '#E0D62E', '#2E97E0', - '#B02EE0', + '#BCE02E', '#E02E75', '#5CE02E', '#E0B02E', From 01976f1663f7d36d18f65574276f7250b506ef94 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Thu, 28 Jul 2011 11:44:18 +0530 Subject: [PATCH 47/98] Handle the cases where URL is too long --- js/tbl_change.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/tbl_change.js b/js/tbl_change.js index fa0a88fce9..4860ead0c7 100644 --- a/js/tbl_change.js +++ b/js/tbl_change.js @@ -293,6 +293,8 @@ function initGISEditorVisualization() { * Restart insertion with 'N' rows. */ $(document).ready(function() { + // Remove the class that is added due to the URL being too long. + $('.open_gis_editor a').removeClass('formLinkSubmit'); $('.open_gis_editor').live('click', function(event) { event.preventDefault(); From 47a8dcfc8885a0086fc8c8b9b5a49e783d81180a Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Thu, 28 Jul 2011 12:06:15 +0530 Subject: [PATCH 48/98] Function based search - for unary functions --- libraries/common.lib.php | 105 ++++++++++++++++++++++++++++++++++++++- tbl_select.php | 63 ++++++++++++++++++++--- 2 files changed, 161 insertions(+), 7 deletions(-) diff --git a/libraries/common.lib.php b/libraries/common.lib.php index 88ea11fa04..21a2030b09 100644 --- a/libraries/common.lib.php +++ b/libraries/common.lib.php @@ -3005,7 +3005,7 @@ function PMA_unsupportedDatatypes() { return $no_support_types; } -function PMA_getGISDatatypes() { +function PMA_getGISDatatypes($upper_case = false) { $gis_data_types = array('geometry', 'point', 'linestring', @@ -3015,9 +3015,112 @@ function PMA_getGISDatatypes() { 'multipolygon', 'geometrycollection' ); + if ($upper_case) { + for ($i = 0; $i < count($gis_data_types); $i++) { + $gis_data_types[$i] = strtoupper($gis_data_types[$i]); + } + } return $gis_data_types; } + +/** + * Returns the names and details of the functions + * that can be applied on geometry data typess. + * + * @param string $geom_type if provided the output is limited to the functions + * that are applicable to the provided geometry type. + * @param bool $binary if set to false functions that take two geometries + * as arguments will not be included. + * @param bool $display if set to true seperators will be added to the + * output array. + * + * @return array names and details of the functions that can be applied on + * geometry data typess. + */ +function PMA_getGISFunctions($geom_type = null, $binary = true, $display = false) { + // Unary functions common to all geomety types + $funcs = array(); + if ($display) { + $funcs[] = array('name' => ' '); + } + + $funcs[] = array('name' => 'Dimension', 'params' => 1, 'type' => 'int'); + //$funcs[] = array('name' => 'Envelope', 'params' => 1, 'type' => 'Polygon'); + $funcs[] = array('name' => 'GeometryType', 'params' => 1, 'type' => 'text'); + $funcs[] = array('name' => 'SRID', 'params' => 1, 'type' => 'int'); + $funcs[] = array('name' => 'IsEmpty', 'params' => 1, 'type' => 'int'); + $funcs[] = array('name' => 'IsSimple', 'params' => 1, 'type' => 'int'); + + $geom_type = trim(strtolower($geom_type)); + if ($display && $geom_type != 'geometry' && $geom_type != 'multipoint') { + $funcs[] = array('name' => '--------'); + } + + if ($geom_type == 'point') { + $funcs[] = array('name' => 'X', 'params' => 1, 'type' => 'float'); + $funcs[] = array('name' => 'Y', 'params' => 1, 'type' => 'float'); + } elseif ($geom_type == 'multipoint') { + // no fucntions here + } elseif ($geom_type == 'linestring') { + //$funcs[] = array('name' => 'EndPoint', 'params' => 1, 'type' => 'Point'); + $funcs[] = array('name' => 'GLength', 'params' => 1, 'type' => 'float'); + $funcs[] = array('name' => 'NumPoints', 'params' => 1, 'type' => 'int'); + //$funcs[] = array('name' => 'StartPoint', 'params' => 1, 'type' => 'Point'); + $funcs[] = array('name' => 'IsRing', 'params' => 1, 'type' => 'int'); + } elseif ($geom_type == 'multilinestring') { + $funcs[] = array('name' => 'GLength', 'params' => 1, 'type' => 'float'); + $funcs[] = array('name' => 'IsClosed', 'params' => 1, 'type' => 'int'); + } elseif ($geom_type == 'polygon') { + $funcs[] = array('name' => 'Area', 'params' => 1, 'type' => 'float'); + //$funcs[] = array('name' => 'ExteriorRing', 'params' => 1, 'type' => 'Linestring'); + $funcs[] = array('name' => 'NumInteriorRings', 'params' => 1, 'type' => 'int'); + } elseif ($geom_type == 'multipolygon') { + $funcs[] = array('name' => 'Area', 'params' => 1, 'type' => 'float'); + //$funcs[] = array('name' => 'Centroid', 'params' => 1, 'type' => 'Point'); + // Not yet implemented in MySQL + //$funcs[] = array('name' => 'PointOnSurface', 'params' => 1, 'type' => 'Point'); + } elseif ($geom_type == 'geometrycollection') { + $funcs[] = array('name' => 'NumGeometries', 'params' => 1, 'type' => 'int'); + } + + // If we are asked for binary functions as well + if ($binary) { + if ($display) { + $funcs[] = array('name' => '--------'); + } + $binary = array( + array('name' => 'Crosses', 'params' => 2, 'type' => 'int'), + array('name' => 'Contains', 'params' => 2, 'type' => 'int'), + array('name' => 'Disjoint', 'params' => 2, 'type' => 'int'), + array('name' => 'Equals', 'params' => 2, 'type' => 'int'), + array('name' => 'Intersects', 'params' => 2, 'type' => 'int'), + array('name' => 'Overlaps', 'params' => 2, 'type' => 'int'), + array('name' => 'Touches', 'params' => 2, 'type' => 'int'), + array('name' => 'Within', 'params' => 2, 'type' => 'int'), + ); + + // If MySQl version is greaeter than or equal 5.6.1, use the ST_ prefix. + if (PMA_MYSQL_INT_VERSION >= 50601) { + for ($i = 0; $i < count($binary); $i++) { + $binary[$i]['name'] = 'ST_' . $binary[$i]['name']; + } + } + $funcs = array_merge($funcs, $binary); + if ($display) { + $funcs[] = array('name' => '--------'); + } + $funcs[] = array('name' => 'MBRContains', 'params' => 2, 'type' => 'int'); + $funcs[] = array('name' => 'MBRDisjoint', 'params' => 2, 'type' => 'int'); + $funcs[] = array('name' => 'MBREquals', 'params' => 2, 'type' => 'int'); + $funcs[] = array('name' => 'MBRIntersects', 'params' => 2, 'type' => 'int'); + $funcs[] = array('name' => 'MBROverlaps', 'params' => 2, 'type' => 'int'); + $funcs[] = array('name' => 'MBRTouches', 'params' => 2, 'type' => 'int'); + $funcs[] = array('name' => 'MBRWithin', 'params' => 2, 'type' => 'int'); + } + return $funcs; +} + /** * Creates a dropdown box with MySQL functions for a particular column. * diff --git a/tbl_select.php b/tbl_select.php index c6b0a35332..eb19a7d285 100644 --- a/tbl_select.php +++ b/tbl_select.php @@ -35,6 +35,7 @@ if ($GLOBALS['cfg']['PropertiesIconic'] == true) { $titles['Browse'] = __('Browse foreign values'); } +$geom_types = PMA_getGISDatatypes(); /** * Not selection yet required -> displays the selection form */ @@ -64,9 +65,14 @@ if (! isset($param) || $param[0] == '') { $result = PMA_DBI_query('SHOW FULL FIELDS FROM ' . PMA_backquote($table) . ' FROM ' . PMA_backquote($db) . ';', null, PMA_DBI_QUERY_STORE); $fields_cnt = PMA_DBI_num_rows($result); $fields_list = $fields_null = $fields_type = $fields_collation = array(); + $geom_column_present = false; while ($row = PMA_DBI_fetch_assoc($result)) { $fields_list[] = $row['Field']; $type = $row['Type']; + // check whether table contains geometric columns + if (in_array($type, $geom_types)) { + $geom_column_present = true; + } // reformat mysql query output if (strncasecmp($type, 'set', 3) == 0 || strncasecmp($type, 'enum', 4) == 0) { @@ -111,7 +117,13 @@ if (! isset($param) || $param[0] == '') { - + '); echo __('Function'); echo(''); + } + ?> + @@ -125,6 +137,27 @@ if (! isset($param) || $param[0] == '') { for ($i = 0; $i < $fields_cnt; $i++) { ?> + '); + // if a geometry column + if (in_array($fields_type[$i], $geom_types)) { + echo(''); + } else { + echo(' '); + } + echo(''); + } + ?> @@ -360,13 +393,31 @@ else { "= ''" => 1, "!= ''" => 1 ); + $geom_unary_operators = array( + 'IsEmpty' => 1, + 'IsSimple' => 1, + 'IsRing' => 1, + 'IsClosed' => 1, + ); $cnt_func = count($func); reset($func); while (list($i, $func_type) = each($func)) { + // If geometry funciton is set apply it to the field name + if (isset($geom_func[$i]) && trim($geom_func[$i]) != '') { + $backquoted_name = $geom_func[$i] . '(' . PMA_backquote($names[$i]) . ')'; + // If the intended where clause is something like 'IsEmpty(`spatial_col_name`)' + if (isset($geom_unary_operators[$geom_func[$i]]) && trim($fields[$i]) == '') { + $w[] = $backquoted_name; + continue; + } + } else { + $backquoted_name = PMA_backquote($names[$i]); + } + list($charsets[$i]) = explode('_', $collations[$i]); if (isset($unary_operators[$func_type])) { $fields[$i] = ''; - $w[] = PMA_backquote($names[$i]) . ' ' . $func_type; + $w[] = $backquoted_name . ' ' . $func_type; } elseif (strncasecmp($types[$i], 'enum', 4) == 0) { if (!empty($fields[$i])) { @@ -393,7 +444,7 @@ else { $enum_where .= ', \'' . PMA_sqlAddSlashes($fields[$i][$e]) . '\''; } - $w[] = PMA_backquote($names[$i]) . ' ' . $func_type . ' ' . $parens_open . $enum_where . $parens_close; + $w[] = $backquoted_name . ' ' . $func_type . ' ' . $parens_open . $enum_where . $parens_close; } } elseif ($fields[$i] != '') { @@ -425,12 +476,12 @@ else { $value = $quot . PMA_sqlAddSlashes(trim($value)) . $quot; if ($func_type == 'BETWEEN' || $func_type == 'NOT BETWEEN') - $w[] = PMA_backquote($names[$i]) . ' ' . $func_type . ' ' . (isset($values[0]) ? $values[0] : '') . ' AND ' . (isset($values[1]) ? $values[1] : ''); + $w[] = $backquoted_name . ' ' . $func_type . ' ' . (isset($values[0]) ? $values[0] : '') . ' AND ' . (isset($values[1]) ? $values[1] : ''); else - $w[] = PMA_backquote($names[$i]) . ' ' . $func_type . ' (' . implode(',', $values) . ')'; + $w[] = $backquoted_name . ' ' . $func_type . ' (' . implode(',', $values) . ')'; } else { - $w[] = PMA_backquote($names[$i]) . ' ' . $func_type . ' ' . $quot . PMA_sqlAddSlashes($fields[$i]) . $quot;; + $w[] = $backquoted_name . ' ' . $func_type . ' ' . $quot . PMA_sqlAddSlashes($fields[$i]) . $quot;; } } // end if From e456f221494e1ccf76d5b8f73ca5e6896feec113 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sun, 31 Jul 2011 01:11:11 +0530 Subject: [PATCH 49/98] Detect the output type of the functions being applied --- libraries/common.lib.php | 108 +++++++++++++++++++++------------------ tbl_select.php | 13 +++-- 2 files changed, 68 insertions(+), 53 deletions(-) diff --git a/libraries/common.lib.php b/libraries/common.lib.php index 21a2030b09..a31ffc682c 100644 --- a/libraries/common.lib.php +++ b/libraries/common.lib.php @@ -3039,84 +3039,92 @@ function PMA_getGISDatatypes($upper_case = false) { * geometry data typess. */ function PMA_getGISFunctions($geom_type = null, $binary = true, $display = false) { - // Unary functions common to all geomety types + $funcs = array(); if ($display) { - $funcs[] = array('name' => ' '); + $funcs[] = array('display' => ' '); } - $funcs[] = array('name' => 'Dimension', 'params' => 1, 'type' => 'int'); - //$funcs[] = array('name' => 'Envelope', 'params' => 1, 'type' => 'Polygon'); - $funcs[] = array('name' => 'GeometryType', 'params' => 1, 'type' => 'text'); - $funcs[] = array('name' => 'SRID', 'params' => 1, 'type' => 'int'); - $funcs[] = array('name' => 'IsEmpty', 'params' => 1, 'type' => 'int'); - $funcs[] = array('name' => 'IsSimple', 'params' => 1, 'type' => 'int'); + // Unary functions common to all geomety types + $funcs['Dimension'] = array('params' => 1, 'type' => 'int'); + $funcs['Envelope'] = array('params' => 1, 'type' => 'Polygon'); + $funcs['GeometryType'] = array('params' => 1, 'type' => 'text'); + $funcs['SRID'] = array('params' => 1, 'type' => 'int'); + $funcs['IsEmpty'] = array('params' => 1, 'type' => 'int'); + $funcs['IsSimple'] = array('params' => 1, 'type' => 'int'); $geom_type = trim(strtolower($geom_type)); if ($display && $geom_type != 'geometry' && $geom_type != 'multipoint') { - $funcs[] = array('name' => '--------'); + $funcs[] = array('display' => '--------'); } + // Unary functions that are specific to each geomety type if ($geom_type == 'point') { - $funcs[] = array('name' => 'X', 'params' => 1, 'type' => 'float'); - $funcs[] = array('name' => 'Y', 'params' => 1, 'type' => 'float'); + $funcs['X'] = array('params' => 1, 'type' => 'float'); + $funcs['Y'] = array('params' => 1, 'type' => 'float'); } elseif ($geom_type == 'multipoint') { // no fucntions here } elseif ($geom_type == 'linestring') { - //$funcs[] = array('name' => 'EndPoint', 'params' => 1, 'type' => 'Point'); - $funcs[] = array('name' => 'GLength', 'params' => 1, 'type' => 'float'); - $funcs[] = array('name' => 'NumPoints', 'params' => 1, 'type' => 'int'); - //$funcs[] = array('name' => 'StartPoint', 'params' => 1, 'type' => 'Point'); - $funcs[] = array('name' => 'IsRing', 'params' => 1, 'type' => 'int'); + $funcs['EndPoint'] = array('params' => 1, 'type' => 'point'); + $funcs['GLength'] = array('params' => 1, 'type' => 'float'); + $funcs['NumPoints'] = array('params' => 1, 'type' => 'int'); + $funcs['StartPoint'] = array('params' => 1, 'type' => 'point'); + $funcs['IsRing'] = array('params' => 1, 'type' => 'int'); } elseif ($geom_type == 'multilinestring') { - $funcs[] = array('name' => 'GLength', 'params' => 1, 'type' => 'float'); - $funcs[] = array('name' => 'IsClosed', 'params' => 1, 'type' => 'int'); + $funcs['GLength'] = array('params' => 1, 'type' => 'float'); + $funcs['IsClosed'] = array('params' => 1, 'type' => 'int'); } elseif ($geom_type == 'polygon') { - $funcs[] = array('name' => 'Area', 'params' => 1, 'type' => 'float'); - //$funcs[] = array('name' => 'ExteriorRing', 'params' => 1, 'type' => 'Linestring'); - $funcs[] = array('name' => 'NumInteriorRings', 'params' => 1, 'type' => 'int'); + $funcs['Area'] = array('params' => 1, 'type' => 'float'); + $funcs['ExteriorRing'] = array('params' => 1, 'type' => 'linestring'); + $funcs['NumInteriorRings'] = array('params' => 1, 'type' => 'int'); } elseif ($geom_type == 'multipolygon') { - $funcs[] = array('name' => 'Area', 'params' => 1, 'type' => 'float'); - //$funcs[] = array('name' => 'Centroid', 'params' => 1, 'type' => 'Point'); + $funcs['Area'] = array('params' => 1, 'type' => 'float'); + $funcs['Centroid'] = array('params' => 1, 'type' => 'point'); // Not yet implemented in MySQL - //$funcs[] = array('name' => 'PointOnSurface', 'params' => 1, 'type' => 'Point'); + //$funcs['PointOnSurface'] = array('params' => 1, 'type' => 'point'); } elseif ($geom_type == 'geometrycollection') { - $funcs[] = array('name' => 'NumGeometries', 'params' => 1, 'type' => 'int'); + $funcs['NumGeometries'] = array('params' => 1, 'type' => 'int'); } // If we are asked for binary functions as well if ($binary) { + // section seperator if ($display) { - $funcs[] = array('name' => '--------'); + $funcs[] = array('display' => '--------'); } - $binary = array( - array('name' => 'Crosses', 'params' => 2, 'type' => 'int'), - array('name' => 'Contains', 'params' => 2, 'type' => 'int'), - array('name' => 'Disjoint', 'params' => 2, 'type' => 'int'), - array('name' => 'Equals', 'params' => 2, 'type' => 'int'), - array('name' => 'Intersects', 'params' => 2, 'type' => 'int'), - array('name' => 'Overlaps', 'params' => 2, 'type' => 'int'), - array('name' => 'Touches', 'params' => 2, 'type' => 'int'), - array('name' => 'Within', 'params' => 2, 'type' => 'int'), - ); + if (PMA_MYSQL_INT_VERSION < 50601) { + $funcs['Crosses'] = array('params' => 2, 'type' => 'int'); + $funcs['Contains'] = array('params' => 2, 'type' => 'int'); + $funcs['Disjoint'] = array('params' => 2, 'type' => 'int'); + $funcs['Equals'] = array('params' => 2, 'type' => 'int'); + $funcs['Intersects'] = array('params' => 2, 'type' => 'int'); + $funcs['Overlaps'] = array('params' => 2, 'type' => 'int'); + $funcs['Touches'] = array('params' => 2, 'type' => 'int'); + $funcs['Within'] = array('params' => 2, 'type' => 'int'); + } else { + // If MySQl version is greaeter than or equal 5.6.1, use the ST_ prefix. + $funcs['ST_Crosses'] = array('params' => 2, 'type' => 'int'); + $funcs['ST_Contains'] = array('params' => 2, 'type' => 'int'); + $funcs['ST_Disjoint'] = array('params' => 2, 'type' => 'int'); + $funcs['ST_Equals'] = array('params' => 2, 'type' => 'int'); + $funcs['ST_Intersects'] = array('params' => 2, 'type' => 'int'); + $funcs['ST_Overlaps'] = array('params' => 2, 'type' => 'int'); + $funcs['ST_Touches'] = array('params' => 2, 'type' => 'int'); + $funcs['ST_Within'] = array('params' => 2, 'type' => 'int'); - // If MySQl version is greaeter than or equal 5.6.1, use the ST_ prefix. - if (PMA_MYSQL_INT_VERSION >= 50601) { - for ($i = 0; $i < count($binary); $i++) { - $binary[$i]['name'] = 'ST_' . $binary[$i]['name']; - } } - $funcs = array_merge($funcs, $binary); + if ($display) { - $funcs[] = array('name' => '--------'); + $funcs[] = array('display' => '--------'); } - $funcs[] = array('name' => 'MBRContains', 'params' => 2, 'type' => 'int'); - $funcs[] = array('name' => 'MBRDisjoint', 'params' => 2, 'type' => 'int'); - $funcs[] = array('name' => 'MBREquals', 'params' => 2, 'type' => 'int'); - $funcs[] = array('name' => 'MBRIntersects', 'params' => 2, 'type' => 'int'); - $funcs[] = array('name' => 'MBROverlaps', 'params' => 2, 'type' => 'int'); - $funcs[] = array('name' => 'MBRTouches', 'params' => 2, 'type' => 'int'); - $funcs[] = array('name' => 'MBRWithin', 'params' => 2, 'type' => 'int'); + // Minimum bounding rectangle functions + $funcs['MBRContains'] = array('params' => 2, 'type' => 'int'); + $funcs['MBRDisjoint'] = array('params' => 2, 'type' => 'int'); + $funcs['MBREquals'] = array('params' => 2, 'type' => 'int'); + $funcs['MBRIntersects'] = array('params' => 2, 'type' => 'int'); + $funcs['MBROverlaps'] = array('params' => 2, 'type' => 'int'); + $funcs['MBRTouches'] = array('params' => 2, 'type' => 'int'); + $funcs['MBRWithin'] = array('params' => 2, 'type' => 'int'); } return $funcs; } diff --git a/tbl_select.php b/tbl_select.php index eb19a7d285..25e1b9aa2f 100644 --- a/tbl_select.php +++ b/tbl_select.php @@ -146,8 +146,8 @@ if (! isset($param) || $param[0] == '') { echo(''); // get the relevant list of functions - $funcs = PMA_getGISFunctions($fields_type[$i], false, true); + $funcs = PMA_getGISFunctions($fields_type[$i], true, true); foreach ($funcs as $func_name => $func) { $name = isset($func['display']) ? $func['display'] : $func_name; echo('
'); // if a geometry column if (in_array($fields_type[$i], $geom_types)) { - echo(''); // get the relevant list of functions $funcs = PMA_getGISFunctions($fields_type[$i], true, true); foreach ($funcs as $func_name => $func) { @@ -253,7 +253,7 @@ if (! isset($param) || $param[0] == '') { // g e o m e t r y echo ' ' . "\n"; - echo(''); + echo(''); echo(PMA_display_html_checkbox('switch[' . $i . ']', __("Switch"), false, '')); echo(''); } elseif (strncasecmp($fields_type[$i], 'enum', 4) == 0) { From 6ae969a5ee3d2e30ccf3d95aefa7f641a3ccd2db Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sun, 31 Jul 2011 14:04:12 +0530 Subject: [PATCH 55/98] Serve OpenStreetMap.js locally --- js/OpenStreetMap.js | 125 ++++++++++++++++++++++++++++++++++++++ sql.php | 8 +++ tbl_change.php | 13 ++-- tbl_gis_visualization.php | 2 +- tbl_select.php | 9 +++ 5 files changed, 149 insertions(+), 8 deletions(-) create mode 100644 js/OpenStreetMap.js diff --git a/js/OpenStreetMap.js b/js/OpenStreetMap.js new file mode 100644 index 0000000000..aebfa65db0 --- /dev/null +++ b/js/OpenStreetMap.js @@ -0,0 +1,125 @@ +/** + * Namespace: Util.OSM + */ +OpenLayers.Util.OSM = {}; + +/** + * Constant: MISSING_TILE_URL + * {String} URL of image to display for missing tiles + */ +OpenLayers.Util.OSM.MISSING_TILE_URL = "http://www.openstreetmap.org/openlayers/img/404.png"; + +/** + * Property: originalOnImageLoadError + * {Function} Original onImageLoadError function. + */ +OpenLayers.Util.OSM.originalOnImageLoadError = OpenLayers.Util.onImageLoadError; + +/** + * Function: onImageLoadError + */ +OpenLayers.Util.onImageLoadError = function() { + if (this.src.match(/^http:\/\/[abc]\.[a-z]+\.openstreetmap\.org\//)) { + this.src = OpenLayers.Util.OSM.MISSING_TILE_URL; + } else if (this.src.match(/^http:\/\/[def]\.tah\.openstreetmap\.org\//)) { + // do nothing - this layer is transparent + } else { + OpenLayers.Util.OSM.originalOnImageLoadError; + } +}; + +/** + * Class: OpenLayers.Layer.OSM.Mapnik + * + * Inherits from: + * - + */ +OpenLayers.Layer.OSM.Mapnik = OpenLayers.Class(OpenLayers.Layer.OSM, { + /** + * Constructor: OpenLayers.Layer.OSM.Mapnik + * + * Parameters: + * name - {String} + * options - {Object} Hashtable of extra options to tag onto the layer + */ + initialize: function(name, options) { + var url = [ + "http://a.tile.openstreetmap.org/${z}/${x}/${y}.png", + "http://b.tile.openstreetmap.org/${z}/${x}/${y}.png", + "http://c.tile.openstreetmap.org/${z}/${x}/${y}.png" + ]; + options = OpenLayers.Util.extend({ + numZoomLevels: 19, + buffer: 0, + transitionEffect: "resize" + }, options); + var newArguments = [name, url, options]; + OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments); + }, + + CLASS_NAME: "OpenLayers.Layer.OSM.Mapnik" +}); + +/** + * Class: OpenLayers.Layer.OSM.Osmarender + * + * Inherits from: + * - + */ +OpenLayers.Layer.OSM.Osmarender = OpenLayers.Class(OpenLayers.Layer.OSM, { + /** + * Constructor: OpenLayers.Layer.OSM.Osmarender + * + * Parameters: + * name - {String} + * options - {Object} Hashtable of extra options to tag onto the layer + */ + initialize: function(name, options) { + var url = [ + "http://a.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png", + "http://b.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png", + "http://c.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png" + ]; + options = OpenLayers.Util.extend({ + numZoomLevels: 18, + buffer: 0, + transitionEffect: "resize" + }, options); + var newArguments = [name, url, options]; + OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments); + }, + + CLASS_NAME: "OpenLayers.Layer.OSM.Osmarender" +}); + +/** + * Class: OpenLayers.Layer.OSM.CycleMap + * + * Inherits from: + * - + */ +OpenLayers.Layer.OSM.CycleMap = OpenLayers.Class(OpenLayers.Layer.OSM, { + /** + * Constructor: OpenLayers.Layer.OSM.CycleMap + * + * Parameters: + * name - {String} + * options - {Object} Hashtable of extra options to tag onto the layer + */ + initialize: function(name, options) { + var url = [ + "http://a.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png", + "http://b.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png", + "http://c.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png" + ]; + options = OpenLayers.Util.extend({ + numZoomLevels: 19, + buffer: 0, + transitionEffect: "resize" + }, options); + var newArguments = [name, url, options]; + OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments); + }, + + CLASS_NAME: "OpenLayers.Layer.OSM.CycleMap" +}); diff --git a/sql.php b/sql.php index 94a0b0d1e5..51521730cf 100644 --- a/sql.php +++ b/sql.php @@ -17,6 +17,14 @@ require_once './libraries/bookmark.lib.php'; $GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js'; $GLOBALS['js_include'][] = 'tbl_change.js'; +// required for GIS editor loaded via AJAX +$GLOBALS['js_include'][] = 'jquery/jquery.svg.js'; +$GLOBALS['js_include'][] = 'jquery/jquery.mousewheel.js'; +$GLOBALS['js_include'][] = 'jquery/jquery.event.drag-2.0.min.js'; +$GLOBALS['js_include'][] = 'tbl_gis_visualization.js'; +$GLOBALS['js_include'][] = 'openlayers/OpenLayers.js'; +$GLOBALS['js_include'][] = 'OpenStreetMap.js'; + if (isset($_SESSION['profiling'])) { $GLOBALS['js_include'][] = 'highcharts/highcharts.js'; /* Files required for chart exporting */ diff --git a/tbl_change.php b/tbl_change.php index 07d6b082e6..32dcbd669e 100644 --- a/tbl_change.php +++ b/tbl_change.php @@ -116,13 +116,17 @@ if ($GLOBALS['cfg']['ShowPropertyComments']) { */ $GLOBALS['js_include'][] = 'functions.js'; $GLOBALS['js_include'][] = 'tbl_change.js'; +$GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js'; +$GLOBALS['js_include'][] = 'jquery/timepicker.js'; + +// required for GIS editor $GLOBALS['js_include'][] = 'jquery/jquery.svg.js'; $GLOBALS['js_include'][] = 'jquery/jquery.mousewheel.js'; $GLOBALS['js_include'][] = 'jquery/jquery.event.drag-2.0.min.js'; $GLOBALS['js_include'][] = 'tbl_gis_visualization.js'; $GLOBALS['js_include'][] = 'openlayers/OpenLayers.js'; -$GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js'; -$GLOBALS['js_include'][] = 'jquery/timepicker.js'; +$GLOBALS['js_include'][] = 'OpenStreetMap.js'; + /** * HTTP and HTML headers */ @@ -968,7 +972,6 @@ foreach ($rows as $row_id => $vrow) { } } if (in_array($field['pma_type'], $gis_data_types)) { - $gis_exists = true; $data_val = isset($vrow[$field['Field']]) ? $vrow[$field['Field']] : ''; $_url_params = array( 'field' => $field['Field_title'], @@ -994,10 +997,6 @@ foreach ($rows as $row_id => $vrow) { echo '

'; } // end foreach on multi-edit -// Conditionally add OpenStreetMap.js if geometry columns exist -if (isset($gis_exists) && $gis_exists == true) { - echo(' From bedd7087f369567288ccdbb0898ed4dec90666e3 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Fri, 12 Aug 2011 14:03:40 +0530 Subject: [PATCH 90/98] Wrap long lines --- libraries/gis_visualization.lib.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libraries/gis_visualization.lib.php b/libraries/gis_visualization.lib.php index 537d27ab44..a35af807ef 100644 --- a/libraries/gis_visualization.lib.php +++ b/libraries/gis_visualization.lib.php @@ -86,7 +86,8 @@ function PMA_GIS_modifyQuery($sql_query, $visualizationSettings) . '`) AS `' . $visualizationSettings['spatialColumn'] . '`, '; // Get the SRID - $modified_query .= 'SRID(`' . $visualizationSettings['spatialColumn'] . '`) AS `srid` '; + $modified_query .= 'SRID(`' . $visualizationSettings['spatialColumn'] + . '`) AS `srid` '; } // Append the rest of the query @@ -100,14 +101,16 @@ function PMA_GIS_modifyQuery($sql_query, $visualizationSettings) function sanitize($select) { $table_col = $select['table_name'] . "." . $select['column']; - $db_table_col = $select['db'] . "." . $select['table_name'] . "." . $select['column']; + $db_table_col = $select['db'] . "." . $select['table_name'] + . "." . $select['column']; if ($select['expr'] == $select['column']) { return "`" . $select['column'] . "`"; } elseif ($select['expr'] == $table_col) { return "`" . $select['table_name'] . "`.`" . $select['column'] . "`"; } elseif ($select['expr'] == $db_table_col) { - return "`" . $select['db'] . "`.`" . $select['table_name'] . "`.`" . $select['column'] . "`"; + return "`" . $select['db'] . "`.`" . $select['table_name'] + . "`.`" . $select['column'] . "`"; } return $select['expr']; } From 005a4ce61b0f5818f8bcba83f8eda7a3192301f3 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Fri, 12 Aug 2011 15:09:03 +0530 Subject: [PATCH 91/98] Unit test for PMA_GIS_modifyQuery --- test/libraries/PMA_GIS_modifyQuery_test.php | 94 +++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 test/libraries/PMA_GIS_modifyQuery_test.php diff --git a/test/libraries/PMA_GIS_modifyQuery_test.php b/test/libraries/PMA_GIS_modifyQuery_test.php new file mode 100644 index 0000000000..04e9e1adad --- /dev/null +++ b/test/libraries/PMA_GIS_modifyQuery_test.php @@ -0,0 +1,94 @@ +assertEquals( + PMA_GIS_modifyQuery($sql_query, $settings), + $modified_query + ); + } + + /** + * data provider for testModifyQuery + * + * @return data for testModifyQuery + */ + public function provider() + { + return array( + // select * + array( + 'SELECT * FROM `foo` WHERE `bar` = `zoo`', + array('spatialColumn' => 'moo', 'labelColumn' => 'noo'), + 'SELECT `noo`, ASTEXT(`moo`) AS `moo`, SRID(`moo`) AS `srid` FROM `foo` WHERE `bar` = `zoo`' + ), + // select * with no label column + array( + 'SELECT * FROM `foo` WHERE `bar` = `zoo`', + array('spatialColumn' => 'moo'), + 'SELECT ASTEXT(`moo`) AS `moo`, SRID(`moo`) AS `srid` FROM `foo` WHERE `bar` = `zoo`' + ), + // more columns + array( + 'SELECT `aaa`, `moo`, `bbb`, `noo` FROM `foo` WHERE `bar` = `zoo`', + array('spatialColumn' => 'moo', 'labelColumn' => 'noo'), + 'SELECT `noo`, ASTEXT(`moo`) AS `moo`, SRID(`moo`) AS `srid` FROM `foo` WHERE `bar` = `zoo`' + ), + // no labelColumn defined + array( + 'SELECT `moo`, `noo` FROM `foo` WHERE `bar` = `zoo`', + array('spatialColumn' => 'moo'), + 'SELECT ASTEXT(`moo`) AS `moo`, SRID(`moo`) AS `srid` FROM `foo` WHERE `bar` = `zoo`' + ), + // alias for spatialColumn + array( + 'SELECT `aaa` AS `moo`, `noo` FROM `foo` WHERE `bar` = `zoo`', + array('spatialColumn' => 'moo', 'labelColumn' => 'noo'), + 'SELECT `noo`, ASTEXT(`aaa`) AS `moo`, SRID(`aaa`) AS `srid` FROM `foo` WHERE `bar` = `zoo`' + ), + // alias for labelColumn + array( + 'SELECT `moo`, `bbb` AS `noo` FROM `foo` WHERE `bar` = `zoo`', + array('spatialColumn' => 'moo', 'labelColumn' => 'noo'), + 'SELECT `bbb` AS `noo`, ASTEXT(`moo`) AS `moo`, SRID(`moo`) AS `srid` FROM `foo` WHERE `bar` = `zoo`' + ), + // with database names + array( + 'SELECT `db`.`moo`, `db`.`noo` FROM `foo` WHERE `bar` = `zoo`', + array('spatialColumn' => 'moo', 'labelColumn' => 'noo'), + 'SELECT `db`.`noo`, ASTEXT(`db`.`moo`) AS `moo`, SRID(`db`.`moo`) AS `srid` FROM `foo` WHERE `bar` = `zoo`' + ), + // database names plus alias + array( + 'SELECT `db`.`aaa` AS `moo`, `noo` FROM `foo` WHERE `bar` = `zoo`', + array('spatialColumn' => 'moo', 'labelColumn' => 'noo'), + 'SELECT `noo`, ASTEXT(`db`.`aaa`) AS `moo`, SRID(`db`.`aaa`) AS `srid` FROM `foo` WHERE `bar` = `zoo`' + ), + ); + } +} +?> \ No newline at end of file From cb176b2648f0d787d115290212ab829372414a16 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sat, 13 Aug 2011 00:17:36 +0530 Subject: [PATCH 92/98] Unit tests for PMA_GIS_Factory class --- test/classes/gis/PMA_GIS_Factory_test.php | 80 +++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 test/classes/gis/PMA_GIS_Factory_test.php diff --git a/test/classes/gis/PMA_GIS_Factory_test.php b/test/classes/gis/PMA_GIS_Factory_test.php new file mode 100644 index 0000000000..fe6118c9f7 --- /dev/null +++ b/test/classes/gis/PMA_GIS_Factory_test.php @@ -0,0 +1,80 @@ +assertInstanceOf($geom, PMA_GIS_Factory::factory($type)); + } + + /** + * data provider for testFactory + * + * @return data for testFactory + */ + public function providerForTestFactory() + { + return array( + array( + 'MULTIPOLYGON', + 'PMA_GIS_Multipolygon' + ), + array( + 'POLYGON', + 'PMA_GIS_Polygon' + ), + array( + 'MULTILINESTRING', + 'PMA_GIS_Multilinestring' + ), + array( + 'LINESTRING', + 'PMA_GIS_Linestring' + ), + array( + 'MULTIPOINT', + 'PMA_GIS_Multipoint' + ), + array( + 'POINT', + 'PMA_GIS_Point' + ), + array( + 'GEOMETRYCOLLECTION', + 'PMA_GIS_Geometrycollection' + ), + ); + } +} +?> \ No newline at end of file From d6bf1cd451be99703fe428fb90747ef71b625a3e Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sat, 13 Aug 2011 10:02:39 +0530 Subject: [PATCH 93/98] Adhere to coding style --- libraries/gis/pma_gis_geometry.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libraries/gis/pma_gis_geometry.php b/libraries/gis/pma_gis_geometry.php index c959c081a5..c49c1a1eb8 100644 --- a/libraries/gis/pma_gis_geometry.php +++ b/libraries/gis/pma_gis_geometry.php @@ -134,13 +134,15 @@ abstract class PMA_GIS_Geometry /** * Generate parameters for the GIS data editor from the value of the GIS column. - * This method performs common work. More specific work is performed by each of the geom classes. + * This method performs common work. + * More specific work is performed by each of the geom classes. * * @param $gis_string $value of the GIS column * - * @return array parameters for the GIS data editor from the value of the GIS column + * @return array parameters for the GIS editor from the value of the GIS column */ - protected function generateParams($value) { + protected function generateParams($value) + { $geom_types = '(POINT|MULTIPOINT|LINESTRING|MULTILINESTRING|POLYGON|MULTIPOLYGON|GEOMETRYCOLLECTION)'; $srid = 0; $wkt = ''; From 9ed1cd7c3ef2eb5cb9b3511aec280f89937b3cd0 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sat, 13 Aug 2011 10:10:32 +0530 Subject: [PATCH 94/98] Use abstract test class to avoid code duplications in tests --- test/classes/gis/PMA_GIS_Geometry_test.php | 60 ++++++++++++++++ test/classes/gis/PMA_GIS_Linestring_test.php | 56 ++------------- .../gis/PMA_GIS_Multilinestring_test.php | 72 ++++--------------- test/classes/gis/PMA_GIS_Multipoint_test.php | 58 ++++----------- .../classes/gis/PMA_GIS_Multipolygon_test.php | 48 +------------ test/classes/gis/PMA_GIS_Point_test.php | 69 +++++------------- test/classes/gis/PMA_GIS_Polygon_test.php | 48 +------------ 7 files changed, 115 insertions(+), 296 deletions(-) create mode 100644 test/classes/gis/PMA_GIS_Geometry_test.php diff --git a/test/classes/gis/PMA_GIS_Geometry_test.php b/test/classes/gis/PMA_GIS_Geometry_test.php new file mode 100644 index 0000000000..37d4c423c5 --- /dev/null +++ b/test/classes/gis/PMA_GIS_Geometry_test.php @@ -0,0 +1,60 @@ + test classes + * + * @package phpMyAdmin-test + */ + +require_once 'libraries/gis/pma_gis_geometry.php'; + +/** + * Abstract parent class for all PMA_GIS_ test classes + */ +abstract class PMA_GIS_GeometryTest extends PHPUnit_Framework_TestCase +{ + /** + * test generateWkt method + * + * @param array $gis_data array of GIS data + * @param int $index index + * @param string $empty string to be insterted in place of missing values + * @param string $wkt expected WKT + * + * @return nothing + * @dataProvider providerForTestGenerateWkt + */ + public function testGenerateWkt($gis_data, $index, $empty, $wkt) + { + if ($empty == null) { + $this->assertEquals($this->object->generateWkt($gis_data, $index), $wkt); + } else { + $this->assertEquals( + $this->object->generateWkt($gis_data, $index, $empty), + $wkt + ); + } + } + + /** + * test generateParams method + * + * @param string $wkt point in WKT form + * @param index $index index + * @param array $params expected output array + * + * @dataProvider providerForTestGenerateParams + * @return nothing + */ + public function testGenerateParams($wkt, $index, $params) + { + if ($index == null) { + $this->assertEquals($this->object->generateParams($wkt), $params); + } else { + $this->assertEquals( + $this->object->generateParams($wkt, $index), + $params + ); + } + } +} +?> \ No newline at end of file diff --git a/test/classes/gis/PMA_GIS_Linestring_test.php b/test/classes/gis/PMA_GIS_Linestring_test.php index 13397e3139..4bef75c3d9 100644 --- a/test/classes/gis/PMA_GIS_Linestring_test.php +++ b/test/classes/gis/PMA_GIS_Linestring_test.php @@ -5,13 +5,14 @@ * @package phpMyAdmin-test */ +require_once 'PMA_GIS_Geometry_test.php'; require_once 'libraries/gis/pma_gis_geometry.php'; require_once 'libraries/gis/pma_gis_linestring.php'; /** * Tests for PMA_GIS_Linestring class */ -class PMA_GIS_LinestringTest extends PHPUnit_Framework_TestCase +class PMA_GIS_LinestringTest extends PMA_GIS_GeometryTest { /** * @var PMA_GIS_Linestring @@ -43,29 +44,6 @@ class PMA_GIS_LinestringTest extends PHPUnit_Framework_TestCase unset($this->object); } - /** - * test generateWkt method - * - * @param array $gis_data array of GIS data - * @param int $index index - * @param string $empty string to be insterted in place of missing values - * @param string $wkt expected WKT - * - * @return nothing - * @dataProvider providerForTestGenerateWkt - */ - public function testGenerateWkt($gis_data, $index, $empty, $wkt) - { - if ($empty == null) { - $this->assertEquals($this->object->generateWkt($gis_data, $index), $wkt); - } else { - $this->assertEquals( - $this->object->generateWkt($gis_data, $index, $empty), - $wkt - ); - } - } - /** * data provider for testGenerateWkt * @@ -75,10 +53,10 @@ class PMA_GIS_LinestringTest extends PHPUnit_Framework_TestCase { $temp1 = array( 0 => array( - 'LINESTRING' => array( + 'LINESTRING' => array( 'no_of_points' => 2, - 0 => array('x' => 5.02, 'y' => 8.45), - 1 => array('x' => 6.14, 'y' => 0.15) + 0 => array('x' => 5.02, 'y' => 8.45), + 1 => array('x' => 6.14, 'y' => 0.15) ) ) ); @@ -125,28 +103,6 @@ class PMA_GIS_LinestringTest extends PHPUnit_Framework_TestCase ); } - /** - * test generateParams method - * - * @param string $wkt point in WKT form - * @param index $index index - * @param array $params expected output array - * - * @dataProvider providerForTestGenerateParams - * @return nothing - */ - public function testGenerateParams($wkt, $index, $params) - { - if ($index == 0) { - $this->assertEquals($this->object->generateParams($wkt), $params); - } else { - $this->assertEquals( - $this->object->generateParams($wkt, $index), - $params - ); - } - } - /** * data provider for testGenerateParams * @@ -167,7 +123,7 @@ class PMA_GIS_LinestringTest extends PHPUnit_Framework_TestCase return array( array( "'LINESTRING(5.02 8.45,6.14 0.15)',124", - 0, + null, array( 'srid' => '124', 0 => $temp diff --git a/test/classes/gis/PMA_GIS_Multilinestring_test.php b/test/classes/gis/PMA_GIS_Multilinestring_test.php index d55cd3fdd9..cef0cefbbc 100644 --- a/test/classes/gis/PMA_GIS_Multilinestring_test.php +++ b/test/classes/gis/PMA_GIS_Multilinestring_test.php @@ -5,15 +5,16 @@ * @package phpMyAdmin-test */ +require_once 'PMA_GIS_Geometry_test.php'; require_once 'libraries/gis/pma_gis_geometry.php'; require_once 'libraries/gis/pma_gis_multilinestring.php'; /** * Tests for PMA_GIS_Multilinestring class */ -class PMA_GIS_MultilinestringTest extends PHPUnit_Framework_TestCase +class PMA_GIS_MultilinestringTest extends PMA_GIS_GeometryTest { - /** + /** * @var PMA_GIS_Multilinestring * @access protected */ @@ -43,29 +44,6 @@ class PMA_GIS_MultilinestringTest extends PHPUnit_Framework_TestCase unset($this->object); } - /** - * test generateWkt method - * - * @param array $gis_data array of GIS data - * @param int $index index - * @param string $empty string to be insterted in place of missing values - * @param string $wkt expected WKT - * - * @return nothing - * @dataProvider providerForTestGenerateWkt - */ - public function testGenerateWkt($gis_data, $index, $empty, $wkt) - { - if ($empty == null) { - $this->assertEquals($this->object->generateWkt($gis_data, $index), $wkt); - } else { - $this->assertEquals( - $this->object->generateWkt($gis_data, $index, $empty), - $wkt - ); - } - } - /** * data provider for testGenerateWkt * @@ -75,18 +53,18 @@ class PMA_GIS_MultilinestringTest extends PHPUnit_Framework_TestCase { $temp = array( 0 => array( - 'MULTILINESTRING' => array( + 'MULTILINESTRING' => array( 'no_of_lines' => 2, - 0 => array( - 'no_of_points' => 2, - 0 => array('x' => 5.02, 'y' => 8.45), - 1 => array('x' => 6.14, 'y' => 0.15) - ), - 1 => array( - 'no_of_points' => 2, - 0 => array('x' => 1.23, 'y' => 4.25), - 1 => array('x' => 9.15, 'y' => 0.47) - ) + 0 => array( + 'no_of_points' => 2, + 0 => array('x' => 5.02, 'y' => 8.45), + 1 => array('x' => 6.14, 'y' => 0.15) + ), + 1 => array( + 'no_of_points' => 2, + 0 => array('x' => 1.23, 'y' => 4.25), + 1 => array('x' => 9.15, 'y' => 0.47) + ) ) ) ); @@ -156,28 +134,6 @@ class PMA_GIS_MultilinestringTest extends PHPUnit_Framework_TestCase ); } - /** - * test generateParams method - * - * @param string $wkt point in WKT form - * @param index $index index - * @param array $params expected output array - * - * @dataProvider providerForTestGenerateParams - * @return nothing - */ - public function testGenerateParams($wkt, $index, $params) - { - if ($index == null) { - $this->assertEquals($this->object->generateParams($wkt), $params); - } else { - $this->assertEquals( - $this->object->generateParams($wkt, $index), - $params - ); - } - } - /** * data provider for testGenerateParams * diff --git a/test/classes/gis/PMA_GIS_Multipoint_test.php b/test/classes/gis/PMA_GIS_Multipoint_test.php index f0d0cf2a59..8ab0aef928 100644 --- a/test/classes/gis/PMA_GIS_Multipoint_test.php +++ b/test/classes/gis/PMA_GIS_Multipoint_test.php @@ -5,13 +5,14 @@ * @package phpMyAdmin-test */ +require_once 'PMA_GIS_Geometry_test.php'; require_once 'libraries/gis/pma_gis_geometry.php'; require_once 'libraries/gis/pma_gis_multipoint.php'; /** * Tests for PMA_GIS_Multipoint class */ -class PMA_GIS_MultipointTest extends PHPUnit_Framework_TestCase +class PMA_GIS_MultipointTest extends PMA_GIS_GeometryTest { /** * @var PMA_GIS_Multipoint @@ -43,21 +44,6 @@ class PMA_GIS_MultipointTest extends PHPUnit_Framework_TestCase unset($this->object); } - /** - * test generateWkt method - * - * @param array $gis_data array of GIS data - * @param int $index index - * @param string $wkt expected WKT - * - * @dataProvider providerForTestGenerateWkt - * @return nothing - */ - public function testGenerateWkt($gis_data, $index, $wkt) - { - $this->assertEquals($this->object->generateWkt($gis_data, $index), $wkt); - } - /** * data provider for testGenerateWkt * @@ -67,15 +53,15 @@ class PMA_GIS_MultipointTest extends PHPUnit_Framework_TestCase { $gis_data1 = array( 0 => array( - 'MULTIPOINT' => array( + 'MULTIPOINT' => array( 'no_of_points' => 2, - 0 => array( - 'x' => 5.02, - 'y' => 8.45 + 0 => array( + 'x' => 5.02, + 'y' => 8.45 ), 1 => array( - 'x' => 1.56, - 'y' => 4.36 + 'x' => 1.56, + 'y' => 4.36 ) ) ) @@ -88,11 +74,13 @@ class PMA_GIS_MultipointTest extends PHPUnit_Framework_TestCase array( $gis_data1, 0, + null, 'MULTIPOINT(5.02 8.45,1.56 4.36)' ), array( $gis_data2, 0, + null, 'MULTIPOINT(5.02 8.45)' ) ); @@ -106,7 +94,7 @@ class PMA_GIS_MultipointTest extends PHPUnit_Framework_TestCase public function testGetShape() { $gis_data = array( - 'numpoints' => 2, + 'numpoints' => 2, 'points' => array( 0 => array('x' => 5.02, 'y' => 8.45), 1 => array('x' => 6.14, 'y' => 0.15) @@ -119,28 +107,6 @@ class PMA_GIS_MultipointTest extends PHPUnit_Framework_TestCase ); } - /** - * test generateParams method - * - * @param string $wkt point in WKT form - * @param index $index index - * @param array $params expected output array - * - * @dataProvider providerForTestGenerateParams - * @return nothing - */ - public function testGenerateParams($wkt, $index, $params) - { - if ($index == 0) { - $this->assertEquals($this->object->generateParams($wkt), $params); - } else { - $this->assertEquals( - $this->object->generateParams($wkt, $index), - $params - ); - } - } - /** * data provider for testGenerateParams * @@ -161,7 +127,7 @@ class PMA_GIS_MultipointTest extends PHPUnit_Framework_TestCase return array( array( "'MULTIPOINT(5.02 8.45,6.14 0.15)',124", - 0, + null, array( 'srid' => '124', 0 => $temp1 diff --git a/test/classes/gis/PMA_GIS_Multipolygon_test.php b/test/classes/gis/PMA_GIS_Multipolygon_test.php index 6ac30a9b2d..1a43555b56 100644 --- a/test/classes/gis/PMA_GIS_Multipolygon_test.php +++ b/test/classes/gis/PMA_GIS_Multipolygon_test.php @@ -5,13 +5,14 @@ * @package phpMyAdmin-test */ +require_once 'PMA_GIS_Geometry_test.php'; require_once 'libraries/gis/pma_gis_geometry.php'; require_once 'libraries/gis/pma_gis_multipolygon.php'; /** * Tests for PMA_GIS_Multipolygon class */ -class PMA_GIS_MultipolygonTest extends PHPUnit_Framework_TestCase +class PMA_GIS_MultipolygonTest extends PMA_GIS_GeometryTest { /** * @var PMA_GIS_Multipolygon @@ -80,29 +81,6 @@ class PMA_GIS_MultipolygonTest extends PHPUnit_Framework_TestCase ); } - /** - * test generateWkt method - * - * @param array $gis_data array of GIS data - * @param int $index index - * @param string $empty string to be insterted in place of missing values - * @param string $wkt expected WKT - * - * @return nothing - * @dataProvider providerForTestGenerateWkt - */ - public function testGenerateWkt($gis_data, $index, $empty, $wkt) - { - if ($empty == null) { - $this->assertEquals($this->object->generateWkt($gis_data, $index), $wkt); - } else { - $this->assertEquals( - $this->object->generateWkt($gis_data, $index, $empty), - $wkt - ); - } - } - /** * data provider for testGenerateWkt * @@ -125,28 +103,6 @@ class PMA_GIS_MultipolygonTest extends PHPUnit_Framework_TestCase ); } - /** - * test generateParams method - * - * @param string $wkt point in WKT form - * @param index $index index - * @param array $params expected output array - * - * @dataProvider providerForTestGenerateParams - * @return nothing - */ - public function testGenerateParams($wkt, $index, $params) - { - if ($index == null) { - $this->assertEquals($this->object->generateParams($wkt), $params); - } else { - $this->assertEquals( - $this->object->generateParams($wkt, $index), - $params - ); - } - } - /** * data provider for testGenerateParams * diff --git a/test/classes/gis/PMA_GIS_Point_test.php b/test/classes/gis/PMA_GIS_Point_test.php index b6bbd208fc..a25a66ab95 100644 --- a/test/classes/gis/PMA_GIS_Point_test.php +++ b/test/classes/gis/PMA_GIS_Point_test.php @@ -5,13 +5,14 @@ * @package phpMyAdmin-test */ +require_once 'PMA_GIS_Geometry_test.php'; require_once 'libraries/gis/pma_gis_geometry.php'; require_once 'libraries/gis/pma_gis_point.php'; /** * Tests for PMA_GIS_Point class. */ -class PMA_GIS_PointTest extends PHPUnit_Framework_TestCase +class PMA_GIS_PointTest extends PMA_GIS_GeometryTest { /** * @var PMA_GIS_Point @@ -43,21 +44,6 @@ class PMA_GIS_PointTest extends PHPUnit_Framework_TestCase unset($this->object); } - /** - * test generateWkt method - * - * @param array $gis_data array containing the GIS data - * @param int $index index to the array - * @param string $wkt expected Well Known Text - * - * @dataProvider providerForTestGenerateWkt - * @return nothing - */ - public function testGenerateWkt($gis_data, $index, $wkt) - { - $this->assertEquals($this->object->generateWkt($gis_data, $index), $wkt); - } - /** * data provider for testGenerateWkt * @@ -69,26 +55,31 @@ class PMA_GIS_PointTest extends PHPUnit_Framework_TestCase array( array(0 => array('POINT' => array('x' => 5.02, 'y' => 8.45))), 0, + null, 'POINT(5.02 8.45)' ), array( array(0 => array('POINT' => array('x' => 5.02, 'y' => 8.45))), 1, + null, 'POINT( )' ), array( array(0 => array('POINT' => array('x' => 5.02))), 0, + null, 'POINT(5.02 )' ), array( array(0 => array('POINT' => array('y' => 8.45))), 0, + null, 'POINT( 8.45)' ), array( array(0 => array('POINT' => array())), 0, + null, 'POINT( )' ), ); @@ -123,28 +114,6 @@ class PMA_GIS_PointTest extends PHPUnit_Framework_TestCase ); } - /** - * test generateParams method - * - * @param string $wkt point in WKT form - * @param array $params expected output array - * @param index $index index - * - * @dataProvider providerForTestGenerateParams - * @return nothing - */ - public function testGenerateParams($wkt, $params, $index) - { - if ($index == 0) { - $this->assertEquals($this->object->generateParams($wkt), $params); - } else { - $this->assertEquals( - $this->object->generateParams($wkt, $index), - $params - ); - } - } - /** * data provider for testGenerateParams * @@ -155,23 +124,23 @@ class PMA_GIS_PointTest extends PHPUnit_Framework_TestCase return array( array( "'POINT(5.02 8.45)',124", + null, array( 'srid' => '124', 0 => array( - 'POINT' => array('x' => '5.02', 'y' => '8.45') - ), - ), - 0 - ), - array( - 'POINT(5.02 8.45)', - array( - 2 => array( - 'gis_type' => 'POINT', 'POINT' => array('x' => '5.02', 'y' => '8.45') ), - ), - 2 + ) + ), + array( + 'POINT(5.02 8.45)', + 2, + array( + 2 => array( + 'gis_type' => 'POINT', + 'POINT' => array('x' => '5.02', 'y' => '8.45') + ), + ) ) ); } diff --git a/test/classes/gis/PMA_GIS_Polygon_test.php b/test/classes/gis/PMA_GIS_Polygon_test.php index 20fde1b20d..b504acc12e 100644 --- a/test/classes/gis/PMA_GIS_Polygon_test.php +++ b/test/classes/gis/PMA_GIS_Polygon_test.php @@ -5,13 +5,14 @@ * @package phpMyAdmin-test */ +require_once 'PMA_GIS_Geometry_test.php'; require_once 'libraries/gis/pma_gis_geometry.php'; require_once 'libraries/gis/pma_gis_polygon.php'; /** * Tests for PMA_GIS_Polygon class */ -class PMA_GIS_PolygonTest extends PHPUnit_Framework_TestCase +class PMA_GIS_PolygonTest extends PMA_GIS_GeometryTest { /** * @var PMA_GIS_Polygon @@ -67,29 +68,6 @@ class PMA_GIS_PolygonTest extends PHPUnit_Framework_TestCase ); } - /** - * test generateWkt method - * - * @param array $gis_data array of GIS data - * @param int $index index - * @param string $empty string to be insterted in place of missing values - * @param string $wkt expected WKT - * - * @return nothing - * @dataProvider providerForTestGenerateWkt - */ - public function testGenerateWkt($gis_data, $index, $empty, $wkt) - { - if ($empty == null) { - $this->assertEquals($this->object->generateWkt($gis_data, $index), $wkt); - } else { - $this->assertEquals( - $this->object->generateWkt($gis_data, $index, $empty), - $wkt - ); - } - } - /** * data provider for testGenerateWkt * @@ -135,28 +113,6 @@ class PMA_GIS_PolygonTest extends PHPUnit_Framework_TestCase ); } - /** - * test generateParams method - * - * @param string $wkt point in WKT form - * @param index $index index - * @param array $params expected output array - * - * @dataProvider providerForTestGenerateParams - * @return nothing - */ - public function testGenerateParams($wkt, $index, $params) - { - if ($index == null) { - $this->assertEquals($this->object->generateParams($wkt), $params); - } else { - $this->assertEquals( - $this->object->generateParams($wkt, $index), - $params - ); - } - } - /** * data provider for testGenerateParams * From 16a039392b4a8ea028b38f969ef7e4e586532b94 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sat, 13 Aug 2011 10:11:08 +0530 Subject: [PATCH 95/98] Remove tab characters --- test/classes/gis/PMA_GIS_Factory_test.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/classes/gis/PMA_GIS_Factory_test.php b/test/classes/gis/PMA_GIS_Factory_test.php index fe6118c9f7..6d778ab799 100644 --- a/test/classes/gis/PMA_GIS_Factory_test.php +++ b/test/classes/gis/PMA_GIS_Factory_test.php @@ -47,7 +47,7 @@ class PMA_GIS_FactoryTest extends PHPUnit_Framework_TestCase { return array( array( - 'MULTIPOLYGON', + 'MULTIPOLYGON', 'PMA_GIS_Multipolygon' ), array( @@ -59,19 +59,19 @@ class PMA_GIS_FactoryTest extends PHPUnit_Framework_TestCase 'PMA_GIS_Multilinestring' ), array( - 'LINESTRING', + 'LINESTRING', 'PMA_GIS_Linestring' ), array( - 'MULTIPOINT', + 'MULTIPOINT', 'PMA_GIS_Multipoint' ), array( - 'POINT', + 'POINT', 'PMA_GIS_Point' ), - array( - 'GEOMETRYCOLLECTION', + array( + 'GEOMETRYCOLLECTION', 'PMA_GIS_Geometrycollection' ), ); From 5744b9622d0bc76250e20127fd4a0329919f4af9 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sat, 13 Aug 2011 17:24:39 +0530 Subject: [PATCH 96/98] Documentation about importing ESRI Shapefiles --- Documentation.html | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/Documentation.html b/Documentation.html index 8f7e66f871..8238b31547 100644 --- a/Documentation.html +++ b/Documentation.html @@ -4373,6 +4373,41 @@ INSERT INTO REL_towns VALUES ('M', 'Montréal');

Not every table can be put to the chart. Only tables with one, two or three columns can be visualised as a chart. Moreover the table must be in a special format for chart script to understand it. Currently supported formats can be found in the wiki.

+

+ 6.30 Import: How can I import ESRI Shapefiles

+ +

+ An ESRI Shapefile is actually a set of several files, where .shp file contains + geometry data and .dbf file contains data related to those geometry data. + To read data from .dbf file you need to have PHP compiled with the dBase extension + (--enable-dbase). Otherwise only geometry data will be imported. +

+ +

To upload these set of files you can use either of the following methods:

+
    +
  • +

    + Configure upload directory with + $cfg['UploadDir'], upload both + .shp and .dbf files with the same filename and chose the .shp file from the import page. +

    +
  • +
  • +

    + Create a Zip archive with .shp and .dbf files and import it. For this to work, + you need to set $cfg['TempDir'] to a + place where the web server user can write (for example './tmp'). +

    + +

    To create the temporary directory on a UNIX-based system, you can do:

    +
    +cd phpMyAdmin
    +mkdir tmp
    +chmod o+rwx tmp
    +
    +
  • +
+

phpMyAdmin project

From 5e11e88a147e16c96c33547e199dca31d1a20c77 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Sat, 13 Aug 2011 17:31:38 +0530 Subject: [PATCH 97/98] Mention the use of TempDir for ESRI Shapefile imports --- Documentation.html | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Documentation.html b/Documentation.html index 8238b31547..758a2bc90f 100644 --- a/Documentation.html +++ b/Documentation.html @@ -2088,9 +2088,10 @@ $cfg['TrustedProxies'] = The name of the directory where temporary files can be stored.

- This is needed to work around limitations of open_basedir - for uploaded files, see - FAQ + This is needed for importing ESRI Shapefiles, see + FAQ + 6.30 and to work around limitations of open_basedir for uploaded + files, see FAQ 1.11.

From 79b5bd602e50cc5eff4c32c85df673f7eac94862 Mon Sep 17 00:00:00 2001 From: Madhura Jayaratne Date: Wed, 17 Aug 2011 19:14:43 +0530 Subject: [PATCH 98/98] Changelog entries for GIS features --- ChangeLog | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ChangeLog b/ChangeLog index e6c1bc4605..f70eae5870 100644 --- a/ChangeLog +++ b/ChangeLog @@ -44,6 +44,9 @@ phpMyAdmin - ChangeLog - bug #3380946 [export] no uid Query result export (Suhosin limit) + Grid editing in browse mode (replaces row inline edit) + Zoom-search in table Search ++ [interface] Editor for GIS data ++ [import] Import GIS data from ESRI Shapefiles ++ [interface] 'Function based search' for GIS data 3.4.5.0 (not yet released) - bug #3375325 [interface] Page list in navigation frame looks odd