Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
91.11% covered (success)
91.11%
41 / 45
80.65% covered (warning)
80.65%
25 / 31
14.58% covered (danger)
14.58%
7 / 48
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
EventService
91.11% covered (success)
91.11%
41 / 45
80.65% covered (warning)
80.65%
25 / 31
14.58% covered (danger)
14.58%
7 / 48
75.00% covered (warning)
75.00%
3 / 4
197.10
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
8 / 8
85.71% covered (warning)
85.71%
6 / 7
37.50% covered (danger)
37.50%
3 / 8
100.00% covered (success)
100.00%
1 / 1
7.91
 fetch
100.00% covered (success)
100.00%
5 / 5
75.00% covered (warning)
75.00%
3 / 4
50.00% covered (danger)
50.00%
1 / 2
100.00% covered (success)
100.00%
1 / 1
4.12
 formatIsValid
100.00% covered (success)
100.00%
2 / 2
66.67% covered (warning)
66.67%
2 / 3
50.00% covered (danger)
50.00%
1 / 2
100.00% covered (success)
100.00%
1 / 1
2.50
 parse
86.67% covered (warning)
86.67%
26 / 30
82.35% covered (warning)
82.35%
14 / 17
5.56% covered (danger)
5.56%
2 / 36
0.00% covered (danger)
0.00%
0 / 1
61.91
1<?php
2namespace Fdsn\Webservices\Event;
3
4use ArrayIterator;
5use IteratorAggregate;
6use Traversable;
7
8use Fdsn\Webservices\Webservice;
9
10use Fdsn\Webservices\Event\Event;
11
12use Fdsn\Webservices\Event\Data\Author;
13use Fdsn\Webservices\Event\Data\Depth;
14use Fdsn\Webservices\Event\Data\Epicenter;
15use Fdsn\Webservices\Event\Data\EventType;
16use Fdsn\Webservices\Event\Data\Id as Id;
17use Fdsn\Webservices\Event\Data\LatLon as LatLon;
18use Fdsn\Webservices\Event\Data\Location as Location;
19use 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 */
30class 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}

Branches

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.

EventService->__construct
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    }
EventService->fetch
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    }
EventService->formatIsValid
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    }
EventService->parse
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    }