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
Event
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 as Fdsnws_Webservice;
9
10use Fdsn\Webservices\Event\SingleInstance as Event_SingleInstance;
11
12use Fdsn\Webservices\Event\Structs\Author as DS_Author;
13use Fdsn\Webservices\Event\Structs\DateTimeRange as DS_DateTimeRange;
14use Fdsn\Webservices\Event\Structs\Depth as DS_Depth;
15use Fdsn\Webservices\Event\Structs\DepthRange as DS_DepthRange;
16use Fdsn\Webservices\Event\Structs\Epicenter as DS_Epicenter;
17use Fdsn\Webservices\Event\Structs\EventType as DS_EventType;
18use Fdsn\Webservices\Event\Structs\Id as DS_Id;
19use Fdsn\Webservices\Event\Structs\LatLon as DS_LatLon;
20use Fdsn\Webservices\Event\Structs\LatLonRange as DS_LatLonRange;
21use Fdsn\Webservices\Event\Structs\Location as DS_Location;
22use Fdsn\Webservices\Event\Structs\Magnitude as DS_Magnitude;
23use Fdsn\Webservices\Event\Structs\MagnitudeRange as DS_MagnitudeRange;
24use Fdsn\Webservices\Event\Structs\Quake as DS_Quake;
25use Fdsn\Webservices\Event\Structs\Radius as DS_Radius;
26use Fdsn\Webservices\Event\Structs\RadiusRange as DS_RadiusRange;
27
28/**
29 * PHP library to access FDSN Webservices and request Event (earthquake) information in text format
30 * @see    https://www.fdsn.org/webservices/fdsnws-event-1.2.pdf FDSN official documentation
31 *
32 * @param string     $format     Accepted output kind format
33 * @param string     $user        Set your app name
34 * @param string     $fdns_server    Fdns webservice domain name (default: webservices.ms.ingv.it)
35 */
36class Event extends Fdsnws_Webservice implements IteratorAggregate {
37    private string $format = 'text';
38    private string $user;
39
40    protected string $url;
41    protected string $eventList;
42    protected array $parameters = array();
43
44    protected DS_Quake $event;
45
46    function __construct( string $format, ?string $user, string $fdns_server = Fdsnws_Webservice::defaultFdsnServer){
47        if( self::debug ) printf("[%s] %d \n", __METHOD__, time()); 
48
49        if( $this->formatIsValid($format) )
50            $this->format = $format; //otherwise it has default value
51
52        $this->user = $user;
53        
54        $this->parameters['format'] = sprintf("format=%s", $this->format);
55        if ( ! empty($user) ) //not implemented/accepted on every service
56            $this->parameters['user'] = sprintf("user=%s", $this->user);
57
58
59        parent::__construct($fdns_server);
60    }
61    
62    /**
63     * Apply all filter and DO the request to the Official ONT Webservice
64     * @return int         Return the number of elems found
65     */
66    public function fetch():int{
67        if( self::debug ) printf("[%s] %d \n", __METHOD__, time()); 
68
69        if( ! $this->fdsnSupportedVersion() ){
70            // @codeCoverageIgnoreStart
71            throw new \ValueError(sprintf("[%s] Error fetching FDSN version from server %s", __METHOD__, $this->fdsnServer));
72            // @codeCoverageIgnoreEnd
73        }
74
75        $this->url = sprintf('%s/query?%s', $this->webserviceFullPath, implode('&', $this->parameters));
76        $response = $this->getFetch( $this->url );
77
78        return $this->parse($response);
79    }
80    
81    /**
82     * Check if format set is valid
83     * @return bool        format is valid?
84     */
85    protected function formatIsValid(string $format):bool{ 
86        if( self::debug ) printf("[%s] %d \n", __METHOD__, time()); 
87
88        return preg_match('/text/', $format); 
89
90        //TODO: 2024-08-13: xml format is still not supported, but i'll fix
91        //return preg_match('/(text|xml)/', $format);  
92    }
93
94//    /**
95//     * Compose URL before do the request
96//     * 
97//     * @return string composed URL
98//     */
99//    protected function composeURL():string{
100//        return sprintf('%s/query?%s', $this->webserviceFullPath, implode('&', $this->parameters));
101//    }
102    
103    /**
104     * Loop over found elems found (in text format) and convert the to \Fdsn\DataStructure\Quake obj
105     */
106    protected function parse(string $response):int {
107        if( self::debug ) printf("[%s] %d \n", __METHOD__, time()); 
108
109        date_default_timezone_set('UTC');
110
111        if( preg_match('/^Error/', $response) )
112            throw new \RuntimeException( sprintf("Error fetching url: %s\nError reported is:\n%s", $this->url, $response) );
113
114        $events = preg_split('/\R/',  $response);
115
116        foreach($events as $details){
117            if(empty($details) || '#' == $details[0]){
118                //error_log('[INF] no data in this event line');
119                continue;
120            }
121
122            list($adsIdEvent, $utcTime, $lat, $lon, $depth, $author, $catalog, $contributor, $contributorID, $magPrefType, $magPrefValue, $magAuthor, $locationName, $eventType) = preg_split('/\|/', $details);
123            try{
124                $singleEvent = new Event_SingleInstance(
125                    $this->format, 
126                    $this->user,
127                    $this->fdsnServer,
128                    new DS_Quake(
129                        new DS_Id($adsIdEvent),
130                        new \DateTime($utcTime),
131                        new DS_Location($locationName),
132                        new DS_Magnitude($magPrefType, $magPrefValue),
133                        new DS_Epicenter(new DS_LatLon($lat, $lon), new DS_Depth($depth)),
134                        new DS_Author($author),
135                        new DS_EventType($eventType)
136                    ) );
137            }
138            catch(\InvalidArgumentException $e){
139                error_log( sprintf("[%s] Skipping malformed event %d, mag: %.1f %s, epicenter: %.3f, %.3f depth: %.1f, location: %s, eventType: %s, author: %s", 
140                        __METHOD__, $adsIdEvent, $magPrefValue, $magPrefType, $lat, $lon, $depth, $locationName, $eventType, $author)); 
141                continue;
142            }
143
144            $this->arrayOfResults[] = $singleEvent;
145        }
146
147        if( 1 == count($this->arrayOfResults) )
148            $this->event = $this->arrayOfResults[0]->details();
149
150        return $this->numRows();
151    }
152}