Skip to content
This repository was archived by the owner on Mar 23, 2024. It is now read-only.

Commit 062acd9

Browse files
committed
✨ SoundCloud (half-) automatic endpoint map creation
1 parent a1d9c6d commit 062acd9

File tree

3 files changed

+850
-69
lines changed

3 files changed

+850
-69
lines changed
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
<?php
2+
/**
3+
* @link https://developers.soundcloud.com/docs/api/explorer/open-api
4+
* @link https://developers.soundcloud.com/docs/api/explorer/swagger-ui-init.js (OpenAPI spec)
5+
*
6+
* @created 21.03.2021
7+
* @author smiley <smiley@chillerlan.net>
8+
* @copyright 2021 smiley
9+
* @license MIT
10+
*/
11+
12+
use chillerlan\OAuth\Providers\SoundCloud\SoundCloud;
13+
14+
$ENVVAR = 'SOUNDCLOUD';
15+
16+
require_once __DIR__.'/create-endpointmap-common.php';
17+
18+
/**
19+
* @var \Psr\Http\Client\ClientInterface $http
20+
* @var \chillerlan\OAuth\Storage\OAuthStorageInterface $storage
21+
* @var \chillerlan\Settings\SettingsContainerInterface $options
22+
* @var \Psr\Log\LoggerInterface $logger
23+
*/
24+
25+
$soundcloud = new SoundCloud($http, $storage, $options, $logger);
26+
$url = 'https://developers.soundcloud.com/docs/api/explorer/open-api';
27+
$openapi = json_decode(file_get_contents(__DIR__.'/soundcloud-openapi.json'));
28+
$content = [];
29+
30+
$fixtures = [
31+
'delete' => 'Delete',
32+
'get' => '',
33+
'patch' => 'Update',
34+
'post' => 'Create',
35+
'put' => 'Update', // doesn't seem there's a difference between PUT and PATCH here
36+
];
37+
38+
foreach($openapi->paths as $path => $meta){
39+
40+
if(in_array($path, ['/connect', '/oauth2/token'])){
41+
continue;
42+
}
43+
44+
$baseName = lcfirst(implode('', array_map('ucfirst', explode('-', str_replace(['{', '}', '/', '_'], '-', $path)))));
45+
$urlparams = [];
46+
47+
$count = 0;
48+
$path = preg_replace_callback('/(?:\{([^\}]+)\})/i', function(array $matches) use (&$count, &$urlparams):string{
49+
$urlparams[] = $matches[1];
50+
return '%'.++$count.'$s';
51+
}, $path);
52+
53+
foreach($meta as $method => $info){
54+
$name = $baseName.$fixtures[$method];
55+
$query = [];
56+
$headers = [];
57+
$body = [];
58+
if(isset($info->parameters)){
59+
foreach($info->parameters as $ref){
60+
$ref = getRef($ref->{'$ref'}, $openapi);
61+
62+
if($ref->in === 'query'){
63+
$query[] = $ref->name;
64+
}
65+
}
66+
}
67+
68+
if(isset($info->requestBody) && empty($headers)){
69+
$contentType = isset($info->requestBody->content->{'application/json'})
70+
? 'application/json'
71+
: 'multipart/x-www-form-urlencoded';
72+
73+
$ref = getRef($info->requestBody->content->{$contentType}->schema->{'$ref'}, $openapi);
74+
$body = array_keys((array)$ref->properties);
75+
$headers[] = '\'Content-Type\' => \''.$contentType.'\'';
76+
}
77+
78+
$content[$name] = '
79+
/**
80+
* '.$info->summary.'
81+
*/
82+
protected array $'.$name.' = [
83+
\'method\' => \''.strtoupper($method).'\',
84+
\'path\' => \''.$path.'\',
85+
\'path_elements\' => '.(!empty($urlparams) ? '[\''.implode('\', \'', $urlparams).'\']' : 'null').',
86+
\'query\' => '.(!empty($query) ? '[\''.implode('\', \'', $query).'\']' : 'null').',
87+
\'body\' => '.(!empty($body) ? '[\''.implode('\', \'', $body).'\']' : 'null').',
88+
\'headers\' => '.(!empty($headers) ? '['.implode(', ', $headers).']' : 'null').',
89+
];';
90+
91+
$logger->info($name. ' - ' .$path);
92+
}
93+
94+
}
95+
96+
// and replace the class
97+
createEndpointMap($content, $url, $soundcloud->endpoints);
98+
99+
exit;
100+
101+
function getRef(string $ref, object $target){
102+
$ref = explode('/', $ref);
103+
104+
if(empty($ref) || array_shift($ref) !== '#'){
105+
throw new Exception('invalid $ref');
106+
}
107+
108+
$segment = $target;
109+
110+
foreach($ref as $r){
111+
if(isset($segment->{$r})){
112+
$segment = $segment->{$r};
113+
}
114+
else{
115+
throw new Exception('cannot find segment: '.$r);
116+
}
117+
}
118+
119+
return $segment;
120+
}

src/SoundCloud/SoundCloud.php

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,70 @@
1616
use chillerlan\OAuth\Core\{OAuth2Provider};
1717

1818
/**
19+
* @method \Psr\Http\Message\ResponseInterface likesPlaylistsPlaylistIdCreate(string $playlist_id)
20+
* @method \Psr\Http\Message\ResponseInterface likesPlaylistsPlaylistIdDelete(string $playlist_id)
21+
* @method \Psr\Http\Message\ResponseInterface likesTracksTrackIdCreate(string $track_id)
22+
* @method \Psr\Http\Message\ResponseInterface likesTracksTrackIdDelete(string $track_id)
1923
* @method \Psr\Http\Message\ResponseInterface me()
20-
* @method \Psr\Http\Message\ResponseInterface user(string $id)
24+
* @method \Psr\Http\Message\ResponseInterface meActivities(array $params = ['limit'])
25+
* @method \Psr\Http\Message\ResponseInterface meActivitiesAllOwn(array $params = ['limit'])
26+
* @method \Psr\Http\Message\ResponseInterface meActivitiesTracks(array $params = ['limit'])
27+
* @method \Psr\Http\Message\ResponseInterface meConnections(array $params = ['limit', 'offset'])
28+
* @method \Psr\Http\Message\ResponseInterface meConnectionsConnectionId(string $connection_id)
29+
* @method \Psr\Http\Message\ResponseInterface meFavoritesIds(array $params = ['limit'])
30+
* @method \Psr\Http\Message\ResponseInterface meFollowers(array $params = ['limit'])
31+
* @method \Psr\Http\Message\ResponseInterface meFollowersFollowerId(string $follower_id)
32+
* @method \Psr\Http\Message\ResponseInterface meFollowings(array $params = ['limit', 'offset'])
33+
* @method \Psr\Http\Message\ResponseInterface meFollowingsTracks(array $params = ['limit', 'offset'])
34+
* @method \Psr\Http\Message\ResponseInterface meFollowingsUserId(string $user_id)
35+
* @method \Psr\Http\Message\ResponseInterface meFollowingsUserIdDelete(string $user_id)
36+
* @method \Psr\Http\Message\ResponseInterface meFollowingsUserIdUpdate(string $user_id)
37+
* @method \Psr\Http\Message\ResponseInterface meLikesTracks(array $params = ['limit', 'linked_partitioning'])
38+
* @method \Psr\Http\Message\ResponseInterface mePlaylists(array $params = ['limit'])
39+
* @method \Psr\Http\Message\ResponseInterface mePlaylistsPlaylistId(string $playlist_id)
40+
* @method \Psr\Http\Message\ResponseInterface meTracks(array $params = ['limit', 'linked_partitioning'])
41+
* @method \Psr\Http\Message\ResponseInterface meTracksTrackId(string $track_id)
42+
* @method \Psr\Http\Message\ResponseInterface meWebProfiles(array $params = ['limit'])
43+
* @method \Psr\Http\Message\ResponseInterface playlists(array $params = ['q', 'limit', 'offset', 'linked_partitioning'])
44+
* @method \Psr\Http\Message\ResponseInterface playlistsCreate(array $body = ['playlist'])
45+
* @method \Psr\Http\Message\ResponseInterface playlistsPlaylistId(string $playlist_id, array $params = ['secret_token'])
46+
* @method \Psr\Http\Message\ResponseInterface playlistsPlaylistIdDelete(string $playlist_id)
47+
* @method \Psr\Http\Message\ResponseInterface playlistsPlaylistIdTracks(string $playlist_id, array $params = ['secret_token', 'linked_partitioning'])
48+
* @method \Psr\Http\Message\ResponseInterface playlistsPlaylistIdUpdate(string $playlist_id, array $body = ['playlist'])
49+
* @method \Psr\Http\Message\ResponseInterface repostsPlaylistsPlaylistIdCreate(string $playlist_id)
50+
* @method \Psr\Http\Message\ResponseInterface repostsPlaylistsPlaylistIdDelete(string $playlist_id)
51+
* @method \Psr\Http\Message\ResponseInterface repostsTracksTrackIdCreate(string $track_id)
52+
* @method \Psr\Http\Message\ResponseInterface repostsTracksTrackIdDelete(string $track_id)
53+
* @method \Psr\Http\Message\ResponseInterface resolve(array $params = ['url'])
54+
* @method \Psr\Http\Message\ResponseInterface tracks(array $params = ['q', 'ids', 'genres', 'tags', 'bpm', 'duration', 'created_at', 'limit', 'offset', 'linked_partitioning'])
55+
* @method \Psr\Http\Message\ResponseInterface tracksCreate(array $body = ['track[title]', 'track[asset_data]', 'track[permalink]', 'track[sharing]', 'track[embeddable_by]', 'track[purchase_url]', 'track[description]', 'track[genre]', 'track[tag_list]', 'track[label_name]', 'track[release]', 'track[release_date]', 'track[streamable]', 'track[downloadable]', 'track[license]', 'track[commentable]', 'track[isrc]', 'track[artwork_data]'])
56+
* @method \Psr\Http\Message\ResponseInterface tracksTrackId(string $track_id, array $params = ['secret_token'])
57+
* @method \Psr\Http\Message\ResponseInterface tracksTrackIdComments(string $track_id, array $params = ['limit', 'offset', 'linked_partitioning'])
58+
* @method \Psr\Http\Message\ResponseInterface tracksTrackIdCommentsCreate(string $track_id)
59+
* @method \Psr\Http\Message\ResponseInterface tracksTrackIdDelete(string $track_id)
60+
* @method \Psr\Http\Message\ResponseInterface tracksTrackIdFavoriters(string $track_id, array $params = ['limit', 'offset'])
61+
* @method \Psr\Http\Message\ResponseInterface tracksTrackIdRelated(string $track_id, array $params = ['limit', 'offset', 'linked_partitioning'])
62+
* @method \Psr\Http\Message\ResponseInterface tracksTrackIdStreams(string $track_id, array $params = ['secret_token'])
63+
* @method \Psr\Http\Message\ResponseInterface tracksTrackIdUpdate(string $track_id, array $body = ['track'])
64+
* @method \Psr\Http\Message\ResponseInterface users(array $params = ['q', 'ids', 'limit', 'offset', 'linked_partitioning'])
65+
* @method \Psr\Http\Message\ResponseInterface usersUserId(string $user_id)
66+
* @method \Psr\Http\Message\ResponseInterface usersUserIdComments(string $user_id, array $params = ['limit', 'offset'])
67+
* @method \Psr\Http\Message\ResponseInterface usersUserIdFavorites(string $user_id, array $params = ['limit', 'linked_partitioning'])
68+
* @method \Psr\Http\Message\ResponseInterface usersUserIdFollowers(string $user_id, array $params = ['limit'])
69+
* @method \Psr\Http\Message\ResponseInterface usersUserIdFollowersFollowerId(string $user_id, string $follower_id)
70+
* @method \Psr\Http\Message\ResponseInterface usersUserIdFollowings(string $user_id, array $params = ['limit'])
71+
* @method \Psr\Http\Message\ResponseInterface usersUserIdFollowingsFollowingId(string $user_id, string $following_id)
72+
* @method \Psr\Http\Message\ResponseInterface usersUserIdLikesTracks(string $user_id, array $params = ['limit', 'linked_partitioning'])
73+
* @method \Psr\Http\Message\ResponseInterface usersUserIdPlaylists(string $user_id, array $params = ['limit', 'linked_partitioning'])
74+
* @method \Psr\Http\Message\ResponseInterface usersUserIdTracks(string $user_id, array $params = ['limit', 'linked_partitioning'])
75+
* @method \Psr\Http\Message\ResponseInterface usersUserIdWebProfiles(string $user_id, array $params = ['limit'])
2176
*/
2277
class SoundCloud extends OAuth2Provider{
2378

2479
public const SCOPE_NONEXPIRING = 'non-expiring';
2580
# public const SCOPE_EMAIL = 'email'; // ???
2681
27-
protected string $authURL = 'https://soundcloud.com/connect';
82+
protected string $authURL = 'https://api.soundcloud.com/connect';
2883
protected string $accessTokenURL = 'https://api.soundcloud.com/oauth2/token';
2984
protected ?string $apiURL = 'https://api.soundcloud.com';
3085
protected ?string $userRevokeURL = 'https://soundcloud.com/settings/connections';

0 commit comments

Comments
 (0)