From: Andy Street Date: Wed, 19 Dec 2018 15:32:23 +0000 (+0000) Subject: Create parent class for datatypes to hold common metadata X-Git-Url: https://git.street.me.uk/andy/gpx.git/commitdiff_plain/09a366237762f61b974b61429d0452e17f89deb6 Create parent class for datatypes to hold common metadata --- diff --git a/src/libgpx/datatype.php b/src/libgpx/datatype.php new file mode 100644 index 0000000..b7512d8 --- /dev/null +++ b/src/libgpx/datatype.php @@ -0,0 +1,223 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * + */ + +namespace libgpx; + +/** + * A GPX data type. + * + * @author Andy Street + */ +abstract class DataType +{ + + /** + * A name. + * + * @var string + */ + protected $name; + + /** + * A comment. + * + * Sent to GPS as comment. + * + * @var string + */ + protected $comment; + + /** + * A text description. + * + * Holds additional information about the element intended for the user, + * not the GPS. + * + * @var string + */ + protected $description; + + /** + * Source of data. + * + * Included to give user some idea of reliability and accuracy of data. + * E.g. "Garmin eTrex", "USGS quad Boston North". + * + * @var string + */ + protected $source; + + /** + * A list of associated links. + * + * @var TypedDoublyLinkedList (Link) + */ + protected $links; + + /** + * Type (classification). + * + * @var string + */ + protected $type; + + /** + * A list of XML snippets describing unsupported data. + * + * @var TypedDoublyLinkedList (string) + */ + protected $extensions; + + /** + * Fetch the name. + * + * @return string|null The name or null if not set. + */ + public function getName() + { + return $this->name; + } + + /** + * Set the name. + * + * @param string $name The name or null to delete. + * @return void + */ + public function setName(string $name = null) + { + $this->name = $name; + } + + /** + * Fetch a comment. + * + * @return string The comment or null if not set. + */ + public function getComment() + { + return $this->comment; + } + + /** + * Set a comment. + * + * @param string $comment The comment or null to delete. + * @return void + */ + public function setComment(string $comment = null) + { + $this->comment = $comment; + } + + /** + * Fetch the description. + * + * @return string The description or null if not set. + */ + public function getDescription() + { + return $this->description; + } + + /** + * Set the description. + * + * @param string $description The description or null to delete. + * @return void + */ + public function setDescription(string $description = null) + { + $this->description = $description; + } + + /** + * Fetch the source of the data. + * + * @return string|null The source or null if not set. + */ + public function getSource() + { + return $this->source; + } + + /** + * Set the source of the data. + * + * @param string $source The source of the data or null to delete. + * @return void + */ + public function setSource(string $source = null) + { + $this->source = $source; + } + + /** + * Fetch a list of associated links. + * + * @param boolean $create Create the list if it does not already exist. + * @return TypedDoublyLinkedList|null A list of Link objects. + */ + public function getLinks(bool $create = true) + { + if ($create && $this->links === null) + $this->links = new TypedDoublyLinkedList('libgpx\Link'); + return $this->links; + } + + /** + * Fetch the type. + * + * @return string|null The type or null if not set. + */ + public function getType() + { + return $this->type; + } + + /** + * Set the type. + * + * @param string $type The type or null to delete. + * @return void + */ + public function setType(string $type = null) + { + $this->type = $type; + } + + /** + * Fetch a list of XML strings that describe unsupported elements. + * + * @param boolean $create Create the list if it does not already exist. + * @return TypedDoublyLinkedList|null A list of XML strings. + */ + public function getExtensions(bool $create = true) + { + if ($create && $this->extensions === null) + $this->extensions = new TypedDoublyLinkedList('string'); + return $this->extensions; + } + +} diff --git a/src/libgpx/gpxreader.php b/src/libgpx/gpxreader.php index 077f85e..b98d2ef 100644 --- a/src/libgpx/gpxreader.php +++ b/src/libgpx/gpxreader.php @@ -435,97 +435,48 @@ class GPXReader $this->string2float($this->xml->getAttribute('lat')), $this->string2float($this->xml->getAttribute('lon')) ); - $struct = [ - 'elements' => [ - 'ele' => function ($point) { - $point->setEle($this->string2float($this->readXSDString())); - }, - 'time' => function ($point) { - $point->setTime($this->string2DateTime($this->readXSDString())); - }, - 'magvar' => function ($point) { - $point->setMagvar($this->string2float($this->readXSDString())); - }, - 'geoidheight' => function ($point) { - $point->setGeoidHeight($this->string2float($this->readXSDString())); - }, - 'name' => function ($point) { - $point->setName($this->readXSDString()); - }, - 'cmt' => function ($point) { - $point->setComment($this->readXSDString()); - }, - 'desc' => function ($point) { - $point->setDescription($this->readXSDString()); - }, - 'src' => function ($point) { - $point->setSource($this->readXSDString()); - }, - 'sym' => function ($point) { - $point->setSymbol($this->readXSDString()); - }, - 'type' => function ($point) { - $point->setType($this->readXSDString()); - }, - 'fix' => function ($point) { - $point->setFix($this->readXSDString()); - }, - 'sat' => function ($point) { - $point->setSatellites($this->string2int($this->readXSDString())); - }, - 'hdop' => function ($point) { - $point->setHdop($this->string2float($this->readXSDString())); - }, - 'vdop' => function ($point) { - $point->setVdop($this->string2float($this->readXSDString())); - }, - 'pdop' => function ($point) { - $point->setPdop($this->string2float($this->readXSDString())); - }, - 'ageofdgpsdata' => function ($point) { - $point->setAgeOfDGPSData($this->string2float($this->readXSDString())); - }, - 'dgpsid' => function ($point) { - $point->setDGPSId($this->string2int($this->readXSDString())); - } - ] - ]; - if ($this->version == '1.1') { - $struct['elements']['link'] = function ($point) { - $point->getLinks()[] = $this->readLink(); - }; - $struct['elements']['extensions'] = function ($point) { - $this->readExtension($point->getExtensions()); - }; - } else { - $struct['elements']['url'] = function ($point, &$state) { - $href = $this->readXSDString(); - $links = $point->getLinks(); - if ($links->isEmpty()) { - $link = new Link($href); - if (isset($state['urlname'])) { - $link->setText($state['urlname']); - unset($state['urlname']); - } - $links[] = $link; - } else { - $links->bottom()->setHref($href); - } - }; - $struct['elements']['urlname'] = function ($point, &$state) { - $text = $this->readXSDString(); - $links = $point->getLinks(); - if ($links->isEmpty()) { - $state['urlname'] = $text; - } else { - $links->bottom()->setText($text); - } - }; - $struct['extensions'] = function ($point) { - $point->getExtensions()[] = $this->xml->readOuterXML(); - $this->xml->next(); + $struct = $this->getDataTypeStruct(); + $struct['elements']['ele'] = function ($point) { + $point->setEle($this->string2float($this->readXSDString())); + }; + $struct['elements']['time'] = function ($point) { + $point->setTime($this->string2DateTime($this->readXSDString())); + }; + $struct['elements']['magvar'] = function ($point) { + $point->setMagvar($this->string2float($this->readXSDString())); + }; + $struct['elements']['geoidheight'] = function ($point) { + $point->setGeoidHeight($this->string2float($this->readXSDString())); + }; + $struct['elements']['sym'] = function ($point) { + $point->setSymbol($this->readXSDString()); + }; + // "type" only appears in "wpt" in GPX 1.0 + if ($this->version == '1.0') + $struct['elements']['type'] = function ($point) { + $point->setType($this->readXSDString()); }; - } + $struct['elements']['fix'] = function ($point) { + $point->setFix($this->readXSDString()); + }; + $struct['elements']['sat'] = function ($point) { + $point->setSatellites($this->string2int($this->readXSDString())); + }; + $struct['elements']['hdop'] = function ($point) { + $point->setHdop($this->string2float($this->readXSDString())); + }; + $struct['elements']['vdop'] = function ($point) { + $point->setVdop($this->string2float($this->readXSDString())); + }; + $struct['elements']['pdop'] = function ($point) { + $point->setPdop($this->string2float($this->readXSDString())); + }; + $struct['elements']['ageofdgpsdata'] = function ($point) { + $point->setAgeOfDGPSData($this->string2float($this->readXSDString())); + }; + $struct['elements']['dgpsid'] = function ($point) { + $point->setDGPSId($this->string2int($this->readXSDString())); + }; $this->readStruct($struct, $result); } catch (DomainException $e) { throw new MalformedGPXException( @@ -547,67 +498,13 @@ class GPXReader { try { $result = new Route(); - $struct = [ - 'elements' => [ - 'name' => function ($route) { - $route->setName($this->readXSDString()); - }, - 'cmt' => function ($route) { - $route->setComment($this->readXSDString()); - }, - 'desc' => function ($route) { - $route->setDescription($this->readXSDString()); - }, - 'src' => function ($route) { - $route->setSource($this->readXSDString()); - }, - 'number' => function ($route) { - $route->setNumber($this->string2int($this->readXSDString())); - }, - 'rtept' => function ($route) { - $route->getPoints()[] = $this->readWpt(); - } - ] - ]; - if ($this->version == '1.1') { - $struct['elements']['link'] = function ($route) { - $route->getLinks()[] = $this->readLink(); - }; - $struct['elements']['type'] = function ($route) { - $route->setType($this->readXSDString()); - }; - $struct['elements']['extensions'] = function ($route) { - $this->readExtension($route->getExtensions()); - }; - } else { - $struct['elements']['url'] = function ($route, &$state) { - $href = $this->readXSDString(); - $links = $route->getLinks(); - if ($links->isEmpty()) { - $link = new Link($href); - if (isset($state['urlname'])) { - $link->setText($state['urlname']); - unset($state['urlname']); - } - $links[] = $link; - } else { - $links->bottom()->setHref($href); - } - }; - $struct['elements']['urlname'] = function ($route, &$state) { - $text = $this->readXSDString(); - $links = $route->getLinks(); - if ($links->isEmpty()) { - $state['urlname'] = $text; - } else { - $links->bottom()->setText($text); - } - }; - $struct['extensions'] = function ($route) { - $route->getExtensions()[] = $this->xml->readOuterXML(); - $this->xml->next(); - }; - } + $struct = $this->getDataTypeStruct(); + $struct['elements']['number'] = function ($route) { + $route->setNumber($this->string2int($this->readXSDString())); + }; + $struct['elements']['rtept'] = function ($route) { + $route->getPoints()[] = $this->readWpt(); + }; $this->readStruct($struct, $result); } catch (DomainException $e) { throw new MalformedGPXException( @@ -702,6 +599,71 @@ class GPXReader } } + /** + * Generate a data structure for reading DataType elements. + * + * @return array + */ + protected function getDataTypeStruct() + { + $result = [ + 'elements' => [ + 'name' => function ($type) { + $type->setName($this->readXSDString()); + }, + 'cmt' => function ($type) { + $type->setComment($this->readXSDString()); + }, + 'desc' => function ($type) { + $type->setDescription($this->readXSDString()); + }, + 'src' => function ($type) { + $type->setSource($this->readXSDString()); + } + ] + ]; + if ($this->version == '1.1') { + $result['elements']['link'] = function ($type) { + $type->getLinks()[] = $this->readLink(); + }; + $result['elements']['type'] = function ($type) { + $type->setType($this->readXSDString()); + }; + $result['elements']['extensions'] = function ($type) { + $this->readExtension($type->getExtensions()); + }; + } else { + $result['elements']['url'] = function ($type, &$state) { + $href = $this->readXSDString(); + $links = $type->getLinks(); + if ($links->isEmpty()) { + $link = new Link($href); + if (isset($state['urlname'])) { + $link->setText($state['urlname']); + unset($state['urlname']); + } + $links[] = $link; + } else { + $links->bottom()->setHref($href); + } + }; + $result['elements']['urlname'] = function ($type, &$state) { + $text = $this->readXSDString(); + $links = $type->getLinks(); + if ($links->isEmpty()) { + $state['urlname'] = $text; + } else { + $links->bottom()->setText($text); + } + }; + $result['extensions'] = function ($type) { + $type->getExtensions()[] = $this->xml->readOuterXML(); + $this->xml->next(); + }; + } + return $result; + } + /** * Read an `xsd:string` type from XML. * diff --git a/src/libgpx/gpxwriter.php b/src/libgpx/gpxwriter.php index bb0af30..342f89e 100644 --- a/src/libgpx/gpxwriter.php +++ b/src/libgpx/gpxwriter.php @@ -414,6 +414,52 @@ class GPXWriter return $timestamp->format($format); } + /** + * Write out the common attributes for all data types. + * + * @param DataType $type The data type to write. + * @param XMLWriter $xml Where to write. + * @return void + */ + protected function writeDataType(DataType $type, XMLWriter $xml) + { + $var = $type->getName(); + if ($var !== null) + $xml->writeElement('name', $var); + $var = $type->getComment(); + if ($var !== null) + $xml->writeElement('cmt', $var); + $var = $type->getDescription(); + if ($var !== null) + $xml->writeElement('desc', $var); + $var = $type->getSource(); + if ($var !== null) + $xml->writeElement('src', $var); + $var = $type->getLinks(false); + if ($var !== null) { + foreach($var as $link) { + $this->writeLink($link, $xml); + if ($this->format == '1.0') + break; + } + } + if ($this->format == '1.1' || $type instanceof Point) { + $var = $type->getType(); + if ($var !== null) + $xml->writeElement('type', $var); + } + $var = $type->getExtensions(false); + if ($var !== null && !$var->isEmpty()) { + if ($this->format == '1.1') + $xml->startElement('extensions'); + foreach ($var as $extension) { + $xml->writeRaw($extension); + } + if ($this->format == '1.1') + $xml->endElement(); + } + } + /** * Generate XML for GPX wpt type. * @@ -439,32 +485,9 @@ class GPXWriter $val = $point->getGeoidHeight(); if ($val !== null) $xml->writeElement('geoidheight', $val); - $var = $point->getName(); - if ($var !== null) - $xml->writeElement('name', $var); - $var = $point->getComment(); - if ($var !== null) - $xml->writeElement('cmt', $var); - $var = $point->getDescription(); - if ($var !== null) - $xml->writeElement('desc', $var); - $var = $point->getSource(); - if ($var !== null) - $xml->writeElement('src', $var); - $var = $point->getLinks(false); - if ($var !== null) { - foreach($var as $link) { - $this->writeLink($link, $xml); - if ($this->format == '1.0') - break; - } - } $var = $point->getSymbol(); if ($var !== null) $xml->writeElement('sym', $var); - $var = $point->getType(); - if ($var !== null) - $xml->writeElement('type', $var); $var = $point->getFix(); if ($var !== null) $xml->writeElement('fix', $var); @@ -486,16 +509,7 @@ class GPXWriter $var = $point->getDGPSId(); if ($var !== null) $xml->writeElement('dgpsid', $var); - $var = $point->getExtensions(false); - if ($var !== null && !$var->isEmpty()) { - if ($this->format == '1.1') - $xml->startElement('extensions'); - foreach ($var as $extension) { - $xml->writeRaw($extension); - } - if ($this->format == '1.1') - $xml->endElement(); - } + $this->writeDataType($point, $xml); $xml->endElement(); } @@ -508,44 +522,10 @@ class GPXWriter protected function writeRoute(Route $route, XMLWriter $xml) { $xml->startElement('rte'); - $var = $route->getName(); - if ($var !== null) - $xml->writeElement('name', $var); - $var = $route->getComment(); - if ($var !== null) - $xml->writeElement('cmt', $var); - $var = $route->getDescription(); - if ($var !== null) - $xml->writeElement('desc', $var); - $var = $route->getSource(); - if ($var !== null) - $xml->writeElement('src', $var); - $var = $route->getLinks(false); - if ($var !== null) { - foreach($var as $link) { - $this->writeLink($link, $xml); - if ($this->format == '1.0') - break; - } - } $var = $route->getNumber(); if ($var !== null) $xml->writeElement('number', $var); - if ($this->format == '1.1') { - $var = $route->getType(); - if ($var !== null) - $xml->writeElement('type', $var); - } - $var = $route->getExtensions(false); - if ($var !== null && !$var->isEmpty()) { - if ($this->format == '1.1') - $xml->startElement('extensions'); - foreach ($var as $extension) { - $xml->writeRaw($extension); - } - if ($this->format == '1.1') - $xml->endElement(); - } + $this->writeDataType($route, $xml); $var = $route->getPoints(false); if ($var !== null) { foreach ($var as $point) { diff --git a/src/libgpx/point.php b/src/libgpx/point.php index 7568821..4b20ffa 100644 --- a/src/libgpx/point.php +++ b/src/libgpx/point.php @@ -34,7 +34,7 @@ use \DateTimeInterface; * * @author Andy Street */ -class Point implements Geographic +class Point extends DataType implements Geographic { /** @@ -84,49 +84,6 @@ class Point implements Geographic */ protected $geoidheight; - /** - * The name of the point. - * - * @var string - */ - protected $name; - - /** - * GPS waypoint comment. - * - * Sent to GPS as comment. - * - * @var string - */ - protected $comment; - - /** - * A text description of the element. - * - * Holds additional information about the element intended for the user, - * not the GPS. - * - * @var string - */ - protected $description; - - /** - * Source of data. - * - * Included to give user some idea of reliability and accuracy of data. - * E.g. "Garmin eTrex", "USGS quad Boston North". - * - * @var string - */ - protected $source; - - /** - * A list of links associated with this point. - * - * @var TypedDoublyLinkedList (Link) - */ - protected $links; - /** * Text of GPS symbol name. * @@ -137,13 +94,6 @@ class Point implements Geographic */ protected $symbol; - /** - * Type (classification) of the point. - * - * @var string - */ - protected $type; - /** * Type of GPS fix. * @@ -198,13 +148,6 @@ class Point implements Geographic */ protected $dgpsid; - /** - * A list of XML snippets describing unsupported data. - * - * @var TypedDoublyLinkedList (string) - */ - protected $extensions; - /** * Create a new point. * @@ -363,103 +306,6 @@ class Point implements Geographic $this->geoidheight = $geoidheight; } - /** - * Fetch the name of the point. - * - * @return string|null The name or null if not set. - */ - public function getName() - { - return $this->name; - } - - /** - * Set the name of the point. - * - * @param string $name The name or null to delete. - * @return void - */ - public function setName(string $name = null) - { - $this->name = $name; - } - - /** - * Fetch a comment for the point. - * - * @return string The comment or null if not set. - */ - public function getComment() - { - return $this->comment; - } - - /** - * Set a comment for the point. - * - * @param string $comment The comment or null to delete. - * @return void - */ - public function setComment(string $comment = null) - { - $this->comment = $comment; - } - - /** - * Fetch the description for the point. - * - * @return string The description or null if not set. - */ - public function getDescription() - { - return $this->description; - } - - /** - * Set the description of the point. - * - * @param string $description The description or null to delete. - * @return void - */ - public function setDescription(string $description = null) - { - $this->description = $description; - } - - /** - * Fetch the source of the data. - * - * @return string|null The source or null if not set. - */ - public function getSource() - { - return $this->source; - } - - /** - * Set the source of the data. - * - * @param string $source The source of the data or null to delete. - * @return void - */ - public function setSource(string $source = null) - { - $this->source = $source; - } - - /** - * Fetch a list of links associated with this point. - * - * @param boolean $create Create the list if it does not already exist. - * @return TypedDoublyLinkedList|null A list of Link objects. - */ - public function getLinks(bool $create = true) - { - if ($create && $this->links === null) - $this->links = new TypedDoublyLinkedList('libgpx\Link'); - return $this->links; - } - /** * Fetch the waypoint symbol. * @@ -481,27 +327,6 @@ class Point implements Geographic $this->symbol = $symbol; } - /** - * Fetch the type of the point. - * - * @return string|null The type or null if not set. - */ - public function getType() - { - return $this->type; - } - - /** - * Set the type of the point. - * - * @param string $type The type or null to delete. - * @return void - */ - public function setType(string $type = null) - { - $this->type = $type; - } - /** * Fetch the fix type for this point. * @@ -662,19 +487,6 @@ class Point implements Geographic return $this->dgpsid = $dgpsid; } - /** - * Fetch a list of XML strings that describe unsupported elements. - * - * @param boolean $create Create the list if it does not already exist. - * @return TypedDoublyLinkedList|null A list of XML strings. - */ - public function getExtensions(bool $create = true) - { - if ($create && $this->extensions === null) - $this->extensions = new TypedDoublyLinkedList('string'); - return $this->extensions; - } - /** * Fetch a bounding box that covers the feature. * diff --git a/src/libgpx/route.php b/src/libgpx/route.php index 17a5000..bdb7212 100644 --- a/src/libgpx/route.php +++ b/src/libgpx/route.php @@ -33,52 +33,9 @@ use \DomainException; * * @author Andy Street */ -class Route implements Geographic +class Route extends DataType implements Geographic { - /** - * The name of the route. - * - * @var string - */ - protected $name; - - /** - * GPS waypoint comment. - * - * Sent to GPS as comment. - * - * @var string - */ - protected $comment; - - /** - * A text description of the element. - * - * Holds additional information about the element intended for the user, - * not the GPS. - * - * @var string - */ - protected $description; - - /** - * Source of data. - * - * Included to give user some idea of reliability and accuracy of data. - * E.g. "Garmin eTrex", "USGS quad Boston North". - * - * @var string - */ - protected $source; - - /** - * A list of links associated with this route. - * - * @var TypedDoublyLinkedList (Link) - */ - protected $links; - /** * GPS route number. * @@ -86,20 +43,6 @@ class Route implements Geographic */ protected $number; - /** - * Type (classification) of route. - * - * @var string - */ - protected $type; - - /** - * A list of XML snippets describing unsupported data. - * - * @var TypedDoublyLinkedList (string) - */ - protected $extensions; - /** * A list of route points. * @@ -107,102 +50,6 @@ class Route implements Geographic */ protected $points; - /** - * Fetch the name of the route. - * - * @return string|null The name or null if not set. - */ - public function getName() - { - return $this->name; - } - - /** - * Set the name of the route. - * - * @param string $name The name or null to delete. - * @return void - */ - public function setName(string $name = null) - { - $this->name = $name; - } - - /** - * Fetch a comment for the route. - * - * @return string The comment or null if not set. - */ - public function getComment() - { - return $this->comment; - } - - /** - * Set a comment for the route. - * - * @param string $comment The comment or null to delete. - * @return void - */ - public function setComment(string $comment = null) - { - $this->comment = $comment; - } - /** - * Fetch the description for the route. - * - * @return string The description or null if not set. - */ - public function getDescription() - { - return $this->description; - } - - /** - * Set the description of the point. - * - * @param string $description The description or null to delete. - * @return void - */ - public function setDescription(string $description = null) - { - $this->description = $description; - } - - /** - * Fetch the source of the data. - * - * @return string|null The source or null if not set. - */ - public function getSource() - { - return $this->source; - } - - /** - * Set the source of the data. - * - * @param string $source The source of the data or null to delete. - * @return void - */ - public function setSource(string $source = null) - { - $this->source = $source; - } - - /** - * Fetch a list of links associated with this route. - * - * @param boolean $create Create the list if it does not already exist. - * @return TypedDoublyLinkedList|null A list of Link objects. - */ - public function getLinks(bool $create = true) - { - if ($create && $this->links === null) - $this->links = new TypedDoublyLinkedList('libgpx\Link'); - return $this->links; - } - /** * Fetch the route number. * @@ -229,40 +76,6 @@ class Route implements Geographic $this->number = $number; } - /** - * Fetch the type of the route. - * - * @return string|null The type or null if not set. - */ - public function getType() - { - return $this->type; - } - - /** - * Set the type of the route. - * - * @param string $type The type or null to delete. - * @return void - */ - public function setType(string $type = null) - { - $this->type = $type; - } - - /** - * Fetch a list of XML strings that describe unsupported elements. - * - * @param boolean $create Create the list if it does not already exist. - * @return TypedDoublyLinkedList|null A list of XML strings. - */ - public function getExtensions(bool $create = true) - { - if ($create && $this->extensions === null) - $this->extensions = new TypedDoublyLinkedList('string'); - return $this->extensions; - } - /** * Fetch an ordered list of route points. *