Skip to content

Commit

Permalink
feature: implement FilterQuery, closes #1 and closes #2
Browse files Browse the repository at this point in the history
  • Loading branch information
g105b committed Aug 15, 2023
1 parent a71b81d commit a9d1e10
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 5 deletions.
8 changes: 5 additions & 3 deletions example/search-getAlbumArtworkForTrackSearch.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
$clientId = $config["client_id"];
$clientSecret = $config["client_secret"];

$artistName = "Richard John Birkin";
$trackName = "Vigil V";
$artistName = "Order of the Toad";
$trackName = "Spirit Man";

$client = new SpotifyClient($clientId, $clientSecret);
$query = new FilterQuery(artist: $artistName, album: $trackName);

$searchResults = $client->search->query(
"artist: '$artistName' album: '$trackName'",
$query,
new SearchFilter(EntityType::album, EntityType::track),
"GB",
limit: 5
Expand Down
60 changes: 60 additions & 0 deletions src/Entity/FilterQuery.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php
namespace SHIFT\Spotify\Entity;

use Stringable;

/**
* There's an explanation for the weird use of "%3A" in the strings.
* Spotify's API doesn't make perfect matches on all searches unless the colons are urlencoded.
* However, if the whole string is encoded (spaces becoming %20), results are mis-matched again.
* From going through a lot of test data, encoding ONLY the colons is the only way to
* get a correct match all of the time from the live API. This may be a bug on Spotify's end,
* but whatever the cause, this is a solution battle tested by TrackShift.
*/
readonly class FilterQuery implements Stringable {
public function __construct(
public string $baseQuery = "",
public ?string $album = null,
public ?string $artist = null,
public ?string $track = null,
public ?string $year = null,
public ?string $upc = null,
public ?string $genre = null,
public bool $new = false,
public bool $hipster = false,
) {}

public function __toString():string {
$stringParts = [];
if($this->baseQuery) {
array_push($stringParts, $this->baseQuery);
}

if($this->album) {
array_push($stringParts, "album%3A$this->album");
}
if($this->artist) {
array_push($stringParts, "artist%3A$this->artist");
}
if($this->track) {
array_push($stringParts, "track%3A$this->track");
}
if($this->year) {
array_push($stringParts, "year%3A$this->year");
}
if($this->upc) {
array_push($stringParts, "upc%3A$this->upc");
}
if($this->genre) {
array_push($stringParts, "genre%3A$this->genre");
}
if($this->new) {
array_push($stringParts, "tag%3Anew");
}
if($this->hipster) {
array_push($stringParts, "tag%3Ahipster");
}

return implode(" ", $stringParts);
}
}
8 changes: 6 additions & 2 deletions src/SpotifyClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,12 @@ public function request(string $endpoint, RequestMethod $method = RequestMethod:
];
if($kvp) {
if($method === RequestMethod::GET) {
$query = new URLSearchParams($kvp);
$endpoint .= "?$query";
$endpoint .= "?";
// This should use URLSearchParams, which handles all encoding to web standards...
// ...but if it's done "correctly", Spotify's API breaks! This is a workaround for some strange API behaviour.
foreach($kvp as $key => $value) {
$endpoint .= "&$key=$value";
}
}
else {
$formData = new FormData();
Expand Down
42 changes: 42 additions & 0 deletions test/phpunit/Entity/FilterQueryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php
namespace SHIFT\Spotify\Test\Entity;

use PHPUnit\Framework\TestCase;
use SHIFT\Spotify\Entity\FilterQuery;

class FilterQueryTest extends TestCase {
public function testConstruct_simpleQuery():void {
$sut = new FilterQuery("One Two Three");
self::assertSame("One Two Three", (string)$sut);
}

public function testConstruct_justArtistAndTrack():void {
$sut = new FilterQuery(artist: "Order of the Toad", track: "Spirit Man");
self::assertSame("artist%3AOrder of the Toad track%3ASpirit Man", (string)$sut);
}

public function testConstruct_albumArtistTrackYear():void {
$sut = new FilterQuery(
album: "white",
artist: "the",
track: "and",
year: "1900-2020",
);
self::assertSame("album%3Awhite artist%3Athe track%3Aand year%3A1900-2020", (string)$sut);
}

public function testConstruct_new():void {
$sut = new FilterQuery(new: true);
self::assertSame("tag%3Anew", (string)$sut);
}

public function testConstruct_hipster():void {
$sut = new FilterQuery(hipster: true);
self::assertSame("tag%3Ahipster", (string)$sut);
}

public function testConstruct_newHipster():void {
$sut = new FilterQuery(new: true, hipster: true);
self::assertSame("tag%3Anew tag%3Ahipster", (string)$sut);
}
}

0 comments on commit a9d1e10

Please sign in to comment.