├── .github └── workflows │ └── run-tests.yml ├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── config └── postgis.php ├── database └── migrations │ └── enable_postgis.php.stub ├── phpunit.php ├── phpunit.xml ├── src ├── Connectors │ └── ConnectionFactory.php ├── DatabaseServiceProvider.php ├── Eloquent │ ├── Builder.php │ └── PostgisTrait.php ├── Exceptions │ ├── PostgisFieldsNotDefinedException.php │ ├── PostgisTypesMalformedException.php │ ├── UnknownWKTTypeException.php │ └── UnsupportedGeomtypeException.php ├── Geometries │ ├── Factory.php │ ├── Geometry.php │ ├── GeometryCollection.php │ ├── GeometryInterface.php │ ├── LineString.php │ ├── MultiLineString.php │ ├── MultiPoint.php │ ├── MultiPolygon.php │ ├── Point.php │ ├── PointCollection.php │ └── Polygon.php ├── PostgisConnection.php └── Schema │ ├── Blueprint.php │ ├── Builder.php │ └── Grammars │ └── PostgisGrammar.php └── tests ├── BaseTestCase.php ├── Connectors └── ConnectionFactoryTest.php ├── Eloquent └── BuilderTest.php ├── Geometries ├── GeometryCollectionTest.php ├── GeometryTest.php ├── LineStringTest.php ├── MultiLineStringTest.php ├── MultiPointTest.php ├── MultiPolygonTest.php ├── PointTest.php ├── PolygonTest.php └── UnderLocaleTest.php ├── PostgisConnectionTest.php ├── Schema ├── BlueprintTest.php ├── BuilderTest.php └── Grammars │ └── PostgisGrammarTest.php └── Stubs └── PDOStub.php /.github/workflows/run-tests.yml: -------------------------------------------------------------------------------- 1 | name: Test Suite 2 | 3 | on: [push] 4 | 5 | jobs: 6 | tests: 7 | runs-on: ubuntu-latest 8 | 9 | strategy: 10 | matrix: 11 | php: [8.0, 8.1] 12 | release: [stable, lowest] 13 | 14 | services: 15 | postgres: 16 | image: kartoza/postgis:12.1 17 | env: 18 | POSTGRES_USER: postgres 19 | POSTGRES_PASSWORD: postgres 20 | POSTGRES_DBNAME: postgres 21 | ports: 22 | - 5432/tcp 23 | options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 3 24 | 25 | steps: 26 | - uses: actions/checkout@v1 27 | - uses: actions/cache@v1 28 | with: 29 | path: ~/.composer/cache/files 30 | key: php-${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }} 31 | - uses: shivammathur/setup-php@v2 32 | with: 33 | php-version: ${{ matrix.php }} 34 | tools: pecl 35 | extensions: mbstring, dom, fileinfo, pgsql, intl 36 | coverage: ${{ matrix.coverage }} 37 | - run: composer update --no-interaction --no-progress --no-suggest --prefer-dist --prefer-${{ matrix.release }} 38 | - run: | 39 | vendor/bin/phpunit 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | composer.lock 3 | .idea 4 | 5 | .phpunit.result.cache 6 | temp -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Peter Haza 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Laravel Wrapper for PostgreSQL's Geo-Extension Postgis 2 | ====================================================== 3 | 4 | ![Build Status](https://github.com/ajthinking/laravel-postgis/workflows/Test%20Suite/badge.svg) 5 | 6 | For Laravel 9+, PHP 8+ only 7 | 8 | ## Features 9 | 10 | * Work with geometry classes instead of arrays. 11 | ```php 12 | $model->myPoint = new Point(1,2); //lat, long 13 | ``` 14 | 15 | * Adds helpers in migrations. 16 | ```php 17 | $table->polygon('myColumn'); 18 | ``` 19 | 20 | 21 | 22 | ## Installation 23 | ```bash 24 | composer require mstaack/laravel-postgis 25 | ``` 26 | 27 | ## Usage 28 | 29 | To start, ensure you have PostGIS enabled in your database - you can do this in a Laravel migration or manually via SQL. 30 | 31 | ### Enable PostGIS via a Laravel migration 32 | 33 | You need to publish the migration to easily enable PostGIS: 34 | 35 | ```sh 36 | php artisan vendor:publish --provider="Ajthinking\LaravelPostgis\DatabaseServiceProvider" --tag="migrations" 37 | ``` 38 | 39 | And then you run the migrations: 40 | 41 | ```sh 42 | php artisan migrate 43 | ``` 44 | 45 | These methods are safe to use and will only enable / disable the PostGIS extension if relevant - they won't cause an error if PostGIS is / isn't already enabled. 46 | 47 | If you prefer, you can use the `enablePostgis()` method which will throw an error if PostGIS is already enabled, and the `disablePostgis()` method twhich will throw an error if PostGIS isn't enabled. 48 | 49 | ### Enable PostGIS manually 50 | 51 | Use an SQL client to connect to your database and run the following command: 52 | 53 | CREATE EXTENSION postgis; 54 | 55 | To verify that PostGIS is enabled you can run: 56 | 57 | SELECT postgis_full_version(); 58 | 59 | ### Migrations 60 | 61 | Now create a model with a migration by running 62 | 63 | php artisan make:model Location 64 | 65 | If you don't want a model and just a migration run 66 | 67 | php artisan make:migration create_locations_table 68 | 69 | Open the created migrations with your editor. 70 | 71 | ```PHP 72 | use Illuminate\Database\Migrations\Migration; 73 | use Ajthinking\LaravelPostgis\Schema\Blueprint; 74 | 75 | class CreateLocationsTable extends Migration { 76 | 77 | /** 78 | * Run the migrations. 79 | * 80 | * @return void 81 | */ 82 | public function up() 83 | { 84 | Schema::create('locations', function(Blueprint $table) 85 | { 86 | $table->increments('id'); 87 | $table->string('name'); 88 | $table->string('address')->unique(); 89 | $table->point('location'); // GEOGRAPHY POINT column with SRID of 4326 (these are the default values). 90 | $table->point('location2', 'GEOGRAPHY', 4326); // GEOGRAPHY POINT column with SRID of 4326 with optional parameters. 91 | $table->point('location3', 'GEOMETRY', 27700); // GEOMETRY column with SRID of 27700. 92 | $table->polygon('polygon'); // GEOGRAPHY POLYGON column with SRID of 4326. 93 | $table->polygon('polygon2', 'GEOMETRY', 27700); // GEOMETRY POLYGON column with SRID of 27700. 94 | $table->timestamps(); 95 | }); 96 | } 97 | 98 | /** 99 | * Reverse the migrations. 100 | * 101 | * @return void 102 | */ 103 | public function down() 104 | { 105 | Schema::drop('locations'); 106 | } 107 | 108 | } 109 | ``` 110 | 111 | Available blueprint geometries: 112 | 113 | * point 114 | * multipoint 115 | * linestring 116 | * multilinestring 117 | * polygon 118 | * multipolygon 119 | * geometrycollection 120 | 121 | other methods: 122 | 123 | * enablePostgis 124 | * disablePostgis 125 | 126 | ### Models 127 | 128 | All models which are to be PostGis enabled **must** use the *PostgisTrait*. 129 | 130 | You must also define an array called `$postgisFields` which defines 131 | what attributes/columns on your model are to be considered geometry objects. By default, all attributes are of type `geography`. If you want to use `geometry` with a custom SRID, you have to define an array called `$postgisTypes`. The keys of this assoc array must match the entries in `$postgisFields` (all missing keys default to `geography`), the values are assoc arrays, too. They must have two keys: `geomtype` which is either `geography` or `geometry` and `srid` which is the desired SRID. **Note**: Custom SRID is only supported for `geometry`, not `geography`. 132 | 133 | ```PHP 134 | use Illuminate\Database\Eloquent\Model; 135 | use Ajthinking\LaravelPostgis\Eloquent\PostgisTrait; 136 | use Ajthinking\LaravelPostgis\Geometries\Point; 137 | 138 | class Location extends Model 139 | { 140 | use PostgisTrait; 141 | 142 | protected $fillable = [ 143 | 'name', 144 | 'address' 145 | ]; 146 | 147 | protected $postgisFields = [ 148 | 'location', 149 | 'location2', 150 | 'location3', 151 | 'polygon', 152 | 'polygon2' 153 | ]; 154 | 155 | protected $postgisTypes = [ 156 | 'location' => [ 157 | 'geomtype' => 'geography', 158 | 'srid' => 4326 159 | ], 160 | 'location2' => [ 161 | 'geomtype' => 'geography', 162 | 'srid' => 4326 163 | ], 164 | 'location3' => [ 165 | 'geomtype' => 'geometry', 166 | 'srid' => 27700 167 | ], 168 | 'polygon' => [ 169 | 'geomtype' => 'geography', 170 | 'srid' => 4326 171 | ], 172 | 'polygon2' => [ 173 | 'geomtype' => 'geometry', 174 | 'srid' => 27700 175 | ] 176 | ] 177 | } 178 | 179 | $linestring = new LineString( 180 | [ 181 | new Point(0, 0), 182 | new Point(0, 1), 183 | new Point(1, 1), 184 | new Point(1, 0), 185 | new Point(0, 0) 186 | ] 187 | ); 188 | 189 | $location1 = new Location(); 190 | $location1->name = 'Googleplex'; 191 | $location1->address = '1600 Amphitheatre Pkwy Mountain View, CA 94043'; 192 | $location1->location = new Point(37.422009, -122.084047); 193 | $location1->location2 = new Point(37.422009, -122.084047); 194 | $location1->location3 = new Point(37.422009, -122.084047); 195 | $location1->polygon = new Polygon([$linestring]); 196 | $location1->polygon2 = new Polygon([$linestring]); 197 | $location1->save(); 198 | 199 | $location2 = Location::first(); 200 | $location2->location instanceof Point // true 201 | ``` 202 | 203 | Available geometry classes: 204 | 205 | * Point 206 | * MultiPoint 207 | * LineString 208 | * MultiLineString 209 | * Polygon 210 | * MultiPolygon 211 | * GeometryCollection 212 | 213 | 214 | ### Achnowledgements 215 | This is a [fork](https://github.com/mstaack/laravel-postgis) from the work of great people. Thanks to : 216 | - https://github.com/njbarrett 217 | - https://github.com/phaza 218 | - https://github.com/mirzap 219 | 220 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ajthinking/laravel-postgis", 3 | "description": "Postgis extensions for laravel. Aims to make it easy to work with geometries from laravel models", 4 | "require": { 5 | "php": ">=7.1", 6 | "illuminate/database": "^9.0", 7 | "geo-io/wkb-parser": "^1.0", 8 | "jmikola/geojson": "^1.0" 9 | }, 10 | "require-dev": { 11 | "illuminate/pagination": "^9.0", 12 | "phpunit/phpunit": "^9.0.0", 13 | "mockery/mockery": "^1.3" 14 | }, 15 | "autoload": { 16 | "psr-4": { 17 | "Ajthinking\\LaravelPostgis\\": "src/" 18 | } 19 | }, 20 | "autoload-dev": { 21 | "psr-4": { 22 | "Ajthinking\\LaravelPostgis\\Tests\\": "tests/" 23 | } 24 | }, 25 | "license": "MIT", 26 | "authors": [ 27 | { 28 | "name": "Peter Haza", 29 | "email": "peter.haza@gmail.com" 30 | }, 31 | { 32 | "name": "Nicholas Barrett", 33 | "email": "njbarrett7@gmail.com" 34 | }, 35 | { 36 | "name": "Max Matteo Staack", 37 | "email": "maxmatteostaack@gmail.com" 38 | } 39 | ], 40 | "extra": { 41 | "laravel": { 42 | "providers": [ 43 | "Ajthinking\\LaravelPostgis\\DatabaseServiceProvider" 44 | ] 45 | } 46 | }, 47 | "scripts": { 48 | "test": "./vendor/bin/phpunit" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /config/postgis.php: -------------------------------------------------------------------------------- 1 | 'public' // Schema for the Postgis extension 5 | ]; 6 | -------------------------------------------------------------------------------- /database/migrations/enable_postgis.php.stub: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | ./tests 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/Connectors/ConnectionFactory.php: -------------------------------------------------------------------------------- 1 | publishes([$config_path => config_path('postgis.php')], 'postgis'); 16 | 17 | if (!class_exists('EnablePostgis')) { 18 | $this->publishes([ 19 | __DIR__ . '/../database/migrations/enable_postgis.php.stub' => database_path('migrations/'.date('Y_m_d_His', time()).'_enable_postgis.php'), 20 | ], 'migrations'); 21 | } 22 | 23 | $this->mergeConfigFrom($config_path, 'postgis'); 24 | } 25 | 26 | /** 27 | * Register the service provider. 28 | * 29 | * @return void 30 | */ 31 | public function register() 32 | { 33 | // The connection factory is used to create the actual connection instances on 34 | // the database. We will inject the factory into the manager so that it may 35 | // make the connections while they are actually needed and not of before. 36 | $this->app->singleton('db.factory', function ($app) { 37 | return new ConnectionFactory($app); 38 | }); 39 | 40 | // The database manager is used to resolve various connections, since multiple 41 | // connections might be managed. It also implements the connection resolver 42 | // interface which may be used by other components requiring connections. 43 | $this->app->singleton('db', function ($app) { 44 | return new DatabaseManager($app, $app['db.factory']); 45 | }); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Eloquent/Builder.php: -------------------------------------------------------------------------------- 1 | &$value) { 13 | if ($value instanceof GeometryInterface) { 14 | if (is_null($this->model)) { 15 | $value = $this->asWKT($value); 16 | } else { 17 | $attrs = $this->model->getPostgisType($key); 18 | $value = $this->model->asWKT($value, $attrs); 19 | } 20 | } 21 | } 22 | 23 | return parent::update($values); 24 | } 25 | 26 | protected function asWKT(GeometryInterface $geometry) 27 | { 28 | return $this->getQuery()->raw(sprintf("%s.ST_GeogFromText('%s')", 29 | function_exists('config') ? config('postgis.schema') : 'public', $geometry->toWKT())); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Eloquent/PostgisTrait.php: -------------------------------------------------------------------------------- 1 | getConnection()->raw(sprintf("%s.ST_GeogFromText('%s')", 32 | function_exists('config') ? config('postgis.schema') : 'public', $geometry->toWKT())); 33 | } 34 | 35 | protected function geomFromText(GeometryInterface $geometry, $srid = 4326) 36 | { 37 | return $this->getConnection()->raw(sprintf("%s.ST_GeomFromText('%s', '%d')", 38 | function_exists('config') ? config('postgis.schema') : 'public', $geometry->toWKT(), $srid)); 39 | } 40 | 41 | public function asWKT(GeometryInterface $geometry, $attrs) 42 | { 43 | switch (strtoupper($attrs['geomtype'])) { 44 | case 'GEOMETRY': 45 | return $this->geomFromText($geometry, $attrs['srid']); 46 | break; 47 | case 'GEOGRAPHY': 48 | default: 49 | return $this->geogFromText($geometry); 50 | break; 51 | } 52 | } 53 | 54 | protected function performInsert(EloquentBuilder $query, array $options = []) 55 | { 56 | foreach ($this->attributes as $key => $value) { 57 | if ($value instanceof GeometryInterface) { 58 | $this->geometries[$key] = $value; //Preserve the geometry objects prior to the insert 59 | if (! $value instanceof GeometryCollection) { 60 | $attrs = $this->getPostgisType($key); 61 | $this->attributes[$key] = $this->asWKT($value, $attrs); 62 | } else { 63 | $this->attributes[$key] = $this->geomFromText($value); 64 | } 65 | } 66 | } 67 | 68 | $insert = parent::performInsert($query, $options); 69 | 70 | foreach($this->geometries as $key => $value){ 71 | $this->attributes[$key] = $value; //Retrieve the geometry objects so they can be used in the model 72 | } 73 | 74 | return $insert; //Return the result of the parent insert 75 | } 76 | 77 | public function setRawAttributes(array $attributes, $sync = false) 78 | { 79 | $pgfields = $this->getPostgisFields(); 80 | 81 | foreach ($attributes as $attribute => &$value) { 82 | if (in_array($attribute, $pgfields) && is_string($value) && strlen($value) >= 15) { 83 | $value = Geometry::fromWKB($value); 84 | } 85 | } 86 | 87 | return parent::setRawAttributes($attributes, $sync); 88 | } 89 | 90 | public function getPostgisType($key) 91 | { 92 | $default = [ 93 | 'geomtype' => 'geography', 94 | 'srid' => 4326 95 | ]; 96 | 97 | if (property_exists($this, 'postgisTypes')) { 98 | if (Arr::isAssoc($this->postgisTypes)) { 99 | if(!array_key_exists($key, $this->postgisTypes)) { 100 | return $default; 101 | } 102 | $column = $this->postgisTypes[$key]; 103 | if (isset($column['geomtype']) && in_array(strtoupper($column['geomtype']), PostgisGrammar::$allowed_geom_types)) { 104 | return $column; 105 | } else { 106 | throw new UnsupportedGeomtypeException('Unsupported GeometryType in $postgisTypes for key ' . $key . ' in ' . __CLASS__); 107 | } 108 | } else { 109 | throw new PostgisTypesMalformedException('$postgisTypes in ' . __CLASS__ . ' has to be an assoc array'); 110 | } 111 | } 112 | 113 | // Return default geography if postgisTypes does not exist (for backward compatibility) 114 | return $default; 115 | } 116 | 117 | public function getPostgisFields() 118 | { 119 | if (property_exists($this, 'postgisFields')) { 120 | return Arr::isAssoc($this->postgisFields) ? //Is the array associative? 121 | array_keys($this->postgisFields) : //Returns just the keys to preserve compatibility with previous versions 122 | $this->postgisFields; //Returns the non-associative array that doesn't define the geometry type. 123 | } else { 124 | throw new PostgisFieldsNotDefinedException(__CLASS__ . ' has to define $postgisFields'); 125 | } 126 | 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/Exceptions/PostgisFieldsNotDefinedException.php: -------------------------------------------------------------------------------- 1 | Point::class, 12 | 2 => LineString::class, 13 | 3 => Polygon::class, 14 | 4 => MultiPoint::class, 15 | 5 => MultiLineString::class, 16 | 6 => MultiPolygon::class, 17 | 7 => GeometryCollection::class 18 | ]; 19 | 20 | public static function getWKTArgument($value) 21 | { 22 | $left = strpos($value, '('); 23 | $right = strrpos($value, ')'); 24 | 25 | return substr($value, $left + 1, $right - $left - 1); 26 | } 27 | 28 | public static function getWKTClass($value) 29 | { 30 | $left = strpos($value, '('); 31 | $type = trim(substr($value, 0, $left)); 32 | 33 | switch (strtoupper($type)) { 34 | case 'POINT': 35 | case 'POINTZ': 36 | case 'POINT Z': 37 | return Point::class; 38 | case 'LINESTRING': 39 | case 'LINESTRINGZ': 40 | case 'LINESTRING Z': 41 | return LineString::class; 42 | case 'POLYGON': 43 | case 'POLYGONZ': 44 | case 'POLYGON Z': 45 | return Polygon::class; 46 | case 'MULTIPOINT': 47 | case 'MULTIPOINTZ': 48 | case 'MULTIPOINT Z': 49 | return MultiPoint::class; 50 | case 'MULTILINESTRING': 51 | case 'MULTILINESTRINGZ': 52 | case 'MULTILINESTRING Z': 53 | return MultiLineString::class; 54 | case 'MULTIPOLYGON': 55 | case 'MULTIPOLYGONZ': 56 | case 'MULTIPOLYGON Z': 57 | return MultiPolygon::class; 58 | case 'GEOMETRYCOLLECTION': 59 | return GeometryCollection::class; 60 | default: 61 | throw new UnknownWKTTypeException('Type was ' . $type); 62 | } 63 | } 64 | 65 | public static function fromWKB($wkb) 66 | { 67 | $parser = new Parser(new Factory()); 68 | 69 | return $parser->parse($wkb); 70 | } 71 | 72 | public static function fromWKT($wkt) 73 | { 74 | $wktArgument = static::getWKTArgument($wkt); 75 | 76 | return static::fromString($wktArgument); 77 | } 78 | 79 | public abstract static function fromGeoJSON($geojson); 80 | 81 | public function toGeoJSON() 82 | { 83 | return $this->jsonSerialize(); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/Geometries/GeometryCollection.php: -------------------------------------------------------------------------------- 1 | geometries = $geometries; 30 | } 31 | 32 | public function getGeometries() 33 | { 34 | return $this->geometries; 35 | } 36 | 37 | public function toWKT() 38 | { 39 | return sprintf('GEOMETRYCOLLECTION(%s)', (string)$this); 40 | } 41 | 42 | public function __toString() 43 | { 44 | return implode( 45 | ',', 46 | array_map( 47 | function (GeometryInterface $geometry) { 48 | return $geometry->toWKT(); 49 | }, 50 | $this->geometries 51 | ) 52 | ); 53 | } 54 | 55 | public static function fromString($wktArgument) 56 | { 57 | $geometry_strings = preg_split('/,\s*(?=[A-Za-z])/', $wktArgument); 58 | 59 | return new static( 60 | array_map( 61 | function ($geometry_string) { 62 | $klass = Geometry::getWKTClass($geometry_string); 63 | 64 | return call_user_func($klass . '::fromWKT', $geometry_string); 65 | 66 | }, 67 | $geometry_strings 68 | ) 69 | ); 70 | } 71 | 72 | public static function fromGeoJSON($geojson) 73 | { 74 | $geometries = $geojson->getGeometries(); 75 | 76 | return new static( 77 | array_map( 78 | function ($geometry) { 79 | $type = $geometry->getType(); 80 | 81 | return call_user_func('\Ajthinking\LaravelPostgis\Geometries\\' . $type . '::fromGeoJSON', $geometry); 82 | 83 | }, 84 | $geometries 85 | ) 86 | ); 87 | } 88 | 89 | public function count() 90 | { 91 | return count($this->geometries); 92 | } 93 | 94 | /** 95 | * Convert to GeoJson GeometryCollection that is jsonable to GeoJSON 96 | * 97 | * @return \GeoJson\Geometry\GeometryCollection 98 | */ 99 | public function jsonSerialize(): mixed 100 | { 101 | $geometries = []; 102 | foreach ($this->geometries as $geometry) { 103 | $geometries[] = $geometry->jsonSerialize(); 104 | } 105 | 106 | return new \GeoJson\Geometry\GeometryCollection($geometries); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/Geometries/GeometryInterface.php: -------------------------------------------------------------------------------- 1 | points) === 0) return false; 10 | return $this->points[0]->is3d(); 11 | } 12 | 13 | public function toWKT() 14 | { 15 | $wktType = 'LINESTRING'; 16 | if ($this->is3d()) $wktType .= ' Z'; 17 | return sprintf('%s(%s)', $wktType, $this->toPairList()); 18 | } 19 | 20 | public static function fromWKT($wkt) 21 | { 22 | $wktArgument = Geometry::getWKTArgument($wkt); 23 | 24 | return static::fromString($wktArgument); 25 | } 26 | 27 | public static function fromString($wktArgument) 28 | { 29 | $pairs = explode(',', trim($wktArgument)); 30 | $points = array_map(function ($pair) { 31 | return Point::fromPair($pair); 32 | }, $pairs); 33 | 34 | return new static($points); 35 | } 36 | 37 | public static function fromGeoJSON($geojson) 38 | { 39 | $coordinates = $geojson->getCoordinates(); 40 | 41 | $points = array_map(function ($coord) { 42 | return new Point((float)$coord[1], (float)$coord[0], isset($coord[2]) ? (float)$coord[2] : null); 43 | }, $coordinates); 44 | 45 | return new static($points); 46 | } 47 | 48 | public function __toString() 49 | { 50 | return $this->toPairList(); 51 | } 52 | 53 | /** 54 | * Convert to GeoJson LineString that is jsonable to GeoJSON 55 | * 56 | * @return \GeoJson\Geometry\LineString 57 | */ 58 | public function jsonSerialize(): mixed 59 | { 60 | $points = []; 61 | foreach ($this->points as $point) { 62 | $points[] = $point->jsonSerialize(); 63 | } 64 | 65 | return new \GeoJson\Geometry\LineString($points); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Geometries/MultiLineString.php: -------------------------------------------------------------------------------- 1 | linestrings = $linestrings; 33 | } 34 | 35 | public function getLineStrings() 36 | { 37 | return $this->linestrings; 38 | } 39 | 40 | public function is3d() 41 | { 42 | if (count($this->linestrings) === 0) return false; 43 | return $this->linestrings[0]->is3d(); 44 | } 45 | 46 | public function toWKT() 47 | { 48 | $wktType = 'MULTILINESTRING'; 49 | if ($this->is3d()) $wktType .= ' Z'; 50 | return sprintf('%s(%s)', $wktType, (string)$this); 51 | } 52 | 53 | public static function fromString($wktArgument) 54 | { 55 | $str = preg_split('/\)\s*,\s*\(/', substr(trim($wktArgument), 1, -1)); 56 | $linestrings = array_map(function ($data) { 57 | return LineString::fromString($data); 58 | }, $str); 59 | 60 | 61 | return new static($linestrings); 62 | } 63 | 64 | public static function fromGeoJSON($geojson) 65 | { 66 | $coordinates = $geojson->getCoordinates(); 67 | 68 | $linestrings = array_map(function ($line) { 69 | $points = array_map(function ($coord) { 70 | return new Point((float)$coord[1], (float)$coord[0], isset($coord[2]) ? (float)$coord[2] : null); 71 | }, $line); 72 | 73 | return new LineString($points); 74 | }, $coordinates); 75 | 76 | return new static($linestrings); 77 | } 78 | 79 | public function __toString() 80 | { 81 | return implode(',', array_map(function (LineString $linestring) { 82 | return sprintf('(%s)', (string)$linestring); 83 | }, $this->getLineStrings())); 84 | } 85 | 86 | public function count() 87 | { 88 | return count($this->linestrings); 89 | } 90 | 91 | /** 92 | * Convert to GeoJson Point that is jsonable to GeoJSON 93 | * 94 | * @return \GeoJson\Geometry\MultiLineString 95 | */ 96 | public function jsonSerialize(): mixed 97 | { 98 | $linestrings = []; 99 | 100 | foreach ($this->linestrings as $linestring) { 101 | $linestrings[] = $linestring->jsonSerialize(); 102 | } 103 | 104 | return new \GeoJson\Geometry\MultiLineString($linestrings); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/Geometries/MultiPoint.php: -------------------------------------------------------------------------------- 1 | points = $points; 22 | } 23 | 24 | public function is3d() 25 | { 26 | if (count($this->points) === 0) return false; 27 | return $this->points[0]->is3d(); 28 | } 29 | 30 | public function toWKT() 31 | { 32 | $wktType = 'MULTIPOINT'; 33 | if ($this->is3d()) $wktType .= ' Z'; 34 | return sprintf('%s(%s)', $wktType, (string)$this); 35 | } 36 | 37 | public static function fromWKT($wkt) 38 | { 39 | $wktArgument = Geometry::getWKTArgument($wkt); 40 | 41 | return static::fromString($wktArgument); 42 | } 43 | 44 | public static function fromString($wktArgument) 45 | { 46 | $matches = []; 47 | preg_match_all('/\(\s*(\d+\s+\d+(\s+\d+)?)\s*\)/', trim($wktArgument), $matches); 48 | 49 | if (count($matches) < 2) { 50 | return new static([]); 51 | } 52 | 53 | $points = array_map(function ($pair) { 54 | return Point::fromPair($pair); 55 | }, $matches[1]); 56 | 57 | return new static($points); 58 | } 59 | 60 | public static function fromGeoJSON($geojson) 61 | { 62 | $coordinates = $geojson->getCoordinates(); 63 | 64 | if (count($coordinates) < 2) { 65 | return new static([]); 66 | } 67 | 68 | $points = array_map(function ($coord) { 69 | return new Point((float)$coord[1], (float)$coord[0], isset($coord[2]) ? (float)$coord[2] : null); 70 | }, $coordinates); 71 | 72 | return new static($points); 73 | } 74 | 75 | public function __toString() 76 | { 77 | return implode(',', array_map(function (Point $point) { 78 | return sprintf('(%s)', $point->toPair()); 79 | }, $this->points)); 80 | } 81 | 82 | /** 83 | * Convert to GeoJson MultiPoint that is jsonable to GeoJSON 84 | * 85 | * @return \GeoJson\Geometry\MultiPoint 86 | */ 87 | public function jsonSerialize(): mixed 88 | { 89 | $points = []; 90 | foreach ($this->points as $point) { 91 | $points[] = $point->jsonSerialize(); 92 | } 93 | 94 | return new \GeoJson\Geometry\MultiPoint($points); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/Geometries/MultiPolygon.php: -------------------------------------------------------------------------------- 1 | polygons = $polygons; 28 | } 29 | 30 | public function is3d() 31 | { 32 | if (count($this->polygons) === 0) return false; 33 | return $this->polygons[0]->is3d(); 34 | } 35 | 36 | public function toWKT() 37 | { 38 | $wktType = 'MULTIPOLYGON'; 39 | if ($this->is3d()) $wktType .= ' Z'; 40 | return sprintf('%s(%s)', $wktType, (string)$this); 41 | } 42 | 43 | public function __toString() 44 | { 45 | return implode(',', array_map(function (Polygon $polygon) { 46 | return sprintf('(%s)', (string)$polygon); 47 | }, $this->polygons)); 48 | } 49 | 50 | public static function fromString($wktArgument) 51 | { 52 | $parts = preg_split('/(\)\s*\)\s*,\s*\(\s*\()/', $wktArgument, -1, PREG_SPLIT_DELIM_CAPTURE); 53 | $polygons = static::assembleParts($parts); 54 | 55 | return new static(array_map(function ($polygonString) { 56 | return Polygon::fromString($polygonString); 57 | }, $polygons)); 58 | } 59 | 60 | public static function fromGeoJSON($geojson) 61 | { 62 | $coordinates = $geojson->getCoordinates(); 63 | 64 | $polygons = array_map(function ($polygon) { 65 | $linestrings = array_map(function ($line) { 66 | $points = array_map(function ($coord) { 67 | return new Point((float)$coord[1], (float)$coord[0], isset($coord[2]) ? (float)$coord[2] : null); 68 | }, $line); 69 | 70 | return new LineString($points); 71 | }, $polygon); 72 | 73 | return new Polygon($linestrings); 74 | }, $coordinates); 75 | 76 | return new static($polygons); 77 | } 78 | 79 | /** 80 | * (PHP 5 >= 5.1.0)
81 | * Count elements of an object 82 | * 83 | * @link http://php.net/manual/en/countable.count.php 84 | * @return int The custom count as an integer. 85 | *

86 | *

87 | * The return value is cast to an integer. 88 | */ 89 | public function count() 90 | { 91 | return count($this->polygons); 92 | } 93 | 94 | /** 95 | * Get the polygons that make up this MultiPolygon 96 | * 97 | * @return array|Polygon[] 98 | */ 99 | public function getPolygons() 100 | { 101 | return $this->polygons; 102 | } 103 | 104 | /** 105 | * Make an array like this: 106 | * "((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1", 107 | * ")), ((", 108 | * "-1 -1,-1 -2,-2 -2,-2 -1,-1 -1", 109 | * ")), ((", 110 | * "-1 -1,-1 -2,-2 -2,-2 -1,-1 -1))" 111 | * 112 | * Into: 113 | * "((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1))", 114 | * "((-1 -1,-1 -2,-2 -2,-2 -1,-1 -1))", 115 | * "((-1 -1,-1 -2,-2 -2,-2 -1,-1 -1))" 116 | * 117 | * @param array $parts 118 | * @return array 119 | */ 120 | protected static function assembleParts(array $parts) 121 | { 122 | $polygons = []; 123 | $count = count($parts); 124 | 125 | for ($i = 0; $i < $count; $i++) { 126 | if ($i % 2 !== 0) { 127 | list($end, $start) = explode(',', $parts[$i]); 128 | $polygons[$i - 1] .= $end; 129 | $polygons[++$i] = $start . $parts[$i]; 130 | } else { 131 | $polygons[] = $parts[$i]; 132 | } 133 | } 134 | 135 | return $polygons; 136 | } 137 | 138 | /** 139 | * Convert to GeoJson MultiPolygon that is jsonable to GeoJSON 140 | * 141 | * @return \GeoJson\Geometry\MultiPolygon 142 | */ 143 | public function jsonSerialize(): mixed 144 | { 145 | $polygons = []; 146 | foreach ($this->polygons as $polygon) { 147 | $polygons[] = $polygon->jsonSerialize(); 148 | } 149 | 150 | return new \GeoJson\Geometry\MultiPolygon($polygons); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/Geometries/Point.php: -------------------------------------------------------------------------------- 1 | lat = (float)$lat; 14 | $this->lng = (float)$lng; 15 | $this->alt = isset($alt) ? (float)$alt : null; 16 | } 17 | 18 | public function getLat() 19 | { 20 | return $this->lat; 21 | } 22 | 23 | public function setLat($lat) 24 | { 25 | $this->lat = (float)$lat; 26 | } 27 | 28 | public function getLng() 29 | { 30 | return $this->lng; 31 | } 32 | 33 | public function setLng($lng) 34 | { 35 | $this->lng = (float)$lng; 36 | } 37 | 38 | public function getAlt() 39 | { 40 | return $this->alt; 41 | } 42 | 43 | public function setAlt($alt) 44 | { 45 | $this->alt = (float)$alt; 46 | } 47 | 48 | public function is3d() 49 | { 50 | return isset($this->alt); 51 | } 52 | 53 | public function toPair() 54 | { 55 | $pair = self::stringifyFloat($this->getLng()) . ' ' . self::stringifyFloat($this->getLat()); 56 | if ($this->is3d()) { 57 | $pair .= ' ' . self::stringifyFloat($this->getAlt()); 58 | } 59 | return $pair; 60 | } 61 | 62 | private static function stringifyFloat($float) 63 | { 64 | // normalized output among locales 65 | return rtrim(rtrim(sprintf('%F', $float), '0'), '.'); 66 | } 67 | 68 | public static function fromPair($pair) 69 | { 70 | $pair = preg_replace('/^[a-zA-Z\(\)]+/', '', trim($pair)); 71 | $splits = explode(' ', trim($pair)); 72 | $lng = $splits[0]; 73 | $lat = $splits[1]; 74 | if (count($splits) > 2) { 75 | $alt = $splits[2]; 76 | } 77 | 78 | return new static((float)$lat, (float)$lng, isset($alt) ? (float)$alt : null); 79 | } 80 | 81 | public function toWKT() 82 | { 83 | $wktType = 'POINT'; 84 | if ($this->is3d()) $wktType .= ' Z'; 85 | return sprintf('%s(%s)', $wktType, (string)$this); 86 | } 87 | 88 | public static function fromString($wktArgument) 89 | { 90 | return static::fromPair($wktArgument); 91 | } 92 | 93 | public static function fromGeoJSON($geojson) 94 | { 95 | $coordinates = $geojson->getCoordinates(); 96 | 97 | return new static((float)$coordinates[1], (float)$coordinates[0], isset($coordinates[2]) ? (float)$coordinates[2] : null); 98 | } 99 | 100 | public function __toString() 101 | { 102 | return $this->toPair(); 103 | } 104 | 105 | /** 106 | * Convert to GeoJson Point that is jsonable to GeoJSON 107 | * 108 | * @return \GeoJson\Geometry\Point 109 | */ 110 | public function jsonSerialize(): mixed 111 | { 112 | $position = [$this->getLng(), $this->getLat()]; 113 | if ($this->is3d()) $position[] = $this->getAlt(); 114 | return new \GeoJson\Geometry\Point($position); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/Geometries/PointCollection.php: -------------------------------------------------------------------------------- 1 | points = $points; 37 | } 38 | 39 | public function getPoints() 40 | { 41 | return $this->points; 42 | } 43 | 44 | public function toArray() 45 | { 46 | return $this->points; 47 | } 48 | 49 | public function getIterator() 50 | { 51 | return new ArrayIterator($this->points); 52 | } 53 | 54 | public function prependPoint(Point $point) 55 | { 56 | array_unshift($this->points, $point); 57 | } 58 | 59 | public function appendPoint(Point $point) 60 | { 61 | $this->points[] = $point; 62 | } 63 | 64 | public function insertPoint($index, Point $point) 65 | { 66 | if (count($this->points) - 1 < $index) { 67 | throw new InvalidArgumentException('$index is greater than the size of the array'); 68 | } 69 | 70 | array_splice($this->points, $offset, 0, [$point]); 71 | } 72 | 73 | public function offsetExists($offset) 74 | { 75 | return isset($this->points[$offset]); 76 | } 77 | 78 | /** 79 | * @param mixed $offset 80 | * @return null|Point 81 | */ 82 | public function offsetGet($offset) 83 | { 84 | return $this->offsetExists($offset) ? $this->points[$offset] : null; 85 | } 86 | 87 | public function offsetSet($offset, $value) 88 | { 89 | if (!($value instanceof Point)) { 90 | throw new InvalidArgumentException('$value must be an instance of Point'); 91 | } 92 | 93 | if (is_null($offset)) { 94 | $this->appendPoint($value); 95 | } else { 96 | $this->points[$offset] = $value; 97 | } 98 | } 99 | 100 | public function offsetUnset($offset) 101 | { 102 | unset($this->points[$offset]); 103 | } 104 | 105 | public function count() 106 | { 107 | return count($this->points); 108 | } 109 | 110 | public function toPairList() 111 | { 112 | return implode(',', array_map(function (Point $point) { 113 | return $point->toPair(); 114 | }, $this->points)); 115 | } 116 | 117 | public abstract static function fromGeoJSON($geojson); 118 | 119 | public function toGeoJSON() 120 | { 121 | return $this->jsonSerialize(); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/Geometries/Polygon.php: -------------------------------------------------------------------------------- 1 | linestrings) === 0) return false; 12 | return $this->linestrings[0]->is3d(); 13 | } 14 | 15 | public function toWKT() 16 | { 17 | $wktType = 'POLYGON'; 18 | if ($this->is3d()) $wktType .= ' Z'; 19 | return sprintf('%s(%s)', $wktType, (string)$this); 20 | } 21 | 22 | /** 23 | * Convert to GeoJson Polygon that is jsonable to GeoJSON 24 | * 25 | * @return \GeoJson\Geometry\Polygon 26 | */ 27 | public function jsonSerialize(): mixed 28 | { 29 | $linearrings = []; 30 | foreach ($this->linestrings as $linestring) { 31 | $linearrings[] = new LinearRing($linestring->jsonSerialize()->getCoordinates()); 32 | } 33 | 34 | return new \GeoJson\Geometry\Polygon($linearrings); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/PostgisConnection.php: -------------------------------------------------------------------------------- 1 | withTablePrefix(new PostgisGrammar()); 28 | } 29 | 30 | 31 | public function getSchemaBuilder() 32 | { 33 | if ($this->schemaGrammar === null) { 34 | $this->useDefaultSchemaGrammar(); 35 | } 36 | 37 | return new Schema\Builder($this); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Schema/Blueprint.php: -------------------------------------------------------------------------------- 1 | inherits = $table; 24 | } 25 | 26 | /** 27 | * Add the index commands fluently specified on columns. 28 | * 29 | * @return void 30 | */ 31 | protected function addFluentIndexes() 32 | { 33 | foreach ($this->columns as $column) { 34 | foreach (array('primary', 'unique', 'index', 'gin', 'gist') as $index) { 35 | // If the index has been specified on the given column, but is simply 36 | // equal to "true" (boolean), no name has been specified for this 37 | // index, so we will simply call the index methods without one. 38 | if ($column->$index === true) { 39 | $this->$index($column->name); 40 | 41 | continue 2; 42 | } 43 | 44 | // If the index has been specified on the column and it is something 45 | // other than boolean true, we will assume a name was provided on 46 | // the index specification, and pass in the name to the method. 47 | elseif (isset($column->$index)) { 48 | $this->$index($column->name, $column->$index); 49 | 50 | continue 2; 51 | } 52 | } 53 | } 54 | } 55 | 56 | /** 57 | * Specify an index for the table. 58 | * 59 | * @param string|array $columns 60 | * @param string $name 61 | * @return \Illuminate\Support\Fluent 62 | */ 63 | public function gin($columns, $name = null) 64 | { 65 | return $this->indexCommand('gin', $columns, $name); 66 | } 67 | 68 | /** 69 | * Specify a gist index for the table. 70 | * 71 | * @param string|array $columns 72 | * @param string $name 73 | * @return \Illuminate\Support\Fluent 74 | */ 75 | public function gist($columns, $name = null) 76 | { 77 | return $this->indexCommand('gist', $columns, $name); 78 | } 79 | 80 | /** 81 | * Create a new character column on the table. 82 | * 83 | * @param string $column 84 | * @param int $length 85 | * @return \Illuminate\Database\Schema\ColumnDefinition 86 | */ 87 | public function character($column, $length = 255) 88 | { 89 | return $this->addColumn('character', $column, compact('length')); 90 | } 91 | 92 | /** 93 | * @param $column 94 | * @return \Illuminate\Database\Schema\ColumnDefinition 95 | */ 96 | public function hstore($column) 97 | { 98 | return $this->addColumn('hstore', $column); 99 | } 100 | 101 | /** 102 | * Create a new netmask (CIDR-notation) (cidr) column on the table. 103 | * 104 | * @param string $column 105 | * @return \Illuminate\Database\Schema\ColumnDefinition 106 | */ 107 | public function netmask($column) 108 | { 109 | return $this->addColumn('netmask', $column); 110 | } 111 | 112 | /** 113 | * Create a new line column on the table. 114 | * 115 | * @param string $column 116 | * @return \Illuminate\Database\Schema\ColumnDefinition 117 | */ 118 | public function line($column) 119 | { 120 | return $this->addColumn('line', $column); 121 | } 122 | 123 | /** 124 | * Create a new line segment (lseg) column on the table. 125 | * 126 | * @param string $column 127 | * @return \Illuminate\Database\Schema\ColumnDefinition 128 | */ 129 | public function lineSegment($column) 130 | { 131 | return $this->addColumn('lineSegment', $column); 132 | } 133 | 134 | /** 135 | * Create a new path column on the table. 136 | * 137 | * @param string $column 138 | * @return \Illuminate\Database\Schema\ColumnDefinition 139 | */ 140 | public function path($column) 141 | { 142 | return $this->addColumn('path', $column); 143 | } 144 | 145 | /** 146 | * Create a new box column on the table. 147 | * 148 | * @param string $column 149 | * @return \Illuminate\Database\Schema\ColumnDefinition 150 | */ 151 | public function box($column) 152 | { 153 | return $this->addColumn('box', $column); 154 | } 155 | 156 | /** 157 | * Create a new circle column on the table. 158 | * 159 | * @param string $column 160 | * @return \Illuminate\Database\Schema\ColumnDefinition 161 | */ 162 | public function circle($column) 163 | { 164 | return $this->addColumn('circle', $column); 165 | } 166 | 167 | /** 168 | * Create a new money column on the table. 169 | * 170 | * @param string $column 171 | * @return \Illuminate\Database\Schema\ColumnDefinition 172 | */ 173 | public function money($column) 174 | { 175 | return $this->addColumn('money', $column); 176 | } 177 | 178 | /** 179 | * Create a new int4range column on the table. 180 | * 181 | * @param string $column 182 | * 183 | * @return \Illuminate\Database\Schema\ColumnDefinition 184 | */ 185 | public function int4range($column) 186 | { 187 | return $this->addColumn('int4range', $column); 188 | } 189 | 190 | /** 191 | * Create a new int8range column on the table. 192 | * 193 | * @param string $column 194 | * 195 | * @return \Illuminate\Database\Schema\ColumnDefinition 196 | */ 197 | public function int8range($column) 198 | { 199 | return $this->addColumn('int8range', $column); 200 | } 201 | 202 | /** 203 | * Create a new numrange column on the table. 204 | * 205 | * @param string $column 206 | * 207 | * @return \Illuminate\Database\Schema\ColumnDefinition 208 | */ 209 | public function numrange($column) 210 | { 211 | return $this->addColumn('numrange', $column); 212 | } 213 | 214 | /** 215 | * Create a new tsrange column on the table. 216 | * 217 | * @param string $column 218 | * 219 | * @return \Illuminate\Database\Schema\ColumnDefinition 220 | */ 221 | public function tsrange($column) 222 | { 223 | return $this->addColumn('tsrange', $column); 224 | } 225 | 226 | /** 227 | * Create a new tstzrange column on the table. 228 | * 229 | * @param string $column 230 | * 231 | * @return \Illuminate\Database\Schema\ColumnDefinition 232 | */ 233 | public function tstzrange($column) 234 | { 235 | return $this->addColumn('tstzrange', $column); 236 | } 237 | 238 | /** 239 | * Create a new daterange column on the table. 240 | * 241 | * @param $column 242 | * 243 | * @return \Illuminate\Database\Schema\ColumnDefinition 244 | */ 245 | public function daterange($column) 246 | { 247 | return $this->addColumn('daterange', $column); 248 | } 249 | 250 | /** 251 | * Create a new tsvector column on the table. 252 | * 253 | * @param $column 254 | * 255 | * @return \Illuminate\Database\Schema\ColumnDefinition 256 | */ 257 | public function tsvector($column) 258 | { 259 | return $this->addColumn('tsvector', $column); 260 | } 261 | 262 | /** 263 | * Add a point column on the table 264 | * 265 | * @param $column 266 | * @return \Illuminate\Database\Schema\ColumnDefinition 267 | */ 268 | public function point($column, $geomtype = 'GEOGRAPHY', $srid = '4326') 269 | { 270 | return $this->addColumn('point', $column, compact('geomtype', 'srid')); 271 | } 272 | 273 | /** 274 | * Add a multipoint column on the table 275 | * 276 | * @param $column 277 | * @return \Illuminate\Database\Schema\ColumnDefinition 278 | */ 279 | public function multipoint($column, $geomtype = 'GEOGRAPHY', $srid = '4326') 280 | { 281 | return $this->addColumn('multipoint', $column, compact('geomtype', 'srid')); 282 | } 283 | 284 | /** 285 | * Add a polygon column on the table 286 | * 287 | * @param $column 288 | * @return \Illuminate\Database\Schema\ColumnDefinition 289 | */ 290 | public function polygon($column, $geomtype = 'GEOGRAPHY', $srid = '4326') 291 | { 292 | return $this->addColumn('polygon', $column, compact('geomtype', 'srid')); 293 | } 294 | 295 | /** 296 | * Add a multipolygon column on the table 297 | * 298 | * @param $column 299 | * @return \Illuminate\Database\Schema\ColumnDefinition 300 | */ 301 | public function multipolygon($column, $geomtype = 'GEOGRAPHY', $srid = '4326') 302 | { 303 | return $this->addColumn('multipolygon', $column, compact('geomtype', 'srid')); 304 | } 305 | 306 | /** 307 | * Add a multipolygonz column on the table 308 | * 309 | * @param $column 310 | * @return \Illuminate\Database\Schema\ColumnDefinition 311 | */ 312 | public function multipolygonz($column, $geomtype = 'GEOGRAPHY', $srid = '4326') 313 | { 314 | return $this->addColumn('multipolygonz', $column, compact('geomtype', 'srid')); 315 | } 316 | 317 | /** 318 | * Add a linestring column on the table 319 | * 320 | * @param $column 321 | * @return \Illuminate\Database\Schema\ColumnDefinition 322 | */ 323 | public function linestring($column, $geomtype = 'GEOGRAPHY', $srid = '4326') 324 | { 325 | return $this->addColumn('linestring', $column, compact('geomtype', 'srid')); 326 | } 327 | 328 | /** 329 | * Add a multilinestring column on the table 330 | * 331 | * @param $column 332 | * @return \Illuminate\Database\Schema\ColumnDefinition 333 | */ 334 | public function multilinestring($column, $geomtype = 'GEOGRAPHY', $srid = '4326') 335 | { 336 | return $this->addColumn('multilinestring', $column, compact('geomtype', 'srid')); 337 | } 338 | 339 | /** 340 | * Add a geography column on the table 341 | * 342 | * @param string $column 343 | * @return \Illuminate\Database\Schema\ColumnDefinition 344 | */ 345 | public function geography($column, $geomtype = 'GEOGRAPHY', $srid = '4326') 346 | { 347 | return $this->addColumn('geography', $column, compact('geomtype', 'srid')); 348 | } 349 | 350 | /** 351 | * Add a geometry column on the table 352 | * 353 | * @param string $column 354 | * @return \Illuminate\Database\Schema\ColumnDefinition 355 | */ 356 | public function geometry($column, $geomtype = 'GEOGRAPHY', $srid = '4326') 357 | { 358 | return $this->addColumn('geometry', $column, compact('geomtype', 'srid')); 359 | } 360 | 361 | /** 362 | * Add a geometrycollection column on the table 363 | * 364 | * @param $column 365 | * @param null $srid 366 | * @param int $dimensions 367 | * @param bool $typmod 368 | * @return \Illuminate\Support\Fluent 369 | */ 370 | public function geometrycollection($column, $srid = null, $dimensions = 2, $typmod = true) 371 | { 372 | return $this->addCommand('geometrycollection', compact('column', 'srid', 'dimensions', 'typmod')); 373 | } 374 | 375 | /** 376 | * Enable postgis on this database. 377 | * Will create the extension in the database. 378 | * 379 | * @return \Illuminate\Support\Fluent 380 | */ 381 | public function enablePostgis() 382 | { 383 | return $this->addCommand('enablePostgis'); 384 | } 385 | 386 | /** 387 | * Enable postgis on this database. 388 | * Will create the extension in the database if it doesn't already exist. 389 | * 390 | * @return \Illuminate\Support\Fluent 391 | */ 392 | public function enablePostgisIfNotExists() 393 | { 394 | return $this->addCommand('enablePostgisIfNotExists'); 395 | } 396 | 397 | /** 398 | * Disable postgis on this database. 399 | * WIll drop the extension in the database. 400 | * 401 | * @return \Illuminate\Support\Fluent 402 | */ 403 | public function disablePostgis() 404 | { 405 | return $this->addCommand('disablePostgis'); 406 | } 407 | 408 | /** 409 | * Disable postgis on this database. 410 | * WIll drop the extension in the database if it exists. 411 | * 412 | * @return \Illuminate\Support\Fluent 413 | */ 414 | public function disablePostgisIfExists() 415 | { 416 | return $this->addCommand('disablePostgisIfExists'); 417 | } 418 | 419 | } 420 | -------------------------------------------------------------------------------- /src/Schema/Builder.php: -------------------------------------------------------------------------------- 1 | connection->statement( 31 | $this->grammar->compileEnablePostgis() 32 | ); 33 | } 34 | 35 | /** 36 | * Enable postgis on this database. 37 | * Will create the extension in the database if it doesn't already exist. 38 | * 39 | * @return bool 40 | */ 41 | public function enablePostgisIfNotExists() 42 | { 43 | return $this->connection->statement( 44 | $this->grammar->compileEnablePostgisIfNotExists() 45 | ); 46 | } 47 | 48 | /** 49 | * Disable postgis on this database. 50 | * WIll drop the extension in the database. 51 | * 52 | * @return bool 53 | */ 54 | public function disablePostgis() 55 | { 56 | return $this->connection->statement( 57 | $this->grammar->compileDisablePostgis() 58 | ); 59 | } 60 | 61 | /** 62 | * Disable postgis on this database. 63 | * WIll drop the extension in the database if it exists. 64 | * 65 | * @return bool 66 | */ 67 | public function disablePostgisIfExists() 68 | { 69 | return $this->connection->statement( 70 | $this->grammar->compileDisablePostgisIfExists() 71 | ); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Schema/Grammars/PostgisGrammar.php: -------------------------------------------------------------------------------- 1 | length})"; 38 | } 39 | 40 | /** 41 | * Create the column definition for a hstore type. 42 | * 43 | * @param Fluent $column 44 | * @return string 45 | */ 46 | protected function typeHstore(Fluent $column) 47 | { 48 | return "hstore"; 49 | } 50 | 51 | /** 52 | * Create the column definition for a uuid type. 53 | * 54 | * @param Fluent $column 55 | * @return string 56 | */ 57 | protected function typeUuid(Fluent $column) 58 | { 59 | return "uuid"; 60 | } 61 | 62 | /** 63 | * Create the column definition for a jsonb type. 64 | * 65 | * @param Fluent $column 66 | * @return string 67 | */ 68 | protected function typeJsonb(Fluent $column) 69 | { 70 | return "jsonb"; 71 | } 72 | 73 | /** 74 | * Create the column definition for an IPv4 or IPv6 address. 75 | * 76 | * @param \Illuminate\Support\Fluent $column 77 | * @return string 78 | */ 79 | protected function typeIpAddress(Fluent $column) 80 | { 81 | return 'inet'; 82 | } 83 | /** 84 | * Create the column definition for a CIDR notation-style netmask. 85 | * 86 | * @param \Illuminate\Support\Fluent $column 87 | * @return string 88 | */ 89 | protected function typeNetmask(Fluent $column) 90 | { 91 | return 'cidr'; 92 | } 93 | 94 | /** 95 | * Create the column definition for a MAC address. 96 | * 97 | * @param \Illuminate\Support\Fluent $column 98 | * @return string 99 | */ 100 | protected function typeMacAddress(Fluent $column) 101 | { 102 | return 'macaddr'; 103 | } 104 | 105 | /** 106 | * Create the column definition for a line represented as a standard linear equation Ax + By + C = 0. 107 | * 108 | * @param \Illuminate\Support\Fluent $column 109 | * @return string 110 | */ 111 | protected function typeLine(Fluent $column) 112 | { 113 | return 'line'; 114 | } 115 | 116 | /** 117 | * Create the column definition for a line segment represented by two points (x1, y1), (x2, y2). 118 | * 119 | * @param \Illuminate\Support\Fluent $column 120 | * @return string 121 | */ 122 | protected function typeLineSegment(Fluent $column) 123 | { 124 | return 'lseg'; 125 | } 126 | 127 | /** 128 | * Create the column definition for a path represented as a list of points (x1, y1), (x2, y2), ..., (xn, yn). 129 | * 130 | * @param \Illuminate\Support\Fluent $column 131 | * @return string 132 | */ 133 | protected function typePath(Fluent $column) 134 | { 135 | return 'path'; 136 | } 137 | 138 | /** 139 | * Create the column definition for a box represented by opposite corners of the box as points (x1, y1), (x2, y2). 140 | * 141 | * @param \Illuminate\Support\Fluent $column 142 | * @return string 143 | */ 144 | protected function typeBox(Fluent $column) 145 | { 146 | return 'box'; 147 | } 148 | 149 | /** 150 | * Create the column definition for a circle represented by a center point and a radius <(x, y), r> 151 | * 152 | * @param \Illuminate\Support\Fluent $column 153 | * @return string 154 | */ 155 | protected function typeCircle(Fluent $column) 156 | { 157 | return 'circle'; 158 | } 159 | 160 | /** 161 | * Create the column definition for storing amounts of currency with a fixed fractional precision. 162 | * 163 | * This will store values in the range of: -92233720368547758.08 to +92233720368547758.07. (92 quadrillion). 164 | * Output is locale-sensitive, see lc_monetary setting of PostgreSQL instance/s. 165 | * 166 | * @param \Illuminate\Support\Fluent $column 167 | * @return string 168 | */ 169 | protected function typeMoney(Fluent $column) 170 | { 171 | return 'money'; 172 | } 173 | 174 | /** 175 | * Create the column definition for an int4range type. 176 | * 177 | * @param Fluent $column 178 | * 179 | * @return string 180 | */ 181 | protected function typeInt4range(Fluent $column) 182 | { 183 | return "int4range"; 184 | } 185 | 186 | /** 187 | * Create the column definition for an int8range type. 188 | * 189 | * @param Fluent $column 190 | * 191 | * @return string 192 | */ 193 | protected function typeInt8range(Fluent $column) 194 | { 195 | return "int8range"; 196 | } 197 | 198 | /** 199 | * Create the column definition for an numrange type. 200 | * 201 | * @param Fluent $column 202 | * 203 | * @return string 204 | */ 205 | protected function typeNumrange(Fluent $column) 206 | { 207 | return "numrange"; 208 | } 209 | 210 | /** 211 | * Create the column definition for an tsrange type. 212 | * 213 | * @param Fluent $column 214 | * 215 | * @return string 216 | */ 217 | protected function typeTsrange(Fluent $column) 218 | { 219 | return "tsrange"; 220 | } 221 | 222 | /** 223 | * Create the column definition for an tstzrange type. 224 | * 225 | * @param Fluent $column 226 | * 227 | * @return string 228 | */ 229 | protected function typeTstzrange(Fluent $column) 230 | { 231 | return "tstzrange"; 232 | } 233 | 234 | /** 235 | * Create the column definition for an daterange type. 236 | * 237 | * @param Fluent $column 238 | * 239 | * @return string 240 | */ 241 | protected function typeDaterange(Fluent $column) 242 | { 243 | return "daterange"; 244 | } 245 | 246 | /** 247 | * Create the column definition for a Text Search Vector type. 248 | * 249 | * @param Fluent $column 250 | * 251 | * @return string 252 | */ 253 | protected function typeTsvector(Fluent $column) 254 | { 255 | return "tsvector"; 256 | } 257 | 258 | /** 259 | * @param mixed $value 260 | * @return mixed|string 261 | */ 262 | protected function getDefaultValue($value) 263 | { 264 | if($this->isUuid($value)) return strval($value); 265 | 266 | return parent::getDefaultValue($value); 267 | } 268 | 269 | /** 270 | * Check if string matches on of uuid_generate functions 271 | * 272 | * @param $value 273 | * @return int 274 | */ 275 | protected function isUuid($value) 276 | { 277 | return preg_match('/^uuid_generate_v/', $value); 278 | } 279 | 280 | /** 281 | * Compile a gin index key command. 282 | * 283 | * @param \Ajthinking\LaravelPostgis\Schema\Blueprint $blueprint 284 | * @param \Illuminate\Support\Fluent $command 285 | * @return string 286 | */ 287 | public function compileGin(Blueprint $blueprint, Fluent $command) 288 | { 289 | $columns = $this->columnize($command->columns); 290 | 291 | return sprintf('CREATE INDEX %s ON %s USING GIN(%s)', $command->index, $this->wrapTable($blueprint), $columns); 292 | } 293 | 294 | /** 295 | * Compile a gist index key command. 296 | * 297 | * @param \Ajthinking\LaravelPostgis\Schema\Blueprint $blueprint 298 | * @param \Illuminate\Support\Fluent $command 299 | * @return string 300 | */ 301 | public function compileGist(Blueprint $blueprint, Fluent $command) 302 | { 303 | $columns = $this->columnize($command->columns); 304 | 305 | return sprintf('CREATE INDEX %s ON %s USING GIST(%s)', $command->index, $this->wrapTable($blueprint), $columns); 306 | } 307 | 308 | /** 309 | * Adds a statement to add a point geometry column 310 | * 311 | * @param \Illuminate\Support\Fluent $column 312 | * @return string 313 | */ 314 | public function typePoint(Fluent $column) 315 | { 316 | return $this->createTypeDefinition($column, 'POINT'); 317 | } 318 | 319 | /** 320 | * Adds a statement to add a point geometry column 321 | * 322 | * @param \Illuminate\Support\Fluent $column 323 | * @return string 324 | */ 325 | public function typeMultipoint(Fluent $column) 326 | { 327 | return $this->createTypeDefinition($column, 'MULTIPOINT'); 328 | } 329 | 330 | /** 331 | * Adds a statement to add a polygon geometry column 332 | * 333 | * @param \Illuminate\Support\Fluent $column 334 | * @return string 335 | */ 336 | public function typePolygon(Fluent $column) 337 | { 338 | return $this->createTypeDefinition($column, 'POLYGON'); 339 | } 340 | 341 | /** 342 | * Adds a statement to add a multipolygon geometry column 343 | * 344 | * @param \Illuminate\Support\Fluent $column 345 | * @return string 346 | */ 347 | public function typeMultipolygon(Fluent $column) 348 | { 349 | return $this->createTypeDefinition($column, 'MULTIPOLYGON'); 350 | } 351 | 352 | /** 353 | * Adds a statement to add a multipolygonz geometry column 354 | * 355 | * @param \Illuminate\Support\Fluent $column 356 | * @return string 357 | */ 358 | public function typeMultiPolygonZ(Fluent $column) 359 | { 360 | return $this->createTypeDefinition($column, 'MULTIPOLYGONZ'); 361 | } 362 | 363 | /** 364 | * Adds a statement to add a linestring geometry column 365 | * 366 | * @param \Illuminate\Support\Fluent $column 367 | * @return string 368 | */ 369 | public function typeLinestring(Fluent $column) 370 | { 371 | return $this->createTypeDefinition($column, 'LINESTRING'); 372 | } 373 | 374 | /** 375 | * Adds a statement to add a multilinestring geometry column 376 | * 377 | * @param \Illuminate\Support\Fluent $column 378 | * @return string 379 | */ 380 | public function typeMultilinestring(Fluent $column) 381 | { 382 | return $this->createTypeDefinition($column, 'MULTILINESTRING'); 383 | } 384 | 385 | /** 386 | * Adds a statement to add a linestring geometry column 387 | * 388 | * @param \Illuminate\Support\Fluent $column 389 | * @return string 390 | */ 391 | public function typeGeography(Fluent $column) 392 | { 393 | return 'GEOGRAPHY'; 394 | } 395 | 396 | /** 397 | * Adds a statement to add a geometry column 398 | * 399 | * @param \Illuminate\Support\Fluent $column 400 | * @return string 401 | */ 402 | public function typeGeometry(Fluent $column) 403 | { 404 | return 'GEOMETRY'; 405 | } 406 | 407 | /** 408 | * Adds a statement to add a geometrycollection geometry column 409 | * 410 | * @param Blueprint $blueprint 411 | * @param Fluent $command 412 | * @return string 413 | */ 414 | public function compileGeometrycollection(Blueprint $blueprint, Fluent $command) 415 | { 416 | $command->type = 'GEOMETRYCOLLECTION'; 417 | 418 | return $this->compileGeometry($blueprint, $command); 419 | } 420 | 421 | /** 422 | * Adds a statement to create the postgis extension 423 | * 424 | * @return string 425 | */ 426 | public function compileEnablePostgis() 427 | { 428 | return 'CREATE EXTENSION postgis'; 429 | } 430 | 431 | /** 432 | * Adds a statement to create the postgis extension, if it doesn't already exist 433 | * 434 | * @return string 435 | */ 436 | public function compileEnablePostgisIfNotExists() 437 | { 438 | return 'CREATE EXTENSION IF NOT EXISTS postgis'; 439 | } 440 | 441 | /** 442 | * Adds a statement to drop the postgis extension 443 | * 444 | * @return string 445 | */ 446 | public function compileDisablePostgis() 447 | { 448 | return 'DROP EXTENSION postgis'; 449 | } 450 | 451 | /** 452 | * Adds a statement to drop the postgis extension, if it exists 453 | * 454 | * @return string 455 | */ 456 | public function compileDisablePostgisIfExists() 457 | { 458 | return 'DROP EXTENSION IF EXISTS postgis'; 459 | } 460 | 461 | /** 462 | * Adds a statement to add a geometry column 463 | * 464 | * @param Blueprint $blueprint 465 | * @param Fluent $command 466 | * @return string 467 | */ 468 | protected function compileGeometry(Blueprint $blueprint, Fluent $command) 469 | { 470 | 471 | $dimensions = $command->dimensions ?: 2; 472 | $typmod = $command->typmod ? 'true' : 'false'; 473 | $srid = $command->srid ?: 4326; 474 | $schema = function_exists('config') ? config('postgis.schema') : 'public'; 475 | 476 | return sprintf( 477 | "SELECT %s.AddGeometryColumn('%s', '%s', %d, '%s.%s', %d, %s)", 478 | $schema, 479 | $blueprint->getTable(), 480 | $command->column, 481 | $srid, 482 | $schema, 483 | strtoupper($command->type), 484 | $dimensions, 485 | $typmod 486 | ); 487 | } 488 | 489 | /** 490 | * Checks if the given $column is a valid geometry type 491 | * 492 | * @param \Illuminate\Support\Fluent $column 493 | * @return boolean 494 | */ 495 | protected function isValid($column) 496 | { 497 | return in_array(strtoupper($column->geomtype), PostgisGrammar::$allowed_geom_types) && is_int((int) $column->srid); 498 | } 499 | 500 | /** 501 | * Create definition for geometry types. 502 | * @param Fluent $column 503 | * @param string $geometryType 504 | * @return string 505 | * @throws UnsupportedGeomtypeException 506 | */ 507 | private function createTypeDefinition(Fluent $column, $geometryType) 508 | { 509 | $schema = function_exists('config') ? config('postgis.schema') : 'public'; 510 | $type = strtoupper($column->geomtype); 511 | if ($this->isValid($column)) { 512 | if ($type == 'GEOGRAPHY' && $column->srid != 4326) { 513 | throw new UnsupportedGeomtypeException('Error with validation of srid! SRID of GEOGRAPHY must be 4326)'); 514 | } 515 | return $schema . '.' . $type . '(' . $geometryType . ', ' . $column->srid . ')'; 516 | } else { 517 | throw new UnsupportedGeomtypeException('Error with validation of geom type or srid!'); 518 | } 519 | } 520 | 521 | } 522 | -------------------------------------------------------------------------------- /tests/BaseTestCase.php: -------------------------------------------------------------------------------- 1 | 'pgsql', 'prefix' => 'prefix', 'database' => 'database', 'name' => 'foo']; 16 | $pdo = new PDOStub(); 17 | 18 | $factory = Mockery::mock(ConnectionFactory::class, [new Container()])->makePartial(); 19 | $factory->shouldAllowMockingProtectedMethods(); 20 | $conn = $factory->createConnection('pgsql', $pdo, 'database', 'prefix', $pgConfig); 21 | 22 | $this->assertInstanceOf(PostgisConnection::class, $conn); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/Eloquent/BuilderTest.php: -------------------------------------------------------------------------------- 1 | queryBuilder = m::mock(QueryBuilder::class); 28 | $this->queryBuilder->makePartial(); 29 | 30 | $this->queryBuilder 31 | ->shouldReceive('from') 32 | ->andReturn($this->queryBuilder); 33 | 34 | $this->queryBuilder 35 | ->shouldReceive('take') 36 | ->with(1) 37 | ->andReturn($this->queryBuilder); 38 | 39 | $this->queryBuilder 40 | ->shouldReceive('get') 41 | ->andReturn([]); 42 | 43 | $this->builder = new Builder($this->queryBuilder); 44 | $this->builder->setModel(new class extends Model { 45 | use PostgisTrait; 46 | protected $postgisFields = [ 47 | 'point' => Point::class, 48 | 'linestring' => LineString::class, 49 | 'polygon' => Polygon::class 50 | ]; 51 | }); 52 | } 53 | 54 | public function testUpdate() 55 | { 56 | $this->queryBuilder 57 | ->shouldReceive('raw') 58 | ->with("public.ST_GeogFromText('POINT(2 1)')") 59 | ->andReturn(new Expression("public.ST_GeogFromText('POINT(2 1)')")); 60 | 61 | $this->queryBuilder 62 | ->shouldReceive('update') 63 | ->andReturn(1); 64 | 65 | $builder = m::mock(Builder::class, [$this->queryBuilder])->makePartial(); 66 | $builder->shouldAllowMockingProtectedMethods(); 67 | $builder 68 | ->shouldReceive('addUpdatedAtColumn') 69 | ->andReturn(['point' => new Point(1, 2)]); 70 | 71 | $builder->update(['point' => new Point(1, 2)]); 72 | } 73 | 74 | public function testUpdateLinestring() 75 | { 76 | $this->queryBuilder 77 | ->shouldReceive('raw') 78 | ->with("public.ST_GeogFromText('LINESTRING(0 0, 1 1, 2 2)')") 79 | ->andReturn(new Expression("public.ST_GeogFromText('LINESTRING(0 0, 1 1, 2 2)')")); 80 | 81 | $this->queryBuilder 82 | ->shouldReceive('update') 83 | ->andReturn(1); 84 | 85 | $linestring = new LineString([new Point(0, 0), new Point(1, 1), new Point(2, 2)]); 86 | 87 | $builder = m::mock(Builder::class, [$this->queryBuilder])->makePartial(); 88 | $builder->shouldAllowMockingProtectedMethods(); 89 | $builder 90 | ->shouldReceive('addUpdatedAtColumn') 91 | ->andReturn(['linestring' => $linestring]); 92 | 93 | $builder 94 | ->shouldReceive('asWKT')->with($linestring)->once(); 95 | 96 | $builder->update(['linestring' => $linestring]); 97 | } 98 | 99 | public function testUpdate3d() 100 | { 101 | $this->queryBuilder 102 | ->shouldReceive('raw') 103 | ->with("public.ST_GeogFromText('POINT Z(2 1 0)')") 104 | ->andReturn(new Expression("public.ST_GeogFromText('POINT Z(2 1 0)')")); 105 | 106 | $this->queryBuilder 107 | ->shouldReceive('update') 108 | ->andReturn(1); 109 | 110 | $builder = m::mock(Builder::class, [$this->queryBuilder])->makePartial(); 111 | $builder->shouldAllowMockingProtectedMethods(); 112 | $builder 113 | ->shouldReceive('addUpdatedAtColumn') 114 | ->andReturn(['point' => new Point(1, 2, 0)]); 115 | 116 | $builder->update(['point' => new Point(1, 2, 0)]); 117 | } 118 | 119 | public function testUpdateLinestring3d() 120 | { 121 | $this->queryBuilder 122 | ->shouldReceive('raw') 123 | ->with("public.ST_GeogFromText('LINESTRING Z(0 0 0, 1 1 1, 2 2 2)')") 124 | ->andReturn(new Expression("public.ST_GeogFromText('LINESTRING Z(0 0 0, 1 1 1, 2 2 2)')")); 125 | 126 | $this->queryBuilder 127 | ->shouldReceive('update') 128 | ->andReturn(1); 129 | 130 | $linestring = new LineString([new Point(0, 0, 0), new Point(1, 1, 1), new Point(2, 2, 2)]); 131 | 132 | $builder = m::mock(Builder::class, [$this->queryBuilder])->makePartial(); 133 | $builder->shouldAllowMockingProtectedMethods(); 134 | $builder 135 | ->shouldReceive('addUpdatedAtColumn') 136 | ->andReturn(['linestring' => $linestring]); 137 | 138 | $builder 139 | ->shouldReceive('asWKT')->with($linestring)->once(); 140 | 141 | $builder->update(['linestring' => $linestring]); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /tests/Geometries/GeometryCollectionTest.php: -------------------------------------------------------------------------------- 1 | collection = new GeometryCollection([$collection, $point]); 33 | 34 | $collection = new LineString( 35 | [ 36 | new Point(1, 1, 1), 37 | new Point(1, 2, 3), 38 | new Point(2, 2, 2), 39 | new Point(2, 1, 0), 40 | new Point(1, 1, 1) 41 | ] 42 | ); 43 | 44 | $point = new Point(100, 200, 300); 45 | 46 | $this->collection3d = new GeometryCollection([$collection, $point]); 47 | } 48 | 49 | public function testFromGeoJSON() 50 | { 51 | $geojson = new \GeoJson\Geometry\GeometryCollection([ 52 | new \GeoJson\Geometry\Point([2, 3]), 53 | new \GeoJson\Geometry\LineString([[2, 3], [3, 4]]), 54 | ]); 55 | 56 | $geometryCollection = GeometryCollection::fromGeoJSON($geojson); 57 | 58 | $this->assertInstanceOf(GeometryCollection::class, $geometryCollection); 59 | $this->assertEquals(2, $geometryCollection->count()); 60 | $this->assertInstanceOf(Point::class, $geometryCollection->getGeometries()[0]); 61 | $this->assertInstanceOf(LineString::class, $geometryCollection->getGeometries()[1]); 62 | $this->assertEquals($geojson, $geometryCollection->toGeoJSON()); 63 | } 64 | 65 | public function testFromGeoJSON3d() 66 | { 67 | $geojson = new \GeoJson\Geometry\GeometryCollection([ 68 | new \GeoJson\Geometry\Point([2, 3, 4]), 69 | new \GeoJson\Geometry\LineString([[2, 3, 4], [3, 4, 5]]), 70 | ]); 71 | 72 | $geometryCollection = GeometryCollection::fromGeoJSON($geojson); 73 | 74 | $this->assertInstanceOf(GeometryCollection::class, $geometryCollection); 75 | $this->assertEquals(2, $geometryCollection->count()); 76 | $this->assertInstanceOf(Point::class, $geometryCollection->getGeometries()[0]); 77 | $this->assertInstanceOf(LineString::class, $geometryCollection->getGeometries()[1]); 78 | $this->assertEquals($geojson, $geometryCollection->toGeoJSON()); 79 | } 80 | 81 | public function testFromWKT() 82 | { 83 | /** 84 | * @var GeometryCollection $geometryCollection 85 | */ 86 | $geometryCollection = GeometryCollection::fromWKT('GEOMETRYCOLLECTION(POINT(2 3),LINESTRING(2 3,3 4))'); 87 | $this->assertInstanceOf(GeometryCollection::class, $geometryCollection); 88 | 89 | $this->assertEquals(2, $geometryCollection->count()); 90 | $this->assertInstanceOf(Point::class, $geometryCollection->getGeometries()[0]); 91 | $this->assertInstanceOf(LineString::class, $geometryCollection->getGeometries()[1]); 92 | } 93 | 94 | public function testFromWKT3d() 95 | { 96 | /** 97 | * @var GeometryCollection $geometryCollection 98 | */ 99 | $geometryCollection = GeometryCollection::fromWKT('GEOMETRYCOLLECTION(POINT Z(2 3 4),LINESTRING Z(2 3 4,3 4 5))'); 100 | $this->assertInstanceOf(GeometryCollection::class, $geometryCollection); 101 | 102 | $this->assertEquals(2, $geometryCollection->count()); 103 | $this->assertInstanceOf(Point::class, $geometryCollection->getGeometries()[0]); 104 | $this->assertInstanceOf(LineString::class, $geometryCollection->getGeometries()[1]); 105 | } 106 | 107 | public function testToWKT() 108 | { 109 | $this->assertEquals( 110 | 'GEOMETRYCOLLECTION(LINESTRING(1 1,2 1,2 2,1 2,1 1),POINT(200 100))', 111 | $this->collection->toWKT() 112 | ); 113 | } 114 | 115 | public function testToWKT3d() 116 | { 117 | $this->assertEquals( 118 | 'GEOMETRYCOLLECTION(LINESTRING Z(1 1 1,2 1 3,2 2 2,1 2 0,1 1 1),POINT Z(200 100 300))', 119 | $this->collection3d->toWKT() 120 | ); 121 | } 122 | 123 | public function testJsonSerialize() 124 | { 125 | $this->assertInstanceOf( 126 | \GeoJson\Geometry\GeometryCollection::class, 127 | $this->collection->jsonSerialize() 128 | ); 129 | 130 | $this->assertSame( 131 | '{"type":"GeometryCollection","geometries":[{"type":"LineString","coordinates":[[1,1],[2,1],[2,2],[1,2],[1,1]]},{"type":"Point","coordinates":[200,100]}]}', 132 | json_encode($this->collection->jsonSerialize()) 133 | ); 134 | 135 | } 136 | 137 | public function testJsonSerialize3d() 138 | { 139 | $this->assertInstanceOf( 140 | \GeoJson\Geometry\GeometryCollection::class, 141 | $this->collection3d->jsonSerialize() 142 | ); 143 | 144 | $this->assertSame( 145 | '{"type":"GeometryCollection","geometries":[{"type":"LineString","coordinates":[[1,1,1],[2,1,3],[2,2,2],[1,2,0],[1,1,1]]},{"type":"Point","coordinates":[200,100,300]}]}', 146 | json_encode($this->collection3d->jsonSerialize()) 147 | ); 148 | 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /tests/Geometries/GeometryTest.php: -------------------------------------------------------------------------------- 1 | assertEquals( 20 | '1 1', 21 | Geometry::getWKTArgument('POINT(1 1)') 22 | ); 23 | $this->assertEquals( 24 | '1 1,1 2,2 2', 25 | Geometry::getWKTArgument('LINESTRING(1 1,1 2,2 2)') 26 | ); 27 | $this->assertEquals( 28 | '(1 1,4 1,4 4,1 4,1 1),(1 1, 2 1, 2 2, 1 2,1 1)', 29 | Geometry::getWKTArgument('POLYGON((1 1,4 1,4 4,1 4,1 1),(1 1, 2 1, 2 2, 1 2,1 1))') 30 | ); 31 | $this->assertEquals( 32 | '(1 1),(1 2)', 33 | Geometry::getWKTArgument('MULTIPOINT((1 1),(1 2))') 34 | ); 35 | $this->assertEquals( 36 | '(1 1,1 2,2 2),(2 3,3 2,5 4)', 37 | Geometry::getWKTArgument('MULTILINESTRING((1 1,1 2,2 2),(2 3,3 2,5 4))') 38 | ); 39 | $this->assertEquals( 40 | '((1 1,4 1,4 4,1 4,1 1),(1 1,2 1,2 2,1 2,1 1)), ((-1 -1,-1 -2,-2 -2,-2 -1,-1 -1))', 41 | Geometry::getWKTArgument('MULTIPOLYGON(((1 1,4 1,4 4,1 4,1 1),(1 1,2 1,2 2,1 2,1 1)), ((-1 -1,-1 -2,-2 -2,-2 -1,-1 -1)))') 42 | ); 43 | $this->assertEquals( 44 | 'POINT(2 3),LINESTRING(2 3,3 4)', 45 | Geometry::getWKTArgument('GEOMETRYCOLLECTION(POINT(2 3),LINESTRING(2 3,3 4))') 46 | ); 47 | } 48 | 49 | public function testGetWKTArgument3d() 50 | { 51 | $this->assertEquals( 52 | '1 1 1', 53 | Geometry::getWKTArgument('POINT Z(1 1 1)') 54 | ); 55 | $this->assertEquals( 56 | '1 1 1,1 2 2,2 2 3', 57 | Geometry::getWKTArgument('LINESTRING Z(1 1 1,1 2 2,2 2 3)') 58 | ); 59 | $this->assertEquals( 60 | '(1 1 1,4 1 1,4 4 1,1 4 1,1 1 1),(1 1 2, 2 1 2, 2 2 2, 1 2 2,1 1 2)', 61 | Geometry::getWKTArgument('POLYGON Z((1 1 1,4 1 1,4 4 1,1 4 1,1 1 1),(1 1 2, 2 1 2, 2 2 2, 1 2 2,1 1 2))') 62 | ); 63 | $this->assertEquals( 64 | '(1 1 1),(1 2 2)', 65 | Geometry::getWKTArgument('MULTIPOINT Z((1 1 1),(1 2 2))') 66 | ); 67 | $this->assertEquals( 68 | '(1 1 1,1 2 1,2 2 1),(2 3 2,3 2 2,5 4 2)', 69 | Geometry::getWKTArgument('MULTILINESTRING Z((1 1 1,1 2 1,2 2 1),(2 3 2,3 2 2,5 4 2))') 70 | ); 71 | $this->assertEquals( 72 | '((1 1 1,4 1 1,4 4 1,1 4 1,1 1 1),(1 1 2,2 1 2,2 2 2,1 2 2,1 1 2)), ((-1 -1 -1,-1 -2 -1,-2 -2 -1,-2 -1 -1,-1 -1 -1))', 73 | Geometry::getWKTArgument('MULTIPOLYGON Z(((1 1 1,4 1 1,4 4 1,1 4 1,1 1 1),(1 1 2,2 1 2,2 2 2,1 2 2,1 1 2)), ((-1 -1 -1,-1 -2 -1,-2 -2 -1,-2 -1 -1,-1 -1 -1)))') 74 | ); 75 | $this->assertEquals( 76 | 'POINT Z(2 3 4),LINESTRING Z(2 3 4,3 4 5)', 77 | Geometry::getWKTArgument('GEOMETRYCOLLECTION(POINT Z(2 3 4),LINESTRING Z(2 3 4,3 4 5))') 78 | ); 79 | } 80 | 81 | public function testGetWKTClass() 82 | { 83 | $this->assertEquals( 84 | Point::class, 85 | Geometry::getWKTClass('POINT(0 0)') 86 | ); 87 | $this->assertEquals( 88 | LineString::class, 89 | Geometry::getWKTClass('LINESTRING(0 0,1 1,1 2)') 90 | ); 91 | $this->assertEquals( 92 | Polygon::class, 93 | Geometry::getWKTClass('POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1))') 94 | ); 95 | $this->assertEquals( 96 | MultiPoint::class, 97 | Geometry::getWKTClass('MULTIPOINT((0 0),(1 2))') 98 | ); 99 | $this->assertEquals( 100 | MultiLineString::class, 101 | Geometry::getWKTClass('MULTILINESTRING((0 0,1 1,1 2),(2 3,3 2,5 4))') 102 | ); 103 | $this->assertEquals( 104 | MultiPolygon::class, 105 | Geometry::getWKTClass('MULTIPOLYGON(((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1)), ((-1 -1,-1 -2,-2 -2,-2 -1,-1 -1)))') 106 | ); 107 | $this->assertEquals( 108 | GeometryCollection::class, 109 | Geometry::getWKTClass('GEOMETRYCOLLECTION(POINT(2 3),LINESTRING(2 3,3 4))') 110 | ); 111 | } 112 | 113 | public function testGetWKTClass3d() 114 | { 115 | $this->assertEquals( 116 | Point::class, 117 | Geometry::getWKTClass('POINT Z(0 0 0)') 118 | ); 119 | $this->assertEquals( 120 | LineString::class, 121 | Geometry::getWKTClass('LINESTRING Z(0 0 0,1 1 1,1 2 3)') 122 | ); 123 | $this->assertEquals( 124 | Polygon::class, 125 | Geometry::getWKTClass('POLYGON Z((0 0 0 ,4 0 3,4 4 4,0 4 0,0 0 0),(1 1 1, 2 1 2, 2 2 2, 1 2 2,1 1 1))') 126 | ); 127 | $this->assertEquals( 128 | MultiPoint::class, 129 | Geometry::getWKTClass('MULTIPOINT Z((0 00),(1 2 3))') 130 | ); 131 | $this->assertEquals( 132 | MultiLineString::class, 133 | Geometry::getWKTClass('MULTILINESTRING Z((0 0 0 ,1 1 1,1 2 3),(2 3 4,3 2 1,5 4 3))') 134 | ); 135 | $this->assertEquals( 136 | MultiPolygon::class, 137 | Geometry::getWKTClass('MULTIPOLYGON Z(((0 0 0,4 0 4,4 4 4,0 4 0,0 0 0),(1 1 1,2 1 2,2 2 2,1 2 2,1 1 1)), ((-1 -1 -1,-1 -2 -1,-2 -2 -1,-2 -1 -1,-1 -1 -1)))') 138 | ); 139 | $this->assertEquals( 140 | GeometryCollection::class, 141 | Geometry::getWKTClass('GEOMETRYCOLLECTION(POINT Z(2 3 4),LINESTRING Z(2 3 4,3 4 5))') 142 | ); 143 | } 144 | 145 | public function testGetWKBClass() 146 | { 147 | $this->assertInstanceOf( 148 | Point::class, 149 | Geometry::fromWKB('0101000000000000000000f03f0000000000000040') 150 | ); 151 | $this->assertInstanceOf( 152 | LineString::class, 153 | Geometry::fromWKB('010200000002000000000000000000f03f000000000000004000000000000008400000000000001040') 154 | ); 155 | $this->assertInstanceOf( 156 | Polygon::class, 157 | Geometry::fromWKB('01030000000100000004000000000000000000f03f00000000000000400000000000000840000000000000104000000000000014400000000000001840000000000000f03f0000000000000040') 158 | ); 159 | $this->assertInstanceOf( 160 | MultiPoint::class, 161 | Geometry::fromWKB('0104000000020000000101000000000000000000f03f0000000000000040010100000000000000000008400000000000001040') 162 | ); 163 | $this->assertInstanceOf( 164 | MultiLineString::class, 165 | Geometry::fromWKB('010500000001000000010200000002000000000000000000f03f000000000000004000000000000008400000000000001040') 166 | ); 167 | $this->assertInstanceOf( 168 | MultiLineString::class, 169 | Geometry::fromWKB('010500000002000000010200000002000000000000000000f03f000000000000004000000000000008400000000000001040010200000002000000000000000000144000000000000018400000000000001c400000000000002040') 170 | ); 171 | $this->assertInstanceOf( 172 | MultiPolygon::class, 173 | Geometry::fromWKB('01060000000200000001030000000100000004000000000000000000f03f00000000000000400000000000000840000000000000104000000000000014400000000000001840000000000000f03f000000000000004001030000000300000004000000000000000000f03f00000000000000400000000000000840000000000000104000000000000014400000000000001840000000000000f03f000000000000004004000000000000000000264000000000000028400000000000002a400000000000002c400000000000002e4000000000000030400000000000002640000000000000284004000000000000000000354000000000000036400000000000003740000000000000384000000000000039400000000000003a4000000000000035400000000000003640') 174 | ); 175 | $this->assertInstanceOf( 176 | GeometryCollection::class, 177 | Geometry::fromWKB('0107000000010000000101000000000000000000f03f0000000000000040') 178 | ); 179 | $this->assertInstanceOf( 180 | GeometryCollection::class, 181 | Geometry::fromWKB('0107000000020000000101000000000000000000f03f0000000000000040010200000002000000000000000000f03f000000000000004000000000000008400000000000001040') 182 | ); 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /tests/Geometries/LineStringTest.php: -------------------------------------------------------------------------------- 1 | points = [new Point(1, 1), new Point(2, 2), new Point(3, 3)]; 17 | $this->points3d = [new Point(1, 1, 1), new Point(2, 2, 2), new Point(3, 3, 3)]; 18 | } 19 | 20 | public function testToWKT() 21 | { 22 | $linestring = new LineString($this->points); 23 | 24 | $this->assertEquals('LINESTRING(1 1,2 2,3 3)', $linestring->toWKT()); 25 | } 26 | 27 | public function testToWKT3d() 28 | { 29 | $linestring = new LineString($this->points3d); 30 | 31 | $this->assertEquals('LINESTRING Z(1 1 1,2 2 2,3 3 3)', $linestring->toWKT()); 32 | } 33 | 34 | public function testFromGeoJSON() 35 | { 36 | $geojson = new \GeoJson\Geometry\LineString([[1, 1], [2, 2], [3, 3]]); 37 | 38 | $linestring = LineString::fromGeoJSON($geojson); 39 | 40 | $this->assertInstanceOf(LineString::class, $linestring); 41 | $this->assertEquals(3, $linestring->count()); 42 | $this->assertEquals($geojson, $linestring->toGeoJSON()); 43 | } 44 | 45 | public function testFromGeoJSON3d() 46 | { 47 | $geojson = new \GeoJson\Geometry\LineString([[1, 1, 1], [2, 2, 2], [3, 3, 3]]); 48 | 49 | $linestring = LineString::fromGeoJSON($geojson); 50 | 51 | $this->assertInstanceOf(LineString::class, $linestring); 52 | $this->assertEquals(3, $linestring->count()); 53 | $this->assertEquals($geojson, $linestring->toGeoJSON()); 54 | } 55 | 56 | public function testFromWKT() 57 | { 58 | $linestring = LineString::fromWKT('LINESTRING(1 1, 2 2,3 3)'); 59 | $this->assertInstanceOf(LineString::class, $linestring); 60 | 61 | $this->assertEquals(3, $linestring->count()); 62 | } 63 | 64 | public function testFromWKT3d() 65 | { 66 | $linestring = LineString::fromWKT('LINESTRING Z(1 1 1, 2 2 2,3 3 3)'); 67 | $this->assertInstanceOf(LineString::class, $linestring); 68 | 69 | $this->assertEquals(3, $linestring->count()); 70 | } 71 | 72 | public function testToString() 73 | { 74 | $linestring = new LineString($this->points); 75 | 76 | $this->assertEquals('1 1,2 2,3 3', (string)$linestring); 77 | } 78 | 79 | public function testToString3d() 80 | { 81 | $linestring = new LineString($this->points3d); 82 | 83 | $this->assertEquals('1 1 1,2 2 2,3 3 3', (string)$linestring); 84 | } 85 | 86 | public function testJsonSerialize() 87 | { 88 | $lineString = new LineString($this->points); 89 | 90 | $this->assertInstanceOf(\GeoJson\Geometry\LineString::class, $lineString->jsonSerialize()); 91 | $this->assertSame('{"type":"LineString","coordinates":[[1,1],[2,2],[3,3]]}', json_encode($lineString)); 92 | } 93 | 94 | public function testJsonSerialize3d() 95 | { 96 | $lineString = new LineString($this->points3d); 97 | 98 | $this->assertInstanceOf(\GeoJson\Geometry\LineString::class, $lineString->jsonSerialize()); 99 | $this->assertSame('{"type":"LineString","coordinates":[[1,1,1],[2,2,2],[3,3,3]]}', json_encode($lineString)); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /tests/Geometries/MultiLineStringTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf(MultiLineString::class, $multilinestring); 19 | $this->assertEquals(2, $multilinestring->count()); 20 | $this->assertEquals($geojson, $multilinestring->toGeoJSON()); 21 | } 22 | 23 | public function testFromGeoJSON3d() 24 | { 25 | $geojson = new \GeoJson\Geometry\MultiLineString([[[1, 1, 1], [2, 2, 2], [2, 3, 4]], [[3, 4, 5], [4, 3, 2], [6, 5, 4]]]); 26 | 27 | $multilinestring = MultiLineString::fromGeoJSON($geojson); 28 | 29 | $this->assertInstanceOf(MultiLineString::class, $multilinestring); 30 | $this->assertEquals(2, $multilinestring->count()); 31 | $this->assertEquals($geojson, $multilinestring->toGeoJSON()); 32 | } 33 | 34 | public function testFromWKT() 35 | { 36 | $multilinestring = MultiLineString::fromWKT('MULTILINESTRING((1 1,2 2,2 3),(3 4,4 3,6 5))'); 37 | $this->assertInstanceOf(MultiLineString::class, $multilinestring); 38 | 39 | $this->assertSame(2, $multilinestring->count()); 40 | } 41 | 42 | public function testFromWKT3d() 43 | { 44 | $multilinestring = MultiLineString::fromWKT('MULTILINESTRING Z((1 1 1,2 2 2,2 3 4),(3 4 5,4 3 2,6 5 4))'); 45 | $this->assertInstanceOf(MultiLineString::class, $multilinestring); 46 | 47 | $this->assertSame(2, $multilinestring->count()); 48 | } 49 | 50 | public function testToWKT() 51 | { 52 | $collection = new LineString( 53 | [ 54 | new Point(1, 1), 55 | new Point(1, 2), 56 | new Point(2, 2), 57 | new Point(2, 1), 58 | new Point(1, 1) 59 | ] 60 | ); 61 | 62 | $multilinestring = new MultiLineString([$collection]); 63 | 64 | $this->assertSame('MULTILINESTRING((1 1,2 1,2 2,1 2,1 1))', $multilinestring->toWKT()); 65 | } 66 | 67 | public function testToWKT3d() 68 | { 69 | $collection = new LineString( 70 | [ 71 | new Point(1, 1, 1), 72 | new Point(1, 2, 3), 73 | new Point(2, 2, 2), 74 | new Point(2, 1, 3), 75 | new Point(1, 1, 1) 76 | ] 77 | ); 78 | 79 | $multilinestring = new MultiLineString([$collection]); 80 | 81 | $this->assertSame('MULTILINESTRING Z((1 1 1,2 1 3,2 2 2,1 2 3,1 1 1))', $multilinestring->toWKT()); 82 | } 83 | 84 | public function testJsonSerialize() 85 | { 86 | $multilinestring = MultiLineString::fromWKT('MULTILINESTRING Z((1 1 1,2 2 2,2 3 4),(3 4 5,4 3 2,6 5 4))'); 87 | 88 | $this->assertInstanceOf(\GeoJson\Geometry\MultiLineString::class, $multilinestring->jsonSerialize()); 89 | $this->assertSame( 90 | '{"type":"MultiLineString","coordinates":[[[1,1,1],[2,2,2],[2,3,4]],[[3,4,5],[4,3,2],[6,5,4]]]}', 91 | json_encode($multilinestring) 92 | ); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /tests/Geometries/MultiPointTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf(MultiPoint::class, $multipoint); 18 | $this->assertEquals(3, $multipoint->count()); 19 | $this->assertEquals($geojson, $multipoint->toGeoJSON()); 20 | } 21 | 22 | public function testFromGeoJSON3d() 23 | { 24 | $geojson = new \GeoJson\Geometry\MultiPoint([[1, 1, 1], [2, 1, 3], [2, 2, 2]]); 25 | 26 | $multipoint = MultiPoint::fromGeoJSON($geojson); 27 | 28 | $this->assertInstanceOf(MultiPoint::class, $multipoint); 29 | $this->assertEquals(3, $multipoint->count()); 30 | $this->assertEquals($geojson, $multipoint->toGeoJSON()); 31 | } 32 | 33 | public function testFromWKT() 34 | { 35 | $multipoint = MultiPoint::fromWKT('MULTIPOINT((1 1),(2 1),(2 2))'); 36 | $this->assertInstanceOf(MultiPoint::class, $multipoint); 37 | 38 | $this->assertEquals(3, $multipoint->count()); 39 | } 40 | 41 | public function testFromWKT3d() 42 | { 43 | $multipoint = MultiPoint::fromWKT('MULTIPOINT Z((1 1 1),(2 1 3),(2 2 2))'); 44 | $this->assertInstanceOf(MultiPoint::class, $multipoint); 45 | 46 | $this->assertEquals(3, $multipoint->count()); 47 | } 48 | 49 | public function testToWKT() 50 | { 51 | $collection = [new Point(1, 1), new Point(1, 2), new Point(2, 2)]; 52 | 53 | $multipoint = new MultiPoint($collection); 54 | 55 | $this->assertEquals('MULTIPOINT((1 1),(2 1),(2 2))', $multipoint->toWKT()); 56 | } 57 | 58 | public function testToWKT3d() 59 | { 60 | $collection = [new Point(1, 1, 1), new Point(1, 2, 3), new Point(2, 2, 2)]; 61 | 62 | $multipoint = new MultiPoint($collection); 63 | 64 | $this->assertEquals('MULTIPOINT Z((1 1 1),(2 1 3),(2 2 2))', $multipoint->toWKT()); 65 | } 66 | 67 | public function testJsonSerialize() 68 | { 69 | $collection = [new Point(1, 1), new Point(1, 2), new Point(2, 2)]; 70 | 71 | $multipoint = new MultiPoint($collection); 72 | 73 | $this->assertInstanceOf(\GeoJson\Geometry\MultiPoint::class, $multipoint->jsonSerialize()); 74 | $this->assertSame('{"type":"MultiPoint","coordinates":[[1,1],[2,1],[2,2]]}', json_encode($multipoint)); 75 | } 76 | 77 | public function testJsonSerialize3d() 78 | { 79 | $collection = [new Point(1, 1, 1), new Point(1, 2, 3), new Point(2, 2, 2)]; 80 | 81 | $multipoint = new MultiPoint($collection); 82 | 83 | $this->assertInstanceOf(\GeoJson\Geometry\MultiPoint::class, $multipoint->jsonSerialize()); 84 | $this->assertSame('{"type":"MultiPoint","coordinates":[[1,1,1],[2,1,3],[2,2,2]]}', json_encode($multipoint)); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /tests/Geometries/MultiPolygonTest.php: -------------------------------------------------------------------------------- 1 | multiPolygon = new MultiPolygon([$polygon1, $polygon2]); 57 | 58 | $collection1 = new LineString( 59 | [ 60 | new Point(1, 1, 1), 61 | new Point(1, 2, 3), 62 | new Point(2, 2, 2), 63 | new Point(2, 1, 0), 64 | new Point(1, 1, 1) 65 | ] 66 | ); 67 | 68 | $collection2 = new LineString( 69 | [ 70 | new Point(10, 10, 10), 71 | new Point(10, 20, 30), 72 | new Point(20, 20, 20), 73 | new Point(20, 10, 0), 74 | new Point(10, 10, 10) 75 | ] 76 | ); 77 | 78 | $polygon1 = new Polygon([$collection1, $collection2]); 79 | 80 | $collection3 = new LineString( 81 | [ 82 | new Point(100, 100, 100), 83 | new Point(100, 200, 300), 84 | new Point(200, 200, 200), 85 | new Point(200, 100, 0), 86 | new Point(100, 100, 100) 87 | ] 88 | ); 89 | 90 | 91 | $polygon2 = new Polygon([$collection3]); 92 | 93 | $this->multiPolygon3d = new MultiPolygon([$polygon1, $polygon2]); 94 | } 95 | 96 | public function testFromGeoJSON() 97 | { 98 | $geojson = new \GeoJson\Geometry\MultiPolygon([ 99 | [[[1, 1], [2, 1], [2, 2], [1, 2], [1, 1]], [[1, 1], [2, 1], [2, 2], [1, 2], [1, 1]]], 100 | [[[-1, -1], [-2, -2], [-2, -2], [-2, -1], [-1, -1]]], 101 | ]); 102 | 103 | $multipolygon = MultiPolygon::fromGeoJSON($geojson); 104 | 105 | $this->assertInstanceOf(MultiPolygon::class, $multipolygon); 106 | $this->assertEquals(2, $multipolygon->count()); 107 | $this->assertEquals($geojson, $multipolygon->toGeoJSON()); 108 | } 109 | 110 | public function testFromGeoJSON3d() 111 | { 112 | $geojson = new \GeoJson\Geometry\MultiPolygon([ 113 | [[[1, 1, 1], [2, 1, 3], [2, 2, 2], [1, 2, 0], [1, 1, 1]], [[1, 1, 1], [2, 1, 3], [2, 2, 2], [1, 2, 0], [1, 1, 1]]], 114 | [[[-1, -1, -1], [-2, -2, -3], [-2, -2, -2], [-2, -1, 0], [-1, -1, -1]]], 115 | ]); 116 | 117 | $multipolygon = MultiPolygon::fromGeoJSON($geojson); 118 | 119 | $this->assertInstanceOf(MultiPolygon::class, $multipolygon); 120 | $this->assertEquals(2, $multipolygon->count()); 121 | $this->assertEquals($geojson, $multipolygon->toGeoJSON()); 122 | } 123 | 124 | public function testFromWKT() 125 | { 126 | $wkt = 'MULTIPOLYGON(((1 1,2 1,2 2,1 2,1 1),(1 1,2 1,2 2,1 2,1 1)),((-1 -1,-1 -2,-2 -2,-2 -1,-1 -1)))'; 127 | $polygon = MultiPolygon::fromWKT($wkt); 128 | 129 | $this->assertInstanceOf(MultiPolygon::class, $polygon); 130 | $this->assertEquals(2, $polygon->count()); 131 | $this->assertEquals($wkt, $polygon->toWKT()); 132 | } 133 | 134 | public function testFromWKT3d() 135 | { 136 | $wkt = 'MULTIPOLYGON Z(((1 1 1,2 1 3,2 2 2,1 2 0,1 1 1),(1 1 1,2 1 3,2 2 2,1 2 0,1 1)),((-1 -1 -1,-1 -2 -3,-2 -2 -2,-2 -1 0,-1 -1 -1)))'; 137 | $polygon = MultiPolygon::fromWKT($wkt); 138 | 139 | $this->assertInstanceOf(MultiPolygon::class, $polygon); 140 | $this->assertEquals(2, $polygon->count()); 141 | $this->assertEquals($wkt, $polygon->toWKT()); 142 | } 143 | 144 | public function testToWKT() 145 | { 146 | $this->assertEquals( 147 | 'MULTIPOLYGON(((1 1,2 1,2 2,1 2,1 1),(10 10,20 10,20 20,10 20,10 10)),((100 100,200 100,200 200,100 200,100 100)))', 148 | $this->multiPolygon->toWKT() 149 | ); 150 | } 151 | 152 | public function testToWKT3d() 153 | { 154 | $this->assertEquals( 155 | 'MULTIPOLYGON Z(((1 1 1,2 1 3,2 2 2,1 2 0,1 1 1),(10 10 10,20 10 30,20 20 20,10 20 0,10 10 10)),((100 100 100,200 100 300,200 200 200,100 200 0,100 100 100)))', 156 | $this->multiPolygon3d->toWKT() 157 | ); 158 | } 159 | 160 | public function testGetPolygons() 161 | { 162 | $polygon = MultiPolygon::fromWKT( 163 | 'MULTIPOLYGON(((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1)), ((-1 -1,-1 -2,-2 -2,-2 -1,-1 -1)))' 164 | ); 165 | 166 | $this->assertInstanceOf(Polygon::class, $polygon->getPolygons()[0]); 167 | } 168 | 169 | public function testGetPolygons3d() 170 | { 171 | $polygon = MultiPolygon::fromWKT( 172 | 'MULTIPOLYGON Z(((0 0 0,4 0 0,4 4 4,0 4 0,0 0 0),(1 1 1,2 1 3,2 2 2,1 2 0,1 1 1)), ((-1 -1 -1,-1 -2 0,-2 -2 -2,-2 -1 -3,-1 -1 -1)))' 173 | ); 174 | 175 | $this->assertInstanceOf(Polygon::class, $polygon->getPolygons()[0]); 176 | } 177 | 178 | public function testIssue12() 179 | { 180 | $polygon = MultiPolygon::fromWKT( 181 | 'MULTIPOLYGON(((-80.214554 25.769598 0 0,-80.2147 25.774514 0 0,-80.212983 25.77456 0 0,-80.212977 25.773597 0 0,-80.211448 25.773655 0 0,-80.211498 25.774579 0 0,-80.209432 25.774665 0 0,-80.209392 25.773667 0 0,-80.204387 25.773834 0 0,-80.199383 25.774324 0 0,-80.197718 25.774031 0 0,-80.197757 25.774975 0 0,-80.193655 25.775108 0 0,-80.193623 25.774134 0 0,-80.191855 25.772551 0 0,-80.193442 25.76969 0 0,-80.192231 25.768345 0 0,-80.192879 25.758009 0 0,-80.196301 25.759985 0 0,-80.195608 25.76152 0 0,-80.198856 25.761454 0 0,-80.200646 25.763287 0 0,-80.20401 25.763164 0 0,-80.204023 25.76367 0 0,-80.205673 25.763141 0 0,-80.214326 25.762935 0 0,-80.214451 25.765883 0 0,-80.214539 25.768649 0 0,-80.216203 25.76858 0 0,-80.214554 25.769598 0 0)))' 182 | ); 183 | 184 | $this->assertInstanceOf(MultiPolygon::class, $polygon); 185 | } 186 | 187 | public function testIssue123d() 188 | { 189 | $polygon = MultiPolygon::fromWKT( 190 | 'MULTIPOLYGON Z(((-80.214554 25.769598 0 0,-80.2147 25.774514 0 0,-80.212983 25.77456 0 0,-80.212977 25.773597 0 0,-80.211448 25.773655 0 0,-80.211498 25.774579 0 0,-80.209432 25.774665 0 0,-80.209392 25.773667 0 0,-80.204387 25.773834 0 0,-80.199383 25.774324 0 0,-80.197718 25.774031 0 0,-80.197757 25.774975 0 0,-80.193655 25.775108 0 0,-80.193623 25.774134 0 0,-80.191855 25.772551 0 0,-80.193442 25.76969 0 0,-80.192231 25.768345 0 0,-80.192879 25.758009 0 0,-80.196301 25.759985 0 0,-80.195608 25.76152 0 0,-80.198856 25.761454 0 0,-80.200646 25.763287 0 0,-80.20401 25.763164 0 0,-80.204023 25.76367 0 0,-80.205673 25.763141 0 0,-80.214326 25.762935 0 0,-80.214451 25.765883 0 0,-80.214539 25.768649 0 0,-80.216203 25.76858 0 0,-80.214554 25.769598 0 0)))' 191 | ); 192 | 193 | $this->assertInstanceOf(MultiPolygon::class, $polygon); 194 | } 195 | 196 | public function testJsonSerialize() 197 | { 198 | $this->assertInstanceOf(\GeoJson\Geometry\MultiPolygon::class, $this->multiPolygon->jsonSerialize()); 199 | $this->assertSame( 200 | '{"type":"MultiPolygon","coordinates":[[[[1,1],[2,1],[2,2],[1,2],[1,1]],[[10,10],[20,10],[20,20],[10,20],[10,10]]],[[[100,100],[200,100],[200,200],[100,200],[100,100]]]]}', 201 | json_encode($this->multiPolygon) 202 | ); 203 | } 204 | 205 | public function testJsonSerialize3d() 206 | { 207 | $this->assertInstanceOf(\GeoJson\Geometry\MultiPolygon::class, $this->multiPolygon3d->jsonSerialize()); 208 | $this->assertSame( 209 | '{"type":"MultiPolygon","coordinates":[[[[1,1,1],[2,1,3],[2,2,2],[1,2,0],[1,1,1]],[[10,10,10],[20,10,30],[20,20,20],[10,20,0],[10,10,10]]],[[[100,100,100],[200,100,300],[200,200,200],[100,200,0],[100,100,100]]]]}', 210 | json_encode($this->multiPolygon3d) 211 | ); 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /tests/Geometries/PointTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf(Point::class, $point); 17 | $this->assertEquals(2, $point->getLat()); 18 | $this->assertEquals(1, $point->getLng()); 19 | $this->assertEquals($geojson, $point->toGeoJSON()); 20 | } 21 | 22 | public function testFromGeoJSON3d() 23 | { 24 | $geojson = new \GeoJson\Geometry\Point([1, 2, 3]); 25 | 26 | $point = Point::fromGeoJSON($geojson); 27 | 28 | $this->assertInstanceOf(Point::class, $point); 29 | $this->assertEquals(2, $point->getLat()); 30 | $this->assertEquals(1, $point->getLng()); 31 | $this->assertEquals(3, $point->getAlt()); 32 | $this->assertEquals($geojson, $point->toGeoJSON()); 33 | } 34 | 35 | public function testFromWKT() 36 | { 37 | $point = Point::fromWKT('POINT(1 2)'); 38 | 39 | $this->assertInstanceOf(Point::class, $point); 40 | $this->assertEquals(2, $point->getLat()); 41 | $this->assertEquals(1, $point->getLng()); 42 | } 43 | 44 | public function testFromWKT3d() 45 | { 46 | $point = Point::fromWKT('POINT(1 2 3)'); 47 | 48 | $this->assertInstanceOf(Point::class, $point); 49 | $this->assertEquals(2, $point->getLat()); 50 | $this->assertEquals(1, $point->getLng()); 51 | $this->assertEquals(3, $point->getAlt()); 52 | } 53 | 54 | public function testToWKT() 55 | { 56 | $point = new Point(1, 2); 57 | 58 | $this->assertEquals('POINT(2 1)', $point->toWKT()); 59 | } 60 | 61 | public function testToWKT3d() 62 | { 63 | $point = new Point(1, 2, 3); 64 | 65 | $this->assertEquals('POINT Z(2 1 3)', $point->toWKT()); 66 | } 67 | 68 | public function testGettersAndSetters() 69 | { 70 | $point = new Point(1, 2); 71 | $this->assertSame(1.0, $point->getLat()); 72 | $this->assertSame(2.0, $point->getLng()); 73 | 74 | $point->setLat('3'); 75 | $point->setLng('4'); 76 | 77 | $this->assertSame(3.0, $point->getLat()); 78 | $this->assertSame(4.0, $point->getLng()); 79 | } 80 | 81 | public function testGettersAndSetters3d() 82 | { 83 | $point = new Point(1, 2, 3); 84 | $this->assertSame(1.0, $point->getLat()); 85 | $this->assertSame(2.0, $point->getLng()); 86 | $this->assertSame(3.0, $point->getAlt()); 87 | 88 | $point->setLat('3'); 89 | $point->setLng('4'); 90 | $point->setAlt('5'); 91 | 92 | $this->assertSame(3.0, $point->getLat()); 93 | $this->assertSame(4.0, $point->getLng()); 94 | $this->assertSame(5.0, $point->getAlt()); 95 | } 96 | 97 | public function testPair() 98 | { 99 | $point = Point::fromPair('1.5 2'); 100 | 101 | $this->assertSame(1.5, $point->getLng()); 102 | $this->assertSame(2.0, $point->getLat()); 103 | 104 | $this->assertSame('1.5 2', $point->toPair()); 105 | } 106 | 107 | public function testPair3d() 108 | { 109 | $point = Point::fromPair('1.5 2 2.5'); 110 | 111 | $this->assertSame(1.5, $point->getLng()); 112 | $this->assertSame(2.0, $point->getLat()); 113 | $this->assertSame(2.5, $point->getAlt()); 114 | 115 | $this->assertSame('1.5 2 2.5', $point->toPair()); 116 | } 117 | 118 | public function testToString() 119 | { 120 | $point = Point::fromString('1.3 2'); 121 | 122 | $this->assertSame(1.3, $point->getLng()); 123 | $this->assertSame(2.0, $point->getLat()); 124 | 125 | $this->assertEquals('1.3 2', (string)$point); 126 | } 127 | 128 | public function testToString3d() 129 | { 130 | $point = Point::fromString('1.3 2 2.3'); 131 | 132 | $this->assertSame(1.3, $point->getLng()); 133 | $this->assertSame(2.0, $point->getLat()); 134 | $this->assertSame(2.3, $point->getAlt()); 135 | 136 | $this->assertEquals('1.3 2 2.3', (string)$point); 137 | } 138 | 139 | public function testJsonSerialize() 140 | { 141 | $point = new Point(1.2, 3.4); 142 | 143 | $this->assertInstanceOf(\GeoJson\Geometry\Point::class, $point->jsonSerialize()); 144 | $this->assertSame('{"type":"Point","coordinates":[3.4,1.2]}', json_encode($point)); 145 | } 146 | 147 | public function testJsonSerialize3d() 148 | { 149 | $point = new Point(1.2, 3.4, 5.6); 150 | 151 | $this->assertInstanceOf(\GeoJson\Geometry\Point::class, $point->jsonSerialize()); 152 | $this->assertSame('{"type":"Point","coordinates":[3.4,1.2,5.6]}', json_encode($point)); 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /tests/Geometries/PolygonTest.php: -------------------------------------------------------------------------------- 1 | polygon = new Polygon([$collection]); 28 | 29 | $collection = new LineString( 30 | [ 31 | new Point(1, 1, 1), 32 | new Point(1, 2, 2), 33 | new Point(2, 2, 2), 34 | new Point(2, 1, 2), 35 | new Point(1, 1, 1) 36 | ] 37 | ); 38 | 39 | $this->polygon3d = new Polygon([$collection]); 40 | } 41 | 42 | public function testFromGeoJSON() 43 | { 44 | $geojson = new \GeoJson\Geometry\Polygon([[[1, 1], [5, 1], [5, 5], [1, 5], [1, 1]], [[2, 2], [3, 2], [3, 3], [2, 3], [2, 2]]]); 45 | 46 | $polygon = Polygon::fromGeoJSON($geojson); 47 | 48 | $this->assertInstanceOf(Polygon::class, $polygon); 49 | $this->assertEquals(2, $polygon->count()); 50 | $this->assertEquals($geojson, $polygon->toGeoJSON()); 51 | } 52 | 53 | public function testFromGeoJSON3d() 54 | { 55 | $geojson = new \GeoJson\Geometry\Polygon([[[1, 1, 1], [5, 1, 1], [5, 5, 1], [1, 5, 1], [1, 1, 1]], [[2, 2, 2], [3, 2, 2], [3, 3, 2], [2, 3, 2], [2, 2, 2]]]); 56 | 57 | $polygon = Polygon::fromGeoJSON($geojson); 58 | 59 | $this->assertInstanceOf(Polygon::class, $polygon); 60 | $this->assertEquals(2, $polygon->count()); 61 | $this->assertEquals($geojson, $polygon->toGeoJSON()); 62 | } 63 | 64 | public function testFromWKT() 65 | { 66 | $wkt = 'POLYGON((1 1,5 1,5 5,1 5,1 1),(2 2,3 2,3 3,2 3,2 2))'; 67 | $polygon = Polygon::fromWKT($wkt); 68 | $this->assertInstanceOf(Polygon::class, $polygon); 69 | 70 | $this->assertEquals(2, $polygon->count()); 71 | $this->assertEquals($wkt, $polygon->toWKT()); 72 | } 73 | 74 | public function testFromWKT3d() 75 | { 76 | $wkt = 'POLYGON Z((1 1 1,5 1 1,5 5 1,1 5 1,1 1 1),(2 2 2,3 2 2,3 3 2,2 3 2,2 2 2))'; 77 | $polygon = Polygon::fromWKT($wkt); 78 | $this->assertInstanceOf(Polygon::class, $polygon); 79 | 80 | $this->assertEquals(2, $polygon->count()); 81 | $this->assertEquals($wkt, $polygon->toWKT()); 82 | } 83 | 84 | public function testToWKT() 85 | { 86 | $this->assertEquals('POLYGON((1 1,2 1,2 2,1 2,1 1))', $this->polygon->toWKT()); 87 | } 88 | 89 | public function testToWKT3d() 90 | { 91 | $this->assertEquals('POLYGON Z((1 1 1,2 1 2,2 2 2,1 2 2,1 1 1))', $this->polygon3d->toWKT()); 92 | } 93 | 94 | public function testJsonSerialize() 95 | { 96 | $this->assertInstanceOf(\GeoJson\Geometry\Polygon::class, $this->polygon->jsonSerialize()); 97 | $this->assertSame( 98 | '{"type":"Polygon","coordinates":[[[1,1],[2,1],[2,2],[1,2],[1,1]]]}', 99 | json_encode($this->polygon) 100 | ); 101 | 102 | } 103 | 104 | public function testJsonSerialize3d() 105 | { 106 | $this->assertInstanceOf(\GeoJson\Geometry\Polygon::class, $this->polygon3d->jsonSerialize()); 107 | $this->assertSame( 108 | '{"type":"Polygon","coordinates":[[[1,1,1],[2,1,2],[2,2,2],[1,2,2],[1,1,1]]]}', 109 | json_encode($this->polygon3d) 110 | ); 111 | 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /tests/Geometries/UnderLocaleTest.php: -------------------------------------------------------------------------------- 1 | markTestSkipped('The locale is not available for testing float output formatting'); 31 | } 32 | } 33 | 34 | public function testPointToWKT() 35 | { 36 | $point = new Point(1.5, 2.5); 37 | $this->assertEquals('POINT(2.5 1.5)', $point->toWKT()); 38 | } 39 | 40 | public function testMultiPointToWKT() 41 | { 42 | $multipoint = new MultiPoint([new Point(1.5, 1.5), new Point(1.5, 2.5), new Point(2.5, 2.5)]); 43 | 44 | $this->assertEquals('MULTIPOINT((1.5 1.5),(2.5 1.5),(2.5 2.5))', $multipoint->toWKT()); 45 | } 46 | 47 | public function testLineStringToWKT() 48 | { 49 | $linestring = new LineString([new Point(1.5, 1.5), new Point(2.5, 2.5), new Point(3.5, 3.5)]); 50 | 51 | $this->assertEquals('LINESTRING(1.5 1.5,2.5 2.5,3.5 3.5)', $linestring->toWKT()); 52 | } 53 | 54 | public function testMultiLineStringToWKT() 55 | { 56 | $collection = new LineString( 57 | [ 58 | new Point(1.5, 1.5), 59 | new Point(1.5, 2.5), 60 | new Point(2.5, 2.5), 61 | new Point(2.5, 1.5), 62 | new Point(1.5, 1.5) 63 | ] 64 | ); 65 | 66 | $multilinestring = new MultiLineString([$collection]); 67 | 68 | $this->assertSame('MULTILINESTRING((1.5 1.5,2.5 1.5,2.5 2.5,1.5 2.5,1.5 1.5))', $multilinestring->toWKT()); 69 | } 70 | 71 | public function testPolygonToWKT() 72 | { 73 | $collection = new LineString( 74 | [ 75 | new Point(1.5, 1.5), 76 | new Point(1.5, 2.5), 77 | new Point(2.5, 2.5), 78 | new Point(2.5, 1.5), 79 | new Point(1.5, 1.5) 80 | ] 81 | ); 82 | 83 | $polygon = new Polygon([$collection]); 84 | 85 | $this->assertEquals('POLYGON((1.5 1.5,2.5 1.5,2.5 2.5,1.5 2.5,1.5 1.5))', $polygon->toWKT()); 86 | } 87 | 88 | public function testMultiPolygonToWKT() 89 | { 90 | $collection1 = new LineString( 91 | [ 92 | new Point(1.5, 1.5), 93 | new Point(1.5, 2.5), 94 | new Point(2.5, 2.5), 95 | new Point(2.5, 1.5), 96 | new Point(1.5, 1.5) 97 | ] 98 | ); 99 | 100 | $collection2 = new LineString( 101 | [ 102 | new Point(10.5, 10.5), 103 | new Point(10.5, 20.5), 104 | new Point(20.5, 20.5), 105 | new Point(20.5, 10.5), 106 | new Point(10.5, 10.5) 107 | ] 108 | ); 109 | 110 | $polygon1 = new Polygon([$collection1, $collection2]); 111 | 112 | $collection3 = new LineString( 113 | [ 114 | new Point(100.5, 100.5), 115 | new Point(100.5, 200.5), 116 | new Point(200.5, 200.5), 117 | new Point(200.5, 100.5), 118 | new Point(100.5, 100.5) 119 | ] 120 | ); 121 | 122 | $polygon2 = new Polygon([$collection3]); 123 | 124 | $multiPolygon = new MultiPolygon([$polygon1, $polygon2]); 125 | 126 | $this->assertEquals( 127 | 'MULTIPOLYGON(((1.5 1.5,2.5 1.5,2.5 2.5,1.5 2.5,1.5 1.5),(10.5 10.5,20.5 10.5,20.5 20.5,10.5 20.5,10.5 10.5)),((100.5 100.5,200.5 100.5,200.5 200.5,100.5 200.5,100.5 100.5)))', 128 | $multiPolygon->toWKT() 129 | ); 130 | } 131 | 132 | public function testGeometryCollectionToWKT() 133 | { 134 | $collection = new LineString( 135 | [ 136 | new Point(1.5, 1.5), 137 | new Point(1.5, 2.5), 138 | new Point(2.5, 2.5), 139 | new Point(2.5, 1.5), 140 | new Point(1.5, 1.5) 141 | ] 142 | ); 143 | 144 | $point = new Point(100.5, 200.5); 145 | 146 | $geo_collection = new GeometryCollection([$collection, $point]); 147 | 148 | $this->assertEquals( 149 | 'GEOMETRYCOLLECTION(LINESTRING(1.5 1.5,2.5 1.5,2.5 2.5,1.5 2.5,1.5 1.5),POINT(200.5 100.5))', 150 | $geo_collection->toWKT() 151 | ); 152 | } 153 | 154 | } 155 | -------------------------------------------------------------------------------- /tests/PostgisConnectionTest.php: -------------------------------------------------------------------------------- 1 | 'pgsql', 'prefix' => 'prefix', 'database' => 'database', 'name' => 'foo']; 16 | $this->postgisConnection = new PostgisConnection(new PDOStub(), 'database', 'prefix', $pgConfig); 17 | } 18 | 19 | public function testGetSchemaBuilder() 20 | { 21 | $builder = $this->postgisConnection->getSchemaBuilder(); 22 | 23 | $this->assertInstanceOf(Builder::class, $builder); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/Schema/BlueprintTest.php: -------------------------------------------------------------------------------- 1 | blueprint = Mockery::mock(Blueprint::class) 18 | ->makePartial()->shouldAllowMockingProtectedMethods(); 19 | } 20 | 21 | public function testMultiPoint() 22 | { 23 | $this->blueprint 24 | ->shouldReceive('addCommand') 25 | ->with('multipoint', ['col', null, 2, true]); 26 | 27 | $this->blueprint->multipoint('col'); 28 | } 29 | 30 | public function testPolygon() 31 | { 32 | $this->blueprint 33 | ->shouldReceive('addCommand') 34 | ->with('polygon', ['col', null, 2, true]); 35 | 36 | $this->blueprint->polygon('col'); 37 | } 38 | 39 | public function testMulltiPolygon() 40 | { 41 | $this->blueprint 42 | ->shouldReceive('addCommand') 43 | ->with('multipolygon', ['col', null, 2, true]); 44 | 45 | $this->blueprint->multipolygon('col'); 46 | } 47 | 48 | public function testLineString() 49 | { 50 | $this->blueprint 51 | ->shouldReceive('addCommand') 52 | ->with('linestring', ['col', null, 2, true]); 53 | 54 | $this->blueprint->linestring('col'); 55 | } 56 | 57 | public function testMultiLineString() 58 | { 59 | $this->blueprint 60 | ->shouldReceive('addCommand') 61 | ->with('multilinestring', ['col', null, 2, true]); 62 | 63 | $this->blueprint->multilinestring('col'); 64 | } 65 | 66 | public function testGeography() 67 | { 68 | $this->blueprint 69 | ->shouldReceive('addCommand') 70 | ->with('geography', ['col', null, 2, true]); 71 | 72 | $this->blueprint->geography('col'); 73 | } 74 | 75 | public function testGeometryCollection() 76 | { 77 | $this->blueprint 78 | ->shouldReceive('addCommand') 79 | ->with('geometrycollection', ['col', null, 2, true]); 80 | 81 | $this->blueprint->geometrycollection('col'); 82 | } 83 | 84 | public function testEnablePostgis() 85 | { 86 | $this->blueprint 87 | ->shouldReceive('addCommand') 88 | ->with('enablePostgis', []); 89 | 90 | $this->blueprint->enablePostgis(); 91 | } 92 | 93 | public function testEnablePostgisIfNotExists() 94 | { 95 | $this->blueprint 96 | ->shouldReceive('addCommand') 97 | ->with('enablePostgis', []); 98 | 99 | $this->blueprint->enablePostgisIfNotExists(); 100 | } 101 | 102 | public function testDisablePostgis() 103 | { 104 | $this->blueprint 105 | ->shouldReceive('addCommand') 106 | ->with('disablePostgis', []); 107 | 108 | $this->blueprint->disablePostgis(); 109 | } 110 | 111 | public function testDisablePostgisIfExists() 112 | { 113 | $this->blueprint 114 | ->shouldReceive('addCommand') 115 | ->with('disablePostgis', []); 116 | 117 | $this->blueprint->disablePostgisIfExists(); 118 | } 119 | 120 | public function testGinIndex() 121 | { 122 | $this->blueprint 123 | ->shouldReceive('indexCommand') 124 | ->with('gin', 'col', 'myName'); 125 | 126 | $this->blueprint->gin('col', 'myName'); 127 | } 128 | 129 | public function testGistIndex() 130 | { 131 | $this->blueprint 132 | ->shouldReceive('indexCommand') 133 | ->with('gist', 'col', 'myName'); 134 | 135 | $this->blueprint->gist('col', 'myName'); 136 | } 137 | 138 | public function testCharacter() 139 | { 140 | $this->blueprint 141 | ->shouldReceive('addColumn') 142 | ->with('character', 'col', 14); 143 | 144 | $this->blueprint->character('col', 14); 145 | } 146 | 147 | public function testHstore() 148 | { 149 | $this->blueprint 150 | ->shouldReceive('addColumn') 151 | ->with('hstore', 'col'); 152 | 153 | $this->blueprint->hstore('col'); 154 | } 155 | 156 | public function testUuid() 157 | { 158 | $this->blueprint 159 | ->shouldReceive('addColumn') 160 | ->with('uuid', 'col'); 161 | 162 | $this->blueprint->uuid('col'); 163 | } 164 | 165 | public function testJsonb() 166 | { 167 | $this->blueprint 168 | ->shouldReceive('addColumn') 169 | ->with('jsonb', 'col'); 170 | 171 | $this->blueprint->jsonb('col'); 172 | } 173 | 174 | public function testInt4range() 175 | { 176 | $this->blueprint 177 | ->shouldReceive('addColumn') 178 | ->with('int4range', 'col'); 179 | 180 | $this->blueprint->int4range('col'); 181 | } 182 | 183 | public function testInt8range() 184 | { 185 | $this->blueprint 186 | ->shouldReceive('addColumn') 187 | ->with('int8range', 'col'); 188 | 189 | $this->blueprint->int8range('col'); 190 | } 191 | 192 | public function testNumrange() 193 | { 194 | $this->blueprint 195 | ->shouldReceive('addColumn') 196 | ->with('numrange', 'col'); 197 | 198 | $this->blueprint->numrange('col'); 199 | } 200 | 201 | public function testTsrange() 202 | { 203 | $this->blueprint 204 | ->shouldReceive('addColumn') 205 | ->with('tsrange', 'col'); 206 | 207 | $this->blueprint->tsrange('col'); 208 | } 209 | 210 | public function testTstzrange() 211 | { 212 | $this->blueprint 213 | ->shouldReceive('addColumn') 214 | ->with('tstzrange', 'col'); 215 | 216 | $this->blueprint->tstzrange('col'); 217 | } 218 | } 219 | -------------------------------------------------------------------------------- /tests/Schema/BuilderTest.php: -------------------------------------------------------------------------------- 1 | shouldReceive('getSchemaGrammar')->once()->andReturn(null); 17 | 18 | $mock = Mockery::mock(Builder::class, [$connection]); 19 | $mock->makePartial()->shouldAllowMockingProtectedMethods(); 20 | $blueprint = $mock->createBlueprint('test', function () { 21 | }); 22 | 23 | $this->assertInstanceOf(Blueprint::class, $blueprint); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/Schema/Grammars/PostgisGrammarTest.php: -------------------------------------------------------------------------------- 1 | point('foo'); 19 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 20 | 21 | $this->assertCount(1, $statements); 22 | $this->assertStringContainsString('GEOGRAPHY(POINT, 4326)', $statements[0]); 23 | } 24 | 25 | public function testAddingPointGeom() 26 | { 27 | $blueprint = new Blueprint('test'); 28 | $blueprint->point('foo', 'GEOMETRY', 27700); 29 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 30 | $this->assertCount(1, $statements); 31 | $this->assertStringContainsString('GEOMETRY(POINT, 27700)', $statements[0]); 32 | } 33 | 34 | public function testAddingPointWrongSrid() 35 | { 36 | $this->expectException(UnsupportedGeomtypeException::class); 37 | $blueprint = new Blueprint('test'); 38 | $blueprint->point('foo', 'GEOGRAPHY', 27700); 39 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 40 | $this->assertCount(1, $statements);; 41 | } 42 | 43 | public function testAddingPointUnsupported() 44 | { 45 | $this->expectException(UnsupportedGeomtypeException::class); 46 | $blueprint = new Blueprint('test'); 47 | $blueprint->point('foo', 'UNSUPPORTED_ENTRY', 27700); 48 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 49 | $this->assertCount(1, $statements);; 50 | } 51 | 52 | public function testAddingLinestring() 53 | { 54 | $blueprint = new Blueprint('test'); 55 | $blueprint->linestring('foo'); 56 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 57 | 58 | $this->assertCount(1, $statements);; 59 | $this->assertStringContainsString('GEOGRAPHY(LINESTRING, 4326)', $statements[0]); 60 | } 61 | 62 | public function testAddingLinestringGeom() 63 | { 64 | $blueprint = new Blueprint('test'); 65 | $blueprint->linestring('foo', 'GEOMETRY', 27700); 66 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 67 | $this->assertCount(1, $statements);; 68 | $this->assertStringContainsString('GEOMETRY(LINESTRING, 27700)', $statements[0]); 69 | } 70 | 71 | public function testAddingLinestringWrongSrid() 72 | { 73 | $this->expectException(UnsupportedGeomtypeException::class); 74 | $blueprint = new Blueprint('test'); 75 | $blueprint->linestring('foo', 'GEOGRAPHY', 27700); 76 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 77 | $this->assertCount(1, $statements);; 78 | } 79 | 80 | public function testAddingLinestringUnsupported() 81 | { 82 | $this->expectException(UnsupportedGeomtypeException::class); 83 | $blueprint = new Blueprint('test'); 84 | $blueprint->linestring('foo', 'UNSUPPORTED_ENTRY', 27700); 85 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 86 | $this->assertCount(1, $statements); 87 | } 88 | 89 | public function testAddingPolygon() 90 | { 91 | $blueprint = new Blueprint('test'); 92 | $blueprint->polygon('foo'); 93 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 94 | 95 | $this->assertCount(1, $statements); 96 | $this->assertStringContainsString('GEOGRAPHY(POLYGON, 4326)', $statements[0]); 97 | } 98 | 99 | public function testAddingPolygonGeom() 100 | { 101 | $blueprint = new Blueprint('test'); 102 | $blueprint->polygon('foo', 'GEOMETRY', 27700); 103 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 104 | $this->assertCount(1, $statements); 105 | $this->assertStringContainsString('GEOMETRY(POLYGON, 27700)', $statements[0]); 106 | } 107 | 108 | public function testAddingPolygonWrongSrid() 109 | { 110 | $this->expectException(UnsupportedGeomtypeException::class); 111 | $blueprint = new Blueprint('test'); 112 | $blueprint->polygon('foo', 'GEOGRAPHY', 27700); 113 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 114 | $this->assertCount(1, $statements); 115 | } 116 | 117 | public function testAddingPolygonUnsupported() 118 | { 119 | $this->expectException(UnsupportedGeomtypeException::class); 120 | $blueprint = new Blueprint('test'); 121 | $blueprint->polygon('foo', 'UNSUPPORTED_ENTRY', 27700); 122 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 123 | $this->assertCount(1, $statements); 124 | } 125 | 126 | public function testAddingMultipoint() 127 | { 128 | $blueprint = new Blueprint('test'); 129 | $blueprint->multipoint('foo'); 130 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 131 | 132 | $this->assertCount(1, $statements); 133 | $this->assertStringContainsString('GEOGRAPHY(MULTIPOINT, 4326)', $statements[0]); 134 | } 135 | 136 | public function testAddingMultipointGeom() 137 | { 138 | $blueprint = new Blueprint('test'); 139 | $blueprint->multipoint('foo', 'GEOMETRY', 27700); 140 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 141 | $this->assertCount(1, $statements); 142 | $this->assertStringContainsString('GEOMETRY(MULTIPOINT, 27700)', $statements[0]); 143 | } 144 | 145 | public function testAddingMultiPointWrongSrid() 146 | { 147 | $this->expectException(UnsupportedGeomtypeException::class); 148 | $blueprint = new Blueprint('test'); 149 | $blueprint->multipoint('foo', 'GEOGRAPHY', 27700); 150 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 151 | $this->assertCount(1, $statements); 152 | } 153 | 154 | public function testAddingMultiPointUnsupported() 155 | { 156 | $this->expectException(UnsupportedGeomtypeException::class); 157 | $blueprint = new Blueprint('test'); 158 | $blueprint->multipoint('foo', 'UNSUPPORTED_ENTRY', 27700); 159 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 160 | $this->assertCount(1, $statements);; 161 | } 162 | 163 | public function testAddingMultiLinestring() 164 | { 165 | $blueprint = new Blueprint('test'); 166 | $blueprint->multilinestring('foo'); 167 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 168 | 169 | $this->assertCount(1, $statements);; 170 | $this->assertStringContainsString('GEOGRAPHY(MULTILINESTRING, 4326)', $statements[0]); 171 | } 172 | 173 | public function testAddingMultiLinestringGeom() 174 | { 175 | $blueprint = new Blueprint('test'); 176 | $blueprint->multilinestring('foo', 'GEOMETRY', 27700); 177 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 178 | $this->assertCount(1, $statements);; 179 | $this->assertStringContainsString('GEOMETRY(MULTILINESTRING, 27700)', $statements[0]); 180 | } 181 | 182 | public function testAddingMultiLinestringWrongSrid() 183 | { 184 | $this->expectException(UnsupportedGeomtypeException::class); 185 | $blueprint = new Blueprint('test'); 186 | $blueprint->multilinestring('foo', 'GEOGRAPHY', 27700); 187 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 188 | $this->assertCount(1, $statements);; 189 | } 190 | 191 | public function testAddingMultiLinestringUnsupported() 192 | { 193 | $this->expectException(UnsupportedGeomtypeException::class); 194 | $blueprint = new Blueprint('test'); 195 | $blueprint->multilinestring('foo', 'UNSUPPORTED_ENTRY', 27700); 196 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 197 | $this->assertCount(1, $statements);; 198 | } 199 | 200 | public function testAddingMultiPolygon() 201 | { 202 | $blueprint = new Blueprint('test'); 203 | $blueprint->multipolygon('foo'); 204 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 205 | 206 | $this->assertCount(1, $statements);; 207 | $this->assertStringContainsString('GEOGRAPHY(MULTIPOLYGON, 4326)', $statements[0]); 208 | } 209 | 210 | public function testAddingMultiPolygonGeom() 211 | { 212 | $blueprint = new Blueprint('test'); 213 | $blueprint->multipolygon('foo', 'GEOMETRY', 27700); 214 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 215 | $this->assertCount(1, $statements);; 216 | $this->assertStringContainsString('GEOMETRY(MULTIPOLYGON, 27700)', $statements[0]); 217 | } 218 | 219 | public function testAddingMultiPolygonWrongSrid() 220 | { 221 | $this->expectException(UnsupportedGeomtypeException::class); 222 | $blueprint = new Blueprint('test'); 223 | $blueprint->multipolygon('foo', 'GEOGRAPHY', 27700); 224 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 225 | $this->assertCount(1, $statements);; 226 | } 227 | 228 | public function testAddingMultiPolygonUnsupported() 229 | { 230 | $this->expectException(UnsupportedGeomtypeException::class); 231 | $blueprint = new Blueprint('test'); 232 | $blueprint->multipolygon('foo', 'UNSUPPORTED_ENTRY', 27700); 233 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 234 | $this->assertCount(1, $statements);; 235 | } 236 | 237 | public function testAddingGeography() 238 | { 239 | $blueprint = new Blueprint('test'); 240 | $blueprint->geography('foo'); 241 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 242 | 243 | $this->assertCount(1, $statements);; 244 | $this->assertStringContainsString('GEOGRAPHY', $statements[0]); 245 | } 246 | 247 | public function testAddingGeometry() 248 | { 249 | $blueprint = new Blueprint('test'); 250 | $blueprint->geometry('foo'); 251 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 252 | $this->assertCount(1, $statements);; 253 | $this->assertStringContainsString('GEOMETRY', $statements[0]); 254 | } 255 | 256 | public function testAddingGeometryCollection() 257 | { 258 | $blueprint = new Blueprint('test'); 259 | $blueprint->geometrycollection('foo'); 260 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 261 | 262 | $this->assertCount(1, $statements);; 263 | $this->assertStringContainsString('AddGeometryColumn', $statements[0]); 264 | $this->assertStringContainsString('GEOMETRYCOLLECTION', $statements[0]); 265 | } 266 | 267 | public function testEnablePostgis() 268 | { 269 | $blueprint = new Blueprint('test'); 270 | $blueprint->enablePostgis(); 271 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 272 | 273 | $this->assertCount(1, $statements);; 274 | $this->assertStringContainsString('CREATE EXTENSION postgis', $statements[0]); 275 | } 276 | 277 | public function testEnablePostgisIfNotExists() 278 | { 279 | $blueprint = new Blueprint('test'); 280 | $blueprint->enablePostgisIfNotExists(); 281 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 282 | 283 | $this->assertCount(1, $statements);; 284 | $this->assertStringContainsString('CREATE EXTENSION IF NOT EXISTS postgis', $statements[0]); 285 | } 286 | 287 | public function testDisablePostgis() 288 | { 289 | $blueprint = new Blueprint('test'); 290 | $blueprint->disablePostgis(); 291 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 292 | 293 | $this->assertCount(1, $statements);; 294 | $this->assertStringContainsString('DROP EXTENSION postgis', $statements[0]); 295 | } 296 | 297 | public function testDisablePostgisIfExists() 298 | { 299 | $blueprint = new Blueprint('test'); 300 | $blueprint->disablePostgisIfExists(); 301 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 302 | 303 | $this->assertCount(1, $statements);; 304 | $this->assertStringContainsString('DROP EXTENSION IF EXISTS postgis', $statements[0]); 305 | } 306 | 307 | /** 308 | * @return Connection 309 | */ 310 | protected function getConnection() 311 | { 312 | return Mockery::mock(PostgisConnection::class); 313 | } 314 | 315 | protected function getGrammar() 316 | { 317 | return new PostgisGrammar(); 318 | } 319 | 320 | public function testAddingGinIndex() 321 | { 322 | $blueprint = new Blueprint('test'); 323 | $blueprint->gin('foo'); 324 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 325 | 326 | $this->assertEquals(1, count($statements)); 327 | 328 | $this->assertStringContainsString('CREATE INDEX', $statements[0]); 329 | $this->assertStringContainsString('GIN("foo")', $statements[0]); 330 | } 331 | 332 | public function testAddingGistIndex() 333 | { 334 | $blueprint = new Blueprint('test'); 335 | $blueprint->gist('foo'); 336 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 337 | 338 | $this->assertEquals(1, count($statements)); 339 | $this->assertStringContainsString('CREATE INDEX', $statements[0]); 340 | $this->assertStringContainsString('GIST("foo")', $statements[0]); 341 | } 342 | 343 | public function testAddingCharacter() 344 | { 345 | $blueprint = new Blueprint('test'); 346 | $blueprint->character('foo', 14); 347 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 348 | 349 | $this->assertEquals(1, count($statements)); 350 | $this->assertStringContainsString('alter table', $statements[0]); 351 | $this->assertStringContainsString('add column "foo" character(14)', $statements[0]); 352 | } 353 | 354 | public function testAddingHstore() 355 | { 356 | $blueprint = new Blueprint('test'); 357 | $blueprint->hstore('foo'); 358 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 359 | 360 | $this->assertEquals(1, count($statements)); 361 | $this->assertStringContainsString('alter table', $statements[0]); 362 | $this->assertStringContainsString('add column "foo" hstore', $statements[0]); 363 | } 364 | 365 | public function testAddingUuid() 366 | { 367 | $blueprint = new Blueprint('test'); 368 | $blueprint->uuid('foo'); 369 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 370 | 371 | $this->assertEquals(1, count($statements)); 372 | $this->assertStringContainsString('alter table', $statements[0]); 373 | $this->assertStringContainsString('add column "foo" uuid', $statements[0]); 374 | } 375 | 376 | public function testAddingJsonb() 377 | { 378 | $blueprint = new Blueprint('test'); 379 | $blueprint->jsonb('foo'); 380 | $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); 381 | 382 | $this->assertEquals(1, count($statements)); 383 | $this->assertStringContainsString('alter table', $statements[0]); 384 | $this->assertStringContainsString('add column "foo" jsonb', $statements[0]); 385 | } 386 | 387 | public function testAddingInt4range() 388 | { 389 | $blueprint = new Blueprint('test'); 390 | $blueprint->int4range('foo'); 391 | $statements = $blueprint->toSql( 392 | $this->getConnection(), 393 | $this->getGrammar() 394 | ); 395 | 396 | $this->assertEquals(1, count($statements)); 397 | $this->assertStringContainsString('alter table', $statements[0]); 398 | $this->assertStringContainsString('add column "foo" int4range', $statements[0]); 399 | } 400 | 401 | public function testAddingInt8range() 402 | { 403 | $blueprint = new Blueprint('test'); 404 | $blueprint->int8range('foo'); 405 | $statements = $blueprint->toSql( 406 | $this->getConnection(), 407 | $this->getGrammar() 408 | ); 409 | 410 | $this->assertEquals(1, count($statements)); 411 | $this->assertStringContainsString('alter table', $statements[0]); 412 | $this->assertStringContainsString('add column "foo" int8range', $statements[0]); 413 | } 414 | 415 | public function testAddingNumrange() 416 | { 417 | $blueprint = new Blueprint('test'); 418 | $blueprint->numrange('foo'); 419 | $statements = $blueprint->toSql( 420 | $this->getConnection(), 421 | $this->getGrammar() 422 | ); 423 | 424 | $this->assertEquals(1, count($statements)); 425 | $this->assertStringContainsString('alter table', $statements[0]); 426 | $this->assertStringContainsString('add column "foo" numrange', $statements[0]); 427 | } 428 | 429 | public function testAddingTsrange() 430 | { 431 | $blueprint = new Blueprint('test'); 432 | $blueprint->tsrange('foo'); 433 | $statements = $blueprint->toSql( 434 | $this->getConnection(), 435 | $this->getGrammar() 436 | ); 437 | 438 | $this->assertEquals(1, count($statements)); 439 | $this->assertStringContainsString('alter table', $statements[0]); 440 | $this->assertStringContainsString('add column "foo" tsrange', $statements[0]); 441 | } 442 | 443 | public function testAddingTstzrange() 444 | { 445 | $blueprint = new Blueprint('test'); 446 | $blueprint->tstzrange('foo'); 447 | $statements = $blueprint->toSql( 448 | $this->getConnection(), 449 | $this->getGrammar() 450 | ); 451 | 452 | $this->assertEquals(1, count($statements)); 453 | $this->assertStringContainsString('alter table', $statements[0]); 454 | $this->assertStringContainsString('add column "foo" tstzrange', $statements[0]); 455 | } 456 | 457 | public function testAddingDatarange() 458 | { 459 | $blueprint = new Blueprint('test'); 460 | $blueprint->daterange('foo'); 461 | $statements = $blueprint->toSql( 462 | $this->getConnection(), 463 | $this->getGrammar() 464 | ); 465 | 466 | $this->assertEquals(1, count($statements)); 467 | $this->assertStringContainsString('alter table', $statements[0]); 468 | $this->assertStringContainsString('add column "foo" daterange', $statements[0]); 469 | } 470 | 471 | public function testAddingTsvector() 472 | { 473 | $blueprint = new Blueprint('test'); 474 | $blueprint->tsvector('foo'); 475 | $statements = $blueprint->toSql( 476 | $this->getConnection(), 477 | $this->getGrammar() 478 | ); 479 | 480 | $this->assertEquals(1, count($statements)); 481 | $this->assertStringContainsString('alter table', $statements[0]); 482 | $this->assertStringContainsString('add column "foo" tsvector', $statements[0]); 483 | } 484 | } 485 | -------------------------------------------------------------------------------- /tests/Stubs/PDOStub.php: -------------------------------------------------------------------------------- 1 |