Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/spatialite integration #8

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
14a3bf0
Extract DoctrineBaseDriver getSearchQueryBuilder method from search
eSlider Jul 24, 2017
036a644
Add spatialite driver
eSlider Jul 24, 2017
adda598
Requiere spatialite driver
eSlider Jul 24, 2017
197cc83
Improve fill method of BaseConfiguration entity to get parse annotations
eSlider Jul 24, 2017
8772328
Add getGeomAttributeAsJson method to PostgreSQL
eSlider Jul 31, 2017
25a122a
Set DataStore to use ContainerAwareTrait instead of ContainerAware
eSlider Aug 28, 2017
9a74058
Get request object from symfony2 request_stack
eSlider Aug 30, 2017
e79c620
Add fallback for save feature, if auto generating ID fails
eSlider Sep 4, 2017
723a2b0
Optimize import of DataStore.php
eSlider Sep 7, 2017
1f1dafa
Fix decode multipart request content
eSlider Dec 13, 2017
84988f3
Extract DoctrineBaseDriver getSearchQueryBuilder method from search
eSlider Jul 24, 2017
c3471c3
Add spatialite driver
eSlider Jul 24, 2017
2fe42d2
Requiere spatialite driver
eSlider Jul 24, 2017
81a2031
Improve fill method of BaseConfiguration entity to get parse annotations
eSlider Jul 24, 2017
0715af6
Add getGeomAttributeAsJson method to PostgreSQL
eSlider Jul 31, 2017
92bace9
Set DataStore to use ContainerAwareTrait instead of ContainerAware
eSlider Aug 28, 2017
e2c11d4
Get request object from symfony2 request_stack
eSlider Aug 30, 2017
ae9c84d
Add fallback for save feature, if auto generating ID fails
eSlider Sep 4, 2017
a842ae4
Optimize import of DataStore.php
eSlider Sep 7, 2017
fb5c541
Set appropriate Content-Type header for JSON-serialized response
werrolf Sep 28, 2017
54fffea
Fix decode multipart request content
eSlider Dec 13, 2017
eb2e810
Merge master branch
eSlider Dec 13, 2017
0b60ddf
Merge feature/spatialite-integration
eSlider Dec 13, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions Component/DataStore.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Statement;
use FOM\UserBundle\Entity\User;
use Mapbender\DataSourceBundle\Component\Drivers\BaseDriver;
use Mapbender\DataSourceBundle\Component\Drivers\DoctrineBaseDriver;
use Mapbender\DataSourceBundle\Component\Drivers\Interfaces\Base;
Expand All @@ -12,7 +11,7 @@
use Mapbender\DataSourceBundle\Component\Drivers\YAML;
use Mapbender\DataSourceBundle\Entity\DataItem;
use Symfony\Component\Config\Definition\Exception\Exception;
use Symfony\Component\DependencyInjection\ContainerAware;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
Expand All @@ -23,8 +22,10 @@
* @package Mapbender\DataSourceBundle
* @author Andriy Oblivantsev <eslider@gmail.com>
*/
class DataStore extends ContainerAware
class DataStore
{
use ContainerAwareTrait;

const ORACLE_PLATFORM = 'oracle';
const POSTGRESQL_PLATFORM = 'postgresql';
const SQLITE_PLATFORM = 'sqlite';
Expand Down
63 changes: 42 additions & 21 deletions Component/Drivers/DoctrineBaseDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -244,27 +244,7 @@ public function getSelectQueryBuilder(array $fields = array())
*/
public function search(array $criteria = array())
{

/** @var Statement $statement */
$maxResults = isset($criteria['maxResults']) ? intval($criteria['maxResults']) : self::MAX_RESULTS;
$where = isset($criteria['where']) ? $criteria['where'] : null;
$queryBuilder = $this->getSelectQueryBuilder();
// $returnType = isset($criteria['returnType']) ? $criteria['returnType'] : null;

// add filter (https://trac.wheregroup.com/cp/issues/3733)
if (!empty($this->sqlFilter)) {
$queryBuilder->andWhere($this->sqlFilter);
}

// add second filter (https://trac.wheregroup.com/cp/issues/4643)
if ($where) {
$queryBuilder->andWhere($where);
}

$queryBuilder->setMaxResults($maxResults);
// $queryBuilder->setParameters($params);
$statement = $queryBuilder->execute();
$rows = $statement->fetchAll();
$rows = $this->getSearchQueryBuilder($criteria)->execute()->fetchAll();
$hasResults = count($rows) > 0;

// Cast array to DataItem array list
Expand Down Expand Up @@ -439,6 +419,34 @@ public function getLastInsertId()
return $this->getConnection()->lastInsertId();
}

/**
* Get search query builder
*
* @param array $criteria
* @return QueryBuilder
*/
public function getSearchQueryBuilder(array $criteria)
{
/** @var Statement $statement */
$maxResults = isset($criteria['maxResults']) ? intval($criteria['maxResults']) : self::MAX_RESULTS;
$where = isset($criteria['where']) ? $criteria['where'] : null;
$queryBuilder = $this->getSelectQueryBuilder();
// $returnType = isset($criteria['returnType']) ? $criteria['returnType'] : null;

// add filter (https://trac.wheregroup.com/cp/issues/3733)
if (!empty($this->sqlFilter)) {
$queryBuilder->andWhere($this->sqlFilter);
}

// add second filter (https://trac.wheregroup.com/cp/issues/4643)
if ($where) {
$queryBuilder->andWhere($where);
}

$queryBuilder->setMaxResults($maxResults);
return $queryBuilder;
}

/**
* Extract ordered type list from two associate key lists of data and types.
*
Expand All @@ -459,4 +467,17 @@ protected function extractTypeValues(array $data, array $types)

return $typeValues;
}

/**
* Return next possible ID
*
* @return mixed
*/
public function getNextPossibleId()
{
$con = $this->connection;
return $con->fetchColumn('SELECT MAX('
. $con->quoteIdentifier($this->getUniqueId())
. ")+1 FROM " . $con->quoteIdentifier($this->getTableName()));
}
}
11 changes: 11 additions & 0 deletions Component/Drivers/PostgreSQL.php
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,17 @@ public function getGeomAttributeAsWkt($geometryAttribute, $sridTo)
return "ST_ASTEXT(ST_TRANSFORM($geomFieldName, $sridTo)) AS $geomFieldName";
}

/**
* @inheritdoc
*/
public function getGeomAttributeAsJson($geometryAttribute, $sridTo)
{
$connection = $this->getConnection();
$geomFieldName = $connection->quoteIdentifier($geometryAttribute);
$sridTo = is_numeric($sridTo)?intval($sridTo):$connection->quote($sridTo);
return "ST_AsGeoJSON(ST_TRANSFORM($geomFieldName, $sridTo)) AS $geomFieldName";
}

/**
* @inheritdoc
*/
Expand Down
132 changes: 131 additions & 1 deletion Component/Drivers/SQLite.php
Original file line number Diff line number Diff line change
@@ -1,14 +1,36 @@
<?php

namespace Mapbender\DataSourceBundle\Component\Drivers;

use Eslider\SpatialiteShellDriver;
use Mapbender\DataSourceBundle\Component\Drivers\Interfaces\Geographic;
use Mapbender\DataSourceBundle\Entity\Feature;

/**
* Class SQLite
*
* @package Mapbender\DataSourceBundle\Component\Drivers
* @author Andriy Oblivantsev <eslider@gmail.com>
*/
class SQLite extends DoctrineBaseDriver
class SQLite extends PostgreSQL implements Geographic
{
/**
* Get spatial driver instance
*
* @return SpatialiteShellDriver|null
*/
public function getSpatialDriver()
{
static $driver = null;

if (!$driver) {
$dbPath = isset($this->settings['path']) ? $this->settings['path'] : $this->container->get('kernel')->getRootDir() . "/app/db/";
$driver = new SpatialiteShellDriver($dbPath);
}

return $driver;
}

/**
* Get table fields
*
Expand All @@ -29,4 +51,112 @@ public function getStoreFields()
}
return $columns;
}

/**
* @inheritdoc
*/
public function search(array $criteria = array())
{
$sql = $this->getSearchQueryBuilder($criteria)->getSQL();
$rows = $this->getSpatialDriver()->query($sql);
$hasResults = count($rows) > 0;

// Cast array to DataItem array list
if ($hasResults) {
$this->prepareResults($rows);
}

return $rows;
}

/**
* Add geometry column
*
* @param $tableName
* @param $type
* @param $srid
* @param string $geomFieldName
* @param string $schemaName
* @param int $dimensions
* @return mixed
*/
public function addGeometryColumn($tableName,
$type,
$srid,
$geomFieldName = "geom",
$schemaName = "public",
$dimensions = 2)
{
$spatialDriver = $this->getSpatialDriver();
return $spatialDriver->addGeometryColumn($tableName, $geomFieldName, $srid, $type);
}

/**
* Get table geometry type
*
* @param $tableName
* @param string $schema
* @return mixed
*/
public function getTableGeomType($tableName, $schema = null)
{
$connection = $this->getSpatialDriver();
if (strpos($tableName, '.')) {
list($schema, $tableName) = explode('.', $tableName);
}
$_schema = $schema ? $connection->quote($schema) : 'current_schema()';

$type = $connection->query("SELECT \"type\"
FROM geometry_columns
WHERE f_table_schema = " . $_schema . "
AND f_table_name = " . $connection->quote($tableName))->fetchColumn();
return $type;
}

/**
* @param $ewkt
* @param null $srid
* @return mixed
* @internal param $wkt
*/
public function transformEwkt($ewkt, $srid = null)
{
$db = $this->getSpatialDriver();
$type = $this->getTableGeomType($this->getTableName());
$wktType = static::getWktType($ewkt);

if ($type
&& $wktType != $type
&& in_array(strtoupper($wktType), Feature::$simpleGeometries)
&& in_array(strtoupper($type), Feature::$complexGeometries)
) {
$ewkt = 'SRID=' . $srid . ';' . $db->fetchColumn("SELECT ST_ASTEXT(ST_TRANSFORM(ST_MULTI(" . $db->quote($ewkt) . "),$srid))");
}

$srid = is_numeric($srid) ? intval($srid) : $db->quote($srid);
$ewkt = $db->quote($ewkt);

return $db->fetchColumn("SELECT ST_TRANSFORM(ST_GEOMFROMTEXT($ewkt), $srid)");
}

/**
* Get WKB geometry attribute as WKT
*
* @param string $tableName
* @param string $geomFieldName
* @return string SQL
*/
public function findGeometryFieldSrid($tableName, $geomFieldName)
{
$connection = $this->getSpatialDriver();
$schemaName = "current_schema()";
if (strpos($tableName, ".")) {
list($schemaName, $tableName) = explode('.', $tableName);
$schemaName = $connection->quote($schemaName);
}

return $connection->fetchColumn("SELECT Find_SRID(" . $schemaName . ",
" . $connection->quote($tableName) . ",
" . $connection->quote($geomFieldName) . ")");
}
}
15 changes: 14 additions & 1 deletion Component/FeatureType.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Doctrine\ORM\Mapping as ORM;
use Mapbender\CoreBundle\Component\Application as AppComponent;
use Mapbender\DataSourceBundle\Component\Drivers\BaseDriver;
use Mapbender\DataSourceBundle\Component\Drivers\DoctrineBaseDriver;
use Mapbender\DataSourceBundle\Component\Drivers\Interfaces\Geographic;
use Mapbender\DataSourceBundle\Component\Drivers\Oracle;
use Mapbender\DataSourceBundle\Component\Drivers\PostgreSQL;
Expand Down Expand Up @@ -191,7 +192,17 @@ public function save($featureData, $autoUpdate = true)
if ($this->allowSave) {
// Insert if no ID given
if (!$autoUpdate || !$feature->hasId()) {
$feature = $this->insert($feature);
try{
$feature = $this->insert($feature);
} catch (\Exception $e){
// Fallback, if can't save, course no auto ID set
// then try it to set it manuel and try to save it one more time.
$driver = $this->getDriver();
if($driver instanceof DoctrineBaseDriver){
$feature->setId($driver->getNextPossibleId());
$feature = $this->insert($feature);
}
}
} // Replace if has ID
else {
$feature = $this->update($feature);
Expand Down Expand Up @@ -313,6 +324,8 @@ public function update($featureData)
*
* @param array $criteria
* @return Feature[]
* @throws \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException
* @throws \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException
*/
public function search(array $criteria = array())
{
Expand Down
2 changes: 1 addition & 1 deletion Controller/BaseController.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class BaseController extends Controller
*/
protected function getRequestData()
{
$content = $this->getRequest()->getContent();
$content = $this->get('request_stack')->getCurrentRequest()->getContent();
$request = array_merge($_POST, $_GET);
if (!empty($content)) {
$request = array_merge($request, json_decode($content, true));
Expand Down
Loading