Exemplo n.º 1
0
function import_new_geometry()
{
    global $conn, $comment, $is_map, $is_new_document, $culture, $name, $map_editor, $map_scale, $map_code, $keepassociations, $region_type, $newgeomtext, $no_oldgeom, $document_id, $a_type, $fullwipe, $oldgeom, $newgeom, $prgmsg;
    info("Importing the new geometry...\n");
    try {
        $conn->beginTransaction();
        $history_metadata = new HistoryMetadata();
        $history_metadata->setComment(isset($comment) ? $comment : ($is_new_document ? 'Imported new ' . ($is_map ? 'map' : 'area') : 'Updated geometry'));
        $history_metadata->set('is_minor', false);
        $history_metadata->set('user_id', 2);
        // C2C user
        $history_metadata->save();
        if ($is_new_document) {
            $doc = $is_map ? new Map() : new Area();
            $doc->setCulture($culture);
            $doc->set('name', $name);
            if ($is_map) {
                $doc->set('editor', $map_editor);
                $doc->set('scale', $map_scale);
                $doc->set('code', $map_code);
            } else {
                $doc->set('area_type', $region_type);
            }
        } else {
            $doc = Document::find($is_map ? 'Map' : 'Area', $document_id);
            $name = $doc->get('name');
            if (!$is_map) {
                $region_type = $doc->get('area_type');
            }
        }
        $doc->set('geom_wkt', $newgeomtext);
        $doc->save();
        info("Geometry uploaded.\n");
        if ($keepassociations) {
            exit;
        }
        if ($is_new_document) {
            $document_id = $doc->get('id');
        }
        // $conn->commit();
        // $conn->beginTransaction();
        if ($is_map) {
            $a_type = 'dm';
        } else {
            switch ($region_type) {
                case 1:
                    // range
                    $a_type = 'dr';
                    break;
                case 2:
                    // country
                    $a_type = 'dc';
                    break;
                case 3:
                    // dept
                    $a_type = 'dd';
                    break;
            }
        }
        // Some explanation for the following queries:
        // - && operator is used to limit docs to the one whose bouding boxes overlap (it uses spatial index)
        // - ST_Within and ST_Intersects are used to work on the actual geometries
        // - ST_Within apears to be faster, so we use it for 'points' (like summits, huts etc), but we have
        //   to use ST_Intersects for 'geometries' (like outings, maps etc)
        // - we only use a buffer of 200m for areas (because of boundaries imprecision), but not for maps
        // - areas are not linked together
        // - maps are not linked to outings, users, and other maps
        // if it is a new document, we create geoassociations for the whole geometry
        // but if its an updated one, we only create geoassociations for the part of the
        // new geometry that does not intersect with the old one
        if ($is_new_document || $no_oldgeom || $fullwipe) {
            // retrieve geom from the database
            $geomquery = '(SELECT geom FROM ' . ($is_map ? 'maps' : 'areas') . ' WHERE id=?)';
            $geomqueryb = '(SELECT buffer(geom, 200) FROM ' . ($is_map ? 'maps' : 'areas') . ' WHERE id=?)';
            $queryparam = array($document_id, $document_id);
        } else {
            $queryparam = array();
            $creategeom = $conn->standaloneQuery("SELECT ST_Difference('{$newgeom}', '{$oldgeom}')")->fetchAll();
            $creategeomb = $conn->standaloneQuery("SELECT ST_Difference(buffer('{$newgeom}', 200), buffer('{$oldgeom}', 200))")->fetchAll();
            $creategeom = $creategeom[0]['st_difference'];
            $creategeomb = $creategeomb[0]['st_difference'];
            $geomquery = "'{$creategeom}'";
            $geomqueryb = "'{$creategeomb}'";
        }
        // for maps, we don't use buffer at all
        if ($is_map) {
            $geomqueryb = $geomquery;
        }
        $queries = array();
        // point geometry
        $queries[] = array("SELECT id, module FROM documents WHERE geom && {$geomqueryb} " . "AND ST_Within(geom, {$geomqueryb}) " . "AND module IN('summits', 'huts', 'sites', 'parkings', 'products', 'portals', 'images'" . ($is_map ? '' : ", 'users'") . ')', $queryparam);
        // multipoint geometry
        $queries[] = array("SELECT id, module FROM documents WHERE geom && {$geomqueryb} " . "AND ST_Intersects(geom, {$geomqueryb}) AND module" . ($is_map ? "='routes'" : " IN('routes', 'outings')"), $queryparam);
        // for maps areas associations, we always compute 'full wipe', without buffer
        $geomquery = '(SELECT geom FROM ' . ($is_map ? 'maps' : 'areas') . ' WHERE id=?)';
        $queries[] = array("SELECT id, module FROM documents WHERE geom && {$geomquery} " . "AND ST_Intersects(geom, {$geomquery}) AND module='" . ($is_map ? 'areas' : 'maps') . "'", array($document_id, $document_id));
        $results_a = array();
        foreach ($queries as $query) {
            $results_a[] = $conn->standaloneQuery($query[0], $query[1])->fetchAll();
        }
        $results = array();
        foreach ($results_a as $results_set) {
            foreach ($results_set as $d) {
                $results[] = $d;
            }
        }
        $prgmsg = "Create new associations...";
        info($prgmsg);
        $tot = count($results);
        foreach ($results as $i => $d) {
            progression($i, $tot);
            // Apparently in some cases, we ar trying to create associations that
            // already exist, so we check first
            if (!GeoAssociation::find($document_id, $d['id'], null, false)) {
                $a = new GeoAssociation();
                $created[$d['module']] = isset($created[$d['module']]) ? $created[$d['module']] + 1 : 1;
                // for map - area geoassociations, links must not be dm but dr, dc, dd...
                if ($is_map && $d['module'] === 'areas') {
                    $area = Document::find('Area', $d['id']);
                    switch ($area->get('area_type')) {
                        case 1:
                            // range
                            $t_a_type = 'dr';
                            break;
                        case 2:
                            // country
                            $t_a_type = 'dc';
                            break;
                        case 3:
                            // dept
                            $t_a_type = 'dd';
                            break;
                    }
                    $a->doSaveWithValues($document_id, $d['id'], $t_a_type);
                } else {
                    $a->doSaveWithValues($d['id'], $document_id, $a_type);
                }
            }
            // inherited docs: we add geoassociations for the 'inherited docs' from sites, routes and summits
            // but not if they already have a geometry (gps track)
            switch ($d['module']) {
                case 'sites':
                case 'routes':
                    if ($is_map) {
                        break;
                    }
                    // we do not link maps to outings
                    $associated_outings = Association::findAllAssociatedDocs($d['id'], array('id', 'geom_wkt'), $d['module'] === 'routes' ? 'ro' : 'to');
                    if (count($associated_outings)) {
                        foreach ($associated_outings as $outing) {
                            if (!$outing['geom_wkt'] && GeoAssociation::find($outing['id'], $document_id, $a_type) === false) {
                                // we create geoassociation (if it already existed, it has been deleted before in the script)
                                $a = new GeoAssociation();
                                $a->doSaveWithValues($outing['id'], $document_id, $a_type);
                                $created['outings'] = isset($created['outings']) ? $created['outings'] + 1 : 1;
                            }
                        }
                    }
                    break;
                case 'summits':
                    // if summit is of type raid, we should not try to update its routes and outings summit_type=5
                    $summit = Document::find('Summit', $d['id']);
                    if ($summit->get('summit_type') == 5) {
                        break;
                    }
                    $associated_routes = Association::findAllAssociatedDocs($d['id'], array('id', 'geom_wkt'), 'sr');
                    if (count($associated_routes)) {
                        foreach ($associated_routes as $route) {
                            $i = $route['id'];
                            if (!$route['geom_wkt'] && GeoAssociation::find($i, $document_id, $a_type) === false) {
                                $a = new GeoAssociation();
                                $a->doSaveWithValues($i, $document_id, $a_type);
                                $created['routes'] = isset($created['routes']) ? $created['routes'] + 1 : 1;
                                if (!$is_map) {
                                    $associated_outings = Association::findAllAssociatedDocs($i, array('id', 'geom_wkt'), 'ro');
                                    if (count($associated_outings)) {
                                        foreach ($associated_outings as $outing) {
                                            $j = $outing['id'];
                                            if (!$outing['geom_wkt'] && GeoAssociation::find($j, $document_id, $a_type) === false) {
                                                $a = new GeoAssociation();
                                                $a->doSaveWithValues($j, $document_id, $a_type);
                                                $created['outings'] = isset($created['outings']) ? $created['outings'] + 1 : 1;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    break;
            }
        }
        info("\n");
        $conn->commit();
        if (isset($created)) {
            associations_result($created);
        }
        if ($is_new_document) {
            info('Added new ' . ($is_map ? 'map' : 'area') . " {$name} ({$document_id})\n");
        } else {
            info('Updated ' . ($is_map ? 'map' : 'area') . " ({$document_id})\n");
        }
    } catch (Exception $e) {
        $conn->rollback();
        throw $e;
    }
}