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}