Code Coverage |
||||||||||||||||
Lines |
Branches |
Paths |
Functions and Methods |
Classes and Traits |
||||||||||||
| Total | |
91.11% |
41 / 45 |
|
80.65% |
25 / 31 |
|
14.58% |
7 / 48 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
| EventService | |
91.11% |
41 / 45 |
|
80.65% |
25 / 31 |
|
14.58% |
7 / 48 |
|
75.00% |
3 / 4 |
197.10 | |
0.00% |
0 / 1 |
| __construct | |
100.00% |
8 / 8 |
|
85.71% |
6 / 7 |
|
37.50% |
3 / 8 |
|
100.00% |
1 / 1 |
7.91 | |||
| fetch | |
100.00% |
5 / 5 |
|
75.00% |
3 / 4 |
|
50.00% |
1 / 2 |
|
100.00% |
1 / 1 |
4.12 | |||
| formatIsValid | |
100.00% |
2 / 2 |
|
66.67% |
2 / 3 |
|
50.00% |
1 / 2 |
|
100.00% |
1 / 1 |
2.50 | |||
| parse | |
86.67% |
26 / 30 |
|
82.35% |
14 / 17 |
|
5.56% |
2 / 36 |
|
0.00% |
0 / 1 |
61.91 | |||
| 1 | <?php |
| 2 | namespace Fdsn\Webservices\Event; |
| 3 | |
| 4 | use ArrayIterator; |
| 5 | use IteratorAggregate; |
| 6 | use Traversable; |
| 7 | |
| 8 | use Fdsn\Webservices\Webservice; |
| 9 | |
| 10 | use Fdsn\Webservices\Event\Event; |
| 11 | |
| 12 | use Fdsn\Webservices\Event\Data\Author; |
| 13 | use Fdsn\Webservices\Event\Data\Depth; |
| 14 | use Fdsn\Webservices\Event\Data\Epicenter; |
| 15 | use Fdsn\Webservices\Event\Data\EventType; |
| 16 | use Fdsn\Webservices\Event\Data\Id as Id; |
| 17 | use Fdsn\Webservices\Event\Data\LatLon as LatLon; |
| 18 | use Fdsn\Webservices\Event\Data\Location as Location; |
| 19 | use Fdsn\Webservices\Event\Data\Magnitude as Magnitude; |
| 20 | |
| 21 | |
| 22 | /** |
| 23 | * PHP library to access FDSN Webservices and request Event (earthquake) information in text format |
| 24 | * @see https://www.fdsn.org/webservices/fdsnws-event-1.2.pdf FDSN official documentation |
| 25 | * |
| 26 | * @param string $format Accepted output kind format |
| 27 | * @param string $user Set your app name |
| 28 | * @param string $fdns_server Fdns webservice domain name (default: webservices.ms.ingv.it) |
| 29 | */ |
| 30 | class EventService extends Webservice implements IteratorAggregate { |
| 31 | private string $format = 'text'; |
| 32 | private string $user; |
| 33 | |
| 34 | protected string $url; |
| 35 | protected string $eventList; |
| 36 | protected array $parameters = array(); |
| 37 | |
| 38 | protected EventData $event; |
| 39 | |
| 40 | function __construct( string $format, ?string $user, string $fdns_server = Webservice::defaultFdsnServer){ |
| 41 | if( self::debug ) printf("[%s] %d \n", __METHOD__, time()); |
| 42 | |
| 43 | if( $this->formatIsValid($format) ) |
| 44 | $this->format = $format; //otherwise it has default value |
| 45 | |
| 46 | $this->user = $user; |
| 47 | |
| 48 | $this->parameters['format'] = sprintf("format=%s", $this->format); |
| 49 | if ( ! empty($user) ) //not implemented/accepted on every service |
| 50 | $this->parameters['user'] = sprintf("user=%s", $this->user); |
| 51 | |
| 52 | |
| 53 | parent::__construct($fdns_server); |
| 54 | } |
| 55 | |
| 56 | /** |
| 57 | * Apply all filter and DO the request to the Official ONT Webservice |
| 58 | * @return int Return the number of elems found |
| 59 | */ |
| 60 | public function fetch():int{ |
| 61 | if( self::debug ) printf("[%s] %d \n", __METHOD__, time()); |
| 62 | |
| 63 | if( ! $this->fdsnSupportedVersion() ){ |
| 64 | // @codeCoverageIgnoreStart |
| 65 | throw new \ValueError(sprintf("[%s] Error fetching FDSN version from server %s", __METHOD__, $this->fdsnServer)); |
| 66 | // @codeCoverageIgnoreEnd |
| 67 | } |
| 68 | |
| 69 | $this->url = sprintf('%s/query?%s', $this->webserviceFullPath, implode('&', $this->parameters)); |
| 70 | $response = $this->getFetch( $this->url ); |
| 71 | |
| 72 | return $this->parse($response); |
| 73 | } |
| 74 | |
| 75 | /** |
| 76 | * Check if format set is valid |
| 77 | * @return bool format is valid? |
| 78 | */ |
| 79 | protected function formatIsValid(string $format):bool{ |
| 80 | if( self::debug ) printf("[%s] %d \n", __METHOD__, time()); |
| 81 | |
| 82 | return preg_match('/text/', $format); |
| 83 | |
| 84 | //TODO: 2024-08-13: xml format is still not supported, but i'll fix |
| 85 | //return preg_match('/(text|xml)/', $format); |
| 86 | } |
| 87 | |
| 88 | // /** |
| 89 | // * Compose URL before do the request |
| 90 | // * |
| 91 | // * @return string composed URL |
| 92 | // */ |
| 93 | // protected function composeURL():string{ |
| 94 | // return sprintf('%s/query?%s', $this->webserviceFullPath, implode('&', $this->parameters)); |
| 95 | // } |
| 96 | |
| 97 | /** |
| 98 | * Loop over found elems found (in text format) and convert the to \Fdsn\DataStructure\Quake obj |
| 99 | */ |
| 100 | protected function parse(string $response):int { |
| 101 | if( self::debug ) printf("[%s] %d \n", __METHOD__, time()); |
| 102 | |
| 103 | date_default_timezone_set('UTC'); |
| 104 | |
| 105 | if( preg_match('/^Error/', $response) ) |
| 106 | throw new \RuntimeException( sprintf("Error fetching url: %s\nError reported is:\n%s", $this->url, $response) ); |
| 107 | |
| 108 | $events = preg_split('/\R/', $response); |
| 109 | |
| 110 | foreach($events as $details){ |
| 111 | if(empty($details) || '#' == $details[0]){ |
| 112 | //error_log('[INF] no data in this event line'); |
| 113 | continue; |
| 114 | } |
| 115 | |
| 116 | list($eventId, $utcTime, $lat, $lon, $depth, $author, $catalog, $contributor, $contributorID, $magPrefType, $magPrefValue, $magAuthor, $locationName, $eventType) = preg_split('/\|/', $details); |
| 117 | try{ |
| 118 | $singleEvent = new Event( |
| 119 | $this->format, |
| 120 | $this->user, |
| 121 | $this->fdsnServer, |
| 122 | new EventData( |
| 123 | new Id($eventId), |
| 124 | new \DateTime($utcTime), |
| 125 | new Location($locationName), |
| 126 | new Magnitude($magPrefType, $magPrefValue), |
| 127 | new Epicenter(new LatLon($lat, $lon), new Depth($depth)), |
| 128 | new Author($author), |
| 129 | new EventType($eventType) |
| 130 | ) ); |
| 131 | } |
| 132 | catch(\InvalidArgumentException $e){ |
| 133 | error_log( sprintf("[%s] Skipping malformed event %d, mag: %.1f %s, epicenter: %.3f, %.3f depth: %.1f, location: %s, eventType: %s, author: %s", |
| 134 | __METHOD__, $eventId, $magPrefValue, $magPrefType, $lat, $lon, $depth, $locationName, $eventType, $author)); |
| 135 | continue; |
| 136 | } |
| 137 | |
| 138 | $this->arrayOfResults[] = $singleEvent; |
| 139 | } |
| 140 | |
| 141 | if( 1 == count($this->arrayOfResults) ) |
| 142 | $this->event = $this->arrayOfResults[0]->details(); |
| 143 | |
| 144 | return $this->numRows(); |
| 145 | } |
| 146 | } |
Below are the source code lines that represent each code branch as identified by Xdebug. Please note a branch is not
necessarily coterminous with a line, a line may contain multiple branches and therefore show up more than once.
Please also be aware that some branches may be implicit rather than explicit, e.g. an if statement
always has an else as part of its logical flow even if you didn't write one.
| 40 | function __construct( string $format, ?string $user, string $fdns_server = Webservice::defaultFdsnServer){ |
| 41 | if( self::debug ) printf("[%s] %d \n", __METHOD__, time()); |
| 41 | if( self::debug ) printf("[%s] %d \n", __METHOD__, time()); |
| 42 | |
| 43 | if( $this->formatIsValid($format) ) |
| 43 | if( $this->formatIsValid($format) ) |
| 44 | $this->format = $format; //otherwise it has default value |
| 45 | |
| 46 | $this->user = $user; |
| 46 | $this->user = $user; |
| 47 | |
| 48 | $this->parameters['format'] = sprintf("format=%s", $this->format); |
| 49 | if ( ! empty($user) ) //not implemented/accepted on every service |
| 50 | $this->parameters['user'] = sprintf("user=%s", $this->user); |
| 51 | |
| 52 | |
| 53 | parent::__construct($fdns_server); |
| 53 | parent::__construct($fdns_server); |
| 54 | } |
| 61 | if( self::debug ) printf("[%s] %d \n", __METHOD__, time()); |
| 61 | if( self::debug ) printf("[%s] %d \n", __METHOD__, time()); |
| 62 | |
| 63 | if( ! $this->fdsnSupportedVersion() ){ |
| 63 | if( ! $this->fdsnSupportedVersion() ){ |
| 69 | $this->url = sprintf('%s/query?%s', $this->webserviceFullPath, implode('&', $this->parameters)); |
| 70 | $response = $this->getFetch( $this->url ); |
| 71 | |
| 72 | return $this->parse($response); |
| 73 | } |
| 79 | protected function formatIsValid(string $format):bool{ |
| 80 | if( self::debug ) printf("[%s] %d \n", __METHOD__, time()); |
| 80 | if( self::debug ) printf("[%s] %d \n", __METHOD__, time()); |
| 81 | |
| 82 | return preg_match('/text/', $format); |
| 82 | return preg_match('/text/', $format); |
| 83 | |
| 84 | //TODO: 2024-08-13: xml format is still not supported, but i'll fix |
| 85 | //return preg_match('/(text|xml)/', $format); |
| 86 | } |
| 100 | protected function parse(string $response):int { |
| 101 | if( self::debug ) printf("[%s] %d \n", __METHOD__, time()); |
| 101 | if( self::debug ) printf("[%s] %d \n", __METHOD__, time()); |
| 102 | |
| 103 | date_default_timezone_set('UTC'); |
| 103 | date_default_timezone_set('UTC'); |
| 104 | |
| 105 | if( preg_match('/^Error/', $response) ) |
| 106 | throw new \RuntimeException( sprintf("Error fetching url: %s\nError reported is:\n%s", $this->url, $response) ); |
| 108 | $events = preg_split('/\R/', $response); |
| 109 | |
| 110 | foreach($events as $details){ |
| 110 | foreach($events as $details){ |
| 111 | if(empty($details) || '#' == $details[0]){ |
| 111 | if(empty($details) || '#' == $details[0]){ |
| 111 | if(empty($details) || '#' == $details[0]){ |
| 113 | continue; |
| 116 | list($eventId, $utcTime, $lat, $lon, $depth, $author, $catalog, $contributor, $contributorID, $magPrefType, $magPrefValue, $magAuthor, $locationName, $eventType) = preg_split('/\|/', $details); |
| 117 | try{ |
| 118 | $singleEvent = new Event( |
| 132 | catch(\InvalidArgumentException $e){ |
| 133 | error_log( sprintf("[%s] Skipping malformed event %d, mag: %.1f %s, epicenter: %.3f, %.3f depth: %.1f, location: %s, eventType: %s, author: %s", |
| 134 | __METHOD__, $eventId, $magPrefValue, $magPrefType, $lat, $lon, $depth, $locationName, $eventType, $author)); |
| 135 | continue; |
| 110 | foreach($events as $details){ |
| 111 | if(empty($details) || '#' == $details[0]){ |
| 112 | //error_log('[INF] no data in this event line'); |
| 113 | continue; |
| 114 | } |
| 115 | |
| 116 | list($eventId, $utcTime, $lat, $lon, $depth, $author, $catalog, $contributor, $contributorID, $magPrefType, $magPrefValue, $magAuthor, $locationName, $eventType) = preg_split('/\|/', $details); |
| 117 | try{ |
| 118 | $singleEvent = new Event( |
| 119 | $this->format, |
| 120 | $this->user, |
| 121 | $this->fdsnServer, |
| 122 | new EventData( |
| 123 | new Id($eventId), |
| 124 | new \DateTime($utcTime), |
| 125 | new Location($locationName), |
| 126 | new Magnitude($magPrefType, $magPrefValue), |
| 127 | new Epicenter(new LatLon($lat, $lon), new Depth($depth)), |
| 128 | new Author($author), |
| 129 | new EventType($eventType) |
| 130 | ) ); |
| 131 | } |
| 132 | catch(\InvalidArgumentException $e){ |
| 133 | error_log( sprintf("[%s] Skipping malformed event %d, mag: %.1f %s, epicenter: %.3f, %.3f depth: %.1f, location: %s, eventType: %s, author: %s", |
| 134 | __METHOD__, $eventId, $magPrefValue, $magPrefType, $lat, $lon, $depth, $locationName, $eventType, $author)); |
| 135 | continue; |
| 136 | } |
| 137 | |
| 138 | $this->arrayOfResults[] = $singleEvent; |
| 110 | foreach($events as $details){ |
| 111 | if(empty($details) || '#' == $details[0]){ |
| 112 | //error_log('[INF] no data in this event line'); |
| 113 | continue; |
| 114 | } |
| 115 | |
| 116 | list($eventId, $utcTime, $lat, $lon, $depth, $author, $catalog, $contributor, $contributorID, $magPrefType, $magPrefValue, $magAuthor, $locationName, $eventType) = preg_split('/\|/', $details); |
| 117 | try{ |
| 118 | $singleEvent = new Event( |
| 119 | $this->format, |
| 120 | $this->user, |
| 121 | $this->fdsnServer, |
| 122 | new EventData( |
| 123 | new Id($eventId), |
| 124 | new \DateTime($utcTime), |
| 125 | new Location($locationName), |
| 126 | new Magnitude($magPrefType, $magPrefValue), |
| 127 | new Epicenter(new LatLon($lat, $lon), new Depth($depth)), |
| 128 | new Author($author), |
| 129 | new EventType($eventType) |
| 130 | ) ); |
| 131 | } |
| 132 | catch(\InvalidArgumentException $e){ |
| 133 | error_log( sprintf("[%s] Skipping malformed event %d, mag: %.1f %s, epicenter: %.3f, %.3f depth: %.1f, location: %s, eventType: %s, author: %s", |
| 134 | __METHOD__, $eventId, $magPrefValue, $magPrefType, $lat, $lon, $depth, $locationName, $eventType, $author)); |
| 135 | continue; |
| 136 | } |
| 137 | |
| 138 | $this->arrayOfResults[] = $singleEvent; |
| 139 | } |
| 140 | |
| 141 | if( 1 == count($this->arrayOfResults) ) |
| 142 | $this->event = $this->arrayOfResults[0]->details(); |
| 143 | |
| 144 | return $this->numRows(); |
| 144 | return $this->numRows(); |
| 145 | } |