Do you wish to register an account?
Browse Source

More refactoring/cleanup

tags/v4.2.0
Timothy Warren 5 months ago
parent
commit
e4b8e6ce51
17 changed files with 192 additions and 270 deletions
  1. +1
    -0
      composer.json
  2. +1
    -1
      phpstan.neon
  3. +36
    -0
      psalm.xml
  4. +2
    -1
      src/API/Kitsu/Transformer/CharacterTransformer.php
  5. +5
    -1
      src/API/Kitsu/Transformer/PersonTransformer.php
  6. +4
    -1
      src/API/Kitsu/Transformer/UserTransformer.php
  7. +66
    -3
      src/Model/AnimeCollection.php
  8. +9
    -2
      src/Model/Collection.php
  9. +0
    -245
      src/Model/MangaCollection.php
  10. +1
    -1
      src/Types/AbstractType.php
  11. +2
    -2
      src/Types/Anime.php
  12. +2
    -2
      src/Types/AnimeListItem.php
  13. +2
    -5
      src/Types/Character.php
  14. +29
    -0
      src/Types/Characters.php
  15. +1
    -1
      src/Types/Config/Database.php
  16. +29
    -0
      src/Types/Media.php
  17. +2
    -5
      src/Types/Person.php

+ 1
- 0
composer.json View File

@@ -60,6 +60,7 @@
"clean": "vendor/bin/robo clean",
"coverage": "phpdbg -qrr -- vendor/bin/phpunit -c build",
"phpstan": "phpstan analyse -c phpstan.neon",
"psalm": "vendor/bin/psalm",
"watch:css": "cd public && npm run watch:css",
"watch:js": "cd public && npm run watch:js",
"test": "vendor/bin/phpunit -c build --no-coverage",


+ 1
- 1
phpstan.neon View File

@@ -1,12 +1,12 @@
parameters:
checkGenericClassInNonGenericObjectType: false
checkMissingIterableValueType: false
inferPrivatePropertyTypeFromConstructor: true
level: 7
autoload_files:
- %rootDir%/../../../tests/mocks.php
paths:
- src
- tests
- ./console
- index.php
ignoreErrors:


+ 36
- 0
psalm.xml View File

@@ -15,5 +15,41 @@

<issueHandlers>
<LessSpecificReturnType errorLevel="info" />

<!-- level 3 issues - slightly lazy code writing, but provably low false-negatives -->

<DeprecatedMethod errorLevel="info" />
<DeprecatedProperty errorLevel="info" />
<DeprecatedClass errorLevel="info" />
<DeprecatedConstant errorLevel="info" />
<DeprecatedFunction errorLevel="info" />
<DeprecatedInterface errorLevel="info" />
<DeprecatedTrait errorLevel="info" />

<InternalMethod errorLevel="info" />
<InternalProperty errorLevel="info" />
<InternalClass errorLevel="info" />

<MissingClosureReturnType errorLevel="info" />
<MissingReturnType errorLevel="info" />
<MissingPropertyType errorLevel="info" />
<InvalidDocblock errorLevel="info" />
<MisplacedRequiredParam errorLevel="info" />

<PropertyNotSetInConstructor errorLevel="info" />
<MissingConstructor errorLevel="info" />
<MissingClosureParamType errorLevel="info" />
<MissingParamType errorLevel="info" />

<RedundantCondition errorLevel="info" />

<DocblockTypeContradiction errorLevel="info" />
<RedundantConditionGivenDocblockType errorLevel="info" />

<UnresolvableInclude errorLevel="info" />

<RawObjectIteration errorLevel="info" />

<InvalidStringClass errorLevel="info" />
</issueHandlers>
</psalm>

+ 2
- 1
src/API/Kitsu/Transformer/CharacterTransformer.php View File

@@ -28,8 +28,9 @@ final class CharacterTransformer extends AbstractTransformer {

/**
* @param array $characterData
* @return Character
*/
public function transform(array $characterData): Character
public function transform($characterData): Character
{
$data = JsonAPI::organizeData($characterData);
$attributes = $data[0]['attributes'];


+ 5
- 1
src/API/Kitsu/Transformer/PersonTransformer.php View File

@@ -25,7 +25,11 @@ use Aviat\Ion\Transformer\AbstractTransformer;
*/
final class PersonTransformer extends AbstractTransformer {

public function transform(array $personData): Person
/**
* @param array|object $personData
* @return Person
*/
public function transform($personData): Person
{
$data = JsonAPI::organizeData($personData);
$included = JsonAPI::organizeIncludes($personData['included']);


+ 4
- 1
src/API/Kitsu/Transformer/UserTransformer.php View File

@@ -24,9 +24,12 @@ use Aviat\Ion\Transformer\AbstractTransformer;

/**
* Transform user profile data for display
*
* @param array|object $profileData
* @return User
*/
final class UserTransformer extends AbstractTransformer {
public function transform(array $profileData): User
public function transform($profileData): User
{
$orgData = JsonAPI::organizeData($profileData)[0];
$attributes = $orgData['attributes'];


+ 66
- 3
src/Model/AnimeCollection.php View File

@@ -75,6 +75,11 @@ final class AnimeCollection extends Collection {
*/
public function getMediaTypeList(): array
{
if ($this->validDatabase === FALSE)
{
return [];
}

$output = [];

$query = $this->db->select('id, type')
@@ -136,6 +141,11 @@ final class AnimeCollection extends Collection {
*/
public function add($data): void
{
if ($this->validDatabase === FALSE)
{
return;
}

$id = $data['id'];

// Check that the anime doesn't already exist
@@ -166,13 +176,16 @@ final class AnimeCollection extends Collection {
/**
* Verify that an item was added
*
* @param $data
* @param array|null|object $data
*
* @return bool
*/
public function wasAdded($data): bool
{
if ($this->validDatabase === FALSE)
{
return FALSE;
}

$row = $this->get($data['id']);

return ! empty($row);
@@ -186,6 +199,11 @@ final class AnimeCollection extends Collection {
*/
public function update($data): void
{
if ($this->validDatabase === FALSE)
{
return;
}

// If there's no id to update, don't update
if ( ! array_key_exists('hummingbird_id', $data))
{
@@ -206,13 +224,17 @@ final class AnimeCollection extends Collection {
/**
* Verify that the collection item was updated
*
* @param $data
* @param array|null|object $data
*
* @return bool
*/
public function wasUpdated($data): bool
{
if ($this->validDatabase === FALSE)
{
return FALSE;
}

$row = $this->get($data['hummingbird_id']);

foreach ($data as $key => $value)
@@ -234,6 +256,11 @@ final class AnimeCollection extends Collection {
*/
public function delete($data): void
{
if ($this->validDatabase === FALSE)
{
return;
}

// If there's no id to update, don't delete
if ( ! array_key_exists('hummingbird_id', $data))
{
@@ -249,9 +276,15 @@ final class AnimeCollection extends Collection {

/**
* @param array|null|object $data
* @return bool
*/
public function wasDeleted($data): bool
{
if ($this->validDatabase === FALSE)
{
return FALSE;
}

$animeRow = $this->get($data['hummingbird_id']);

return empty($animeRow);
@@ -265,6 +298,11 @@ final class AnimeCollection extends Collection {
*/
public function get($kitsuId)
{
if ($this->validDatabase === FALSE)
{
return FALSE;
}

$query = $this->db->from('anime_set')
->where('hummingbird_id', $kitsuId)
->get();
@@ -280,6 +318,11 @@ final class AnimeCollection extends Collection {
*/
public function getGenreList(array $filter = []): array
{
if ($this->validDatabase === FALSE)
{
return [];
}

$output = [];

// Catch the missing table PDOException
@@ -337,6 +380,11 @@ final class AnimeCollection extends Collection {
*/
private function updateGenre($animeId): void
{
if ($this->validDatabase === FALSE)
{
return;
}

// Get api information
$anime = $this->animeModel->getAnimeById($animeId);

@@ -379,6 +427,11 @@ final class AnimeCollection extends Collection {
*/
private function addNewGenres(array $genres): void
{
if ($this->validDatabase === FALSE)
{
return;
}

$existingGenres = $this->getExistingGenres();
$newGenres = array_diff($genres, $existingGenres);

@@ -416,6 +469,11 @@ final class AnimeCollection extends Collection {

private function getExistingGenres(): array
{
if ($this->validDatabase === FALSE)
{
return [];
}

$genres = [];

// Get existing genres
@@ -435,6 +493,11 @@ final class AnimeCollection extends Collection {

private function getExistingGenreLinkEntries(): array
{
if ($this->validDatabase === FALSE)
{
return [];
}

$links = [];

$query = $this->db->select('hummingbird_id, genre_id')


+ 9
- 2
src/Model/Collection.php View File

@@ -19,6 +19,7 @@ namespace Aviat\AnimeClient\Model;
use Aviat\Ion\Di\ContainerInterface;
use PDOException;

use Query\Query_Builder_Interface;
use function Query;

/**
@@ -28,7 +29,7 @@ class Collection extends DB {

/**
* The query builder object
* @var \Query\Query_Builder_Interface
* @var Query_Builder_Interface
*/
protected $db;

@@ -52,7 +53,13 @@ class Collection extends DB {
$this->db = Query($this->dbConfig);
$this->validDatabase = TRUE;
}
catch (PDOException $e) {}
catch (PDOException $e)
{
$this->db = Query([
'type' => 'sqlite',
'file' => ':memory:',
]);
}

// Is database valid? If not, set a flag so the
// app can be run without a valid database


+ 0
- 245
src/Model/MangaCollection.php View File

@@ -17,7 +17,6 @@
namespace Aviat\AnimeClient\Model;

use Aviat\Ion\Di\ContainerInterface;
use PDO;

/**
* Model for getting anime collection data
@@ -40,249 +39,5 @@ final class MangaCollection extends Collection {
parent::__construct($container);
$this->mangaModel = $container->get('manga-model');
}

/**
* Get collection from the database, and organize by media type
*
* @return array
*/
public function getCollection(): array
{
$rawCollection = $this->getCollectionFromDatabase();

$collection = [];

foreach ($rawCollection as $row)
{
if (array_key_exists($row['media'], $collection))
{
$collection[$row['media']][] = $row;
}
else
{
$collection[$row['media']] = [$row];
}
}

return $collection;
}

/**
* Get list of media types
*
* @return array
*/
public function getMediaTypeList(): array
{
$output = [];

$query = $this->db->select('id, type')
->from('media')
->get();

foreach ($query->fetchAll(PDO::FETCH_ASSOC) as $row)
{
$output[$row['id']] = $row['type'];
}

return $output;
}

/**
* Get full collection from the database
*
* @return array
*/
private function getCollectionFromDatabase(): array
{
if ( ! $this->validDatabase)
{
return [];
}

$query = $this->db->select('hummingbird_id, slug, title, alternate_title, show_type,
age_rating, episode_count, episode_length, cover_image, notes, media.type as media')
->from('manga_set a')
->join('media', 'media.id=a.media_id', 'inner')
->order_by('media')
->order_by('title')
->get();

return $query->fetchAll(PDO::FETCH_ASSOC);
}

/**
* Add an item to the anime collection
*
* @param array $data
* @return void
*/
public function add($data): void
{
$anime = (object)$this->mangaModel->getMangaById($data['id']);
$this->db->set([
'hummingbird_id' => $data['id'],
'slug' => $anime->slug,
'title' => array_shift($anime->titles),
'alternate_title' => implode('<br />', $anime->titles),
'show_type' => $anime->show_type,
'age_rating' => $anime->age_rating,
'cover_image' => $anime->cover_image,
'episode_count' => $anime->episode_count,
'episode_length' => $anime->episode_length,
'media_id' => $data['media_id'],
'notes' => $data['notes']
])->insert('manga_set');

$this->updateGenre($data['id']);
}

/**
* Update a collection item
*
* @param array $data
* @return void
*/
public function update($data): void
{
// If there's no id to update, don't update
if ( ! array_key_exists('hummingbird_id', $data))
{
return;
}

$id = $data['hummingbird_id'];
unset($data['hummingbird_id']);

$this->db->set($data)
->where('hummingbird_id', $id)
->update('manga_set');
}

/**
* Remove a collection item
*
* @param array $data
* @return void
*/
public function delete($data): void
{
// If there's no id to update, don't delete
if ( ! array_key_exists('hummingbird_id', $data))
{
return;
}

$this->db->where('hummingbird_id', $data['hummingbird_id'])
->delete('genre_manga_set_link');

$this->db->where('hummingbird_id', $data['hummingbird_id'])
->delete('manga_set');
}

/**
* Get the details of a collection item
*
* @param string $kitsuId
* @return array
*/
public function get($kitsuId): array
{
$query = $this->db->from('manga_set')
->where('hummingbird_id', $kitsuId)
->get();

return $query->fetch(PDO::FETCH_ASSOC);
}

/**
* Update genre information for selected manga
*
* @param string $mangaId The current manga
* @return void
*/
private function updateGenre($mangaId): void
{
$genreInfo = $this->getGenreData();
$genres = $genreInfo['genres'];
$links = $genreInfo['links'];

// Get api information
$manga = $this->mangaModel->getMangaById($mangaId);

foreach ($manga['genres'] as $genre)
{
// Add genres that don't currently exist
if ( ! \in_array($genre, $genres, TRUE))
{
$this->db->set('genre', $genre)
->insert('genres');

$genres[] = $genre;
}

// Update link table
// Get id of genre to put in link table
$flippedGenres = array_flip($genres);

$insertArray = [
'hummingbird_id' => $mangaId,
'genre_id' => $flippedGenres[$genre]
];

if (array_key_exists($mangaId, $links))
{
if ( ! \in_array($flippedGenres[$genre], $links[$mangaId], TRUE))
{
$this->db->set($insertArray)->insert('genre_manga_set_link');
}
}
else
{
$this->db->set($insertArray)->insert('genre_manga_set_link');
}
}
}

/**
* Get list of existing genres
*
* @return array
*/
private function getGenreData(): array
{
$genres = [];
$links = [];

// Get existing genres
$query = $this->db->select('id, genre')
->from('genres')
->get();
foreach ($query->fetchAll(PDO::FETCH_ASSOC) as $genre)
{
$genres[$genre['id']] = $genre['genre'];
}

// Get existing link table entries
$query = $this->db->select('hummingbird_id, genre_id')
->from('genre_manga_set_link')
->get();
foreach ($query->fetchAll(PDO::FETCH_ASSOC) as $link)
{
if (array_key_exists($link['hummingbird_id'], $links))
{
$links[$link['hummingbird_id']][] = $link['genre_id'];
}
else
{
$links[$link['hummingbird_id']] = [$link['genre_id']];
}
}

return [
'genres' => $genres,
'links' => $links
];
}
}
// End of MangaCollectionModel.php

+ 1
- 1
src/Types/AbstractType.php View File

@@ -179,7 +179,7 @@ abstract class AbstractType implements ArrayAccess, Countable {
/**
* Recursively cast properties to an array
*
* @param null $parent
* @param mixed $parent
* @return mixed
*/
public function toArray($parent = null)


+ 2
- 2
src/Types/Anime.php View File

@@ -38,12 +38,12 @@ class Anime extends AbstractType {
public $cover_image;

/**
* @var string|number
* @var string|int
*/
public $episode_count;

/**
* @var string|number
* @var string|int
*/
public $episode_length;



+ 2
- 2
src/Types/AnimeListItem.php View File

@@ -74,12 +74,12 @@ final class AnimeListItem extends AbstractType {
public $rewatching;

/**
* @var number
* @var int
*/
public $rewatched;

/**
* @var number
* @var int
*/
public $user_rating;



+ 2
- 5
src/Types/Character.php View File

@@ -41,7 +41,7 @@ final class Character extends AbstractType {
public $included;

/**
* @var array
* @var Media
*/
public $media;

@@ -62,9 +62,6 @@ final class Character extends AbstractType {

public function setMedia ($media): void
{
$this->media = new class($media) extends AbstractType {
public $anime;
public $manga;
};
$this->media = new Media($media);
}
}

+ 29
- 0
src/Types/Characters.php View File

@@ -0,0 +1,29 @@
<?php declare(strict_types=1);
/**
* Hummingbird Anime List Client
*
* An API client for Kitsu to manage anime and manga watch lists
*
* PHP version 7.2
*
* @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 4.2
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
*/

namespace Aviat\AnimeClient\Types;

final class Characters extends AbstractType {
/**
* @var array
*/
public $main;

/**
* @var array
*/
public $supporting;
}

+ 1
- 1
src/Types/Config/Database.php View File

@@ -40,7 +40,7 @@ class Database extends AbstractType {
public $pass;

/**
* @var string|number
* @var string|int
*/
public $port;



+ 29
- 0
src/Types/Media.php View File

@@ -0,0 +1,29 @@
<?php declare(strict_types=1);
/**
* Hummingbird Anime List Client
*
* An API client for Kitsu to manage anime and manga watch lists
*
* PHP version 7.2
*
* @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2015 - 2019 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 4.2
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
*/

namespace Aviat\AnimeClient\Types;

final class Media extends AbstractType {
/**
* @var array
*/
public $anime = [];

/**
* @var array
*/
public $manga = [];
}

+ 2
- 5
src/Types/Person.php View File

@@ -31,7 +31,7 @@ final class Person extends AbstractType {
public $name;

/**
* @var object
* @var Characters
*/
public $characters;

@@ -42,9 +42,6 @@ final class Person extends AbstractType {

public function setCharacters($characters): void
{
$this->characters = new class($characters) extends AbstractType {
public $main;
public $supporting;
};
$this->characters = new Characters($characters);
}
}

Loading…
Cancel
Save