Skip to content

Commit

Permalink
Merge pull request #16 from benrowe/releases/build-4
Browse files Browse the repository at this point in the history
Releases/build 4
  • Loading branch information
benrowe authored Dec 27, 2016
2 parents 2d15286 + d18d9fb commit 4aef779
Show file tree
Hide file tree
Showing 31 changed files with 566 additions and 53 deletions.
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
APP_ENV=dev

LASTFM_KEY=
LASTFM_SECRET=
LASTFM_SECRET=
LASTFM_PAGINATION_LIMIT=5
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/vendor/
.env
.idea
.idea
/storage/views/
28 changes: 28 additions & 0 deletions app/Http/Controllers/ArtistController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace App\Http\Controllers;

use App\Exceptions\HttpException;
use App\Services\LastFm\Response\Artist;

class ArtistController extends AbstractController
{
public function actionView($id)
{
return $this->view('artist', ['artist' => $this->getModel($id)]);
}

/**
* @param string $id
* @return Artist
* @throws HttpException
*/
private function getModel($id)
{
$model = \App\app()->get('lastfm')->artist->find($id);
if (!$model) {
throw new HttpException('Artist not found', 404);
}
return $model;
}
}
13 changes: 13 additions & 0 deletions app/Http/Controllers/DefaultController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace App\Http\Controllers;

use App\Models\Country;
use App\Models\Forms\SearchForm;

/**
* Class DefaultController
*
Expand All @@ -14,6 +17,16 @@ class DefaultController extends AbstractController
*/
public function actionIndex()
{
$searchForm = new SearchForm;

if ($this->hasRequestParam('SearchForm')) {
$searchForm->fill($this->getRequestParam('SearchForm'));
}

return $this->view('default', [
'countries' => Country::all(),
'model' => $searchForm,
'results' => $searchForm->isSearchable() ? $searchForm->results() : null,
]);
}
}
1 change: 1 addition & 0 deletions app/Http/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
* @var \League\Route\RouteCollection $route
*/
$route->addRoute('GET', '/', DefaultController::class.'::index');
$route->addRoute('GET', '/artist/{id}', ArtistController::class.'::view');
52 changes: 52 additions & 0 deletions app/Models/AbstractModel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace App\Models;

use App\Exceptions\InvalidParamException;

/**
*
* @package App\Models
*/
abstract class AbstractModel
{
protected $attributes = [];

public function __construct($attributes = null)
{
if (is_array($attributes)) {
$this->attributes = $attributes;
}
}

public function fill(array $attributes)
{
$this->attributes = array_merge($this->attributes, $attributes);
}

/**
* Access attributes as properties
*
* @param string $key
* @return mixed
* @throws InvalidParamException
*/
public function __get($key)
{
if (array_key_exists($key, $this->attributes)) {
return $this->attributes[$key];
}
throw new InvalidParamException(sprintf("Unknown property %s", $key));
}

/**
* Set the attribute
*
* @param string $key
* @param mixed $value
*/
public function __set($key, $value)
{
$this->attributes[$key] = $value;
}
}
70 changes: 70 additions & 0 deletions app/Models/Forms/SearchForm.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

namespace App\Models\Forms;

use App\Models\AbstractModel;
use App\Models\Country;
use App\Services\LastFm\Client;

/**
*
* @property Country country
* @package App\Models
*/
class SearchForm extends AbstractModel
{
/**
* Default attributes
*
* @var array
*/
protected $attributes = ['country' => 'AU'];

/**
* Calculate the result set based on the current state of the object
*
* @return ResultSet
*/
public function results()
{
$client = $this->getLastFmApi();

return $client->geo->topArtists($this->country()->name);
}

/**
* Check the state of the SearchForm model to determine if a search could
* return possible results
*
* @return boolean [description]
*/
public function isSearchable()
{
return count(array_filter($this->attributes)) > 0;
}

/**
* Get the country model
*
* @return Country|null
*/
public function country()
{
if ($this->country) {
return Country::findById($this->country);
}

return null;
}

/**
* Get the LastFm Api Client
*
* @return Client
* @todo move this app container injection
*/
public function getLastFmApi(): Client
{
return \App\app()->get('lastfm');
}
}
97 changes: 86 additions & 11 deletions app/Services/LastFm/Api/Artist.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,46 +12,74 @@
use App\Services\LastFm\Exception;
use App\Services\LastFm\Response\AbstractResponse;
use App\Services\LastFm\Response\Artist as ArtistResponse;
use App\Services\LastFm\Response\Track;
use App\Services\LastFm\SearchRequest;
use App\Services\LastFm\Support\Musicbrainz;

/**
* Artist API
*
* @package App\Services\LastFm\Api
*/
class Artist implements Searchable
{
/**
* @var Client
*/
private $client;

/**
* Artist constructor.
*
* @param Client $client
*/
public function __construct(Client $client)
{
$this->client = $client;
}

public function search(SearchRequest $request): ResultSet
/**
* Search last fm for artists based on the provided SearchRequest criteria
*
* @param SearchRequest $request
* @param array $params
* @return ResultSet
*/
public function search(SearchRequest $request, array $params = []): ResultSet
{
$response = $this->client->request('artist.search', $request->toArray());
$params = array_merge($params, $request->toArray());
$response = $this->client->request(
'artist.search',
$params
);

return AbstractResponse::makeResultSet($this->client, $response, ArtistResponse::class, 'results.artistmatches.artist');
return AbstractResponse::makeResultSet(
$this->client,
$response,
ArtistResponse::class,
'results.artistmatches.artist'
);
}

/**
* Find the artist by their id
*
* @param string $id either the musicbrainz id or the artist name
* @param string $artistRef either the musicbrainz id or the artist name
* @return ArtistResponse|bool false when no artist found
* @throws Exception
*/
public function find($id)
public function find($artistRef)
{
if ((new Musicbrainz())->isValidId($id)) {
$params = ['mbid' => $id];
} else {
$params = ['artist' => $id];
}
$params = $this->buildArtistParams($artistRef);

try {
$response = $this->client->request('artist.getInfo', $params);
return AbstractResponse::make($this->client, $response, ArtistResponse::class, 'artist');
return AbstractResponse::make(
$this->client,
$response,
ArtistResponse::class,
'artist'
);
} catch (Exception $e) {
if ($e->getCode() == 6) {
// artist not found
Expand All @@ -60,4 +88,51 @@ public function find($id)
throw $e;
}
}

/**
* Get top tracks for specified artist
*
* @param string $artistRef either the musicbrainz id or the artist name
* @param array $params additional api params
* @return \App\Services\LastFm\Response\ResultSet|bool
* @throws Exception
*/
public function topTracks($artistRef, array $params = [])
{
$params = $this->buildArtistParams($artistRef);
$params = array_merge($params, $params);
try {
$response = $this->client->request(
'artist.gettoptracks',
$params
);
} catch (Exception $e) {
if ($e->getCode() == 6) {
return false;
}
throw $e;
}

return AbstractResponse::makeResultSet(
$this->client,
$response,
Track::class,
'toptracks.track'
);
}

/**
* Build the arist api params based on the type of data being provided
*
* @param string $artistRef
* @return array
*/
private function buildArtistParams($artistRef): array
{
if ((new Musicbrainz())->isValidId($artistRef)) {
return ['mbid' => $artistRef];
}

return ['artist' => $artistRef];
}
}
39 changes: 39 additions & 0 deletions app/Services/LastFm/Api/Geo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace App\Services\LastFm\Api;

use App\Services\LastFm\Client;
use App\Services\LastFm\Response\AbstractResponse;
use App\Services\LastFm\Response\Artist as ArtistResponse;

/**
*
* @package App\Services\LastFm
*/
class Geo
{
/**
* @var Client
*/
private $client;

public function __construct(Client $client)
{
$this->client = $client;
}

/**
* Get the top artists per country
*
* @param string $countryCode ISO 3166-1 country code
* @param array $params additional params for the api request
* @return ResultSet
*/
public function topArtists($countryCode, array $params = [])
{
$params = array_merge($params, ['country' => $countryCode]);
$response = $this->client->request('geo.gettopartists', $params);

return AbstractResponse::makeResultSet($this->client, $response, ArtistResponse::class, 'topartists.artist');
}
}
Loading

0 comments on commit 4aef779

Please sign in to comment.