vendor/geo-io/wkt-parser/src/Parser.php line 18

Open in your IDE?
  1. <?php
  2. namespace GeoIO\WKT\Parser;
  3. use GeoIO\Dimension;
  4. use GeoIO\Factory;
  5. use GeoIO\WKT\Parser\Exception\ParserException;
  6. use JMS\Parser\AbstractParser;
  7. class Parser extends AbstractParser
  8. {
  9.     private $factory;
  10.     private $srid;
  11.     public function __construct(Factory $factory)
  12.     {
  13.         $this->factory $factory;
  14.         parent::__construct(new Lexer());
  15.     }
  16.     public function parse($str$context null)
  17.     {
  18.         try {
  19.             return parent::parse($str$context);
  20.         } catch (\Exception $e) {
  21.             throw new ParserException('Parsing failed: ' $e->getMessage(), 0$e);
  22.         }
  23.     }
  24.     protected function parseInternal()
  25.     {
  26.         $this->srid();
  27.         return $this->geometry();
  28.     }
  29.     private function srid()
  30.     {
  31.         $this->srid null;
  32.         if ($this->lexer->isNext('SRID')) {
  33.             $this->match('SRID');
  34.             $this->match('=');
  35.             $this->srid $this->match('INTEGER');
  36.             $this->match(';');
  37.         }
  38.     }
  39.     private function geometry(&$dimension null)
  40.     {
  41.         $types = array(
  42.             'POINT',
  43.             'LINESTRING',
  44.             'POLYGON',
  45.             'MULTIPOINT',
  46.             'MULTILINESTRING',
  47.             'MULTIPOLYGON',
  48.             'GEOMETRYCOLLECTION',
  49.         );
  50.         switch ($this->matchAny($types)) {
  51.             case 'POINT':
  52.                 return $this->point($dimension);
  53.             case 'LINESTRING':
  54.                 return $this->lineString($dimension);
  55.             case 'POLYGON':
  56.                 return $this->polygon($dimension);
  57.             case 'MULTIPOINT':
  58.                 return $this->multiPoint($dimension);
  59.             case 'MULTILINESTRING':
  60.                 return $this->multiLineString($dimension);
  61.             case 'MULTIPOLYGON':
  62.                 return $this->multiPolygon($dimension);
  63.             default:
  64.                 return $this->geometryCollection($dimension);
  65.         }
  66.     }
  67.     private function dimension($dimension)
  68.     {
  69.         if ((Dimension::DIMENSION_4D === $dimension || null === $dimension) &&
  70.             $this->lexer->isNext('ZM')) {
  71.             $this->match('ZM');
  72.             return Dimension::DIMENSION_4D;
  73.         }
  74.         if ((Dimension::DIMENSION_3DM === $dimension || null === $dimension) &&
  75.             $this->lexer->isNext('M')) {
  76.             $this->match('M');
  77.             return Dimension::DIMENSION_3DM;
  78.         }
  79.         if ((Dimension::DIMENSION_3DZ === $dimension || null === $dimension) &&
  80.             $this->lexer->isNext('Z')) {
  81.             $this->match('Z');
  82.             return Dimension::DIMENSION_3DZ;
  83.         }
  84.         return $dimension;
  85.     }
  86.     private function coordinates(&$dimension null)
  87.     {
  88.         $coordinates = array(
  89.             'x' => $this->matchAny(array('FLOAT''INTEGER')),
  90.             'y' => $this->matchAny(array('FLOAT''INTEGER')),
  91.             'z' => null,
  92.             'm' => null
  93.         );
  94.         if (Dimension::DIMENSION_3DZ === $dimension ||
  95.             Dimension::DIMENSION_4D === $dimension ||
  96.             (null === $dimension && $this->lexer->isNextAny(array('FLOAT''INTEGER')))) {
  97.             $coordinates['z'] = $this->matchAny(array('FLOAT''INTEGER'));
  98.         }
  99.         if (Dimension::DIMENSION_3DM === $dimension ||
  100.             Dimension::DIMENSION_4D === $dimension ||
  101.             (null === $dimension && $this->lexer->isNextAny(array('FLOAT''INTEGER')))) {
  102.             $coordinates['m'] = $this->matchAny(array('FLOAT''INTEGER'));
  103.         }
  104.         if (null === $dimension) {
  105.             if (isset($coordinates['z']) && isset($coordinates['m'])) {
  106.                 $dimension Dimension::DIMENSION_4D;
  107.             } elseif (isset($coordinates['z'])) {
  108.                 $dimension Dimension::DIMENSION_3DZ;
  109.             }
  110.         }
  111.         return $this->factory->createPoint(
  112.             $dimension ?: Dimension::DIMENSION_2D,
  113.             $coordinates,
  114.             $this->srid
  115.         );
  116.     }
  117.     private function point(&$dimension null)
  118.     {
  119.         $dimension $this->dimension($dimension);
  120.         if ($this->lexer->isNext('EMPTY')) {
  121.             $this->match('EMPTY');
  122.             return $this->factory->createPoint(
  123.                 $dimension ?: Dimension::DIMENSION_2D,
  124.                 array(),
  125.                 $this->srid
  126.             );
  127.         }
  128.         $this->match('(');
  129.         $point $this->coordinates($dimension);
  130.         $this->match(')');
  131.         return $point;
  132.     }
  133.     private function lineStringText(&$dimension null$isLinearRing false)
  134.     {
  135.         $this->match('(');
  136.         $points = array();
  137.         while (true) {
  138.             $points[] = $this->coordinates($dimension);
  139.             if (!$this->lexer->isNext(',')) {
  140.                 break;
  141.             }
  142.             $this->match(',');
  143.         }
  144.         $this->match(')');
  145.         if ($isLinearRing) {
  146.             return $this->factory->createLinearRing(
  147.                 $dimension ?: Dimension::DIMENSION_2D,
  148.                 $points,
  149.                 $this->srid
  150.             );
  151.         }
  152.         return $this->factory->createLineString(
  153.             $dimension ?: Dimension::DIMENSION_2D,
  154.             $points,
  155.             $this->srid
  156.         );
  157.     }
  158.     private function lineString(&$dimension null)
  159.     {
  160.         $dimension $this->dimension($dimension);
  161.         if ($this->lexer->isNext('EMPTY')) {
  162.             $this->match('EMPTY');
  163.             return $this->factory->createLineString(
  164.                 $dimension ?: Dimension::DIMENSION_2D,
  165.                 array(),
  166.                 $this->srid
  167.             );
  168.         }
  169.         return $this->lineStringText($dimension);
  170.     }
  171.     private function polygonText(&$dimension null)
  172.     {
  173.         $this->match('(');
  174.         $lineStrings = array();
  175.         while (true) {
  176.             $lineStrings[] = $this->lineStringText($dimensiontrue);
  177.             if (!$this->lexer->isNext(',')) {
  178.                 break;
  179.             }
  180.             $this->match(',');
  181.         }
  182.         $this->match(')');
  183.         return $this->factory->createPolygon(
  184.             $dimension ?: Dimension::DIMENSION_2D,
  185.             $lineStrings,
  186.             $this->srid
  187.         );
  188.     }
  189.     private function polygon(&$dimension null)
  190.     {
  191.         $dimension $this->dimension($dimension);
  192.         if ($this->lexer->isNext('EMPTY')) {
  193.             $this->match('EMPTY');
  194.             return $this->factory->createPolygon(
  195.                 $dimension ?: Dimension::DIMENSION_2D,
  196.                 array(),
  197.                 $this->srid
  198.             );
  199.         }
  200.         return $this->polygonText($dimension);
  201.     }
  202.     private function multiPoint(&$dimension null)
  203.     {
  204.         $dimension $this->dimension($dimension);
  205.         if ($this->lexer->isNext('EMPTY')) {
  206.             $this->match('EMPTY');
  207.             return $this->factory->createMultiPoint(
  208.                 $dimension ?: Dimension::DIMENSION_2D,
  209.                 array(),
  210.                 $this->srid
  211.             );
  212.         }
  213.         $this->match('(');
  214.         $points = array();
  215.         while (true) {
  216.             $nonStandardPoint true;
  217.             if ($this->lexer->isNext('(')) {
  218.                 $this->match('(');
  219.                 $nonStandardPoint false;
  220.             }
  221.             $points[] = $this->coordinates($dimension);
  222.             if (!$nonStandardPoint) {
  223.                 $this->match(')');
  224.             }
  225.             if (!$this->lexer->isNext(',')) {
  226.                 break;
  227.             }
  228.             $this->match(',');
  229.         }
  230.         $this->match(')');
  231.         return $this->factory->createMultiPoint(
  232.             $dimension ?: Dimension::DIMENSION_2D,
  233.             $points,
  234.             $this->srid
  235.         );
  236.     }
  237.     private function multiLineString(&$dimension null)
  238.     {
  239.         $dimension $this->dimension($dimension);
  240.         if ($this->lexer->isNext('EMPTY')) {
  241.             $this->match('EMPTY');
  242.             return $this->factory->createMultiLineString(
  243.                 $dimension ?: Dimension::DIMENSION_2D,
  244.                 array(),
  245.                 $this->srid
  246.             );
  247.         }
  248.         $this->match('(');
  249.         $lineStrings = array();
  250.         while (true) {
  251.             $lineStrings[] = $this->lineStringText($dimension);
  252.             if (!$this->lexer->isNext(',')) {
  253.                 break;
  254.             }
  255.             $this->match(',');
  256.         }
  257.         $this->match(')');
  258.         return $this->factory->createMultiLineString(
  259.             $dimension ?: Dimension::DIMENSION_2D,
  260.             $lineStrings,
  261.             $this->srid
  262.         );
  263.     }
  264.     private function multiPolygon(&$dimension null)
  265.     {
  266.         $dimension $this->dimension($dimension);
  267.         if ($this->lexer->isNext('EMPTY')) {
  268.             $this->match('EMPTY');
  269.             return $this->factory->createMultiPolygon(
  270.                 $dimension ?: Dimension::DIMENSION_2D,
  271.                 array(),
  272.                 $this->srid
  273.             );
  274.         }
  275.         $this->match('(');
  276.         $polygons = array();
  277.         while (true) {
  278.             $polygons[] = $this->polygonText($dimension);
  279.             if (!$this->lexer->isNext(',')) {
  280.                 break;
  281.             }
  282.             $this->match(',');
  283.         }
  284.         $this->match(')');
  285.         return $this->factory->createMultiPolygon(
  286.             $dimension ?: Dimension::DIMENSION_2D,
  287.             $polygons,
  288.             $this->srid
  289.         );
  290.     }
  291.     private function geometryCollection(&$dimension null)
  292.     {
  293.         $dimension $this->dimension($dimension);
  294.         if ($this->lexer->isNext('EMPTY')) {
  295.             $this->match('EMPTY');
  296.             return $this->factory->createGeometryCollection(
  297.                 $dimension ?: Dimension::DIMENSION_2D,
  298.                 array(),
  299.                 $this->srid
  300.             );
  301.         }
  302.         $this->match('(');
  303.         $geometries = array();
  304.         while (true) {
  305.             $geometries[] = $this->geometry($dimension);
  306.             if (!$this->lexer->isNext(',')) {
  307.                 break;
  308.             }
  309.             $this->match(',');
  310.         }
  311.         $this->match(')');
  312.         return $this->factory->createGeometryCollection(
  313.             $dimension ?: Dimension::DIMENSION_2D,
  314.             $geometries,
  315.             $this->srid
  316.         );
  317.     }
  318. }