HummingBirdAnimeClient/src/AnimeClient.php

271 lines
5.5 KiB
PHP
Raw Normal View History

2016-10-20 22:09:36 -04:00
<?php declare(strict_types=1);
2015-11-16 19:30:04 -05:00
/**
* Hummingbird Anime List Client
2015-11-16 19:30:04 -05:00
*
2018-08-22 13:48:27 -04:00
* An API client for Kitsu to manage anime and manga watch lists
2015-11-16 19:30:04 -05:00
*
2018-10-01 11:35:51 -04:00
* PHP version 7.1
2016-08-30 10:01:18 -04:00
*
2015-11-16 19:30:04 -05:00
* @package HummingbirdAnimeClient
2016-08-30 10:01:18 -04:00
* @author Timothy J. Warren <tim@timshomepage.net>
2018-01-15 14:43:15 -05:00
* @copyright 2015 - 2018 Timothy J. Warren
2016-08-30 10:01:18 -04:00
* @license http://www.opensource.org/licenses/mit-license.html MIT License
2018-10-01 11:35:51 -04:00
* @version 4.1
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
2015-11-16 19:30:04 -05:00
*/
namespace Aviat\AnimeClient;
use Aviat\Ion\ConfigInterface;
2018-08-20 13:01:16 -04:00
use Yosymfony\Toml\{Toml, TomlBuilder};
// ----------------------------------------------------------------------------
//! TOML Functions
// ----------------------------------------------------------------------------
/**
* Load configuration options from .toml files
*
* @param string $path - Path to load config
* @return array
*/
function loadToml(string $path): array
2017-12-06 14:40:13 -05:00
{
$output = [];
$files = glob("{$path}/*.toml");
foreach ($files as $file)
{
$key = str_replace('.toml', '', basename($file));
if ($key === 'admin-override')
{
continue;
}
$config = Toml::parseFile($file);
if ($key === 'config')
{
foreach($config as $name => $value)
{
$output[$name] = $value;
}
continue;
}
$output[$key] = $config;
}
return $output;
2017-12-06 14:40:13 -05:00
}
/**
* Load config from one specific TOML file
*
* @param string $filename
* @return array
*/
function loadTomlFile(string $filename): array
{
return Toml::parseFile($filename);
}
2018-08-20 13:01:16 -04:00
function _iterateToml(TomlBuilder $builder, $data, $parentKey = NULL): void
{
foreach ($data as $key => $value)
{
if ($value === NULL)
{
continue;
}
if (is_scalar($value) || isSequentialArray($value))
{
// $builder->addTable('');
$builder->addValue($key, $value);
continue;
}
$newKey = ($parentKey !== NULL)
? "{$parentKey}.{$key}"
: $key;
if ( ! isSequentialArray($value))
{
$builder->addTable($newKey);
}
_iterateToml($builder, $value, $newKey);
}
}
/**
* Serialize config data into a Toml file
*
* @param mixed $data
* @return string
*/
function arrayToToml($data): string
{
$builder = new TomlBuilder();
_iterateToml($builder, $data);
return $builder->getTomlString();
}
/**
* Serialize toml back to an array
*
* @param string $toml
* @return array
*/
function tomlToArray(string $toml): array
{
return Toml::parse($toml);
}
// ----------------------------------------------------------------------------
//! Misc Functions
// ----------------------------------------------------------------------------
/**
* Is the array sequential, not associative?
*
* @param mixed $array
* @return bool
*/
function isSequentialArray($array): bool
{
if ( ! is_array($array))
{
return FALSE;
}
$i = 0;
foreach ($array as $k => $v)
{
if ($k !== $i++)
{
return FALSE;
}
}
return TRUE;
}
/**
* Check that folder permissions are correct for proper operation
*
* @param ConfigInterface $config
* @return array
*/
function checkFolderPermissions(ConfigInterface $config): array
{
$errors = [];
$publicDir = $config->get('asset_dir');
$pathMap = [
'app/config' => realpath(__DIR__ . '/../app/config'),
'app/logs' => realpath(__DIR__ . '/../app/logs'),
'public/images/avatars' => "{$publicDir}/images/avatars",
'public/images/anime' => "{$publicDir}/images/anime",
'public/images/characters' => "{$publicDir}/images/characters",
'public/images/manga' => "{$publicDir}/images/manga",
'public/images/people' => "{$publicDir}/images/people",
];
foreach ($pathMap as $pretty => $actual)
{
// Make sure the folder exists first
if ( ! is_dir($actual))
{
$errors['missing'][] = $pretty;
continue;
}
$writable = is_writable($actual) && is_executable($actual);
if ( ! $writable)
{
$errors['writable'][] = $pretty;
}
}
return $errors;
}
/**
* Generate the path for the cached image from the original iamge
*
* @param string $kitsuUrl
* @return string
*/
function getLocalImg ($kitsuUrl): string
{
if ( ! is_string($kitsuUrl))
{
return 'images/404/404.png';
}
$parts = parse_url($kitsuUrl);
if ($parts === FALSE)
{
return 'images/404/404.png';
}
$file = basename($parts['path']);
$fileParts = explode('.', $file);
$ext = array_pop($fileParts);
$segments = explode('/', trim($parts['path'], '/'));
$type = $segments[0] === 'users' ? $segments[1] : $segments[0];
$id = $segments[count($segments) - 2];
return implode('/', ['images', $type, "{$id}.{$ext}"]);
}
/**
* Create a transparent placeholder image
*
* @param string $path
* @param int $width
* @param int $height
* @param string $text
*/
function createPlaceholderImage ($path, $width, $height, $text = 'Image Unavailable')
{
$width = $width ?? 200;
$height = $height ?? 200;
$img = imagecreate($width, $height);
$path = rtrim($path, '/');
// Background is the first color by default
imagecolorallocatealpha($img, 255, 255, 255, 127);
$textColor = imagecolorallocate($img, 64, 64, 64);
imagealphablending($img, TRUE);
// Generate placeholder text
$fontSize = 10;
$fontWidth = imagefontwidth($fontSize);
$fontHeight = imagefontheight($fontSize);
$length = strlen($text);
$textWidth = $length * $fontWidth;
$fxPos = (int) ceil((imagesx($img) - $textWidth) / 2);
$fyPos = (int) ceil((imagesy($img) - $fontHeight) / 2);
// Add the image text
imagestring($img, $fontSize, $fxPos, $fyPos, $text, $textColor);
// Save the images
imagesavealpha($img, TRUE);
imagepng($img, $path . '/placeholder.png', 9);
imagedestroy($img);
}