diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..dd9a2b51 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false + +[*.{yml,yaml}] +indent_size = 2 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..9e9519b3 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,19 @@ +# Path-based git attributes +# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html + +# Ignore all test and documentation with "export-ignore". +/.github export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore +/phpunit.xml.dist export-ignore +/art export-ignore +/docs export-ignore +/tests export-ignore +/.editorconfig export-ignore +/.php_cs.dist.php export-ignore +/psalm.xml export-ignore +/psalm.xml.dist export-ignore +/testbench.yaml export-ignore +/UPGRADING.md export-ignore +/phpstan.neon.dist export-ignore +/phpstan-baseline.neon export-ignore diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml new file mode 100644 index 00000000..fccf1bec --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -0,0 +1,66 @@ +name: Bug Report +description: Report an Issue or Bug with the Package +title: "[Bug]: " +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + We're sorry to hear you have a problem. Can you help us solve it by providing the following details. + - type: textarea + id: what-happened + attributes: + label: What happened? + description: What did you expect to happen? + placeholder: I cannot currently do X thing because when I do, it breaks X thing. + validations: + required: true + - type: textarea + id: how-to-reproduce + attributes: + label: How to reproduce the bug + description: How did this occur, please add any config values used and provide a set of reliable steps if possible. + placeholder: When I do X I see Y. + validations: + required: true + - type: input + id: package-version + attributes: + label: Package Version + description: What version of our Package are you running? Please be as specific as possible + placeholder: 2.0.0 + validations: + required: true + - type: input + id: php-version + attributes: + label: PHP Version + description: What version of PHP are you running? Please be as specific as possible + placeholder: 8.2.0 + validations: + required: true + - type: input + id: laravel-version + attributes: + label: Laravel Version + description: What version of Laravel are you running? Please be as specific as possible + placeholder: 10.0.0 + validations: + required: true + - type: dropdown + id: operating-systems + attributes: + label: Which operating systems does with happen with? + description: You may select more than one. + multiple: true + options: + - macOS + - Windows + - Linux + - type: textarea + id: notes + attributes: + label: Notes + description: Use this field to provide any other notes that you feel might be relevant to the issue. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..718844b8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +blank_issues_enabled: false +contact_links: + - name: Ask a question + url: https://github.com/limenet/laravel-mysql-spatial/discussions/new?category=q-a + about: Ask the community for help + - name: Request a feature + url: https://github.com/limenet/laravel-mysql-spatial/discussions/new?category=ideas + about: Share ideas for new features + - name: Report a security issue + url: https://github.com/limenet/laravel-mysql-spatial/security/policy + about: Learn how to notify us for sensitive bugs diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..30c8a493 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +# Please see the documentation for all configuration options: +# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + labels: + - "dependencies" \ No newline at end of file diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml new file mode 100644 index 00000000..32f77541 --- /dev/null +++ b/.github/workflows/dependabot-auto-merge.yml @@ -0,0 +1,32 @@ +name: dependabot-auto-merge +on: pull_request_target + +permissions: + pull-requests: write + contents: write + +jobs: + dependabot: + runs-on: ubuntu-latest + if: ${{ github.actor == 'dependabot[bot]' }} + steps: + + - name: Dependabot metadata + id: metadata + uses: dependabot/fetch-metadata@v1.3.6 + with: + github-token: "${{ secrets.GITHUB_TOKEN }}" + + - name: Auto-merge Dependabot PRs for semver-minor updates + if: ${{steps.metadata.outputs.update-type == 'version-update:semver-minor'}} + run: gh pr merge --auto --merge "$PR_URL" + env: + PR_URL: ${{github.event.pull_request.html_url}} + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} + + - name: Auto-merge Dependabot PRs for semver-patch updates + if: ${{steps.metadata.outputs.update-type == 'version-update:semver-patch'}} + run: gh pr merge --auto --merge "$PR_URL" + env: + PR_URL: ${{github.event.pull_request.html_url}} + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/.github/workflows/fix-php-code-style-issues.yml b/.github/workflows/fix-php-code-style-issues.yml new file mode 100644 index 00000000..d9314f2b --- /dev/null +++ b/.github/workflows/fix-php-code-style-issues.yml @@ -0,0 +1,26 @@ +name: Fix PHP code style issues + +on: + push: + paths: + - "**.php" + pull_request: + branches: [master] + +jobs: + php-code-styling: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: ${{ github.head_ref }} + + - name: Fix PHP code style issues + uses: aglipanci/laravel-pint-action@2.1.0 + + - name: Commit changes + uses: stefanzweifel/git-auto-commit-action@v4 + with: + commit_message: Fix styling diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml new file mode 100644 index 00000000..7d9a5987 --- /dev/null +++ b/.github/workflows/phpstan.yml @@ -0,0 +1,41 @@ +name: PHPStan + +on: + push: + paths: + - "**.php" + - "phpstan.neon.dist" + pull_request: + branches: [master] + +jobs: + phpstan: + name: phpstan + runs-on: ubuntu-latest + + env: + DB_DATABASE: "laravel" + DB_HOST: "127.0.0.1" + DB_PORT: "3306" + DB_USERNAME: "root" + DB_PASSWORD: "root" + + steps: + - name: Set up MySQL + run: | + sudo /etc/init.d/mysql start + mysql -e 'CREATE DATABASE laravel' -uroot -proot + + - uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: "8.1" + coverage: none + + - name: Install composer dependencies + uses: ramsey/composer-install@v2 + + - name: Run PHPStan + run: ./vendor/bin/phpstan --error-format=github diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml new file mode 100644 index 00000000..346f83e2 --- /dev/null +++ b/.github/workflows/run-tests.yml @@ -0,0 +1,56 @@ +name: PHP Tests + +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + test: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: true + matrix: + os: [ubuntu-latest] + php: [8.2, 8.1] + laravel: [10.*] + stability: [prefer-lowest, prefer-stable] + include: + - laravel: 10.* + testbench: 8.* + carbon: ^2.63 + + name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }} + + steps: + - name: Set up MySQL + run: | + sudo /etc/init.d/mysql start + mysql -e 'CREATE DATABASE laravel' -uroot -proot + + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo, mysql + coverage: xdebug + + - name: Setup problem matchers + run: | + echo "::add-matcher::${{ runner.tool_cache }}/php.json" + echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + + - name: Install dependencies + run: | + composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" "nesbot/carbon:${{ matrix.carbon }}" --no-interaction --no-update + composer update --${{ matrix.stability }} --prefer-dist --no-interaction + + - name: List Installed Dependencies + run: composer show -D + + - name: Execute tests + run: vendor/bin/phpunit diff --git a/.gitignore b/.gitignore index 52370244..0bbeb929 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,13 @@ -.idea/ -vendor/ +.idea +.phpunit.result.cache +build composer.lock +coverage +docs +phpunit.xml +phpstan.neon +testbench.yaml +vendor _db/ -build/ \ No newline at end of file +node_modules +.phpunit.cache diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index f6a2a31f..00000000 --- a/.travis.yml +++ /dev/null @@ -1,33 +0,0 @@ -language: php - -php: - - '7.3' - - '7.4' - -env: - - MYSQL_VERSION=8.0 - -dist: trusty - -sudo: required - -services: - - docker - -before_install: - - echo "memory_limit=3G" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini - - sudo /etc/init.d/mysql stop - - make start_db V=$MYSQL_VERSION - -install: composer install - -before_script: - - mkdir -p build/logs - - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter - - chmod +x ./cc-test-reporter - - ./cc-test-reporter before-build - -script: vendor/bin/phpunit --coverage-clover build/logs/clover.xml - -after_script: ./cc-test-reporter after-build --coverage-input-type clover --exit-code $TRAVIS_TEST_RESULT - diff --git a/LICENSE b/LICENSE index bcaa7e02..e204b8e7 100644 --- a/LICENSE +++ b/LICENSE @@ -2,6 +2,7 @@ MIT License Original work Copyright (c) 2015 Peter Haza Modified work Copyright (c) 2017 Joseph Estefane +Modified work Copyright (c) 2023 Linus Metzler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -19,4 +20,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file +SOFTWARE. diff --git a/Makefile b/Makefile deleted file mode 100644 index 62db4599..00000000 --- a/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -V=8.0 -DB_DIR=$(shell pwd)/_db-$(V) -mV=10.3 -mDB_DIR=$(shell pwd)/_db-$(mV) - -start_db: - @echo Starting MySQL $(V) - docker run --rm -d --name spatial-mysql \ - -p 3306:3306 \ - -v $(DB_DIR):/var/lib/mysql \ - -e MYSQL_DATABASE=spatial_test \ - -e MYSQL_ALLOW_EMPTY_PASSWORD=yes \ - mysql:$(V) --character-set-server=utf8 --collation-server=utf8_general_ci --default-authentication-plugin=mysql_native_password - -start_db_maria: - @echo Starting MariaDB $(mV) - docker run --rm -d --name spatial-mysql \ - -p 3306:3306 \ - -v $(DB_DIR):/var/lib/mysql \ - -e MYSQL_DATABASE=spatial_test \ - -e MYSQL_ALLOW_EMPTY_PASSWORD=yes \ - mariadb:$(mV) --character-set-server=utf8 --collation-server=utf8_general_ci --default-authentication-plugin=mysql_native_password - - -rm_db: - docker stop spatial-mysql || true - rm -Rf $(DB_DIR) - -refresh_db: rm_db start_db - -get_ip: - @docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' spatial-mysql \ No newline at end of file diff --git a/README.md b/README.md index 39d5303c..cc538de3 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,13 @@ # Laravel MySQL Spatial extension -[![Build Status](https://img.shields.io/travis/grimzy/laravel-mysql-spatial.svg?style=flat-square)](https://travis-ci.org/grimzy/laravel-mysql-spatial) -[![Code Climate](https://img.shields.io/codeclimate/maintainability/grimzy/laravel-mysql-spatial.svg?style=flat-square)](https://codeclimate.com/github/grimzy/laravel-mysql-spatial/maintainability) -[![Code Climate](https://img.shields.io/codeclimate/c/grimzy/laravel-mysql-spatial.svg?style=flat-square&colorB=4BCA2A)](https://codeclimate.com/github/grimzy/laravel-mysql-spatial/test_coverage) [![Packagist](https://img.shields.io/packagist/v/grimzy/laravel-mysql-spatial.svg?style=flat-square)](https://packagist.org/packages/grimzy/laravel-mysql-spatial) -[![Packagist](https://img.shields.io/packagist/dt/grimzy/laravel-mysql-spatial.svg?style=flat-square)](https://packagist.org/packages/grimzy/laravel-mysql-spatial) [![StyleCI](https://github.styleci.io/repos/83766141/shield?branch=master)](https://github.styleci.io/repos/83766141) -[![license](https://img.shields.io/github/license/mashape/apistatus.svg?style=flat-square)](LICENSE) +[![Packagist](https://img.shields.io/packagist/dt/limenet/laravel-mysql-spatial.svg?style=flat-square)](https://packagist.org/packages/limenet/laravel-mysql-spatial) +[![license](https://img.shields.io/github/license/limenet/laravel-mysql-spatial.svg?style=flat-square)](LICENSE) Laravel package to easily work with [MySQL Spatial Data Types](https://dev.mysql.com/doc/refman/8.0/en/spatial-type-overview.html) and [MySQL Spatial Functions](https://dev.mysql.com/doc/refman/8.0/en/spatial-function-reference.html). Please check the documentation for your MySQL version. MySQL's Extension for Spatial Data was added in MySQL 5.5 but many Spatial Functions were changed in 5.6 and 5.7. -**Versions** - -- `1.x.x`: MySQL 5.6 (also supports MySQL 5.5 but not all spatial analysis functions) -- `2.x.x`: MySQL 5.7 and 8.0 (Laravel version < 8.0) -- `3.x.x`: MySQL 8.0 with SRID support (Laravel version < 8.0) -- **`4.x.x`: MySQL 8.0 with SRID support (Laravel 8+) [Current branch]** -- `5.x.x`: MySQL 5.7 and 8.0 (Laravel 8+) +**This package is a fork of https://github.com/grimzy/laravel-mysql-spatial and virtually all code was written by the contributors to that repo. Thank you!** This package also works with MariaDB. Please refer to the [MySQL/MariaDB Spatial Support Matrix](https://mariadb.com/kb/en/library/mysqlmariadb-spatial-support-matrix/) for compatibility. @@ -25,34 +16,16 @@ This package also works with MariaDB. Please refer to the [MySQL/MariaDB Spatial Add the package using composer: ```sh -$ composer require grimzy/laravel-mysql-spatial:^4.0 - -# or for Laravel version < 8.0 -$ composer require grimzy/laravel-mysql-spatial:^3.0 -``` - -For MySQL 5.7: - -```shell -$ composer require grimzy/laravel-mysql-spatial:^2.0 +$ composer require limenet/laravel-mysql-spatial ``` -For MySQL 5.6 and 5.5: +If you need support for older versions, please consider using the package `grimzy/laravel-mysql-spatial` instead. -```shell -$ composer require grimzy/laravel-mysql-spatial:^1.0 -``` +### Migration from `grimzy/laravel-mysql-spatial` -For Laravel versions before 5.5 or if not using auto-discovery, register the service provider in `config/app.php`: - -```php -'providers' => [ - /* - * Package Service Providers... - */ - Grimzy\LaravelMysqlSpatial\SpatialServiceProvider::class, -], -``` +1. Run `composer remove grimzy/laravel-mysql-spatial` +2. Run `composer require limenet/laravel-mysql-spatial` +3. Replace `Grimzy\` with `Limenet\` throughout your codebase (most likely, this only affects `use` statements) ## Quickstart @@ -64,23 +37,14 @@ From the command line: php artisan make:migration create_places_table ``` -Then edit the migration you just created by adding at least one spatial data field. For Laravel versions prior to 5.5, you can use the Blueprint provided by this package (Grimzy\LaravelMysqlSpatial\Schema\Blueprint): +Then edit the migration you just created by adding at least one spatial data field. ```php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; -// For Laravel < 5.5 -// use Grimzy\LaravelMysqlSpatial\Schema\Blueprint; - class CreatePlacesTable extends Migration { - - /** - * Run the migrations. - * - * @return void - */ - public function up() + public function up(): void { Schema::create('places', function(Blueprint $table) { @@ -92,9 +56,9 @@ class CreatePlacesTable extends Migration { $table->polygon('area')->nullable(); $table->timestamps(); }); - + // Or create the spatial fields with an SRID (e.g. 4326 WGS84 spheroid) - + // Schema::create('places', function(Blueprint $table) // { // $table->increments('id'); @@ -107,12 +71,7 @@ class CreatePlacesTable extends Migration { // }); } - /** - * Reverse the migrations. - * - * @return void - */ - public function down() + public function down(): void { Schema::drop('places'); } @@ -139,11 +98,11 @@ Then edit the model you just created. It must use the `SpatialTrait` and define namespace App; use Illuminate\Database\Eloquent\Model; -use Grimzy\LaravelMysqlSpatial\Eloquent\SpatialTrait; +use Limenet\LaravelMysqlSpatial\Eloquent\SpatialTrait; /** - * @property \Grimzy\LaravelMysqlSpatial\Types\Point $location - * @property \Grimzy\LaravelMysqlSpatial\Types\Polygon $area + * @property \Limenet\LaravelMysqlSpatial\Types\Point $location + * @property \Limenet\LaravelMysqlSpatial\Types\Polygon $area */ class Place extends Model { @@ -163,9 +122,9 @@ class Place extends Model ### Saving a model ```php -use Grimzy\LaravelMysqlSpatial\Types\Point; -use Grimzy\LaravelMysqlSpatial\Types\Polygon; -use Grimzy\LaravelMysqlSpatial\Types\LineString; +use Limenet\LaravelMysqlSpatial\Types\Point; +use Limenet\LaravelMysqlSpatial\Types\Polygon; +use Limenet\LaravelMysqlSpatial\Types\LineString; $place1 = new Place(); $place1->name = 'Empire State Building'; @@ -188,9 +147,9 @@ $place1->save(); Or if your database fields were created with a specific SRID: ```php -use Grimzy\LaravelMysqlSpatial\Types\Point; -use Grimzy\LaravelMysqlSpatial\Types\Polygon; -use Grimzy\LaravelMysqlSpatial\Types\LineString; +use Limenet\LaravelMysqlSpatial\Types\Point; +use Limenet\LaravelMysqlSpatial\Types\Polygon; +use Limenet\LaravelMysqlSpatial\Types\LineString; $place1 = new Place(); $place1->name = 'Empire State Building'; @@ -226,21 +185,21 @@ $lng = $place2->location->getLng(); // -73.9878441 ### Available Geometry classes -| Grimzy\LaravelMysqlSpatial\Types | OpenGIS Class | -| ------------------------------------------------------------ | ------------------------------------------------------------ | -| `Point($lat, $lng, $srid = 0)` | [Point](https://dev.mysql.com/doc/refman/8.0/en/gis-class-point.html) | -| `MultiPoint(Point[], $srid = 0)` | [MultiPoint](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multipoint.html) | -| `LineString(Point[], $srid = 0)` | [LineString](https://dev.mysql.com/doc/refman/8.0/en/gis-class-linestring.html) | -| `MultiLineString(LineString[], $srid = 0)` | [MultiLineString](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multilinestring.html) | -| `Polygon(LineString[], $srid = 0)` *([exterior and interior boundaries](https://dev.mysql.com/doc/refman/8.0/en/gis-class-polygon.html))* | [Polygon](https://dev.mysql.com/doc/refman/8.0/en/gis-class-polygon.html) | -| `MultiPolygon(Polygon[], $srid = 0)` | [MultiPolygon](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multipolygon.html) | -| `GeometryCollection(Geometry[], $srid = 0)` | [GeometryCollection](https://dev.mysql.com/doc/refman/8.0/en/gis-class-geometrycollection.html) | +| `Limenet\LaravelMysqlSpatial\Types` | OpenGIS Class | +| ----------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | +| `Point($lat, $lng, $srid = 0)` | [Point](https://dev.mysql.com/doc/refman/8.0/en/gis-class-point.html) | +| `MultiPoint(Point[], $srid = 0)` | [MultiPoint](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multipoint.html) | +| `LineString(Point[], $srid = 0)` | [LineString](https://dev.mysql.com/doc/refman/8.0/en/gis-class-linestring.html) | +| `MultiLineString(LineString[], $srid = 0)` | [MultiLineString](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multilinestring.html) | +| `Polygon(LineString[], $srid = 0)` *([exterior and interior boundaries](https://dev.mysql.com/doc/refman/8.0/en/gis-class-polygon.html))* | [Polygon](https://dev.mysql.com/doc/refman/8.0/en/gis-class-polygon.html) | +| `MultiPolygon(Polygon[], $srid = 0)` | [MultiPolygon](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multipolygon.html) | +| `GeometryCollection(Geometry[], $srid = 0)` | [GeometryCollection](https://dev.mysql.com/doc/refman/8.0/en/gis-class-geometrycollection.html) | Check out the [Class diagram](https://user-images.githubusercontent.com/1837678/30788608-a5afd894-a16c-11e7-9a51-0a08b331d4c4.png). ### Using Geometry classes -In order for your Eloquent Model to handle the Geometry classes, it must use the `Grimzy\LaravelMysqlSpatial\Eloquent\SpatialTrait` trait and define a `protected` property `$spatialFields` as an array of MySQL Spatial Data Type column names (example in [Quickstart](#user-content-create-a-model)). +In order for your Eloquent Model to handle the Geometry classes, it must use the `Limenet\LaravelMysqlSpatial\Eloquent\SpatialTrait` trait and define a `protected` property `$spatialFields` as an array of MySQL Spatial Data Type column names (example in [Quickstart](#user-content-create-a-model)). #### IteratorAggregate and ArrayAccess @@ -336,19 +295,6 @@ Available scopes: *Note that behavior and availability of MySQL spatial analysis functions differs in each MySQL version (cf. [documentation](https://dev.mysql.com/doc/refman/8.0/en/spatial-function-reference.html)).* -## Migrations - -For Laravel versions prior to 5.5, you can use the Blueprint provided with this package: `Grimzy\LaravelMysqlSpatial\Schema\Blueprint`. - -```php -use Illuminate\Database\Migrations\Migration; -use Grimzy\LaravelMysqlSpatial\Schema\Blueprint; - -class CreatePlacesTable extends Migration { - // ... -} -``` - ### Columns Available [MySQL Spatial Types](https://dev.mysql.com/doc/refman/8.0/en/spatial-type-overview.html) migration blueprints: @@ -403,7 +349,7 @@ class UpdatePlacesTable extends Migration Schema::table('places', function (Blueprint $table) { // Make sure point is not nullable $table->point('location')->change(); - + // Add a spatial index on the location field $table->spatialIndex('location'); }); @@ -433,9 +379,6 @@ class UpdatePlacesTable extends Migration ```shell $ composer test -# or -$ composer test:unit -$ composer test:integration ``` Integration tests require a running MySQL database. If you have Docker installed, you can start easily start one: @@ -448,7 +391,7 @@ $ make start_db V=5.7 # starts MySQL 5.7 ## Contributing -Recommendations and pull request are most welcome! Pull requests with tests are the best! There are still a lot of MySQL spatial functions to implement or creative ways to use spatial functions. +Recommendations and pull request are most welcome! Pull requests with tests are the best! There are still a lot of MySQL spatial functions to implement or creative ways to use spatial functions. ## Credits diff --git a/composer.json b/composer.json index 4451cb50..1cd5a3e6 100644 --- a/composer.json +++ b/composer.json @@ -1,10 +1,15 @@ { - "name": "grimzy/laravel-mysql-spatial", + "name": "limenet/laravel-mysql-spatial", "description": "MySQL spatial data types extension for Laravel.", + "homepage": "https://github.com/limenet/laravel-mysql-spatial", "scripts": { - "test": "phpunit -c phpunit.xml.dist", - "test:unit": "phpunit -c phpunit.xml.dist --testsuite unit", - "test:integration": "phpunit -c phpunit.xml.dist --testsuite integration" + "post-autoload-dump": "@php ./vendor/bin/testbench package:discover --ansi", + "analyse": "vendor/bin/phpstan analyse", + "test": "vendor/bin/phpunit", + "test-coverage": "vendor/bin/phpunit --coverage", + "format": "vendor/bin/pint", + "post-update-cmd": "@composer bump -D", + "rector": "./vendor/bin/rector process" }, "type": "library", "license": "MIT", @@ -12,42 +17,61 @@ { "name": "Joseph Estefane", "email": "estefanejoe@gmail.com" + }, + { + "name": "Linus Metzler", + "email": "hi@linusmetzler.me" } ], "require": { - "php": ">=7.3", - "ext-pdo": "*", + "php": "^8.1", "ext-json": "*", - "illuminate/database": "^8.0", + "ext-pdo": "*", + "doctrine/dbal": "^3.5", "geo-io/wkb-parser": "^1.0", + "illuminate/contracts": "^10.0", + "illuminate/database": "^10.0", "jmikola/geojson": "^1.0" }, + "conflict": {}, "require-dev": { - "phpunit/phpunit": "~6.5", - "laravel/laravel": "^8.0", - "doctrine/dbal": "^2.5", - "laravel/browser-kit-testing": "^2.0", - "mockery/mockery": "^1.3" + "driftingly/rector-laravel": "^0.21.0", + "laravel/browser-kit-testing": "^7.0", + "laravel/laravel": "^10.2.4", + "laravel/pint": "^1.10.3", + "mockery/mockery": "^1.6.2", + "nunomaduro/collision": "^7.7.0", + "nunomaduro/larastan": "^2.6.3", + "orchestra/testbench": "^8.5.9", + "phpstan/extension-installer": "^1.3.1", + "phpstan/phpstan-deprecation-rules": "^1.1.3", + "phpstan/phpstan-phpunit": "^1.3.13", + "phpunit/phpunit": "^10.2.3", + "rector/rector": "^0.17.2" }, "autoload": { "psr-4": { - "Grimzy\\LaravelMysqlSpatial\\": "src/" + "Limenet\\LaravelMysqlSpatial\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Limenet\\LaravelMysqlSpatial\\Tests\\": "tests" } }, - "autoload-dev" : { - "classmap" : [ - "tests/Unit", - "tests/Integration" - ] + "config": { + "sort-packages": true, + "allow-plugins": { + "phpstan/extension-installer": true + } }, "extra": { - "branch-alias": { - "dev-master": "4.0.x-dev" - }, "laravel": { "providers": [ - "Grimzy\\LaravelMysqlSpatial\\SpatialServiceProvider" + "Limenet\\LaravelMysqlSpatial\\SpatialServiceProvider" ] } - } + }, + "minimum-stability": "stable", + "prefer-stable": true } diff --git a/docker-compose.yml b/docker-compose.yml index fb41dd07..9aa3a874 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,10 +1,10 @@ version: '3.3' services: db: - image: mysql:5.7 - ports: - - "3306:3306" - environment: - MYSQL_DATABASE: 'spatial_test' - MYSQL_ROOT_PASSWORD: '' - MYSQL_ALLOW_EMPTY_PASSWORD: 1 \ No newline at end of file + image: mysql:8.0 + ports: + - "33306:3306" + environment: + MYSQL_DATABASE: 'laravel' + MYSQL_ROOT_PASSWORD: 'root' + MYSQL_ALLOW_EMPTY_PASSWORD: 1 diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 00000000..5c48ae35 --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,62 @@ +parameters: + ignoreErrors: + - + message: "#^PHPDoc type Limenet\\\\LaravelMysqlSpatial\\\\Types\\\\GeometryInterface of property Limenet\\\\LaravelMysqlSpatial\\\\Eloquent\\\\SpatialExpression\\:\\:\\$value is not covariant with PHPDoc type float\\|int\\|string of overridden property Illuminate\\\\Database\\\\Query\\\\Expression\\:\\:\\$value\\.$#" + count: 1 + path: src/Eloquent/SpatialExpression.php + + - + message: "#^Call to function is_null\\(\\) with Illuminate\\\\Database\\\\Schema\\\\Grammars\\\\Grammar will always evaluate to false\\.$#" + count: 1 + path: src/MysqlConnection.php + + - + message: "#^Method Limenet\\\\LaravelMysqlSpatial\\\\MysqlConnection\\:\\:getDefaultSchemaGrammar\\(\\) should return Illuminate\\\\Database\\\\Schema\\\\Grammars\\\\MySqlGrammar but returns Illuminate\\\\Database\\\\Grammar\\.$#" + count: 1 + path: src/MysqlConnection.php + + - + message: "#^Method Limenet\\\\LaravelMysqlSpatial\\\\Schema\\\\Blueprint\\:\\:spatialIndex\\(\\) should return Illuminate\\\\Database\\\\Schema\\\\IndexDefinition but returns Illuminate\\\\Support\\\\Fluent\\.$#" + count: 1 + path: src/Schema/Blueprint.php + + - + message: "#^Access to an undefined property Illuminate\\\\Support\\\\Fluent\\:\\:\\$srid\\.$#" + count: 1 + path: src/Schema/Grammars/MySqlGrammar.php + + - + message: "#^Method Limenet\\\\LaravelMysqlSpatial\\\\Types\\\\Geometry\\:\\:fromWKT\\(\\) should return static\\(Limenet\\\\LaravelMysqlSpatial\\\\Types\\\\Geometry\\) but returns Limenet\\\\LaravelMysqlSpatial\\\\Types\\\\GeometryInterface\\.$#" + count: 1 + path: src/Types/Geometry.php + + - + message: "#^Unsafe usage of new static\\(\\)\\.$#" + count: 3 + path: src/Types/GeometryCollection.php + + - + message: "#^Unsafe usage of new static\\(\\)\\.$#" + count: 1 + path: src/Types/LineString.php + + - + message: "#^Unsafe usage of new static\\(\\)\\.$#" + count: 1 + path: src/Types/MultiLineString.php + + - + message: "#^Unsafe usage of new static\\(\\)\\.$#" + count: 1 + path: src/Types/MultiPoint.php + + - + message: "#^Unsafe usage of new static\\(\\)\\.$#" + count: 1 + path: src/Types/MultiPolygon.php + + - + message: "#^Unsafe usage of new static\\(\\)\\.$#" + count: 1 + path: src/Types/Point.php + diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 00000000..5ab06e2b --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,11 @@ +includes: + - phpstan-baseline.neon + +parameters: + level: 8 + paths: + - src + tmpDir: build/phpstan + checkModelProperties: true + checkMissingIterableValueType: false + checkGenericClassInNonGenericObjectType: false diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 1456a6ac..5d8dd7a1 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,45 +1,34 @@ - - - - ./tests/Unit - - - ./tests/Integration - - - - - - - - - ./src - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + tests + + + + + ./src + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pint.json b/pint.json new file mode 100644 index 00000000..6aad9090 --- /dev/null +++ b/pint.json @@ -0,0 +1,6 @@ +{ + "preset": "laravel", + "rules": { + "use_arrow_functions": true + } +} diff --git a/rector.php b/rector.php new file mode 100644 index 00000000..599c7fea --- /dev/null +++ b/rector.php @@ -0,0 +1,20 @@ +paths([ + __DIR__.'/src', + ]); + + $rectorConfig->sets([ + LevelSetList::UP_TO_PHP_81, + LaravelSetList::LARAVEL_100, + SetList::CODE_QUALITY, + ]); +}; diff --git a/src/Connectors/ConnectionFactory.php b/src/Connectors/ConnectionFactory.php index 223cea13..3c50fd95 100644 --- a/src/Connectors/ConnectionFactory.php +++ b/src/Connectors/ConnectionFactory.php @@ -1,20 +1,18 @@ value->toWkt(); } - public function getSrid() + public function getSrid(): int { return $this->value->getSrid(); } + + public function toWkt(): string + { + return $this->value->toWkt(); + } } diff --git a/src/Eloquent/SpatialTrait.php b/src/Eloquent/SpatialTrait.php index 5cc3f4b1..05042609 100755 --- a/src/Eloquent/SpatialTrait.php +++ b/src/Eloquent/SpatialTrait.php @@ -1,13 +1,13 @@ spatialFields; } else { - throw new SpatialFieldsNotDefinedException(__CLASS__.' has to define $spatialFields'); + throw new SpatialFieldsNotDefinedException(self::class.' has to define $spatialFields'); } } - public function isColumnAllowed($geometryColumn) + public function isColumnAllowed($geometryColumn): bool { - if (!in_array($geometryColumn, $this->getSpatialFields())) { + if (! in_array($geometryColumn, $this->getSpatialFields())) { throw new SpatialFieldsNotDefinedException(); } @@ -163,7 +162,7 @@ public function scopeDistanceValue($query, $geometryColumn, $geometry) $columns = $query->getQuery()->columns; - if (!$columns) { + if (! $columns) { $query->select('*'); } @@ -206,7 +205,7 @@ public function scopeDistanceSphereValue($query, $geometryColumn, $geometry) $columns = $query->getQuery()->columns; - if (!$columns) { + if (! $columns) { $query->select('*'); } $query->selectRaw("st_distance_sphere(`$geometryColumn`, ST_GeomFromText(?, ?, 'axis-order=long-lat')) as distance", [ @@ -219,7 +218,7 @@ public function scopeComparison($query, $geometryColumn, $geometry, $relationshi { $this->isColumnAllowed($geometryColumn); - if (!in_array($relationship, $this->stRelations)) { + if (! in_array($relationship, $this->stRelations)) { throw new UnknownSpatialRelationFunction($relationship); } @@ -275,7 +274,7 @@ public function scopeOrderBySpatial($query, $geometryColumn, $geometry, $orderFu { $this->isColumnAllowed($geometryColumn); - if (!in_array($orderFunction, $this->stOrderFunctions)) { + if (! in_array($orderFunction, $this->stOrderFunctions)) { throw new UnknownSpatialFunctionException($orderFunction); } diff --git a/src/Exceptions/InvalidGeoJsonException.php b/src/Exceptions/InvalidGeoJsonException.php index 3374fdb7..f82d6ff8 100644 --- a/src/Exceptions/InvalidGeoJsonException.php +++ b/src/Exceptions/InvalidGeoJsonException.php @@ -1,7 +1,17 @@ getDoctrineSchemaManager()->getDatabasePlatform(); + $dbPlatform = $this->getDoctrineConnection()->getDatabasePlatform(); foreach ($geometries as $type) { $dbPlatform->registerDoctrineTypeMapping($type, 'string'); } @@ -35,20 +35,16 @@ public function __construct($pdo, $database = '', $tablePrefix = '', array $conf /** * Get the default schema grammar instance. - * - * @return \Illuminate\Database\Grammar */ - protected function getDefaultSchemaGrammar() + protected function getDefaultSchemaGrammar(): \Illuminate\Database\Grammar { return $this->withTablePrefix(new MySqlGrammar()); } /** * Get a schema builder instance for the connection. - * - * @return \Illuminate\Database\Schema\MySqlBuilder */ - public function getSchemaBuilder() + public function getSchemaBuilder(): \Illuminate\Database\Schema\MySqlBuilder { if (is_null($this->schemaGrammar)) { $this->useDefaultSchemaGrammar(); diff --git a/src/Schema/Blueprint.php b/src/Schema/Blueprint.php index 0a333f06..037425e4 100644 --- a/src/Schema/Blueprint.php +++ b/src/Schema/Blueprint.php @@ -1,6 +1,6 @@ addColumn('geometry', $column, compact('srid')); + return $this->addColumn('geometry', $column, ['srid' => $srid]); } /** * Add a point column on the table. * - * @param string $column - * @param null|int $srid - * - * @return \Illuminate\Support\Fluent + * @param ?int $srid */ - public function point($column, $srid = null) + public function point($column, $srid = null): \Illuminate\Support\Fluent { - return $this->addColumn('point', $column, compact('srid')); + return $this->addColumn('point', $column, ['srid' => $srid]); } /** * Add a linestring column on the table. - * - * @param string $column - * @param null|int $srid - * - * @return \Illuminate\Support\Fluent */ - public function lineString($column, $srid = null) + public function lineString($column, ?int $srid = null): \Illuminate\Support\Fluent { - return $this->addColumn('linestring', $column, compact('srid')); + return $this->addColumn('linestring', $column, ['srid' => $srid]); } /** * Add a polygon column on the table. - * - * @param string $column - * @param null|int $srid - * - * @return \Illuminate\Support\Fluent */ - public function polygon($column, $srid = null) + public function polygon($column, ?int $srid = null): \Illuminate\Support\Fluent { - return $this->addColumn('polygon', $column, compact('srid')); + return $this->addColumn('polygon', $column, ['srid' => $srid]); } /** * Add a multipoint column on the table. - * - * @param string $column - * @param null|int $srid - * - * @return \Illuminate\Support\Fluent */ - public function multiPoint($column, $srid = null) + public function multiPoint($column, ?int $srid = null): \Illuminate\Support\Fluent { - return $this->addColumn('multipoint', $column, compact('srid')); + return $this->addColumn('multipoint', $column, ['srid' => $srid]); } /** * Add a multilinestring column on the table. - * - * @param string $column - * @param null|int $srid - * - * @return \Illuminate\Support\Fluent */ - public function multiLineString($column, $srid = null) + public function multiLineString($column, ?int $srid = null): \Illuminate\Support\Fluent { - return $this->addColumn('multilinestring', $column, compact('srid')); + return $this->addColumn('multilinestring', $column, ['srid' => $srid]); } /** * Add a multipolygon column on the table. - * - * @param string $column - * @param null|int $srid - * - * @return \Illuminate\Support\Fluent */ - public function multiPolygon($column, $srid = null) + public function multiPolygon($column, ?int $srid = null): \Illuminate\Support\Fluent { - return $this->addColumn('multipolygon', $column, compact('srid')); + return $this->addColumn('multipolygon', $column, ['srid' => $srid]); } /** * Add a geometrycollection column on the table. - * - * @param string $column - * @param null|int $srid - * - * @return \Illuminate\Support\Fluent */ - public function geometryCollection($column, $srid = null) + public function geometryCollection($column, ?int $srid = null): \Illuminate\Support\Fluent { - return $this->addColumn('geometrycollection', $column, compact('srid')); + return $this->addColumn('geometrycollection', $column, ['srid' => $srid]); } /** * Specify a spatial index for the table. * - * @param string|array $columns - * @param string $name - * - * @return \Illuminate\Support\Fluent + * @param string|array $columns + * @param string $name */ - public function spatialIndex($columns, $name = null) + public function spatialIndex($columns, $name = null): \Illuminate\Support\Fluent { - return $this->indexCommand('spatial', $columns, $name); + return $this->indexCommand( + 'spatial', + $columns, + $name ?: $this->createIndexName('spatial', is_array($columns) ? $columns : [$columns]) + ); } /** * Indicate that the given index should be dropped. * - * @param string|array $index - * - * @return \Illuminate\Support\Fluent + * @param string|array $index */ - public function dropSpatialIndex($index) + public function dropSpatialIndex($index): \Illuminate\Support\Fluent { return $this->dropIndexCommand('dropIndex', 'spatial', $index); } diff --git a/src/Schema/Builder.php b/src/Schema/Builder.php index baf8dc58..fb884387 100644 --- a/src/Schema/Builder.php +++ b/src/Schema/Builder.php @@ -1,6 +1,6 @@ modifiers)) { + if (! in_array(self::COLUMN_MODIFIER_SRID, $this->modifiers)) { $this->modifiers[] = self::COLUMN_MODIFIER_SRID; } } /** * Adds a statement to add a geometry column. - * - * @param Fluent $column - * - * @return string */ - public function typeGeometry(Fluent $column) + public function typeGeometry(Fluent $column): string { return 'GEOMETRY'; } /** * Adds a statement to add a point column. - * - * @param Fluent $column - * - * @return string */ - public function typePoint(Fluent $column) + public function typePoint(Fluent $column): string { return 'POINT'; } /** * Adds a statement to add a linestring column. - * - * @param Fluent $column - * - * @return string */ - public function typeLinestring(Fluent $column) + public function typeLinestring(Fluent $column): string { return 'LINESTRING'; } /** * Adds a statement to add a polygon column. - * - * @param Fluent $column - * - * @return string */ - public function typePolygon(Fluent $column) + public function typePolygon(Fluent $column): string { return 'POLYGON'; } /** * Adds a statement to add a multipoint column. - * - * @param Fluent $column - * - * @return string */ - public function typeMultipoint(Fluent $column) + public function typeMultipoint(Fluent $column): string { return 'MULTIPOINT'; } /** * Adds a statement to add a multilinestring column. - * - * @param Fluent $column - * - * @return string */ - public function typeMultilinestring(Fluent $column) + public function typeMultilinestring(Fluent $column): string { return 'MULTILINESTRING'; } /** * Adds a statement to add a multipolygon column. - * - * @param Fluent $column - * - * @return string */ - public function typeMultipolygon(Fluent $column) + public function typeMultipolygon(Fluent $column): string { return 'MULTIPOLYGON'; } /** * Adds a statement to add a geometrycollection column. - * - * @param Fluent $column - * - * @return string */ - public function typeGeometrycollection(Fluent $column) + public function typeGeometrycollection(Fluent $column): string { return 'GEOMETRYCOLLECTION'; } /** * Compile a spatial index key command. - * - * @param Blueprint $blueprint - * @param Fluent $command - * - * @return string */ - public function compileSpatial(Blueprint $blueprint, Fluent $command) + public function compileSpatial(Blueprint $blueprint, Fluent $command): string { return $this->compileKey($blueprint, $command, 'spatial'); } /** * Get the SQL for a SRID column modifier. - * - * @param \Illuminate\Database\Schema\Blueprint $blueprint - * @param Fluent $column - * - * @return string|null */ - protected function modifySrid(\Illuminate\Database\Schema\Blueprint $blueprint, Fluent $column) + protected function modifySrid(\Illuminate\Database\Schema\Blueprint $blueprint, Fluent $column): ?string { - if (!is_null($column->srid) && is_int($column->srid) && $column->srid > 0) { + if (! is_null($column->srid) && is_int($column->srid) && $column->srid > 0) { return ' srid '.$column->srid; } + + return null; } } diff --git a/src/SpatialServiceProvider.php b/src/SpatialServiceProvider.php index 3b859f8e..973e4480 100644 --- a/src/SpatialServiceProvider.php +++ b/src/SpatialServiceProvider.php @@ -1,19 +1,19 @@ app->singleton('db.factory', function ($app) { - return new ConnectionFactory($app); - }); + $this->app->singleton('db.factory', fn ($app) => new ConnectionFactory($app)); // The database manager is used to resolve various connections, since multiple // connections might be managed. It also implements the connection resolver // interface which may be used by other components requiring connections. - $this->app->singleton('db', function ($app) { - return new DatabaseManager($app, $app['db.factory']); - }); + $this->app->singleton('db', fn ($app) => new DatabaseManager($app, $app['db.factory'])); if (class_exists(DoctrineType::class)) { // Prevent geometry type fields from throwing a 'type not found' error when changing them $geometries = [ - 'geometry' => Geometry::class, - 'point' => Point::class, - 'linestring' => LineString::class, - 'polygon' => Polygon::class, - 'multipoint' => MultiPoint::class, - 'multilinestring' => MultiLineString::class, - 'multipolygon' => MultiPolygon::class, + 'geometry' => Geometry::class, + 'point' => Point::class, + 'linestring' => LineString::class, + 'polygon' => Polygon::class, + 'multipoint' => MultiPoint::class, + 'multilinestring' => MultiLineString::class, + 'multipolygon' => MultiPolygon::class, 'geometrycollection' => GeometryCollection::class, ]; $typeNames = array_keys(DoctrineType::getTypesMap()); foreach ($geometries as $type => $class) { - if (!in_array($type, $typeNames)) { + if (! in_array($type, $typeNames)) { DoctrineType::addType($type, $class); } } diff --git a/src/Types/Factory.php b/src/Types/Factory.php index ed04ac2d..4b6ffccd 100755 --- a/src/Types/Factory.php +++ b/src/Types/Factory.php @@ -1,45 +1,77 @@ Point::class, 2 => LineString::class, 3 => Polygon::class, @@ -19,24 +21,21 @@ abstract class Geometry implements GeometryInterface, Jsonable, \JsonSerializabl 7 => GeometryCollection::class, ]; - protected $srid; - - public function __construct($srid = 0) + public function __construct(protected int $srid = 0) { - $this->srid = (int) $srid; } - public function getSrid() + public function getSrid(): int { return $this->srid; } - public function setSrid($srid) + public function setSrid(int $srid): void { - $this->srid = (int) $srid; + $this->srid = $srid; } - public static function getWKTArgument($value) + public static function getWKTArgument(string $value): string { $left = strpos($value, '('); $right = strrpos($value, ')'); @@ -44,35 +43,39 @@ public static function getWKTArgument($value) return substr($value, $left + 1, $right - $left - 1); } - public static function getWKTClass($value) + /** @return class-string */ + public static function getWKTClass(string $value): string { $left = strpos($value, '('); - $type = trim(substr($value, 0, $left)); - switch (strtoupper($type)) { - case 'POINT': - return Point::class; - case 'LINESTRING': - return LineString::class; - case 'POLYGON': - return Polygon::class; - case 'MULTIPOINT': - return MultiPoint::class; - case 'MULTILINESTRING': - return MultiLineString::class; - case 'MULTIPOLYGON': - return MultiPolygon::class; - case 'GEOMETRYCOLLECTION': - return GeometryCollection::class; - default: - throw new UnknownWKTTypeException('Type was '.$type); + if ($left === false) { + throw new UnknownWKTTypeException('Could not parse '.$value); } + + $type = trim(substr($value, 0, $left)); + + return match (strtoupper($type)) { + 'POINT' => Point::class, + 'LINESTRING' => LineString::class, + 'POLYGON' => Polygon::class, + 'MULTIPOINT' => MultiPoint::class, + 'MULTILINESTRING' => MultiLineString::class, + 'MULTIPOLYGON' => MultiPolygon::class, + 'GEOMETRYCOLLECTION' => GeometryCollection::class, + default => throw new UnknownWKTTypeException('Type was '.$type) + }; } - public static function fromWKB($wkb) + public static function fromWKB(string $wkb): Geometry { $srid = substr($wkb, 0, 4); - $srid = unpack('L', $srid)[1]; + $unpacked = unpack('L', $srid); + + if ($unpacked === false) { + throw new UnknownWKBException($wkb); + } + + $srid = $unpacked[1]; $wkb = substr($wkb, 4); $parser = new Parser(new Factory()); @@ -87,34 +90,35 @@ public static function fromWKB($wkb) return $parsed; } - public static function fromWKT($wkt, $srid = null) + public static function fromWKT(string $wkt, int $srid = 0): static { $wktArgument = static::getWKTArgument($wkt); return static::fromString($wktArgument, $srid); } - public static function fromJson($geoJson) + public static function fromJson(string|GeoJson $geoJson): self { if (is_string($geoJson)) { - $geoJson = GeoJson::jsonUnserialize(json_decode($geoJson)); + $geoJson = GeoJson::jsonUnserialize(json_decode($geoJson, flags: JSON_THROW_ON_ERROR)); } if ($geoJson->getType() === 'FeatureCollection') { return GeometryCollection::fromJson($geoJson); } + /** @var Feature $geoJson */ if ($geoJson->getType() === 'Feature') { $geoJson = $geoJson->getGeometry(); } - $type = '\Grimzy\LaravelMysqlSpatial\Types\\'.$geoJson->getType(); + $type = '\Limenet\LaravelMysqlSpatial\Types\\'.$geoJson?->getType(); return $type::fromJson($geoJson); } public function toJson($options = 0) { - return json_encode($this, $options); + return json_encode($this, $options | JSON_THROW_ON_ERROR); } } diff --git a/src/Types/GeometryCollection.php b/src/Types/GeometryCollection.php index 35f093f7..bc296f08 100755 --- a/src/Types/GeometryCollection.php +++ b/src/Types/GeometryCollection.php @@ -1,85 +1,85 @@ + */ +class GeometryCollection extends Geometry implements IteratorAggregate, ArrayAccess, Arrayable, Countable, GeometryInterface, \Stringable { /** * The minimum number of items required to create this collection. - * - * @var int */ - protected $minimumCollectionItems = 0; + protected int $minimumCollectionItems = 0; /** * The class of the items in the collection. - * - * @var string */ - protected $collectionItemType = GeometryInterface::class; + protected string $collectionItemType = GeometryInterface::class; /** * The items contained in the spatial collection. * - * @var GeometryInterface[] + * @var GeoType[] */ - protected $items = []; + protected array $items = []; /** - * @param GeometryInterface[] $geometries - * @param int $srid + * @param GeoType[] $geometries * * @throws InvalidArgumentException */ - public function __construct(array $geometries, $srid = 0) + public function __construct(array $geometries, ?int $srid = 0) { - parent::__construct($srid); + parent::__construct((int) $srid); $this->validateItems($geometries); $this->items = $geometries; } - public function getGeometries() + /** + * @return GeoType[] + */ + public function getGeometries(): array { return $this->items; } - public function toWKT() + public function toWKT(): string { return sprintf('GEOMETRYCOLLECTION(%s)', (string) $this); } - public function __toString() + public function __toString(): string { - return implode(',', array_map(function (GeometryInterface $geometry) { - return $geometry->toWKT(); - }, $this->items)); + return implode(',', array_map(fn (GeometryInterface $geometry) => $geometry->toWKT(), $this->items)); } - public static function fromString($wktArgument, $srid = 0) + public static function fromString(string $wktArgument, int $srid = 0): static { - if (empty($wktArgument)) { + if ($wktArgument === '') { return new static([]); } $geometry_strings = preg_split('/,\s*(?=[A-Za-z])/', $wktArgument); + if ($geometry_strings === false) { + return new static([]); + } - return new static(array_map(function ($geometry_string) { - $klass = Geometry::getWKTClass($geometry_string); - - return call_user_func($klass.'::fromWKT', $geometry_string); - }, $geometry_strings), $srid); + return new static(array_map(fn ($geometry_string) => call_user_func([Geometry::getWKTClass($geometry_string), 'fromWKT'], $geometry_string), $geometry_strings), $srid); } public function toArray() @@ -87,22 +87,23 @@ public function toArray() return $this->items; } - public function getIterator() + public function getIterator(): ArrayIterator { return new ArrayIterator($this->items); } - public function offsetExists($offset) + public function offsetExists($offset): bool { return isset($this->items[$offset]); } + #[\ReturnTypeWillChange] public function offsetGet($offset) { return $this->offsetExists($offset) ? $this->items[$offset] : null; } - public function offsetSet($offset, $value) + public function offsetSet($offset, $value): void { $this->validateItemType($value); @@ -113,24 +114,24 @@ public function offsetSet($offset, $value) } } - public function offsetUnset($offset) + public function offsetUnset($offset): void { unset($this->items[$offset]); } - public function count() + public function count(): int { return count($this->items); } - public static function fromJson($geoJson) + public static function fromJson(string|GeoJson $geoJson): self { if (is_string($geoJson)) { - $geoJson = GeoJson::jsonUnserialize(json_decode($geoJson)); + $geoJson = GeoJson::jsonUnserialize(json_decode($geoJson, flags: JSON_THROW_ON_ERROR)); } - if (!is_a($geoJson, FeatureCollection::class)) { - throw new InvalidGeoJsonException('Expected '.FeatureCollection::class.', got '.get_class($geoJson)); + if (! $geoJson instanceof FeatureCollection) { + throw new InvalidGeoJsonException(FeatureCollection::class, $geoJson::class); } $set = []; @@ -143,9 +144,8 @@ public static function fromJson($geoJson) /** * Convert to GeoJson GeometryCollection that is jsonable to GeoJSON. - * - * @return \GeoJson\Geometry\GeometryCollection */ + #[\ReturnTypeWillChange] public function jsonSerialize() { $geometries = []; @@ -159,9 +159,9 @@ public function jsonSerialize() /** * Checks whether the items are valid to create this collection. * - * @param array $items + * @param GeoType[] $items */ - protected function validateItems(array $items) + protected function validateItems(array $items): void { $this->validateItemCount($items); @@ -173,18 +173,18 @@ protected function validateItems(array $items) /** * Checks whether the array has enough items to generate a valid WKT. * - * @param array $items + * @param GeoType[] $items * * @see $minimumCollectionItems */ - protected function validateItemCount(array $items) + protected function validateItemCount(array $items): void { if (count($items) < $this->minimumCollectionItems) { $entries = $this->minimumCollectionItems === 1 ? 'entry' : 'entries'; throw new InvalidArgumentException(sprintf( '%s must contain at least %d %s', - get_class($this), + static::class, $this->minimumCollectionItems, $entries )); @@ -194,16 +194,15 @@ protected function validateItemCount(array $items) /** * Checks the type of the items in the array. * - * @param $item * * @see $collectionItemType */ - protected function validateItemType($item) + protected function validateItemType(mixed $item): void { - if (!$item instanceof $this->collectionItemType) { + if (! $item instanceof $this->collectionItemType) { throw new InvalidArgumentException(sprintf( '%s must be a collection of %s', - get_class($this), + static::class, $this->collectionItemType )); } diff --git a/src/Types/GeometryInterface.php b/src/Types/GeometryInterface.php index 4f0dd1ef..48735e6f 100644 --- a/src/Types/GeometryInterface.php +++ b/src/Types/GeometryInterface.php @@ -1,16 +1,29 @@ toPairList()); } - public static function fromWkt($wkt, $srid = 0) + public static function fromWKT(string $wkt, int $srid = 0): static { $wktArgument = Geometry::getWKTArgument($wkt); return static::fromString($wktArgument, $srid); } - public static function fromString($wktArgument, $srid = 0) + public static function fromString(string $wktArgument, int $srid = 0): static { $pairs = explode(',', trim($wktArgument)); - $points = array_map(function ($pair) { - return Point::fromPair($pair); - }, $pairs); + $points = array_map(fn ($pair) => Point::fromPair($pair), $pairs); return new static($points, $srid); } - public function __toString() + public function __toString(): string { return $this->toPairList(); } - public static function fromJson($geoJson) + public static function fromJson(string|GeoJson $geoJson): self { if (is_string($geoJson)) { - $geoJson = GeoJson::jsonUnserialize(json_decode($geoJson)); + $geoJson = GeoJson::jsonUnserialize(json_decode($geoJson, null, 512, JSON_THROW_ON_ERROR)); } - if (!is_a($geoJson, GeoJsonLineString::class)) { - throw new InvalidGeoJsonException('Expected '.GeoJsonLineString::class.', got '.get_class($geoJson)); + if (! $geoJson instanceof GeoJsonLineString) { + throw new InvalidGeoJsonException(GeoJsonLineString::class, $geoJson::class); } $set = []; @@ -62,9 +58,8 @@ public static function fromJson($geoJson) /** * Convert to GeoJson LineString that is jsonable to GeoJSON. - * - * @return \GeoJson\Geometry\LineString */ + #[\ReturnTypeWillChange] public function jsonSerialize() { $points = []; diff --git a/src/Types/MultiLineString.php b/src/Types/MultiLineString.php index 62c4d576..dc51edaf 100644 --- a/src/Types/MultiLineString.php +++ b/src/Types/MultiLineString.php @@ -1,69 +1,72 @@ + * + * @extends GeometryCollection + */ +class MultiLineString extends GeometryCollection implements GeometryInterface, \Stringable { /** * The minimum number of items required to create this collection. - * - * @var int */ - protected $minimumCollectionItems = 1; + protected int $minimumCollectionItems = 1; /** * The class of the items in the collection. - * - * @var string */ - protected $collectionItemType = LineString::class; + protected string $collectionItemType = LineString::class; - public function getLineStrings() + public function getLineStrings(): array { return $this->items; } - public function toWKT() + public function toWKT(): string { return sprintf('MULTILINESTRING(%s)', (string) $this); } - public static function fromString($wktArgument, $srid = 0) + public static function fromString(string $wktArgument, int $srid = 0): static { $str = preg_split('/\)\s*,\s*\(/', substr(trim($wktArgument), 1, -1)); - $lineStrings = array_map(function ($data) { - return LineString::fromString($data); - }, $str); + + if ($str === false) { + throw new RuntimeException(); + } + + $lineStrings = array_map(fn ($data) => LineString::fromString($data), $str); return new static($lineStrings, $srid); } - public function __toString() + public function __toString(): string { - return implode(',', array_map(function (LineString $lineString) { - return sprintf('(%s)', (string) $lineString); - }, $this->getLineStrings())); + return implode(',', array_map(fn (LineString $lineString) => sprintf('(%s)', (string) $lineString), $this->getLineStrings())); } - public function offsetSet($offset, $value) + public function offsetSet($offset, $value): void { $this->validateItemType($value); parent::offsetSet($offset, $value); } - public static function fromJson($geoJson) + public static function fromJson(string|GeoJson $geoJson): self { if (is_string($geoJson)) { - $geoJson = GeoJson::jsonUnserialize(json_decode($geoJson)); + $geoJson = GeoJson::jsonUnserialize(json_decode($geoJson, flags: JSON_THROW_ON_ERROR)); } - if (!is_a($geoJson, GeoJsonMultiLineString::class)) { - throw new InvalidGeoJsonException('Expected '.GeoJsonMultiLineString::class.', got '.get_class($geoJson)); + if (! $geoJson instanceof GeoJsonMultiLineString) { + throw new InvalidGeoJsonException(GeoJsonMultiLineString::class, $geoJson::class); } $set = []; @@ -80,9 +83,8 @@ public static function fromJson($geoJson) /** * Convert to GeoJson Point that is jsonable to GeoJSON. - * - * @return \GeoJson\Geometry\MultiLineString */ + #[\ReturnTypeWillChange] public function jsonSerialize() { $lineStrings = []; diff --git a/src/Types/MultiPoint.php b/src/Types/MultiPoint.php index 752967eb..be0e37af 100644 --- a/src/Types/MultiPoint.php +++ b/src/Types/MultiPoint.php @@ -1,59 +1,56 @@ + */ +class MultiPoint extends PointCollection implements GeometryInterface, \Stringable { /** * The minimum number of items required to create this collection. - * - * @var int */ - protected $minimumCollectionItems = 1; + protected int $minimumCollectionItems = 1; - public function toWKT() + public function toWKT(): string { return sprintf('MULTIPOINT(%s)', (string) $this); } - public static function fromWkt($wkt, $srid = 0) + public static function fromWKT(string $wkt, int $srid = 0): static { $wktArgument = Geometry::getWKTArgument($wkt); return static::fromString($wktArgument, $srid); } - public static function fromString($wktArgument, $srid = 0) + public static function fromString(string $wktArgument, int $srid = 0): static { $matches = []; preg_match_all('/\(\s*(\d+\s+\d+)\s*\)/', trim($wktArgument), $matches); - $points = array_map(function ($pair) { - return Point::fromPair($pair); - }, $matches[1]); + $points = array_map(fn ($pair) => Point::fromPair($pair), $matches[1]); return new static($points, $srid); } - public function __toString() + public function __toString(): string { - return implode(',', array_map(function (Point $point) { - return sprintf('(%s)', $point->toPair()); - }, $this->items)); + return implode(',', array_map(fn (Point $point) => sprintf('(%s)', $point->toPair()), $this->items)); } - public static function fromJson($geoJson) + public static function fromJson(string|GeoJson $geoJson): self { if (is_string($geoJson)) { - $geoJson = GeoJson::jsonUnserialize(json_decode($geoJson)); + $geoJson = GeoJson::jsonUnserialize(json_decode($geoJson, flags: JSON_THROW_ON_ERROR)); } - if (!is_a($geoJson, GeoJsonMultiPoint::class)) { - throw new InvalidGeoJsonException('Expected '.GeoJsonMultiPoint::class.', got '.get_class($geoJson)); + if (! $geoJson instanceof GeoJsonMultiPoint) { + throw new InvalidGeoJsonException(GeoJsonMultiPoint::class, $geoJson::class); } $set = []; @@ -66,8 +63,6 @@ public static function fromJson($geoJson) /** * Convert to GeoJson MultiPoint that is jsonable to GeoJSON. - * - * @return \GeoJson\Geometry\MultiPoint */ public function jsonSerialize() { diff --git a/src/Types/MultiPolygon.php b/src/Types/MultiPolygon.php index cdea3a9c..f0e00016 100644 --- a/src/Types/MultiPolygon.php +++ b/src/Types/MultiPolygon.php @@ -1,55 +1,56 @@ + * + * @extends GeometryCollection + */ +class MultiPolygon extends GeometryCollection implements GeometryInterface, \Stringable { /** * The minimum number of items required to create this collection. - * - * @var int */ - protected $minimumCollectionItems = 1; + protected int $minimumCollectionItems = 1; /** * The class of the items in the collection. - * - * @var string */ - protected $collectionItemType = Polygon::class; + protected string $collectionItemType = Polygon::class; - public function toWKT() + public function toWKT(): string { return sprintf('MULTIPOLYGON(%s)', (string) $this); } - public function __toString() + public function __toString(): string { - return implode(',', array_map(function (Polygon $polygon) { - return sprintf('(%s)', (string) $polygon); - }, $this->items)); + return implode(',', array_map(fn (Polygon $polygon) => sprintf('(%s)', (string) $polygon), $this->items)); } - public static function fromString($wktArgument, $srid = 0) + public static function fromString(string $wktArgument, int $srid = 0): static { $parts = preg_split('/(\)\s*\)\s*,\s*\(\s*\()/', $wktArgument, -1, PREG_SPLIT_DELIM_CAPTURE); + + if ($parts === false) { + throw new RuntimeException(); + } + $polygons = static::assembleParts($parts); - return new static(array_map(function ($polygonString) { - return Polygon::fromString($polygonString); - }, $polygons), $srid); + return new static(array_map(fn ($polygonString) => Polygon::fromString($polygonString), $polygons), $srid); } /** * Get the polygons that make up this MultiPolygon. - * - * @return array|Polygon[] */ - public function getPolygons() + public function getPolygons(): array { return $this->items; } @@ -66,19 +67,15 @@ public function getPolygons() * "((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))", * "((-1 -1,-1 -2,-2 -2,-2 -1,-1 -1))" - * - * @param array $parts - * - * @return array */ - protected static function assembleParts(array $parts) + protected static function assembleParts(array $parts): array { $polygons = []; $count = count($parts); for ($i = 0; $i < $count; $i++) { if ($i % 2 !== 0) { - list($end, $start) = explode(',', $parts[$i]); + [$end, $start] = explode(',', (string) $parts[$i]); $polygons[$i - 1] .= $end; $polygons[++$i] = $start.$parts[$i]; } else { @@ -89,21 +86,21 @@ protected static function assembleParts(array $parts) return $polygons; } - public function offsetSet($offset, $value) + public function offsetSet($offset, $value): void { $this->validateItemType($value); parent::offsetSet($offset, $value); } - public static function fromJson($geoJson) + public static function fromJson(string|GeoJson $geoJson): self { if (is_string($geoJson)) { - $geoJson = GeoJson::jsonUnserialize(json_decode($geoJson)); + $geoJson = GeoJson::jsonUnserialize(json_decode($geoJson, flags: JSON_THROW_ON_ERROR)); } - if (!is_a($geoJson, GeoJsonMultiPolygon::class)) { - throw new InvalidGeoJsonException('Expected '.GeoJsonMultiPolygon::class.', got '.get_class($geoJson)); + if (! $geoJson instanceof GeoJsonMultiPolygon) { + throw new InvalidGeoJsonException(GeoJsonMultiPolygon::class, $geoJson::class); } $set = []; @@ -124,9 +121,8 @@ public static function fromJson($geoJson) /** * Convert to GeoJson MultiPolygon that is jsonable to GeoJSON. - * - * @return \GeoJson\Geometry\MultiPolygon */ + #[\ReturnTypeWillChange] public function jsonSerialize() { $polygons = []; diff --git a/src/Types/Point.php b/src/Types/Point.php index d424ec5e..b1fb9ddd 100644 --- a/src/Types/Point.php +++ b/src/Types/Point.php @@ -1,85 +1,80 @@ + */ +class Point extends Geometry implements GeometryInterface, \Stringable { - protected $lat; - - protected $lng; - - public function __construct($lat, $lng, $srid = 0) + public function __construct(protected float $lat, protected float $lng, ?int $srid = 0) { - parent::__construct($srid); - - $this->lat = (float) $lat; - $this->lng = (float) $lng; + parent::__construct((int) $srid); } - public function getLat() + public function getLat(): float { return $this->lat; } - public function setLat($lat) + public function setLat(float $lat): void { - $this->lat = (float) $lat; + $this->lat = $lat; } - public function getLng() + public function getLng(): float { return $this->lng; } - public function setLng($lng) + public function setLng(float $lng): void { - $this->lng = (float) $lng; + $this->lng = $lng; } - public function toPair() + public function toPair(): string { return $this->getLng().' '.$this->getLat(); } - public static function fromPair($pair, $srid = 0) + public static function fromPair(string $pair, int $srid = 0): static { - list($lng, $lat) = explode(' ', trim($pair, "\t\n\r \x0B()")); + [$lng, $lat] = explode(' ', trim($pair, "\t\n\r \x0B()")); - return new static((float) $lat, (float) $lng, (int) $srid); + return new static((float) $lat, (float) $lng, $srid); } - public function toWKT() + public function toWKT(): string { return sprintf('POINT(%s)', (string) $this); } - public static function fromString($wktArgument, $srid = 0) + public static function fromString(string $wktArgument, int $srid = 0): self { return static::fromPair($wktArgument, $srid); } - public function __toString() + public function __toString(): string { return $this->getLng().' '.$this->getLat(); } /** * @param $geoJson \GeoJson\Feature\Feature|string - * - * @return \Grimzy\LaravelMysqlSpatial\Types\Point + * @return \Limenet\LaravelMysqlSpatial\Types\Point */ - public static function fromJson($geoJson) + public static function fromJson(string|GeoJson $geoJson): self { if (is_string($geoJson)) { - $geoJson = GeoJson::jsonUnserialize(json_decode($geoJson)); + $geoJson = GeoJson::jsonUnserialize(json_decode($geoJson, flags: JSON_THROW_ON_ERROR)); } - if (!is_a($geoJson, GeoJsonPoint::class)) { - throw new InvalidGeoJsonException('Expected '.GeoJsonPoint::class.', got '.get_class($geoJson)); + if (! $geoJson instanceof GeoJsonPoint) { + throw new InvalidGeoJsonException(GeoJsonPoint::class, $geoJson::class); } $coordinates = $geoJson->getCoordinates(); @@ -89,9 +84,8 @@ public static function fromJson($geoJson) /** * Convert to GeoJson Point that is jsonable to GeoJSON. - * - * @return \GeoJson\Geometry\Point */ + #[\ReturnTypeWillChange] public function jsonSerialize() { return new GeoJsonPoint([$this->getLng(), $this->getLat()]); diff --git a/src/Types/PointCollection.php b/src/Types/PointCollection.php index 30d1b8de..4fc482fb 100755 --- a/src/Types/PointCollection.php +++ b/src/Types/PointCollection.php @@ -1,78 +1,31 @@ + */ abstract class PointCollection extends GeometryCollection { /** * The class of the items in the collection. - * - * @var string */ - protected $collectionItemType = Point::class; + protected string $collectionItemType = Point::class; - public function toPairList() + public function toPairList(): string { - return implode(',', array_map(function (Point $point) { - return $point->toPair(); - }, $this->items)); + return implode(',', array_map(fn (Point $point): string => $point->toPair(), $this->items)); } - public function offsetSet($offset, $value) + public function offsetSet($offset, $value): void { $this->validateItemType($value); parent::offsetSet($offset, $value); } - /** - * @return array|\Grimzy\LaravelMysqlSpatial\Types\Point[] - */ - public function getPoints() + public function getPoints(): array { return $this->items; } - - /** - * @param \Grimzy\LaravelMysqlSpatial\Types\Point $point - * - * @deprecated 2.1.0 Use array_unshift($multipoint, $point); instead - * @see array_unshift - * @see ArrayAccess - */ - public function prependPoint(Point $point) - { - array_unshift($this->items, $point); - } - - /** - * @param \Grimzy\LaravelMysqlSpatial\Types\Point $point - * - * @deprecated 2.1.0 Use $multipoint[] = $point; instead - * @see ArrayAccess - */ - public function appendPoint(Point $point) - { - $this->items[] = $point; - } - - /** - * @param $index - * @param \Grimzy\LaravelMysqlSpatial\Types\Point $point - * - * @deprecated 2.1.0 Use array_splice($multipoint, $index, 0, [$point]); instead - * @see array_splice - * @see ArrayAccess - */ - public function insertPoint($index, Point $point) - { - if (count($this->items) - 1 < $index) { - throw new InvalidArgumentException('$index is greater than the size of the array'); - } - - array_splice($this->items, $index, 0, [$point]); - } } diff --git a/src/Types/Polygon.php b/src/Types/Polygon.php index 9c10cecc..e880b0d9 100644 --- a/src/Types/Polygon.php +++ b/src/Types/Polygon.php @@ -1,26 +1,29 @@ + */ +class Polygon extends MultiLineString implements GeometryInterface { - public function toWKT() + public function toWKT(): string { return sprintf('POLYGON(%s)', (string) $this); } - public static function fromJson($geoJson) + public static function fromJson(string|GeoJson $geoJson): self { if (is_string($geoJson)) { - $geoJson = GeoJson::jsonUnserialize(json_decode($geoJson)); + $geoJson = GeoJson::jsonUnserialize(json_decode($geoJson, flags: JSON_THROW_ON_ERROR)); } - if (!is_a($geoJson, GeoJsonPolygon::class)) { - throw new InvalidGeoJsonException('Expected '.GeoJsonPolygon::class.', got '.get_class($geoJson)); + if (! $geoJson instanceof GeoJsonPolygon) { + throw new InvalidGeoJsonException(GeoJsonPolygon::class, $geoJson::class); } $set = []; @@ -37,9 +40,8 @@ public static function fromJson($geoJson) /** * Convert to GeoJson Polygon that is jsonable to GeoJSON. - * - * @return \GeoJson\Geometry\Polygon */ + #[\ReturnTypeWillChange] public function jsonSerialize() { $linearRings = []; diff --git a/tests/Integration/Eloquent/TestModel.php b/tests/Integration/Eloquent/TestModel.php new file mode 100644 index 00000000..3c9a4ad0 --- /dev/null +++ b/tests/Integration/Eloquent/TestModel.php @@ -0,0 +1,26 @@ +hasMany(TestRelatedModel::class); + } + + public function testrelatedmodels2() + { + return $this->belongsToMany(TestRelatedModel::class); + } +} diff --git a/tests/Integration/Eloquent/TestRelatedModel.php b/tests/Integration/Eloquent/TestRelatedModel.php new file mode 100644 index 00000000..72a99851 --- /dev/null +++ b/tests/Integration/Eloquent/TestRelatedModel.php @@ -0,0 +1,16 @@ +belongsTo(TestModel::class); + } + + public function testmodels() + { + return $this->belongsToMany(TestModel::class); + } +} diff --git a/tests/Integration/IntegrationBaseTestCase.php b/tests/Integration/IntegrationBaseCase.php similarity index 75% rename from tests/Integration/IntegrationBaseTestCase.php rename to tests/Integration/IntegrationBaseCase.php index 04634734..287166df 100644 --- a/tests/Integration/IntegrationBaseTestCase.php +++ b/tests/Integration/IntegrationBaseCase.php @@ -1,20 +1,23 @@ register(SpatialServiceProvider::class); @@ -41,29 +44,27 @@ public function createApplication() /** * Setup DB before each test. - * - * @return void */ - public function setUp() + public function setUp(): void { parent::setUp(); $this->after_fix = $this->isMySQL8AfterFix(); - $this->onMigrations(function ($migrationClass) { - (new $migrationClass())->up(); - }); + $this->artisan('migrate:fresh'); + + (new CreateTables)->up(); + (new UpdateTables)->up(); //\DB::listen(function($sql) { // var_dump($sql); //}); } - public function tearDown() + public function tearDown(): void { - $this->onMigrations(function ($migrationClass) { - (new $migrationClass())->down(); - }, true); + (new UpdateTables)->down(); + (new CreateTables)->down(); parent::tearDown(); } @@ -71,7 +72,7 @@ public function tearDown() // MySQL 8.0.4 fixed bug #26941370 and bug #88031 private function isMySQL8AfterFix() { - $results = DB::select(DB::raw('select version()')); + $results = DB::select(DB::raw('select version()')->getValue(DB::connection()->getQueryGrammar())); $mysql_version = $results[0]->{'version()'}; return version_compare($mysql_version, '8.0.4', '>='); @@ -90,7 +91,7 @@ protected function assertException($exceptionName, $exceptionMessage = null) { if (method_exists(parent::class, 'expectException')) { parent::expectException($exceptionName); - if (!is_null($exceptionMessage)) { + if (! is_null($exceptionMessage)) { $this->expectExceptionMessage($exceptionMessage); } } else { @@ -98,7 +99,7 @@ protected function assertException($exceptionName, $exceptionMessage = null) } } - private function onMigrations(\Closure $closure, $reverse_sort = false) + private function onMigrations(Closure $closure, $reverse_sort = false) { $migrations = $this->migrations; $reverse_sort ? rsort($migrations, SORT_STRING) : sort($migrations, SORT_STRING); diff --git a/tests/Integration/MigrationTest.php b/tests/Integration/MigrationTest.php index 6b740d0f..627f7297 100644 --- a/tests/Integration/MigrationTest.php +++ b/tests/Integration/MigrationTest.php @@ -1,12 +1,16 @@ charset = 'utf8mb4'; + $table->collation = 'utf8mb4_unicode_ci'; + $table->increments('id'); + $table->geometryCollection('geometrycollection')->default(null)->nullable(); + $table->lineString('linestring')->default(null)->nullable(); + $table->multiLineString('multilinestring')->default(null)->nullable(); + $table->multiPoint('multipoint')->default(null)->nullable(); + $table->multiPolygon('multipolygon')->default(null)->nullable(); + $table->point('point')->default(null)->nullable(); + $table->polygon('polygon')->default(null)->nullable(); + $table->timestamps(); + }); + Schema::create('geometry', function (Blueprint $table) { $table->charset = 'utf8mb4'; $table->collation = 'utf8mb4_unicode_ci'; @@ -50,13 +64,12 @@ public function up() /** * Reverse the migrations. - * - * @return void */ - public function down() + public function down(): void { Schema::drop('geometry'); Schema::drop('no_spatial_fields'); Schema::drop('with_srid'); + Schema::drop('test_models'); } } diff --git a/tests/Integration/Migrations/UpdateTables.php b/tests/Integration/Migrations/UpdateTables.php index 83915b81..f306747c 100644 --- a/tests/Integration/Migrations/UpdateTables.php +++ b/tests/Integration/Migrations/UpdateTables.php @@ -1,17 +1,17 @@ dropSpatialIndex(['location']); // either an array of column names or the index name diff --git a/tests/Integration/Models/GeometryModel.php b/tests/Integration/Models/GeometryModel.php index 854be5f1..5b8913ae 100644 --- a/tests/Integration/Models/GeometryModel.php +++ b/tests/Integration/Models/GeometryModel.php @@ -1,15 +1,15 @@ geometry = new Point(1, 2); $geo->save(); - $this->assertException(\Grimzy\LaravelMysqlSpatial\Exceptions\SpatialFieldsNotDefinedException::class); + $this->assertException(\Limenet\LaravelMysqlSpatial\Exceptions\SpatialFieldsNotDefinedException::class); NoSpatialFieldsModel::all(); } @@ -212,7 +216,7 @@ public function testDistanceValue() $a = GeometryModel::distanceValue('location', $loc1->location)->get(); $this->assertCount(2, $a); $this->assertEquals(0, $a[0]->distance); - $this->assertEquals(1.4142135623, $a[1]->distance); // PHP floats' 11th+ digits don't matter + $this->assertEqualsWithDelta(1.4142135623, $a[1]->distance, 0.00000001); // PHP floats' 11th+ digits don't matter } public function testDistanceSphereValue() @@ -230,9 +234,9 @@ public function testDistanceSphereValue() $this->assertEquals(0, $a[0]->distance); if ($this->after_fix) { - $this->assertEquals(44.7414064842, $a[1]->distance); // PHP floats' 11th+ digits don't matter + $this->assertEqualsWithDelta(44.7414064842, $a[1]->distance, 0.00000001); // PHP floats' 11th+ digits don't matter } else { - $this->assertEquals(44.7414064845, $a[1]->distance); // PHP floats' 11th+ digits don't matter + $this->assertEqualsWithDelta(44.7414064845, $a[1]->distance, 0.00000001); // PHP floats' 11th+ digits don't matter } } @@ -241,7 +245,7 @@ public function testOrderBySpatialWithUnknownFunction() $loc = new GeometryModel(); $loc->location = new Point(1, 1); - $this->assertException(\Grimzy\LaravelMysqlSpatial\Exceptions\UnknownSpatialFunctionException::class); + $this->assertException(\Limenet\LaravelMysqlSpatial\Exceptions\UnknownSpatialFunctionException::class); GeometryModel::orderBySpatial('location', $loc->location, 'does-not-exist')->get(); } @@ -315,9 +319,9 @@ public function testOrderByDistanceSphere() //public function testBounding() { // $point = new Point(0, 0); // - // $linestring1 = \Grimzy\LaravelMysqlSpatial\Types\LineString::fromWkt("LINESTRING(1 1, 2 2)"); - // $linestring2 = \Grimzy\LaravelMysqlSpatial\Types\LineString::fromWkt("LINESTRING(20 20, 24 24)"); - // $linestring3 = \Grimzy\LaravelMysqlSpatial\Types\LineString::fromWkt("LINESTRING(0 10, 10 10)"); + // $linestring1 = \Limenet\LaravelMysqlSpatial\Types\LineString::fromWkt("LINESTRING(1 1, 2 2)"); + // $linestring2 = \Limenet\LaravelMysqlSpatial\Types\LineString::fromWkt("LINESTRING(20 20, 24 24)"); + // $linestring3 = \Limenet\LaravelMysqlSpatial\Types\LineString::fromWkt("LINESTRING(0 10, 10 10)"); // // $geo1 = new GeometryModel(); // $geo1->location = $point; diff --git a/tests/Unit/Eloquent/SpatialTraitTest.php b/tests/Integration/SpatialTraitTest.php similarity index 58% rename from tests/Unit/Eloquent/SpatialTraitTest.php rename to tests/Integration/SpatialTraitTest.php index 8ece7d25..c988dbfc 100644 --- a/tests/Unit/Eloquent/SpatialTraitTest.php +++ b/tests/Integration/SpatialTraitTest.php @@ -1,35 +1,37 @@ model = new TestModel(); - $this->queries = &$this->model->getConnection()->getPdo()->queries; + DB::listen(function (QueryExecuted $query) { + $this->queries[] = $query->sql; + }); } - public function tearDown() + public function tearDown(): void { - $this->model->getConnection()->getPdo()->resetQueries(); + $this->queries = []; } public function testInsertUpdatePointHasCorrectSql() @@ -40,7 +42,7 @@ public function testInsertUpdatePointHasCorrectSql() $this->model->save(); $this->assertStringStartsWith('insert', $this->queries[0]); - $this->assertContains('insert into `test_models` (`point`) values (ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $this->queries[0]); + $this->assertStringContainsString('insert into `test_models` (`point`) values (ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $this->queries[0]); // TODO: assert bindings in query $this->assertTrue($this->model->exists); @@ -48,7 +50,7 @@ public function testInsertUpdatePointHasCorrectSql() $this->model->save(); $this->assertStringStartsWith('update', $this->queries[1]); - $this->assertContains('update `test_models` set `point` = ST_GeomFromText(?, ?, \'axis-order=long-lat\') where `id` = ?', $this->queries[1]); + $this->assertStringContainsString('update `test_models` set `point` = ST_GeomFromText(?, ?, \'axis-order=long-lat\') where `id` = ?', $this->queries[1]); // TODO: assert bindings in query } @@ -59,19 +61,19 @@ public function testInsertUpdateLineStringHasCorrectSql() $this->assertFalse($this->model->exists); - $this->model->linestring = new \Grimzy\LaravelMysqlSpatial\Types\LineString([$point1, $point2]); + $this->model->linestring = new \Limenet\LaravelMysqlSpatial\Types\LineString([$point1, $point2]); $this->model->save(); $this->assertStringStartsWith('insert', $this->queries[0]); - $this->assertContains('insert into `test_models` (`linestring`) values (ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $this->queries[0]); + $this->assertStringContainsString('insert into `test_models` (`linestring`) values (ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $this->queries[0]); // TODO: assert bindings in query $this->assertTrue($this->model->exists); - $this->model->linestring = new \Grimzy\LaravelMysqlSpatial\Types\LineString([$point1, $point2]); + $this->model->linestring = new \Limenet\LaravelMysqlSpatial\Types\LineString([$point1, $point2]); $this->model->save(); $this->assertStringStartsWith('update', $this->queries[1]); - $this->assertContains('update `test_models` set `linestring` = ST_GeomFromText(?, ?, \'axis-order=long-lat\') where `id` = ?', $this->queries[1]); + $this->assertStringContainsString('update `test_models` set `linestring` = ST_GeomFromText(?, ?, \'axis-order=long-lat\') where `id` = ?', $this->queries[1]); // TODO: assert bindings in query } @@ -79,25 +81,32 @@ public function testInsertUpdatePolygonHasCorrectSql() { $point1 = new Point(1, 2); $point2 = new Point(2, 3); - $linestring1 = new \Grimzy\LaravelMysqlSpatial\Types\LineString([$point1, $point2]); $point3 = new Point(3, 2); $point4 = new Point(2, 1); - $linestring2 = new \Grimzy\LaravelMysqlSpatial\Types\LineString([$point3, $point4]); + + $polygon = new \Limenet\LaravelMysqlSpatial\Types\Polygon([ + new \Limenet\LaravelMysqlSpatial\Types\LineString([$point1, $point2, $point3, $point4, $point1]), + ]); $this->assertFalse($this->model->exists); - $this->model->polygon = new \Grimzy\LaravelMysqlSpatial\Types\Polygon([$linestring1, $linestring2]); + $this->model->polygon = $polygon; $this->model->save(); $this->assertStringStartsWith('insert', $this->queries[0]); - $this->assertContains('insert into `test_models` (`polygon`) values (ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $this->queries[0]); + $this->assertStringContainsString('insert into `test_models` (`polygon`) values (ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $this->queries[0]); // TODO: assert bindings in query $this->assertTrue($this->model->exists); - $this->model->polygon = new \Grimzy\LaravelMysqlSpatial\Types\Polygon([$linestring1, $linestring2]); + $polygon = new \Limenet\LaravelMysqlSpatial\Types\Polygon([ + new \Limenet\LaravelMysqlSpatial\Types\LineString([$point1, $point2, $point3, $point4, $point1]), + ]); + + $this->model->polygon = $polygon; $this->model->save(); + $this->assertStringStartsWith('update', $this->queries[1]); - $this->assertContains('update `test_models` set `polygon` = ST_GeomFromText(?, ?, \'axis-order=long-lat\') where `id` = ?', $this->queries[1]); + $this->assertStringContainsString('update `test_models` set `polygon` = ST_GeomFromText(?, ?, \'axis-order=long-lat\') where `id` = ?', $this->queries[1]); // TODO: assert bindings in query } @@ -108,19 +117,19 @@ public function testInsertUpdateMultiPointHasCorrectSql() $this->assertFalse($this->model->exists); - $this->model->multipoint = new \Grimzy\LaravelMysqlSpatial\Types\MultiPoint([$point1, $point2]); + $this->model->multipoint = new \Limenet\LaravelMysqlSpatial\Types\MultiPoint([$point1, $point2]); $this->model->save(); $this->assertStringStartsWith('insert', $this->queries[0]); - $this->assertContains('insert into `test_models` (`multipoint`) values (ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $this->queries[0]); + $this->assertStringContainsString('insert into `test_models` (`multipoint`) values (ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $this->queries[0]); // TODO: assert bindings in query $this->assertTrue($this->model->exists); - $this->model->multipoint = new \Grimzy\LaravelMysqlSpatial\Types\MultiPoint([$point1, $point2]); + $this->model->multipoint = new \Limenet\LaravelMysqlSpatial\Types\MultiPoint([$point1, $point2]); $this->model->save(); $this->assertStringStartsWith('update', $this->queries[1]); - $this->assertContains('update `test_models` set `multipoint` = ST_GeomFromText(?, ?, \'axis-order=long-lat\') where `id` = ?', $this->queries[1]); + $this->assertStringContainsString('update `test_models` set `multipoint` = ST_GeomFromText(?, ?, \'axis-order=long-lat\') where `id` = ?', $this->queries[1]); // TODO: assert bindings in query } @@ -128,25 +137,25 @@ public function testInsertUpdateMultiLineStringHasCorrectSql() { $point1 = new Point(1, 2); $point2 = new Point(2, 3); - $linestring1 = new \Grimzy\LaravelMysqlSpatial\Types\LineString([$point1, $point2]); + $linestring1 = new \Limenet\LaravelMysqlSpatial\Types\LineString([$point1, $point2]); $point3 = new Point(3, 2); $point4 = new Point(2, 1); - $linestring2 = new \Grimzy\LaravelMysqlSpatial\Types\LineString([$point3, $point4]); + $linestring2 = new \Limenet\LaravelMysqlSpatial\Types\LineString([$point3, $point4]); $this->assertFalse($this->model->exists); - $this->model->multilinestring = new \Grimzy\LaravelMysqlSpatial\Types\MultiLineString([$linestring1, $linestring2]); + $this->model->multilinestring = new \Limenet\LaravelMysqlSpatial\Types\MultiLineString([$linestring1, $linestring2]); $this->model->save(); $this->assertStringStartsWith('insert', $this->queries[0]); - $this->assertContains('insert into `test_models` (`multilinestring`) values (ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $this->queries[0]); + $this->assertStringContainsString('insert into `test_models` (`multilinestring`) values (ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $this->queries[0]); // TODO: assert bindings in query $this->assertTrue($this->model->exists); - $this->model->multilinestring = new \Grimzy\LaravelMysqlSpatial\Types\MultiLineString([$linestring1, $linestring2]); + $this->model->multilinestring = new \Limenet\LaravelMysqlSpatial\Types\MultiLineString([$linestring1, $linestring2]); $this->model->save(); $this->assertStringStartsWith('update', $this->queries[1]); - $this->assertContains('update `test_models` set `multilinestring` = ST_GeomFromText(?, ?, \'axis-order=long-lat\') where `id` = ?', $this->queries[1]); + $this->assertStringContainsString('update `test_models` set `multilinestring` = ST_GeomFromText(?, ?, \'axis-order=long-lat\') where `id` = ?', $this->queries[1]); // TODO: assert bindings in query } @@ -154,34 +163,34 @@ public function testInsertUpdateMultiPolygonHasCorrectSql() { $point1 = new Point(1, 2); $point2 = new Point(2, 3); - $linestring1 = new \Grimzy\LaravelMysqlSpatial\Types\LineString([$point1, $point2]); $point3 = new Point(3, 2); $point4 = new Point(2, 1); - $linestring2 = new \Grimzy\LaravelMysqlSpatial\Types\LineString([$point3, $point4]); - $polygon1 = new \Grimzy\LaravelMysqlSpatial\Types\Polygon([$linestring1, $linestring2]); + $polygon1 = new \Limenet\LaravelMysqlSpatial\Types\Polygon([ + new \Limenet\LaravelMysqlSpatial\Types\LineString([$point1, $point2, $point3, $point1]), + ]); $point5 = new Point(4, 5); $point6 = new Point(5, 6); - $linestring3 = new \Grimzy\LaravelMysqlSpatial\Types\LineString([$point5, $point6]); $point7 = new Point(6, 5); $point8 = new Point(5, 4); - $linestring4 = new \Grimzy\LaravelMysqlSpatial\Types\LineString([$point7, $point8]); - $polygon2 = new \Grimzy\LaravelMysqlSpatial\Types\Polygon([$linestring3, $linestring4]); + $polygon2 = new \Limenet\LaravelMysqlSpatial\Types\Polygon([ + new \Limenet\LaravelMysqlSpatial\Types\LineString([$point5, $point6, $point7, $point5]), + ]); $this->assertFalse($this->model->exists); - $this->model->multipolygon = new \Grimzy\LaravelMysqlSpatial\Types\MultiPolygon([$polygon1, $polygon2]); + $this->model->multipolygon = new \Limenet\LaravelMysqlSpatial\Types\MultiPolygon([$polygon1, $polygon2]); $this->model->save(); $this->assertStringStartsWith('insert', $this->queries[0]); - $this->assertContains('insert into `test_models` (`multipolygon`) values (ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $this->queries[0]); + $this->assertStringContainsString('insert into `test_models` (`multipolygon`) values (ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $this->queries[0]); // TODO: assert bindings in query $this->assertTrue($this->model->exists); - $this->model->multipolygon = new \Grimzy\LaravelMysqlSpatial\Types\MultiPolygon([$polygon1, $polygon2]); + $this->model->multipolygon = new \Limenet\LaravelMysqlSpatial\Types\MultiPolygon([$polygon1, $polygon2]); $this->model->save(); $this->assertStringStartsWith('update', $this->queries[1]); - $this->assertContains('update `test_models` set `multipolygon` = ST_GeomFromText(?, ?, \'axis-order=long-lat\') where `id` = ?', $this->queries[1]); + $this->assertStringContainsString('update `test_models` set `multipolygon` = ST_GeomFromText(?, ?, \'axis-order=long-lat\') where `id` = ?', $this->queries[1]); // TODO: assert bindings in query } @@ -190,22 +199,22 @@ public function testInsertUpdateGeometryCollectionHasCorrectSql() $point1 = new Point(1, 2); $point2 = new Point(2, 3); $point3 = new Point(3, 3); - $linestring1 = new \Grimzy\LaravelMysqlSpatial\Types\LineString([$point2, $point3]); + $linestring1 = new \Limenet\LaravelMysqlSpatial\Types\LineString([$point2, $point3]); $this->assertFalse($this->model->exists); - $this->model->geometrycollection = new \Grimzy\LaravelMysqlSpatial\Types\GeometryCollection([$point1, $linestring1]); + $this->model->geometrycollection = new \Limenet\LaravelMysqlSpatial\Types\GeometryCollection([$point1, $linestring1]); $this->model->save(); $this->assertStringStartsWith('insert', $this->queries[0]); - $this->assertContains('insert into `test_models` (`geometrycollection`) values (ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $this->queries[0]); + $this->assertStringContainsString('insert into `test_models` (`geometrycollection`) values (ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $this->queries[0]); // TODO: assert bindings in query $this->assertTrue($this->model->exists); - $this->model->geometrycollection = new \Grimzy\LaravelMysqlSpatial\Types\GeometryCollection([$point1, $linestring1]); + $this->model->geometrycollection = new \Limenet\LaravelMysqlSpatial\Types\GeometryCollection([$point1, $linestring1]); $this->model->save(); $this->assertStringStartsWith('update', $this->queries[1]); - $this->assertContains('update `test_models` set `geometrycollection` = ST_GeomFromText(?, ?, \'axis-order=long-lat\') where `id` = ?', $this->queries[1]); + $this->assertStringContainsString('update `test_models` set `geometrycollection` = ST_GeomFromText(?, ?, \'axis-order=long-lat\') where `id` = ?', $this->queries[1]); // TODO: assert bindings in query } @@ -219,10 +228,17 @@ public function testSettingRawAttributes() public function testSpatialFieldsNotDefinedException() { - $model = new TestNoSpatialModel(); + $model = new class extends Model + { + use SpatialTrait; + }; $this->assertException( SpatialFieldsNotDefinedException::class, - 'TestNoSpatialModel has to define $spatialFields' + 'TestNoSpatialModel' + ); + $this->assertException( + SpatialFieldsNotDefinedException::class, + ' has to define $spatialFields' ); $model->getSpatialFields(); } @@ -232,7 +248,7 @@ public function testScopeDistance() $point = new Point(1, 2); $query = TestModel::distance('point', $point, 10); - $this->assertInstanceOf(\Grimzy\LaravelMysqlSpatial\Eloquent\Builder::class, $query); + $this->assertInstanceOf(\Limenet\LaravelMysqlSpatial\Eloquent\Builder::class, $query); $q = $query->getQuery(); $this->assertNotEmpty($q->wheres); $bindings = $q->getRawBindings()['where']; @@ -247,7 +263,7 @@ public function testScopeDistanceExcludingSelf() $point = new Point(1, 2); $query = TestModel::distanceExcludingSelf('point', $point, 10); - $this->assertInstanceOf(\Grimzy\LaravelMysqlSpatial\Eloquent\Builder::class, $query); + $this->assertInstanceOf(\Limenet\LaravelMysqlSpatial\Eloquent\Builder::class, $query); $q = $query->getQuery(); $this->assertNotEmpty($q->wheres); $bindings = $q->getRawBindings()['where']; @@ -264,7 +280,7 @@ public function testScopeDistanceSphere() $point = new Point(1, 2); $query = TestModel::distanceSphere('point', $point, 10); - $this->assertInstanceOf(\Grimzy\LaravelMysqlSpatial\Eloquent\Builder::class, $query); + $this->assertInstanceOf(\Limenet\LaravelMysqlSpatial\Eloquent\Builder::class, $query); $q = $query->getQuery(); $this->assertNotEmpty($q->wheres); $bindings = $q->getRawBindings()['where']; @@ -279,7 +295,7 @@ public function testScopeDistanceSphereExcludingSelf() $point = new Point(1, 2); $query = TestModel::distanceSphereExcludingSelf('point', $point, 10); - $this->assertInstanceOf(\Grimzy\LaravelMysqlSpatial\Eloquent\Builder::class, $query); + $this->assertInstanceOf(\Limenet\LaravelMysqlSpatial\Eloquent\Builder::class, $query); $q = $query->getQuery(); $this->assertNotEmpty($q->wheres); $bindings = $q->getRawBindings()['where']; @@ -296,14 +312,14 @@ public function testScopeDistanceValue() $point = new Point(1, 2); $query = TestModel::distanceValue('point', $point); - $this->assertInstanceOf(\Grimzy\LaravelMysqlSpatial\Eloquent\Builder::class, $query); + $this->assertInstanceOf(\Limenet\LaravelMysqlSpatial\Eloquent\Builder::class, $query); $q = $query->getQuery(); $this->assertNotEmpty($q->columns); $bindings = $q->getRawBindings()['select']; $this->assertNotEmpty($bindings); $this->assertEquals('*', $q->columns[0]); $this->assertInstanceOf(\Illuminate\Database\Query\Expression::class, $q->columns[1]); - $this->assertEquals('st_distance(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\')) as distance', $q->columns[1]->getValue()); + $this->assertEquals('st_distance(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\')) as distance', $q->columns[1]->getValue(DB::connection()->getQueryGrammar())); $this->assertEquals('POINT(2 1)', $bindings[0]); } @@ -312,14 +328,14 @@ public function testScopeDistanceValueWithSelect() $point = new Point(1, 2); $query = TestModel::select('some_column')->distanceValue('point', $point); - $this->assertInstanceOf(\Grimzy\LaravelMysqlSpatial\Eloquent\Builder::class, $query); + $this->assertInstanceOf(\Limenet\LaravelMysqlSpatial\Eloquent\Builder::class, $query); $q = $query->getQuery(); $this->assertNotEmpty($q->columns); $bindings = $q->getRawBindings()['select']; $this->assertNotEmpty($bindings); $this->assertEquals('some_column', $q->columns[0]); $this->assertInstanceOf(\Illuminate\Database\Query\Expression::class, $q->columns[1]); - $this->assertEquals('st_distance(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\')) as distance', $q->columns[1]->getValue()); + $this->assertEquals('st_distance(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\')) as distance', $q->columns[1]->getValue(DB::connection()->getQueryGrammar())); $this->assertEquals('POINT(2 1)', $bindings[0]); } @@ -328,14 +344,14 @@ public function testScopeDistanceSphereValue() $point = new Point(1, 2); $query = TestModel::distanceSphereValue('point', $point); - $this->assertInstanceOf(\Grimzy\LaravelMysqlSpatial\Eloquent\Builder::class, $query); + $this->assertInstanceOf(\Limenet\LaravelMysqlSpatial\Eloquent\Builder::class, $query); $q = $query->getQuery(); $this->assertNotEmpty($q->columns); $bindings = $q->getRawBindings()['select']; $this->assertNotEmpty($bindings); $this->assertEquals('*', $q->columns[0]); $this->assertInstanceOf(\Illuminate\Database\Query\Expression::class, $q->columns[1]); - $this->assertEquals('st_distance_sphere(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\')) as distance', $q->columns[1]->getValue()); + $this->assertEquals('st_distance_sphere(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\')) as distance', $q->columns[1]->getValue(DB::connection()->getQueryGrammar())); $this->assertEquals('POINT(2 1)', $bindings[0]); } @@ -344,14 +360,14 @@ public function testScopeDistanceSphereValueWithSelect() $point = new Point(1, 2); $query = TestModel::select('some_column')->distanceSphereValue('point', $point); - $this->assertInstanceOf(\Grimzy\LaravelMysqlSpatial\Eloquent\Builder::class, $query); + $this->assertInstanceOf(\Limenet\LaravelMysqlSpatial\Eloquent\Builder::class, $query); $q = $query->getQuery(); $this->assertNotEmpty($q->columns); $bindings = $q->getRawBindings()['select']; $this->assertNotEmpty($bindings); $this->assertEquals('some_column', $q->columns[0]); $this->assertInstanceOf(\Illuminate\Database\Query\Expression::class, $q->columns[1]); - $this->assertEquals('st_distance_sphere(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\')) as distance', $q->columns[1]->getValue()); + $this->assertEquals('st_distance_sphere(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\')) as distance', $q->columns[1]->getValue(DB::connection()->getQueryGrammar())); $this->assertEquals('POINT(2 1)', $bindings[0]); } @@ -359,27 +375,27 @@ private function buildTestPolygon() { $point1 = new Point(1, 1); $point2 = new Point(1, 2); - $linestring1 = new \Grimzy\LaravelMysqlSpatial\Types\LineString([$point1, $point2]); + $linestring1 = new \Limenet\LaravelMysqlSpatial\Types\LineString([$point1, $point2]); $point3 = new Point(1, 2); $point4 = new Point(2, 2); - $linestring2 = new \Grimzy\LaravelMysqlSpatial\Types\LineString([$point3, $point4]); + $linestring2 = new \Limenet\LaravelMysqlSpatial\Types\LineString([$point3, $point4]); $point5 = new Point(2, 2); $point6 = new Point(1, 1); - $linestring3 = new \Grimzy\LaravelMysqlSpatial\Types\LineString([$point5, $point6]); + $linestring3 = new \Limenet\LaravelMysqlSpatial\Types\LineString([$point5, $point6]); - return new \Grimzy\LaravelMysqlSpatial\Types\Polygon([$linestring1, $linestring2, $linestring3]); + return new \Limenet\LaravelMysqlSpatial\Types\Polygon([$linestring1, $linestring2, $linestring3]); } public function testScopeComparison() { $query = TestModel::comparison('point', $this->buildTestPolygon(), 'within'); - $this->assertInstanceOf(\Grimzy\LaravelMysqlSpatial\Eloquent\Builder::class, $query); + $this->assertInstanceOf(\Limenet\LaravelMysqlSpatial\Eloquent\Builder::class, $query); $q = $query->getQuery(); $this->assertNotEmpty($q->wheres); $bindings = $q->getRawBindings()['where']; $this->assertNotEmpty($bindings); - $this->assertContains('st_within(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $q->wheres[0]['sql']); + $this->assertStringContainsString('st_within(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $q->wheres[0]['sql']); $this->assertEquals('POLYGON((1 1,2 1),(2 1,2 2),(2 2,1 1))', $bindings[0]); } @@ -387,12 +403,12 @@ public function testScopeWithin() { $query = TestModel::within('point', $this->buildTestPolygon()); - $this->assertInstanceOf(\Grimzy\LaravelMysqlSpatial\Eloquent\Builder::class, $query); + $this->assertInstanceOf(\Limenet\LaravelMysqlSpatial\Eloquent\Builder::class, $query); $q = $query->getQuery(); $this->assertNotEmpty($q->wheres); $bindings = $q->getRawBindings()['where']; $this->assertNotEmpty($bindings); - $this->assertContains('st_within(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $q->wheres[0]['sql']); + $this->assertStringContainsString('st_within(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $q->wheres[0]['sql']); $this->assertEquals('POLYGON((1 1,2 1),(2 1,2 2),(2 2,1 1))', $bindings[0]); } @@ -400,12 +416,12 @@ public function testScopeCrosses() { $query = TestModel::crosses('point', $this->buildTestPolygon()); - $this->assertInstanceOf(\Grimzy\LaravelMysqlSpatial\Eloquent\Builder::class, $query); + $this->assertInstanceOf(\Limenet\LaravelMysqlSpatial\Eloquent\Builder::class, $query); $q = $query->getQuery(); $this->assertNotEmpty($q->wheres); $bindings = $q->getRawBindings()['where']; $this->assertNotEmpty($bindings); - $this->assertContains('st_crosses(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $q->wheres[0]['sql']); + $this->assertStringContainsString('st_crosses(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $q->wheres[0]['sql']); $this->assertEquals('POLYGON((1 1,2 1),(2 1,2 2),(2 2,1 1))', $bindings[0]); } @@ -413,12 +429,12 @@ public function testScopeContains() { $query = TestModel::contains('point', $this->buildTestPolygon()); - $this->assertInstanceOf(\Grimzy\LaravelMysqlSpatial\Eloquent\Builder::class, $query); + $this->assertInstanceOf(\Limenet\LaravelMysqlSpatial\Eloquent\Builder::class, $query); $q = $query->getQuery(); $this->assertNotEmpty($q->wheres); $bindings = $q->getRawBindings()['where']; $this->assertNotEmpty($bindings); - $this->assertContains('st_contains(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $q->wheres[0]['sql']); + $this->assertStringContainsString('st_contains(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $q->wheres[0]['sql']); $this->assertEquals('POLYGON((1 1,2 1),(2 1,2 2),(2 2,1 1))', $bindings[0]); } @@ -426,12 +442,12 @@ public function testScopeDisjoint() { $query = TestModel::disjoint('point', $this->buildTestPolygon()); - $this->assertInstanceOf(\Grimzy\LaravelMysqlSpatial\Eloquent\Builder::class, $query); + $this->assertInstanceOf(\Limenet\LaravelMysqlSpatial\Eloquent\Builder::class, $query); $q = $query->getQuery(); $this->assertNotEmpty($q->wheres); $bindings = $q->getRawBindings()['where']; $this->assertNotEmpty($bindings); - $this->assertContains('st_disjoint(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $q->wheres[0]['sql']); + $this->assertStringContainsString('st_disjoint(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $q->wheres[0]['sql']); $this->assertEquals('POLYGON((1 1,2 1),(2 1,2 2),(2 2,1 1))', $bindings[0]); } @@ -439,12 +455,12 @@ public function testScopeEquals() { $query = TestModel::equals('point', $this->buildTestPolygon()); - $this->assertInstanceOf(\Grimzy\LaravelMysqlSpatial\Eloquent\Builder::class, $query); + $this->assertInstanceOf(\Limenet\LaravelMysqlSpatial\Eloquent\Builder::class, $query); $q = $query->getQuery(); $this->assertNotEmpty($q->wheres); $bindings = $q->getRawBindings()['where']; $this->assertNotEmpty($bindings); - $this->assertContains('st_equals(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $q->wheres[0]['sql']); + $this->assertStringContainsString('st_equals(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $q->wheres[0]['sql']); $this->assertEquals('POLYGON((1 1,2 1),(2 1,2 2),(2 2,1 1))', $bindings[0]); } @@ -452,12 +468,12 @@ public function testScopeIntersects() { $query = TestModel::intersects('point', $this->buildTestPolygon()); - $this->assertInstanceOf(\Grimzy\LaravelMysqlSpatial\Eloquent\Builder::class, $query); + $this->assertInstanceOf(\Limenet\LaravelMysqlSpatial\Eloquent\Builder::class, $query); $q = $query->getQuery(); $this->assertNotEmpty($q->wheres); $bindings = $q->getRawBindings()['where']; $this->assertNotEmpty($bindings); - $this->assertContains('st_intersects(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $q->wheres[0]['sql']); + $this->assertStringContainsString('st_intersects(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $q->wheres[0]['sql']); $this->assertEquals('POLYGON((1 1,2 1),(2 1,2 2),(2 2,1 1))', $bindings[0]); } @@ -465,12 +481,12 @@ public function testScopeOverlaps() { $query = TestModel::overlaps('point', $this->buildTestPolygon()); - $this->assertInstanceOf(\Grimzy\LaravelMysqlSpatial\Eloquent\Builder::class, $query); + $this->assertInstanceOf(\Limenet\LaravelMysqlSpatial\Eloquent\Builder::class, $query); $q = $query->getQuery(); $this->assertNotEmpty($q->wheres); $bindings = $q->getRawBindings()['where']; $this->assertNotEmpty($bindings); - $this->assertContains('st_overlaps(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $q->wheres[0]['sql']); + $this->assertStringContainsString('st_overlaps(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $q->wheres[0]['sql']); $this->assertEquals('POLYGON((1 1,2 1),(2 1,2 2),(2 2,1 1))', $bindings[0]); } @@ -478,12 +494,12 @@ public function testScopeDoesTouch() { $query = TestModel::doesTouch('point', $this->buildTestPolygon()); - $this->assertInstanceOf(\Grimzy\LaravelMysqlSpatial\Eloquent\Builder::class, $query); + $this->assertInstanceOf(\Limenet\LaravelMysqlSpatial\Eloquent\Builder::class, $query); $q = $query->getQuery(); $this->assertNotEmpty($q->wheres); $bindings = $q->getRawBindings()['where']; $this->assertNotEmpty($bindings); - $this->assertContains('st_touches(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $q->wheres[0]['sql']); + $this->assertStringContainsString('st_touches(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\'))', $q->wheres[0]['sql']); $this->assertEquals('POLYGON((1 1,2 1),(2 1,2 2),(2 2,1 1))', $bindings[0]); } @@ -491,7 +507,7 @@ public function testScopeOrderBySpatialThrowsExceptionWhenFunctionNotRegistered( { $point = new Point(1, 2); $this->assertException( - \Grimzy\LaravelMysqlSpatial\Exceptions\UnknownSpatialFunctionException::class, + \Limenet\LaravelMysqlSpatial\Exceptions\UnknownSpatialFunctionException::class, 'does-not-exist' ); TestModel::orderBySpatial('point', $point, 'does-not-exist'); @@ -502,12 +518,12 @@ public function testScopeOrderByDistance() $point = new Point(1, 2); $query = TestModel::orderByDistance('point', $point); - $this->assertInstanceOf(\Grimzy\LaravelMysqlSpatial\Eloquent\Builder::class, $query); + $this->assertInstanceOf(\Limenet\LaravelMysqlSpatial\Eloquent\Builder::class, $query); $q = $query->getQuery(); $this->assertNotEmpty($q->orders); $bindings = $q->getRawBindings()['order']; $this->assertNotEmpty($bindings); - $this->assertContains('st_distance(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\')) asc', $q->orders[0]['sql']); + $this->assertStringContainsString('st_distance(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\')) asc', $q->orders[0]['sql']); $this->assertEquals('POINT(2 1)', $bindings[0]); } @@ -516,90 +532,12 @@ public function testScopeOrderByDistanceSphere() $point = new Point(1, 2); $query = TestModel::orderByDistanceSphere('point', $point); - $this->assertInstanceOf(\Grimzy\LaravelMysqlSpatial\Eloquent\Builder::class, $query); + $this->assertInstanceOf(\Limenet\LaravelMysqlSpatial\Eloquent\Builder::class, $query); $q = $query->getQuery(); $this->assertNotEmpty($q->orders); $bindings = $q->getRawBindings()['order']; $this->assertNotEmpty($bindings); - $this->assertContains('st_distance_sphere(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\')) asc', $q->orders[0]['sql']); + $this->assertStringContainsString('st_distance_sphere(`point`, ST_GeomFromText(?, ?, \'axis-order=long-lat\')) asc', $q->orders[0]['sql']); $this->assertEquals('POINT(2 1)', $bindings[0]); } } - -class TestModel extends Model -{ - use \Grimzy\LaravelMysqlSpatial\Eloquent\SpatialTrait; - - protected $spatialFields = ['point']; // TODO: only required when fetching, not saving - - public $timestamps = false; - - public static $pdo; - - public static function resolveConnection($connection = null) - { - if (is_null(static::$pdo)) { - static::$pdo = m::mock('TestPDO')->makePartial(); - } - - return new MysqlConnection(static::$pdo); - } - - public function testrelatedmodels() - { - return $this->hasMany(TestRelatedModel::class); - } - - public function testrelatedmodels2() - { - return $this->belongsToMany(TestRelatedModel::class); - } -} - -class TestRelatedModel extends TestModel -{ - public function testmodel() - { - return $this->belongsTo(TestModel::class); - } - - public function testmodels() - { - return $this->belongsToMany(TestModel::class); - } -} - -class TestNoSpatialModel extends Model -{ - use \Grimzy\LaravelMysqlSpatial\Eloquent\SpatialTrait; -} - -class TestPDO extends PDO -{ - public $queries = []; - - public $counter = 1; - - public function prepare($statement, $driver_options = []) - { - $this->queries[] = $statement; - - $stmt = m::mock('PDOStatement'); - $stmt->shouldReceive('bindValue')->zeroOrMoreTimes(); - $stmt->shouldReceive('execute'); - $stmt->shouldReceive('fetchAll')->andReturn([['id' => 1, 'point' => 'POINT(1 2)']]); - $stmt->shouldReceive('rowCount')->andReturn(1); - - return $stmt; - } - - public function lastInsertId($name = null) - { - return $this->counter++; - } - - public function resetQueries() - { - $this->queries = []; - } -} diff --git a/tests/Integration/SridSpatialTest.php b/tests/Integration/SridSpatialTest.php index f57c6cb2..e26b7d82 100644 --- a/tests/Integration/SridSpatialTest.php +++ b/tests/Integration/SridSpatialTest.php @@ -1,17 +1,20 @@ location = new Point(1, 2); $this->assertException( - Illuminate\Database\QueryException::class, - 'SQLSTATE[HY000]: General error: 3643 The SRID of the geometry '. - 'does not match the SRID of the column \'location\'. The SRID '. - 'of the geometry is 0, but the SRID of the column is 3857. '. - 'Consider changing the SRID of the geometry or the SRID property '. - 'of the column. (SQL: insert into `with_srid` (`location`) values '. - '(ST_GeomFromText(POINT(2 1), 0, \'axis-order=long-lat\')))' + \Illuminate\Database\QueryException::class, + "SQLSTATE[HY000]: General error: 3643 The SRID of the geometry does not match the SRID of the column 'location'. The SRID of the geometry is 0, but the SRID of the column is 3857. Consider changing the SRID of the geometry or the SRID property of the column. (Connection: mysql, SQL: insert into `with_srid` (`location`) values (ST_GeomFromText(POINT(2 1), 0, 'axis-order=long-lat')))" ); $geo->save(); } diff --git a/tests/Unit/BaseTestCase.php b/tests/Unit/BaseTestCase.php index 219f737d..b8f0ce8b 100644 --- a/tests/Unit/BaseTestCase.php +++ b/tests/Unit/BaseTestCase.php @@ -1,10 +1,13 @@ createMock(\PDO::class); $factory = Mockery::mock(ConnectionFactory::class, [new Container()])->makePartial(); $factory->shouldAllowMockingProtectedMethods(); @@ -20,7 +23,7 @@ public function testMakeCallsCreateConnection() public function testCreateConnectionDifferentDriver() { - $pdo = new PDOStub(); + $pdo = $this->createMock(\PDO::class); $factory = Mockery::mock(ConnectionFactory::class, [new Container()])->makePartial(); $factory->shouldAllowMockingProtectedMethods(); diff --git a/tests/Unit/Eloquent/BuilderTest.php b/tests/Unit/Eloquent/BuilderTest.php index d9a12a55..5909f8a5 100644 --- a/tests/Unit/Eloquent/BuilderTest.php +++ b/tests/Unit/Eloquent/BuilderTest.php @@ -1,26 +1,27 @@ makePartial(); $grammar = Mockery::mock(MySqlGrammar::class)->makePartial(); @@ -32,7 +33,14 @@ protected function setUp() ->andReturn($this->queryBuilder); $this->builder = new Builder($this->queryBuilder); - $this->builder->setModel(new TestBuilderModel()); + $this->builder->setModel(new class extends Model + { + use SpatialTrait; + + public $timestamps = false; + + protected $spatialFields = ['point', 'linestring', 'polygon']; + }); } public function testUpdatePoint() @@ -129,11 +137,3 @@ public function testUpdatePolygonWithSrid() $this->assertSame(1, $result); } } - -class TestBuilderModel extends Model -{ - use SpatialTrait; - - public $timestamps = false; - protected $spatialFields = ['point', 'linestring', 'polygon']; -} diff --git a/tests/Unit/MysqlConnectionTest.php b/tests/Unit/MysqlConnectionTest.php index cae970a2..a2a3eee0 100644 --- a/tests/Unit/MysqlConnectionTest.php +++ b/tests/Unit/MysqlConnectionTest.php @@ -1,18 +1,19 @@ 'mysql', 'prefix' => 'prefix', 'database' => 'database', 'name' => 'foo']; - $this->mysqlConnection = new MysqlConnection(new PDOStub(), 'database', 'prefix', $mysqlConfig); + $this->mysqlConnection = new MysqlConnection($this->createMock(\PDO::class), 'database', 'prefix', $mysqlConfig); } public function testGetSchemaBuilder() diff --git a/tests/Unit/Schema/BlueprintTest.php b/tests/Unit/Schema/BlueprintTest.php index c22c9518..b47d561e 100644 --- a/tests/Unit/Schema/BlueprintTest.php +++ b/tests/Unit/Schema/BlueprintTest.php @@ -1,20 +1,17 @@ assertEquals($expectedSql, $dropStatements[4]); } - /** - * @return Connection - */ - protected function getConnection() + protected function getConnection($connection = null, $table = null) { return Mockery::mock(MysqlConnection::class); } diff --git a/tests/Unit/Stubs/PDOStub.php b/tests/Unit/Stubs/PDOStub.php deleted file mode 100644 index 99d2d806..00000000 --- a/tests/Unit/Stubs/PDOStub.php +++ /dev/null @@ -1,10 +0,0 @@ -assertException( InvalidArgumentException::class, - 'Grimzy\LaravelMysqlSpatial\Types\GeometryCollection must be a collection of Grimzy\LaravelMysqlSpatial\Types\GeometryInterface' + 'Limenet\LaravelMysqlSpatial\Types\GeometryCollection must be a collection of Limenet\LaravelMysqlSpatial\Types\GeometryInterface' ); $geometrycollection = new GeometryCollection([ $this->getPoint(), @@ -71,7 +75,7 @@ public function testToArray() { $geometryCollection = $this->getGeometryCollection(); - $this->assertInternalType('array', $geometryCollection->toArray()); + $this->assertIsArray($geometryCollection->toArray()); } public function testIteratorAggregate() @@ -112,7 +116,7 @@ public function testArrayAccess() // assert invalid $this->assertException( InvalidArgumentException::class, - 'Grimzy\LaravelMysqlSpatial\Types\GeometryCollection must be a collection of Grimzy\LaravelMysqlSpatial\Types\GeometryInterface' + 'Limenet\LaravelMysqlSpatial\Types\GeometryCollection must be a collection of Limenet\LaravelMysqlSpatial\Types\GeometryInterface' ); $geometryCollection[] = 1; } @@ -130,8 +134,8 @@ public function testFromJson() public function testInvalidGeoJsonException() { $this->assertException( - \Grimzy\LaravelMysqlSpatial\Exceptions\InvalidGeoJsonException::class, - sprintf('Expected %s, got %s', GeoJson\Feature\FeatureCollection::class, GeoJson\Geometry\Point::class) + \Limenet\LaravelMysqlSpatial\Exceptions\InvalidGeoJsonException::class, + sprintf('Expected %s, got %s', \GeoJson\Feature\FeatureCollection::class, \GeoJson\Geometry\Point::class) ); GeometryCollection::fromJson('{"type":"Point","coordinates":[3.4,1.2]}'); } diff --git a/tests/Unit/Types/GeometryTest.php b/tests/Unit/Types/GeometryTest.php index e51022d5..4927d226 100644 --- a/tests/Unit/Types/GeometryTest.php +++ b/tests/Unit/Types/GeometryTest.php @@ -1,14 +1,17 @@ points = [new Point(0, 0), new Point(1, 1), new Point(2, 2)]; } @@ -46,8 +49,8 @@ public function testFromJson() public function testInvalidGeoJsonException() { $this->assertException( - \Grimzy\LaravelMysqlSpatial\Exceptions\InvalidGeoJsonException::class, - sprintf('Expected %s, got %s', \GeoJson\Geometry\LineString::class, GeoJson\Geometry\Point::class) + \Limenet\LaravelMysqlSpatial\Exceptions\InvalidGeoJsonException::class, + sprintf('Expected %s, got %s', \GeoJson\Geometry\LineString::class, \GeoJson\Geometry\Point::class) ); LineString::fromJson('{"type":"Point","coordinates":[3.4,1.2]}'); } diff --git a/tests/Unit/Types/MultiLineStringTest.php b/tests/Unit/Types/MultiLineStringTest.php index 16477feb..fb6e728b 100644 --- a/tests/Unit/Types/MultiLineStringTest.php +++ b/tests/Unit/Types/MultiLineStringTest.php @@ -1,8 +1,12 @@ assertException( - \Grimzy\LaravelMysqlSpatial\Exceptions\InvalidGeoJsonException::class, - sprintf('Expected %s, got %s', GeoJson\Geometry\MultiLineString::class, GeoJson\Geometry\Point::class) + \Limenet\LaravelMysqlSpatial\Exceptions\InvalidGeoJsonException::class, + sprintf('Expected %s, got %s', \GeoJson\Geometry\MultiLineString::class, \GeoJson\Geometry\Point::class) ); MultiLineString::fromJson('{"type":"Point","coordinates":[3.4,1.2]}'); } @@ -64,7 +68,7 @@ public function testInvalidArgumentExceptionAtLeastOneEntry() { $this->assertException( InvalidArgumentException::class, - 'Grimzy\LaravelMysqlSpatial\Types\MultiLineString must contain at least 1 entry' + 'Limenet\LaravelMysqlSpatial\Types\MultiLineString must contain at least 1 entry' ); $multilinestring = new MultiLineString([]); } @@ -73,7 +77,7 @@ public function testInvalidArgumentExceptionNotArrayOfLineString() { $this->assertException( InvalidArgumentException::class, - 'Grimzy\LaravelMysqlSpatial\Types\MultiLineString must be a collection of Grimzy\LaravelMysqlSpatial\Types\LineString' + 'Limenet\LaravelMysqlSpatial\Types\MultiLineString must be a collection of Limenet\LaravelMysqlSpatial\Types\LineString' ); $multilinestring = new MultiLineString([ new LineString([new Point(0, 0), new Point(1, 1)]), @@ -109,7 +113,7 @@ public function testArrayAccess() // assert invalid $this->assertException( InvalidArgumentException::class, - 'Grimzy\LaravelMysqlSpatial\Types\MultiLineString must be a collection of Grimzy\LaravelMysqlSpatial\Types\LineString' + 'Limenet\LaravelMysqlSpatial\Types\MultiLineString must be a collection of Limenet\LaravelMysqlSpatial\Types\LineString' ); $multilinestring[] = 1; } diff --git a/tests/Unit/Types/MultiPointTest.php b/tests/Unit/Types/MultiPointTest.php index a8a94f41..a58be077 100644 --- a/tests/Unit/Types/MultiPointTest.php +++ b/tests/Unit/Types/MultiPointTest.php @@ -1,7 +1,11 @@ assertException( - \Grimzy\LaravelMysqlSpatial\Exceptions\InvalidGeoJsonException::class, - sprintf('Expected %s, got %s', GeoJson\Geometry\MultiPoint::class, GeoJson\Geometry\Point::class) + \Limenet\LaravelMysqlSpatial\Exceptions\InvalidGeoJsonException::class, + sprintf('Expected %s, got %s', \GeoJson\Geometry\MultiPoint::class, \GeoJson\Geometry\Point::class) ); MultiPoint::fromJson('{"type":"Point","coordinates":[3.4,1.2]}'); } @@ -63,7 +67,7 @@ public function testInvalidArgumentExceptionAtLeastOneEntry() { $this->assertException( InvalidArgumentException::class, - 'Grimzy\LaravelMysqlSpatial\Types\MultiPoint must contain at least 1 entry' + 'Limenet\LaravelMysqlSpatial\Types\MultiPoint must contain at least 1 entry' ); $multipoint = new MultiPoint([]); } @@ -72,7 +76,7 @@ public function testInvalidArgumentExceptionNotArrayOfLineString() { $this->assertException( InvalidArgumentException::class, - 'Grimzy\LaravelMysqlSpatial\Types\MultiPoint must be a collection of Grimzy\LaravelMysqlSpatial\Types\Point' + 'Limenet\LaravelMysqlSpatial\Types\MultiPoint must be a collection of Limenet\LaravelMysqlSpatial\Types\Point' ); $multipoint = new MultiPoint([ new Point(0, 0), @@ -98,56 +102,8 @@ public function testArrayAccess() // assert invalid $this->assertException( InvalidArgumentException::class, - 'Grimzy\LaravelMysqlSpatial\Types\MultiPoint must be a collection of Grimzy\LaravelMysqlSpatial\Types\Point' + 'Limenet\LaravelMysqlSpatial\Types\MultiPoint must be a collection of Limenet\LaravelMysqlSpatial\Types\Point' ); $multipoint[] = 1; } - - public function testDeprecatedPrependPoint() - { - $point1 = new Point(1, 1); - $point2 = new Point(2, 2); - $multipoint = new MultiPoint([$point1, $point2]); - - $point0 = new Point(0, 0); - $multipoint->prependPoint($point0); - - $this->assertEquals($point0, $multipoint[0]); - $this->assertEquals($point1, $multipoint[1]); - $this->assertEquals($point2, $multipoint[2]); - } - - public function testDeprecatedAppendPoint() - { - $point0 = new Point(0, 0); - $point1 = new Point(1, 1); - $multipoint = new MultiPoint([$point0, $point1]); - - $point2 = new Point(2, 2); - $multipoint->appendPoint($point2); - - $this->assertEquals($point0, $multipoint[0]); - $this->assertEquals($point1, $multipoint[1]); - $this->assertEquals($point2, $multipoint[2]); - } - - public function testDeprecatedInsertPoint() - { - $point1 = new Point(1, 1); - $point3 = new Point(3, 3); - $multipoint = new MultiPoint([$point1, $point3]); - - $point2 = new Point(2, 2); - $multipoint->insertPoint(1, $point2); - - $this->assertEquals($point1, $multipoint[0]); - $this->assertEquals($point2, $multipoint[1]); - $this->assertEquals($point3, $multipoint[2]); - - $this->assertException( - InvalidArgumentException::class, - '$index is greater than the size of the array' - ); - $multipoint->insertPoint(100, new Point(100, 100)); - } } diff --git a/tests/Unit/Types/MultiPolygonTest.php b/tests/Unit/Types/MultiPolygonTest.php index 3e49d32d..84e77f20 100644 --- a/tests/Unit/Types/MultiPolygonTest.php +++ b/tests/Unit/Types/MultiPolygonTest.php @@ -1,9 +1,13 @@ assertException( - \Grimzy\LaravelMysqlSpatial\Exceptions\InvalidGeoJsonException::class, - sprintf('Expected %s, got %s', GeoJson\Geometry\MultiPolygon::class, GeoJson\Geometry\Point::class) + \Limenet\LaravelMysqlSpatial\Exceptions\InvalidGeoJsonException::class, + sprintf('Expected %s, got %s', \GeoJson\Geometry\MultiPolygon::class, \GeoJson\Geometry\Point::class) ); MultiPolygon::fromJson('{"type":"Point","coordinates":[3.4,1.2]}'); } @@ -82,7 +86,7 @@ public function testInvalidArgumentExceptionAtLeastOneEntry() { $this->assertException( InvalidArgumentException::class, - 'Grimzy\LaravelMysqlSpatial\Types\MultiPolygon must contain at least 1 entry' + 'Limenet\LaravelMysqlSpatial\Types\MultiPolygon must contain at least 1 entry' ); $multipolygon = new MultiPolygon([]); } @@ -91,7 +95,7 @@ public function testInvalidArgumentExceptionNotArrayOfPolygon() { $this->assertException( InvalidArgumentException::class, - 'Grimzy\LaravelMysqlSpatial\Types\MultiPolygon must be a collection of Grimzy\LaravelMysqlSpatial\Types\Polygon' + 'Limenet\LaravelMysqlSpatial\Types\MultiPolygon must be a collection of Limenet\LaravelMysqlSpatial\Types\Polygon' ); $multipolygon = new MultiPolygon([ $this->getPolygon1(), @@ -118,7 +122,7 @@ public function testArrayAccess() // assert invalid $this->assertException( InvalidArgumentException::class, - 'Grimzy\LaravelMysqlSpatial\Types\MultiPolygon must be a collection of Grimzy\LaravelMysqlSpatial\Types\Polygon' + 'Limenet\LaravelMysqlSpatial\Types\MultiPolygon must be a collection of Limenet\LaravelMysqlSpatial\Types\Polygon' ); $multipolygon[] = 1; } diff --git a/tests/Unit/Types/PointTest.php b/tests/Unit/Types/PointTest.php index 518a8a56..26248b11 100644 --- a/tests/Unit/Types/PointTest.php +++ b/tests/Unit/Types/PointTest.php @@ -1,6 +1,9 @@ assertException( - \Grimzy\LaravelMysqlSpatial\Exceptions\InvalidGeoJsonException::class, + \Limenet\LaravelMysqlSpatial\Exceptions\InvalidGeoJsonException::class, 'Expected GeoJson\Geometry\Point, got GeoJson\Geometry\LineString' ); Point::fromJson('{"type": "LineString","coordinates":[[1,1],[2,2]]}'); diff --git a/tests/Unit/Types/PolygonTest.php b/tests/Unit/Types/PolygonTest.php index aaab437b..5adb9112 100644 --- a/tests/Unit/Types/PolygonTest.php +++ b/tests/Unit/Types/PolygonTest.php @@ -1,14 +1,17 @@ assertException( - \Grimzy\LaravelMysqlSpatial\Exceptions\InvalidGeoJsonException::class, + \Limenet\LaravelMysqlSpatial\Exceptions\InvalidGeoJsonException::class, 'Expected GeoJson\Geometry\Polygon, got GeoJson\Geometry\Point' ); Polygon::fromJson('{"type":"Point","coordinates":[3.4,1.2]}');