diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 3087b82..99972ee 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -6,11 +6,16 @@ require_once './vendor/autoload.php'; use Nextcloud\CodingStandard\Config; -class MyConfig extends Config { +class MyConfig extends Config +{ public function getRules(): array { $rules = parent::getRules(); + $rules['@PhpCsFixer'] = true; $rules['curly_braces_position']['classes_opening_brace'] = 'next_line_unless_newline_at_signature_end'; + $rules['phpdoc_separation'] = false; + $rules['phpdoc_to_comment'] = false; + $rules['single_line_comment_style'] = false; return $rules; } } diff --git a/appinfo/routes.php b/appinfo/routes.php index 5ffdd49..08ed701 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -5,7 +5,7 @@ declare(strict_types=1); /** * Create your routes in here. The name is the lowercase name of the controller * without the controller part, the stuff after the hash is the method. - * e.g. page#index -> OCA\RePod\Controller\PageController->index() + * e.g. page#index -> OCA\RePod\Controller\PageController->index(). * * The controller class has to be registered in the application.php file since * it's instantiated in there @@ -14,6 +14,6 @@ return [ 'routes' => [ ['name' => 'page#index', 'url' => '/', 'verb' => 'GET'], ['name' => 'top#index', 'url' => '/top/{count}', 'verb' => 'GET'], - ['name' => 'search#index', 'url' => '/search/{value}', 'verb' => 'GET'] - ] + ['name' => 'search#index', 'url' => '/search/{value}', 'verb' => 'GET'], + ], ]; diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 15e5e93..c64bd0c 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -18,13 +18,16 @@ class Application extends App implements IBootstrap public const APP_ID = 'repod'; private const GPODDERSYNC_ID = 'gpoddersync'; - public function __construct() { + public function __construct() + { parent::__construct(self::APP_ID); } - public function boot(IBootContext $context): void { + public function boot(IBootContext $context): void + { /** @psalm-suppress DeprecatedInterface */ $appContainer = $context->getAppContainer(); + /** @var IAppManager $appManager */ $appManager = $appContainer->get(IAppManager::class); @@ -40,10 +43,12 @@ class Application extends App implements IBootstrap Util::connectHook('\OCP\Config', 'js', $this, 'extendJsConfig'); } - public function register(IRegistrationContext $context): void { + public function register(IRegistrationContext $context): void + { } - public static function extendJsConfig(array $settings): void { + public static function extendJsConfig(array $settings): void + { /** @var IAppManager $appManager */ $appManager = Server::get(IAppManager::class); @@ -51,7 +56,7 @@ class Application extends App implements IBootstrap /** @var array $appConfig */ $appConfig = json_decode((string) $settings['array']['oc_appconfig'], true); $appConfig['repod'] = [ - 'gpodder' => $appManager->isEnabledForUser(self::GPODDERSYNC_ID) + 'gpodder' => $appManager->isEnabledForUser(self::GPODDERSYNC_ID), ]; $settings['array']['oc_appconfig'] = json_encode($appConfig); } diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php index 1b1d0be..1a47bb7 100644 --- a/lib/Controller/PageController.php +++ b/lib/Controller/PageController.php @@ -14,7 +14,8 @@ use OCP\Util; class PageController extends Controller { - public function __construct(IRequest $request, private IConfig $config) { + public function __construct(IRequest $request, private IConfig $config) + { parent::__construct(Application::APP_ID, $request); } @@ -22,7 +23,8 @@ class PageController extends Controller * @NoAdminRequired * @NoCSRFRequired */ - public function index(): TemplateResponse { + public function index(): TemplateResponse + { Util::addScript(Application::APP_ID, 'repod-main'); $csp = new ContentSecurityPolicy(); @@ -36,6 +38,7 @@ class PageController extends Controller $response = new TemplateResponse(Application::APP_ID, 'main'); $response->setContentSecurityPolicy($csp); + return $response; } } diff --git a/lib/Controller/SearchController.php b/lib/Controller/SearchController.php index addef5c..18ddf77 100644 --- a/lib/Controller/SearchController.php +++ b/lib/Controller/SearchController.php @@ -4,52 +4,102 @@ declare(strict_types=1); namespace OCA\RePod\Controller; -use Exception; use OCA\RePod\AppInfo\Application; use OCP\AppFramework\Controller; use OCP\AppFramework\Http\JSONResponse; use OCP\Http\Client\IClientService; use OCP\IRequest; +use OCP\IUserSession; +use OCP\L10N\IFactory; class SearchController extends Controller { public function __construct( IRequest $request, - private IClientService $clientService + private IClientService $clientService, + private IFactory $l10n, + private IUserSession $userSession ) { parent::__construct(Application::APP_ID, $request); } - public function index(string $value): JSONResponse { + public function index(string $value): JSONResponse + { $podcasts = []; try { $fyydClient = $this->clientService->newClient(); - $fyydReponse = $fyydClient->get("https://api.fyyd.de/0.2/search/podcast", [ + $fyydReponse = $fyydClient->get('https://api.fyyd.de/0.2/search/podcast', [ 'query' => [ 'title' => $value, - 'term' => $value - ] + 'term' => $value, + ], ]); $fyydJson = (array) json_decode((string) $fyydReponse->getBody(), true, flags: JSON_THROW_ON_ERROR); if (array_key_exists('data', $fyydJson) && is_array($fyydJson['data'])) { /** @var string[] $fyydFeed */ foreach ($fyydJson['data'] as $fyydFeed) { - $podcasts[] = [ - 'id' => $fyydFeed['id'], - 'title' => $fyydFeed['title'], - 'description' => $fyydFeed['description'], - 'image' => $fyydFeed['imgURL'], - 'url' => $fyydFeed['xmlURL'], - 'lang' => $fyydFeed['language'], - 'lastpub' => $fyydFeed['lastpub'] - ]; + $lastPub = date_format(new \DateTime($fyydFeed['lastpub']), DATE_ATOM); + + if ($lastPub) { + $podcasts[] = [ + 'provider' => 'fyyd', + 'id' => $fyydFeed['id'], + 'title' => $fyydFeed['title'], + 'author' => $fyydFeed['author'], + 'image' => $fyydFeed['imgURL'], + 'provider_url' => $fyydFeed['htmlURL'], + 'feed_url' => $fyydFeed['xmlURL'], + 'last_pub' => $lastPub, + 'nb_episodes' => $fyydFeed['episode_count'], + ]; + } } } - } catch (Exception $e) { + } catch (\Exception $e) { } + try { + $itunesClient = $this->clientService->newClient(); + $itunesResponse = $itunesClient->get('https://itunes.apple.com/search', [ + 'query' => [ + 'media' => 'podcast', + 'term' => $value, + 'lang' => $this->l10n->getUserLanguage($this->userSession->getUser()), + ], + ]); + $itunesJson = (array) json_decode((string) $itunesResponse->getBody(), true, flags: JSON_THROW_ON_ERROR); + + if (array_key_exists('data', $itunesJson) && is_array($itunesJson['data'])) { + /** @var string[] $itunesFeed */ + foreach ($itunesJson['results'] as $itunesFeed) { + $lastPub = date_format(new \DateTime($itunesFeed['releaseDate']), DATE_ATOM); + + if ($lastPub) { + $podcasts[] = [ + 'id' => $itunesFeed['id'], + 'title' => $itunesFeed['trackName'], + 'author' => $itunesFeed['artistName'], + 'image' => $itunesFeed['artworkUrl600'], + 'provider_url' => $itunesFeed['trackViewUrl'], + 'feed_url' => $itunesFeed['feedUrl'], + 'last_pub' => $lastPub, + 'nb_episodes' => $itunesFeed['trackCount'], + ]; + } + } + } + } catch (\Exception $e) { + } + + /** + * string[] $a + * string[] $b. + */ + usort($podcasts, fn (array $a, array $b) => $a['last_pub'] <=> $b['last_pub']); + $podcasts = array_intersect_key($podcasts, array_unique(array_map(fn (array $feed) => $feed['feed_url'], $podcasts))); + return new JSONResponse($podcasts); } } diff --git a/lib/Controller/TopController.php b/lib/Controller/TopController.php index 7560237..85a454a 100644 --- a/lib/Controller/TopController.php +++ b/lib/Controller/TopController.php @@ -4,7 +4,6 @@ declare(strict_types=1); namespace OCA\RePod\Controller; -use Exception; use OCA\RePod\AppInfo\Application; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; @@ -29,12 +28,13 @@ class TopController extends Controller * @NoAdminRequired * @NoCSRFRequired */ - public function index(int $count = 10): JSONResponse { + public function index(int $count = 10): JSONResponse + { $language = 'en'; try { $langClient = $this->clientService->newClient(); - $langResponse = $langClient->get("https://api.fyyd.de/0.2/feature/podcast/hot/languages"); + $langResponse = $langClient->get('https://api.fyyd.de/0.2/feature/podcast/hot/languages'); $langJson = (array) json_decode((string) $langResponse->getBody(), true, flags: JSON_THROW_ON_ERROR); if (array_key_exists('data', $langJson) && is_array($langJson['data'])) { $language = $this->l10n->getUserLanguage($this->userSession->getUser()); @@ -42,20 +42,21 @@ class TopController extends Controller $language = count($language) > 1 ? $language[1] : $language[0]; $language = in_array($language, $langJson['data']) ? $language : 'en'; } - } catch (Exception $e) { + } catch (\Exception $e) { } try { $podcastClient = $this->clientService->newClient(); - $podcastReponse = $podcastClient->get("https://api.fyyd.de/0.2/feature/podcast/hot", [ + $podcastReponse = $podcastClient->get('https://api.fyyd.de/0.2/feature/podcast/hot', [ 'query' => [ 'count' => $count, - 'language' => $language - ] + 'language' => $language, + ], ]); $podcastJson = (array) json_decode((string) $podcastReponse->getBody(), true, flags: JSON_THROW_ON_ERROR); + return new JSONResponse($podcastJson, $podcastReponse->getStatusCode()); - } catch (Exception $e) { + } catch (\Exception $e) { return new JSONResponse([$e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR); } }