2 /* vim: set expandtab sw=4 ts=4 sts=4: */
4 * ESRI Shape file import plugin for phpMyAdmin
6 * @package PhpMyAdmin-Import
7 * @subpackage ESRI_Shape
9 if (! defined('PHPMYADMIN')) {
13 // Drizzle does not support GIS data types
18 /* Get the import interface*/
19 require_once 'libraries/plugins/ImportPlugin.class.php';
20 /* Get the ShapeFile class */
21 require_once 'libraries/bfShapeFiles/ShapeFile.lib.php';
22 require_once 'libraries/plugins/import/ShapeFile.class.php';
23 require_once 'libraries/plugins/import/ShapeRecord.class.php';
26 * Handles the import for ESRI Shape files
28 * @package PhpMyAdmin-Import
29 * @subpackage ESRI_Shape
31 class ImportShp
extends ImportPlugin
36 public function __construct()
38 $this->setProperties();
42 * Sets the import plugin properties.
43 * Called in the constructor.
47 protected function setProperties()
49 $props = 'libraries/properties/';
50 include_once "$props/plugins/ImportPluginProperties.class.php";
52 $importPluginProperties = new ImportPluginProperties();
53 $importPluginProperties->setText(__('ESRI Shape File'));
54 $importPluginProperties->setExtension('shp');
55 $importPluginProperties->setOptions(array());
56 $importPluginProperties->setOptionsText(__('Options'));
58 $this->properties
= $importPluginProperties;
62 * This method is called when any PluginManager to which the observer
63 * is attached calls PluginManager::notify()
65 * @param SplSubject $subject The PluginManager notifying the observer
70 public function update (SplSubject
$subject)
75 * Handles the whole import logic
79 public function doImport()
81 global $db, $error, $finished, $compression,
82 $import_file, $local_import_file;
84 if ((int) ini_get('memory_limit') < 512) {
85 @ini_set
('memory_limit', '512M');
89 $GLOBALS['finished'] = false;
94 $shp = new PMA_ShapeFile(1);
95 // If the zip archive has more than one file,
96 // get the correct content to the buffer from .shp file.
97 if ($compression == 'application/zip'
98 && PMA_getNoOfFilesInZip($import_file) > 1
100 $zip_content = PMA_getZipContents($import_file, '/^.*\.shp$/i');
101 $GLOBALS['import_text'] = $zip_content['data'];
104 $temp_dbf_file = false;
105 // We need dbase extension to handle .dbf file
106 if (extension_loaded('dbase')) {
107 // If we can extract the zip archive to 'TempDir'
108 // and use the files in it for import
109 if ($compression == 'application/zip'
110 && ! empty($GLOBALS['cfg']['TempDir'])
111 && is_writable($GLOBALS['cfg']['TempDir'])
113 $dbf_file_name = PMA_findFileFromZipArchive(
114 '/^.*\.dbf$/i', $import_file
116 // If the corresponding .dbf file is in the zip archive
117 if ($dbf_file_name) {
118 // Extract the .dbf file and point to it.
119 $extracted = PMA_zipExtract(
121 realpath($GLOBALS['cfg']['TempDir']),
122 array($dbf_file_name)
125 $dbf_file_path = realpath($GLOBALS['cfg']['TempDir'])
126 . (PMA_IS_WINDOWS ?
'\\' : '/') . $dbf_file_name;
127 $temp_dbf_file = true;
128 // Replace the .dbf with .*, as required
129 // by the bsShapeFiles library.
131 $dbf_file_path, 0, strlen($dbf_file_path) - 4
133 $shp->FileName
= $file_name;
136 } elseif (! empty($local_import_file)
137 && ! empty($GLOBALS['cfg']['UploadDir'])
138 && $compression == 'none'
140 // If file is in UploadDir, use .dbf file in the same UploadDir
141 // to load extra data.
142 // Replace the .shp with .*,
143 // so the bsShapeFiles library correctly locates .dbf file.
144 $file_name = substr($import_file, 0, strlen($import_file) - 4)
146 $shp->FileName
= $file_name;
151 $shp->loadFromFile('');
152 if ($shp->lastError
!= "") {
154 $message = PMA_Message
::error(
155 __('There was an error importing the ESRI shape file: "%s".')
157 $message->addParam($shp->lastError
);
161 // Delete the .dbf file extracted to 'TempDir'
163 && isset($dbf_file_path)
164 && file_exists($dbf_file_path)
166 unlink($dbf_file_path);
186 switch ($shp->shapeType
) {
196 $gis_type = 'multilinestring';
200 $gis_type = 'multipolygon';
204 $gis_type = 'multipoint';
208 if (! isset($esri_types[$shp->shapeType
])) {
209 $message = PMA_Message
::error(
211 'You tried to import an invalid file or the imported file'
212 . ' contains invalid data'
216 $message = PMA_Message
::error(
217 __('MySQL Spatial Extension does not support ESRI type "%s".')
219 $message->addParam($param);
224 if (isset($gis_type)) {
225 include_once './libraries/gis/pma_gis_factory.php';
226 $gis_obj = PMA_GIS_Factory
::factory($gis_type);
231 $num_rows = count($shp->records
);
232 // If .dbf file is loaded, the number of extra data columns
233 $num_data_cols = isset($shp->DBFHeader
) ?
count($shp->DBFHeader
) : 0;
236 $col_names = array();
237 if ($num_rows != 0) {
238 foreach ($shp->records
as $record) {
240 if ($gis_obj == null) {
243 $tempRow[] = "GeomFromText('"
244 . $gis_obj->getShape($record->SHPData
) . "')";
247 if (isset($shp->DBFHeader
)) {
248 foreach ($shp->DBFHeader
as $c) {
249 $cell = trim($record->DBFData
[$c[0]]);
251 if (! strcmp($cell, '')) {
262 if (count($rows) == 0) {
264 $message = PMA_Message
::error(
265 __('The imported file does not contain any data')
270 // Column names for spatial column and the rest of the columns,
271 // if they are available
272 $col_names[] = 'SPATIAL';
273 for ($n = 0; $n < $num_data_cols; $n++
) {
274 $col_names[] = $shp->DBFHeader
[$n][0];
277 // Set table name based on the number of tables
279 $result = PMA_DBI_fetch_result('SHOW TABLES');
280 $table_name = 'TABLE '.(count($result) +
1);
282 $table_name = 'TBL_NAME';
284 $tables = array(array($table_name, $col_names, $rows));
286 // Use data from shape file to chose best-fit MySQL types for each column
288 $analyses[] = PMA_analyzeTable($tables[0]);
290 $table_no = 0; $spatial_col = 0;
291 $analyses[$table_no][TYPES
][$spatial_col] = GEOMETRY
;
292 $analyses[$table_no][FORMATTEDSQL
][$spatial_col] = true;
294 // Set database name to the currently selected one, if applicable
297 $options = array('create_db' => false);
303 // Created and execute necessary SQL statements from data
305 PMA_buildSQL($db_name, $tables, $analyses, $null_param, $options);
313 // Commit any possible data in buffers
314 PMA_importRunQuery();
318 * Returns specified number of bytes from the buffer.
319 * Buffer automatically fetches next chunk of data when the buffer
321 * Sets $eof when $GLOBALS['finished'] is set and the buffer falls short.
323 * @param int $length number of bytes
327 public static function readFromBuffer($length)
329 global $buffer, $eof;
331 if (strlen($buffer) < $length) {
332 if ($GLOBALS['finished']) {
335 $buffer .= PMA_importGetNextChunk();
338 $result = substr($buffer, 0, $length);
339 $buffer = substr($buffer, $length);