|
| 1 | +# Upgrading from 3.x to 4.0.0 |
| 2 | + |
| 3 | +## Requirements |
| 4 | + |
| 5 | +- PHP **8.2** or higher (raised from 8.1) |
| 6 | +- `surfoo/oauth2-geocaching` **^3.0** (new required package — see Authentication section) |
| 7 | + |
| 8 | +Update your dependencies: |
| 9 | + |
| 10 | +```bash |
| 11 | +composer require surfoo/geocaching-php-sdk:^4.0 surfoo/oauth2-geocaching:^3.0 |
| 12 | +``` |
| 13 | + |
| 14 | +--- |
| 15 | + |
| 16 | +## Breaking Changes |
| 17 | + |
| 18 | +### PHP 8.1 dropped |
| 19 | + |
| 20 | +PHP 8.1 is no longer supported. Update your runtime to PHP 8.2+. |
| 21 | + |
| 22 | +### `GeocachingSdkInterface` removed |
| 23 | + |
| 24 | +The `GeocachingSdkInterface` interface has been removed. `GeocachingSdk` is no longer `final` either. If you were type-hinting against the interface, switch to the concrete class or your own interface. |
| 25 | + |
| 26 | +**Before:** |
| 27 | +```php |
| 28 | +use Geocaching\GeocachingSdkInterface; |
| 29 | + |
| 30 | +function doSomething(GeocachingSdkInterface $sdk): void { ... } |
| 31 | +``` |
| 32 | + |
| 33 | +**After:** |
| 34 | +```php |
| 35 | +use Geocaching\GeocachingSdk; |
| 36 | + |
| 37 | +function doSomething(GeocachingSdk $sdk): void { ... } |
| 38 | +``` |
| 39 | + |
| 40 | +### `ClientBuilder::getHttpClient()` return type changed |
| 41 | + |
| 42 | +The return type of `ClientBuilder::getHttpClient()` changed from `ClientInterface` (PSR-18) to `HttpMethodsClientInterface` (HTTPlug), which is a superset. This is only a breaking change if you stored the result in a typed variable or type-hinted against `ClientInterface`. |
| 43 | + |
| 44 | +**Before:** |
| 45 | +```php |
| 46 | +use Psr\Http\Client\ClientInterface; |
| 47 | + |
| 48 | +$client = $options->getClientBuilder()->getHttpClient(); // ClientInterface |
| 49 | +``` |
| 50 | + |
| 51 | +**After:** |
| 52 | +```php |
| 53 | +use Http\Client\Common\HttpMethodsClientInterface; |
| 54 | + |
| 55 | +$client = $options->getClientBuilder()->getHttpClient(); // HttpMethodsClientInterface |
| 56 | +``` |
| 57 | + |
| 58 | +### `Options` and `ClientBuilder` are no longer `final` |
| 59 | + |
| 60 | +Both classes were `final` in 3.x. In 4.0 this restriction is removed, so extension is now possible. |
| 61 | + |
| 62 | +### `setGeocacheUserWaypoint()` signature changed |
| 63 | + |
| 64 | +The `$referenceCode` first parameter has been removed. |
| 65 | + |
| 66 | +**Before:** |
| 67 | +```php |
| 68 | +$sdk->setGeocacheUserWaypoint($referenceCode, $body, $headers); |
| 69 | +``` |
| 70 | + |
| 71 | +**After:** |
| 72 | +```php |
| 73 | +$sdk->setGeocacheUserWaypoint($body, $headers); |
| 74 | +``` |
| 75 | + |
| 76 | +### `updateUserWaypoint()` parameter renamed |
| 77 | + |
| 78 | +The third parameter was `array $query` (misleading); it is now `array $waypoint` to reflect its actual purpose. The call signature is unchanged but semantics are clearer. |
| 79 | + |
| 80 | +### `updateGeocacheNote()` parameter renamed |
| 81 | + |
| 82 | +The parameter `array $note` is now `array $notes` (plural). No functional change. |
| 83 | + |
| 84 | +### `getHQPromotions()` now accepts a `$query` parameter |
| 85 | + |
| 86 | +**Before:** |
| 87 | +```php |
| 88 | +$sdk->getHQPromotions($headers); |
| 89 | +``` |
| 90 | + |
| 91 | +**After:** |
| 92 | +```php |
| 93 | +$sdk->getHQPromotions($query, $headers); |
| 94 | +// or keep passing only headers (first arg defaults to []) |
| 95 | +$sdk->getHQPromotions([], $headers); |
| 96 | +``` |
| 97 | + |
| 98 | +### `getGeocachesGeotour()` renamed to `getGeotourGeocaches()` |
| 99 | + |
| 100 | +**Before:** |
| 101 | +```php |
| 102 | +$sdk->getGeocachesGeotour($referenceCode, $query, $headers); |
| 103 | +``` |
| 104 | + |
| 105 | +**After:** |
| 106 | +```php |
| 107 | +$sdk->getGeotourGeocaches($referenceCode, $query, $headers); |
| 108 | +``` |
| 109 | + |
| 110 | +### `getStartLocationAdventure()` removed |
| 111 | + |
| 112 | +This endpoint was removed from the Geocaching API and is no longer available. |
| 113 | + |
| 114 | +--- |
| 115 | + |
| 116 | +## New Features |
| 117 | + |
| 118 | +The sections below describe what 4.0 adds. Nothing else you already use has been removed. |
| 119 | + |
| 120 | +### Automatic token refresh |
| 121 | + |
| 122 | +Pass a `TokenStorageInterface` and a `reference_code` (the user's Geocaching reference code, e.g. `'PR12345'`) to `Options` to enable automatic access-token refresh on `401` responses. The SDK will refresh, store the new token, and retry the request transparently. |
| 123 | + |
| 124 | +```php |
| 125 | +use Geocaching\Options; |
| 126 | +use Geocaching\Enum\Environment; |
| 127 | +use League\OAuth2\Client\Provider\Geocaching as OAuthProvider; |
| 128 | + |
| 129 | +$provider = new OAuthProvider([ |
| 130 | + 'clientId' => 'your-client-id', |
| 131 | + 'clientSecret' => 'your-client-secret', |
| 132 | + 'redirectUri' => 'https://example.com/callback', |
| 133 | + 'environment' => 'production', |
| 134 | +]); |
| 135 | + |
| 136 | +$options = new Options([ |
| 137 | + 'environment' => Environment::PRODUCTION, |
| 138 | + 'access_token' => $storedAccessToken, |
| 139 | + 'token_storage' => new MyTokenStorage(), // implements TokenStorageInterface |
| 140 | + 'reference_code' => 'PR12345', |
| 141 | +]); |
| 142 | +``` |
| 143 | + |
| 144 | +`TokenStorageInterface` and `TokenSet` come from `surfoo/oauth2-geocaching ^3.0`. See that package's `UPGRADE-3.0.md` for implementation details. |
| 145 | + |
| 146 | +When `token_storage` and `reference_code` are omitted, the SDK behaves exactly as in 3.x with a static bearer token. |
| 147 | + |
| 148 | +### HTTP request/response logging |
| 149 | + |
| 150 | +```php |
| 151 | +use Psr\Log\LogLevel; |
| 152 | + |
| 153 | +$options->enableHttpLogging( |
| 154 | + 'php://stdout', // destination: file path, php://stdout, php://stderr |
| 155 | + LogLevel::INFO, // minimum log level |
| 156 | + false, // log request/response bodies |
| 157 | + true, // mask bearer tokens in logs |
| 158 | + 1000 // max body length before truncation |
| 159 | +); |
| 160 | +``` |
| 161 | + |
| 162 | +Each request gets a unique correlation ID so requests and responses can be matched. Sensitive tokens are masked automatically. HTTP 4xx/5xx responses are logged at `WARNING`/`ERROR` level regardless of the configured level. |
| 163 | + |
| 164 | +### Reliability plugins |
| 165 | + |
| 166 | +#### Retry |
| 167 | + |
| 168 | +```php |
| 169 | +use Geocaching\Reliability\ExponentialBackoffStrategy; |
| 170 | +use Geocaching\Reliability\FixedDelayStrategy; |
| 171 | + |
| 172 | +// Exponential back-off: 100ms, 200ms, 400ms, … |
| 173 | +$options->enableRetry( |
| 174 | + maxRetries: 3, |
| 175 | + strategy: new ExponentialBackoffStrategy(initialDelayMs: 100) |
| 176 | +); |
| 177 | + |
| 178 | +// Fixed delay |
| 179 | +$options->enableRetry( |
| 180 | + maxRetries: 3, |
| 181 | + strategy: new FixedDelayStrategy(delayMs: 500) |
| 182 | +); |
| 183 | +``` |
| 184 | + |
| 185 | +#### Circuit breaker |
| 186 | + |
| 187 | +```php |
| 188 | +$options->enableCircuitBreaker( |
| 189 | + failureThreshold: 5, // open after this many consecutive failures |
| 190 | + resetTimeout: 60 // seconds before attempting to close again |
| 191 | +); |
| 192 | +``` |
| 193 | + |
| 194 | +#### Combined reliability plugin |
| 195 | + |
| 196 | +`ReliabilityPlugin` bundles retry and circuit breaker together: |
| 197 | + |
| 198 | +```php |
| 199 | +$options->enableReliability( |
| 200 | + maxRetries: 3, |
| 201 | + strategy: new ExponentialBackoffStrategy(100), |
| 202 | + failureThreshold: 5, |
| 203 | + resetTimeout: 60 |
| 204 | +); |
| 205 | +``` |
| 206 | + |
| 207 | +### New enum: `Attribute` |
| 208 | + |
| 209 | +`Geocaching\Enum\Attribute` covers all 65 geocache attributes (dogs, wheelchair accessible, night cache, etc.) with `id()` returning the Groundspeak attribute ID. |
| 210 | + |
| 211 | +```php |
| 212 | +use Geocaching\Enum\Attribute; |
| 213 | + |
| 214 | +$attr = Attribute::WHEELCHAIR_ACCESSIBLE; |
| 215 | +$attr->value; // 'Wheelchair accessible' |
| 216 | +$attr->id(); // 24 |
| 217 | +``` |
| 218 | + |
| 219 | +### `EnumTrait` on all enums |
| 220 | + |
| 221 | +All enums now use `EnumTrait`, which adds three helpers: |
| 222 | + |
| 223 | +```php |
| 224 | +// Look up an enum by its integer ID |
| 225 | +$type = GeocacheType::fromId(2); // GeocacheType::TRADITIONAL |
| 226 | + |
| 227 | +// Get all human-readable values |
| 228 | +GeocacheType::getList(); // ['Traditional Cache', 'Multi-cache', ...] |
| 229 | + |
| 230 | +// Get all IDs |
| 231 | +GeocacheType::getListId(); // [2, 3, ...] |
| 232 | +``` |
| 233 | + |
| 234 | +### New method: `getDifficultyTerrainStatistics()` |
| 235 | + |
| 236 | +Returns aggregated D/T statistics from the Geocaching API: |
| 237 | + |
| 238 | +```php |
| 239 | +$response = $sdk->getDifficultyTerrainStatistics(); |
| 240 | +``` |
| 241 | + |
| 242 | +### New method: `deleteImageFromLogdraft()` |
| 243 | + |
| 244 | +```php |
| 245 | +$sdk->deleteImageFromLogdraft($referenceCode, $guid, $headers); |
| 246 | +``` |
| 247 | + |
| 248 | +### `ClientBuilderInterface` |
| 249 | + |
| 250 | +A new `ClientBuilderInterface` is available if you need to swap or mock the client builder in your own code: |
| 251 | + |
| 252 | +```php |
| 253 | +use Geocaching\ClientBuilderInterface; |
| 254 | +``` |
| 255 | + |
| 256 | +--- |
| 257 | + |
| 258 | +## New exception: `CircuitBreakerOpenException` |
| 259 | + |
| 260 | +Thrown by `CircuitBreakerPlugin` when the circuit is open and the request is rejected immediately. Catch it to short-circuit your own retry logic: |
| 261 | + |
| 262 | +```php |
| 263 | +use Geocaching\Exception\CircuitBreakerOpenException; |
| 264 | + |
| 265 | +try { |
| 266 | + $response = $sdk->getGeocache('GC12345'); |
| 267 | +} catch (CircuitBreakerOpenException $e) { |
| 268 | + // API is unavailable; serve from cache or return a degraded response |
| 269 | +} |
| 270 | +``` |
0 commit comments