Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 100
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
StravaActivityParser
0.00% covered (danger)
0.00%
0 / 100
0.00% covered (danger)
0.00%
0 / 3
240
0.00% covered (danger)
0.00%
0 / 1
 parse_strava_activity_html
0.00% covered (danger)
0.00%
0 / 46
0.00% covered (danger)
0.00%
0 / 1
90
 parseDateEn
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 1
12
 parseDateDe
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3namespace Olz\Parsers;
4
5use Olz\Utils\WithUtilsTrait;
6
7class StravaActivityParser {
8    use WithUtilsTrait;
9
10    /**
11     * @return array{
12     *   name: ?string,
13     *   sportType: ?string,
14     *   runAt: ?\DateTime,
15     *   distanceMeters: ?int,
16     *   elevationMeters: ?int,
17     * } */
18    public function parse_strava_activity_html(string $html_content): array {
19        $content = str_replace("\n", " ", $html_content);
20        $res = preg_match(
21            "/<span class=\"title\">\\s*<a[^>]*>([^<]+)<\\/a>\\s*[–-]+\\s*([^<]+)<\\/span>/",
22            $content,
23            $matches
24        );
25        $name = $res ? trim($matches[1]) : null;
26        $sport_type = $res ? trim($matches[2]) : null;
27
28        $res = preg_match(
29            "/<div class=\"details\"> <time>([^<]+)<\\/time>/",
30            $content,
31            $matches
32        );
33        $date_string = $res ? trim($matches[1]) : null;
34        $date = $date_string ? ($this->parseDateDe($date_string) ?? $this->parseDateEn($date_string)) : null;
35
36        $res = preg_match(
37            "/<strong>([0-9\\.\\,]+)<abbr[^>]*>\\s*km<\\/abbr><\\/strong>\\s*<div class=\"label\">(?:Distanz|Distance)<\\/div>/",
38            $content,
39            $matches
40        );
41        $distance1 = $res ? intval(floatval(str_replace(',', '.', trim($matches[1]))) * 1000) : null;
42
43        $res = preg_match(
44            "/<div[^>]*>(?:Distanz|Distance)<\\/div>\\s*<div[^>]*>\\s*<strong>([0-9\\.\\,]+)<abbr[^>]*>\\s*km<\\/abbr><\\/strong>/",
45            $content,
46            $matches
47        );
48        $distance2 = $res ? intval(floatval(str_replace(',', '.', trim($matches[1]))) * 1000) : null;
49
50        $res = preg_match(
51            "/<strong>([0-9\\.\\,]+)<abbr[^>]*>\\s*m<\\/abbr><\\/strong>\\s*<div class=\"label\">(?:Höhenmeter|Elevation)<\\/div>/",
52            $content,
53            $matches
54        );
55        $elevation1 = $res ? intval(str_replace(',', '.', trim($matches[1]))) : null;
56
57        $res = preg_match(
58            "/<div[^>]*>(?:Höhenmeter|Elevation)<\\/div>\\s*<div[^>]*>\\s*<strong>([0-9\\.\\,]+)<abbr[^>]*>\\s*m<\\/abbr><\\/strong>/",
59            $content,
60            $matches
61        );
62        $elevation2 = $res ? intval(str_replace(',', '.', trim($matches[1]))) : null;
63
64        return [
65            'name' => $name,
66            'sportType' => $sport_type,
67            'runAt' => $date,
68            'distanceMeters' => $distance1 ?? $distance2,
69            'elevationMeters' => $elevation1 ?? $elevation2,
70        ];
71    }
72
73    protected function parseDateEn(string $date_string): ?\DateTime {
74        $pattern = '/([0-9]+):([0-9]+) on \w+, ([0-9]+) (\w+) ([0-9]+)/';
75        $res = preg_match($pattern, $date_string, $matches);
76        if (!$res) {
77            return null;
78        }
79        $hour = $matches[1];
80        $minute = $matches[2];
81        $day = $matches[3];
82        $pretty_month = strtolower($matches[4]);
83        $month_map = [
84            'january' => '01',
85            'february' => '02',
86            'march' => '03',
87            'april' => '04',
88            'may' => '05',
89            'june' => '06',
90            'july' => '07',
91            'august' => '08',
92            'september' => '09',
93            'october' => '10',
94            'november' => '11',
95            'december' => '12',
96        ];
97        $month = $month_map[$pretty_month] ?? null;
98        $year = $matches[5];
99        try {
100            return new \DateTime("{$year}-{$month}-{$day} {$hour}:{$minute}:00");
101        } catch (\Throwable $th) {
102            return null;
103        }
104    }
105
106    protected function parseDateDe(string $date_string): ?\DateTime {
107        $pattern = '/([0-9]+):([0-9]+) am \w+, den ([0-9]+). (\w+) ([0-9]+)/';
108        $res = preg_match($pattern, $date_string, $matches);
109        if (!$res) {
110            return null;
111        }
112        $hour = $matches[1];
113        $minute = $matches[2];
114        $day = $matches[3];
115        $pretty_month = strtolower($matches[4]);
116        $month_map = [
117            'januar' => '01',
118            'februar' => '02',
119            'märz' => '03',
120            'april' => '04',
121            'mai' => '05',
122            'juni' => '06',
123            'juli' => '07',
124            'august' => '08',
125            'september' => '09',
126            'oktober' => '10',
127            'november' => '11',
128            'dezember' => '12',
129        ];
130        $month = $month_map[$pretty_month] ?? null;
131        $year = $matches[5];
132        try {
133            return new \DateTime("{$year}-{$month}-{$day} {$hour}:{$minute}:00");
134        } catch (\Throwable $th) {
135            return null;
136        }
137    }
138}