From 844c73ba3f429791dd801149632837ee7fce8fb7 Mon Sep 17 00:00:00 2001 From: Maurice Renck Date: Tue, 27 Feb 2024 21:46:39 +0100 Subject: [PATCH] fix: localhost api requests run into timeout this should fix #65 removed api request and switched to site and page methods --- app/{FeedMethods.php => PageMethods.php} | 10 + app/Podcast.php | 44 ++- app/SiteMethods.php | 10 + blueprints/tabs/episode.yml | 14 +- blueprints/tabs/feed-details.yml | 173 ++++++----- blueprints/tabs/feed-player.yml | 290 +++++++++--------- composer.json | 3 +- .../podcast-seasons/feed/podcasterfeed.en.txt | 195 ++++++++++-- index.php | 41 +-- 9 files changed, 470 insertions(+), 310 deletions(-) rename app/{FeedMethods.php => PageMethods.php} (61%) create mode 100644 app/SiteMethods.php diff --git a/app/FeedMethods.php b/app/PageMethods.php similarity index 61% rename from app/FeedMethods.php rename to app/PageMethods.php index 44c5cf3..f465a79 100644 --- a/app/FeedMethods.php +++ b/app/PageMethods.php @@ -18,4 +18,14 @@ return $this->podcasterCover()->toFile()->url(); }, + + 'podloveRoles' => function () { + $podcast = new Podcast(); + return $podcast->getPodloveRoles($this->slug()); + }, + + 'podloveGroups' => function () { + $podcast = new Podcast(); + return $podcast->getPodloveGroups($this->slug()); + }, ]; diff --git a/app/Podcast.php b/app/Podcast.php index 87519d3..ad261c9 100644 --- a/app/Podcast.php +++ b/app/Podcast.php @@ -3,8 +3,11 @@ namespace mauricerenck\Podcaster; use Exception; +use Kirby\Cms\Collection; +use Kirby\Cms\Structure; use Kirby\Filesystem\F; use Kirby\Toolkit\Str; +use Kirby\Http\Remote; class Podcast { @@ -83,19 +86,19 @@ public function getAudioFile($episode) return $episode->podcasterAudio()->toFile(); } - if(!is_null($episode->podcasterMp3())) { + if (!is_null($episode->podcasterMp3())) { $audioFile = $episode->audio($episode->podcasterMp3()->first())->first(); if (is_null($audioFile)) { return null; } - + return $audioFile; } - + $audioFile = $episode->audio()->first(); - if (is_null($audioFile)) { + if (is_null($audioFile)) { return null; } @@ -217,10 +220,10 @@ public function getPodloveGroups($episodeSlug) public function getPodloveContributors($contributorsField, $contributorRoles, $contributorGroups) { - if($contributorRoles->toStructure()->isEmpty() || $contributorGroups->toStructure()->isEmpty()) { + if ($contributorRoles->toStructure()->isEmpty() || $contributorGroups->toStructure()->isEmpty()) { return []; } - + $contributors = []; $roles = $contributorRoles->toStructure(); $groups = $contributorGroups->toStructure(); @@ -451,4 +454,33 @@ public function getPodloveConfigJson($episode) return $config; } + + public function getAppleMetadata($endpoint) + { + $keyValueList = []; + + if (option('mauricerenck.podcaster.useApi', true)) { + $apiCache = kirby()->cache('mauricerenck.podcaster'); + $jsonString = $apiCache->get($endpoint); + + if ($jsonString === null) { + $response = new Remote('https://api.podcaster-plugin.com/' . $endpoint); + $apiCache->set($endpoint, $response->content(), 7 * 24 * 60); + } + } else { + $jsonString = file_get_contents(__DIR__ . '/../res/' . $endpoint . '.json'); + } + + $json = json_decode($jsonString, JSON_OBJECT_AS_ARRAY); + + foreach ($json as $key => $label) { + $keyValueList[] = ['text' => $label, 'value' => $key]; + } + + if (is_null($keyValueList)) { + return []; + } + + return $keyValueList; + } } diff --git a/app/SiteMethods.php b/app/SiteMethods.php new file mode 100644 index 0000000..eed4412 --- /dev/null +++ b/app/SiteMethods.php @@ -0,0 +1,10 @@ + function ($endpoint = 'categories') { + $podcast = new Podcast(); + return $podcast->getAppleMetadata($endpoint); + } +]; diff --git a/blueprints/tabs/episode.yml b/blueprints/tabs/episode.yml index 47effa3..e6b3959 100644 --- a/blueprints/tabs/episode.yml +++ b/blueprints/tabs/episode.yml @@ -23,8 +23,10 @@ columns: label: Language type: select options: - type: api - url: "{{ site.url('') }}/podcaster/api/languages" + type: query + query: site.getAppleMetadata('languages') + value: '{{ item.value }}' + text: '{{ item.text }}' required: true podcasterTranscriptFile: type: files @@ -177,16 +179,16 @@ columns: type: select label: Role options: - type: api - url: "{{ site.url('') }}/podcaster/podlove/roles/{{ page.uri }}" + type: query + query: page.podloveRoles text: '{{ item.title }}' value: '{{ item.id }}' contributorGroup: type: select label: Group options: - type: api - url: "{{ site.url('') }}/podcaster/podlove/groups/{{ page.uri }}" + type: query + query: page.podloveGroups text: '{{ item.title }}' value: '{{ item.id }}' columns: diff --git a/blueprints/tabs/feed-details.yml b/blueprints/tabs/feed-details.yml index e296640..f71723a 100644 --- a/blueprints/tabs/feed-details.yml +++ b/blueprints/tabs/feed-details.yml @@ -1,89 +1,92 @@ label: Show details icon: star columns: - - width: 1/1 - sections: - spacer: - type: fields - fields: - headlineInfos: - type: headline - label: Podcast details - - width: 1/4 - sections: - graphics: - type: fields - fields: - podcasterCover: - type: files - label: Cover Image - layout: cards - multiple: false - template: podcaster-cover - query: page.images - image: - cover: true - ratio: 1/1 - - width: 2/4 - sections: - infos: - type: fields - fields: - podcasterTitle: - label: Podcast Title - type: text - required: true - podcasterSubtitle: - label: Podcast Subtitle - type: text - podcasterDescription: - label: Description - type: textarea - size: medium - podcasterCopyright: - label: Copyright - type: text - required: true - - - width: 1/4 - sections: - taxonomy: - type: fields - fields: - podcasterKeywords: - label: Apple Keywords - type: tags - podcasterCategories: - label: Apple Categories - type: structure - required: true - fields: - podcasterMainCategory: - label: Main - type: select - options: - type: api - url: "{{ site.url('') }}/podcaster/api/categories" - podcasterType: - label: Podcast type - type: radio - default: episodic - options: - episodic: Episodic - serial: Serial - podcasterLanguage: - label: Language - type: select - options: - type: api - url: "{{ site.url('') }}/podcaster/api/languages" - required: true - podcasterAuthor: - label: Author - type: users - max: 1 - podcasterOwner: - label: Owner - type: users - max: 1 + - width: 1/1 + sections: + spacer: + type: fields + fields: + headlineInfos: + type: headline + label: Podcast details + - width: 1/4 + sections: + graphics: + type: fields + fields: + podcasterCover: + type: files + label: Cover Image + layout: cards + multiple: false + template: podcaster-cover + query: page.images + image: + cover: true + ratio: 1/1 + - width: 2/4 + sections: + infos: + type: fields + fields: + podcasterTitle: + label: Podcast Title + type: text + required: true + podcasterSubtitle: + label: Podcast Subtitle + type: text + podcasterDescription: + label: Description + type: textarea + size: medium + podcasterCopyright: + label: Copyright + type: text + required: true + - width: 1/4 + sections: + taxonomy: + type: fields + fields: + podcasterKeywords: + label: Apple Keywords + type: tags + podcasterCategories: + label: Apple Categories + type: structure + required: true + fields: + podcasterMainCategory: + label: Main + type: select + options: + type: query + query: site.getAppleMetadata('categories') + value: '{{ item.value }}' + text: '{{ item.text }}' + podcasterType: + label: Podcast type + type: radio + default: episodic + options: + episodic: Episodic + serial: Serial + podcasterLanguage: + label: Language + type: select + options: + type: query + query: site.getAppleMetadata('languages') + value: '{{ item.value }}' + text: '{{ item.text }}' + required: true + podcasterAuthor: + label: Author + type: users + max: 1 + podcasterOwner: + label: Owner + type: users + max: 1 diff --git a/blueprints/tabs/feed-player.yml b/blueprints/tabs/feed-player.yml index f4fe324..3e70b44 100644 --- a/blueprints/tabs/feed-player.yml +++ b/blueprints/tabs/feed-player.yml @@ -1,150 +1,152 @@ label: Website Player icon: file-audio columns: - - width: 1/4 - sections: - player: - type: fields - fields: - headlinePlayer: - type: headline - label: Website Player - playerType: - label: Player Type - type: select - default: podlove - options: - html5: Standard HTML5 Player - podlove: Advanced Podlove Player - infoPlayer: - label: Add to Template - type: info - theme: info - text: You need to put the player snippet in your template file. Just add where you want the player to appear. - - width: 2/4 - sections: - podloveConfig: - type: fields - fields: - headlinePodlove: - type: headline - label: Podlove Player Configuration - podcasterPodloveActiveTab: - label: Active Tab - type: select - default: chapters - options: - chapters: Chapters - files: Files - share: 'Share' - # playlist: 'Playlist' - podcasterPodloveColors: - label: Colors - type: structure - fields: - colorType: - type: select - required: true - options: - brand: Brand - brandDark: Brand Dark - brandDarkest: Brand Darkest - brandLightest: Brand Lightest - shadeBase: Shade Base - shadeDark: Shade Dark - contrast: Contrast - alt: Alt - hex: - type: text - required: true - help: hex code - pattern: '^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$' + - width: 1/4 + sections: + player: + type: fields + fields: + headlinePlayer: + type: headline + label: Website Player + playerType: + label: Player Type + type: select + default: podlove + options: + html5: Standard HTML5 Player + podlove: Advanced Podlove Player + infoPlayer: + label: Add to Template + type: info + theme: info + text: You need to put the player snippet in your template file. Just add where you want the player to appear. + - width: 2/4 + sections: + podloveConfig: + type: fields + fields: + headlinePodlove: + type: headline + label: Podlove Player Configuration + podcasterPodloveActiveTab: + label: Active Tab + type: select + default: chapters + options: + chapters: Chapters + files: Files + share: 'Share' + # playlist: 'Playlist' + podcasterPodloveColors: + label: Colors + type: structure + fields: + colorType: + type: select + required: true + options: + brand: Brand + brandDark: Brand Dark + brandDarkest: Brand Darkest + brandLightest: Brand Lightest + shadeBase: Shade Base + shadeDark: Shade Dark + contrast: Contrast + alt: Alt + hex: + type: text + required: true + help: hex code + pattern: '^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$' - podcasterPodloveFonts: - label: Fonts - type: structure - fields: - fontType: - type: select - required: true - options: - ci: CI - regular: Regular - bold: Bold - name: - type: text - required: true - label: Font Name - family: - type: tags - required: true - label: Font Family - weight: - type: number - required: true - label: Font Weight - src: - type: tags - required: true - label: Source Path + podcasterPodloveFonts: + label: Fonts + type: structure + fields: + fontType: + type: select + required: true + options: + ci: CI + regular: Regular + bold: Bold + name: + type: text + required: true + label: Font Name + family: + type: tags + required: true + label: Font Family + weight: + type: number + required: true + label: Font Weight + src: + type: tags + required: true + label: Source Path - podcasterPodloveClients: - label: Clients - type: structure - fields: - client: - type: select - required: true - options: - type: api - url: "{{ site.url('') }}/podcaster/api//podlove-clients" - service: - type: text - label: Service + podcasterPodloveClients: + label: Clients + type: structure + fields: + client: + type: select + required: true + options: + type: query + query: site.getAppleMetadata('podlove-clients') + value: '{{ item.value }}' + text: '{{ item.text }}' + service: + type: text + label: Service - podcasterPodloveShareChannels: - label: Share Channels - type: multiselect - options: - facebook: Facebook - twitter: Twitter - "whats-app": WhatsApp - linkedin: LinkedIn - pinterest: Pinterest - xing: Xing - mail: Mail - link: Link - podcasterPodloveSharePlaytime: - label: Share Playtime - type: toggle - default: yes - text: - - Do not share Playtime - - Share Playtime - - podcasterPodloveRoles: - label: Contributer Roles - type: structure - width: 1/1 - fields: - roleId: - type: number - label: ID - roleTitle: - type: text - label: Role Title - when: - playerType: podlove - podcasterPodloveGroups: - label: Contributer Groups - type: structure - width: 1/1 - fields: - groupId: - type: number - label: ID - groupTitle: - type: text - label: Group Title - when: - playerType: podlove \ No newline at end of file + podcasterPodloveShareChannels: + label: Share Channels + type: multiselect + options: + facebook: Facebook + twitter: Twitter + 'whats-app': WhatsApp + linkedin: LinkedIn + pinterest: Pinterest + xing: Xing + mail: Mail + link: Link + podcasterPodloveSharePlaytime: + label: Share Playtime + type: toggle + default: yes + text: + - Do not share Playtime + - Share Playtime + + podcasterPodloveRoles: + label: Contributer Roles + type: structure + width: 1/1 + fields: + roleId: + type: number + label: ID + roleTitle: + type: text + label: Role Title + when: + playerType: podlove + podcasterPodloveGroups: + label: Contributer Groups + type: structure + width: 1/1 + fields: + groupId: + type: number + label: ID + groupTitle: + type: text + label: Group Title + when: + playerType: podlove diff --git a/composer.json b/composer.json index 6469d9b..a97384b 100644 --- a/composer.json +++ b/composer.json @@ -34,7 +34,8 @@ } }, "scripts": { - "test": "vendor/bin/phpunit --testdox tests", + "start": ["Composer\\Config::disableProcessTimeout", "php -S localhost:8000 kirby/router.php"], + "test": "vendor/bin/phpunit --testdox --colors=always tests", "build-test-package": "git archive HEAD -o podcaster.zip --worktree-attributes", "build-composer": "composer install --no-dev --optimize-autoloader", "build-release": ["composer test", "composer install --no-dev --optimize-autoloader", "npm run build"] diff --git a/content/phpunit/podcast-seasons/feed/podcasterfeed.en.txt b/content/phpunit/podcast-seasons/feed/podcasterfeed.en.txt index d95abee..8b1c1cd 100644 --- a/content/phpunit/podcast-seasons/feed/podcasterfeed.en.txt +++ b/content/phpunit/podcast-seasons/feed/podcasterfeed.en.txt @@ -2,31 +2,36 @@ Title: feed ---- -Podcastid: phpunit +Podcastercover: - file://vRSfYjGx9PD0ZMqg ---- -Podcasterlink: https://erzaehl.es +Podcastertitle: Test Podcast ---- -Podcasteratomlink: https://erzaehl.es +Podcastersubtitle: Podcast Subtitle ---- -Podcasterlanguage: de +Podcasterdescription: Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. ---- -Podcasterauthor: - user://9u0svKwr +Podcastercopyright: Copyright xxxx ---- -Podcasterowner: - user://9u0svKwr +Podcasterkeywords: apple, keyword ---- -Podcastersource: - page://lZUGnLSojsId8GLj +Podcastercategories: + +- + podcastermaincategory: Arts +- + podcastermaincategory: Arts/Design ---- @@ -34,36 +39,47 @@ Podcastertype: episodic ---- -Podcastercover: - file://vRSfYjGx9PD0ZMqg +Podcasterlanguage: de ---- -Podcastertitle: Test Podcast +Podcasterauthor: - user://9u0svKwr ---- -Podcastersubtitle: Podcast Subtitle +Podcasterowner: - user://9u0svKwr ---- -Podcasterdescription: Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. +Podcastid: phpunit ---- -Podcastercopyright: Copyright xxxx +Podcasterlink: https://erzaehl.es ---- -Podcasterkeywords: apple, keyword +Podcasteratomlink: https://erzaehl.es ---- -Podcastercategories: +Podcastersource: - page://lZUGnLSojsId8GLj -- - podcastermaincategory: Arts -- - podcastermaincategory: Education/Courses +---- + +Podcasterblock: false + +---- + +Podcasterexplicit: false + +---- + +Podcastercomplete: false + +---- + +Podcasternewfeedurl: ---- @@ -71,31 +87,108 @@ Playertype: podlove ---- -Podcasterpodlovemaincolor: +Podcasterpodloveactivetab: chapters ---- -Podcasterpodlovehighlighcolor: +Podcasterpodlovecolors: + +- + colortype: brand + hex: '#166255' +- + colortype: brandDark + hex: '#166255' +- + colortype: brandDarkest + hex: '#1A3A4A' +- + colortype: brandLightest + hex: '#E5EAEC' +- + colortype: shadeDark + hex: '#807E7C' +- + colortype: shadeBase + hex: '#807E7C' +- + colortype: contrast + hex: '#000' +- + colortype: alt + hex: '#fff' ---- -Podcasterpodlovetabsinfo: false +Podcasterpodlovefonts: + +- + fonttype: ci + name: RobotoBlack + family: > + RobotoBlack, Calibri, Candara, Arial, + Helvetica, sans-serif + weight: 900 + src: ./assets/Roboto-Black.ttf +- + fonttype: regular + name: FiraSansLight + family: > + FiraSansLight, Calibri, Candara, Arial, + Helvetica, sans-serif + weight: 300 + src: ./assets/FiraSans-Light.ttf +- + fonttype: bold + name: FiraSansBold + family: > + FiraSansBold, Calibri, Candara, Arial, + Helvetica, sans-serif + weight: 700 + src: ./assets/FiraSans-Bold.ttf ---- -Podcasterpodlovetabsshare: false +Podcasterpodloveclients: + +- + client: apple-podcasts + service: "12345678" +- + client: pocket-casts + service: "12345678" +- + client: overcast + service: "" +- + client: rss + service: "" ---- -Podcasterpodlovetabschapters: false +Podcasterpodlovesharechannels: facebook, twitter, whats-app, linkedin, pinterest, xing, mail, link ---- -Podcasterpodlovetabsaudio: false +Podcasterpodloveshareplaytime: true ---- -Podcasterpodlovetabsdownload: false +Podcasterpodloveroles: + +- + roleid: 1 + roletitle: Team Role + +---- + +Podcasterpodlovegroups: + +- + groupid: 1 + grouptitle: On Air + roleid: 1 + roletitle: On Air ---- @@ -167,19 +260,63 @@ Podtracurl: https://dts.podtrac.com/redirect.mp3/ ---- -Podcasterblock: false +Podcasterpodlovemaincolor: ---- -Podcasterexplicit: false +Podcasterpodlovehighlighcolor: ---- -Podcastercomplete: false +Podcasterpodlovetabsinfo: false ---- -Podcasternewfeedurl: +Podcasterpodlovetabsshare: false + +---- + +Podcasterpodlovetabschapters: false + +---- + +Podcasterpodlovetabsaudio: false + +---- + +Podcasterpodlovetabsdownload: false + +---- + +Podcasterpodlovecolorbrand: #166255 + +---- + +Podcasterpodlovecolorbranddark: #166255 + +---- + +Podcasterpodlovecolorbranddarkest: #1A3A4A + +---- + +Podcasterpodlovecolorbrandlightest: #E5EAEC + +---- + +Podcasterpodlovecolorshadedark: #807E7C + +---- + +Podcasterpodlovecolorshadebase: #807E7C + +---- + +Podcasterpodlovecolorcontrast: #000 + +---- + +Podcasterpodlovecoloralt: #fff ---- diff --git a/index.php b/index.php index 1b4f8f8..424efd7 100644 --- a/index.php +++ b/index.php @@ -4,7 +4,6 @@ use Kirby; use Kirby\Http\Response; -use Kirby\Http\Remote; @include_once __DIR__ . '/vendor/autoload.php'; @@ -21,14 +20,14 @@ 'tabs/podcaster/feed-player' => __DIR__ . '/blueprints/tabs/feed-player.yml', 'tabs/podcaster/feed-tracking' => __DIR__ . '/blueprints/tabs/feed-tracking.yml', - //'pages/podcasterwizard' => __DIR__ . '/blueprints/pages/podcasterwizard.yml', 'files/podcaster-episode' => __DIR__ . '/blueprints/files/podcaster-episode.yml', 'files/podcaster-cover' => __DIR__ . '/blueprints/files/podcaster-cover.yml', ], 'templates' => [ 'podcasterfeed' => __DIR__ . '/templates/podcasterfeed.php', ], - 'pageMethods' => require_once __DIR__ . '/app/FeedMethods.php', + 'pageMethods' => require_once __DIR__ . '/app/PageMethods.php', + 'siteMethods' => require_once __DIR__ . '/app/SiteMethods.php', 'fileTypes' => require_once __DIR__ . '/app/FileTypes.php', 'api' => require_once(__DIR__ . '/internal/api.php'), 'hooks' => require_once(__DIR__ . '/internal/hooks.php'), @@ -123,22 +122,6 @@ return $podcast->getAudioFile($episode); }, ], - [ - 'pattern' => 'podcaster/podlove/roles/(:all)', - 'action' => function ($episodeSlug) { - $podcast = new Podcast(); - - return new Response(json_encode($podcast->getPodloveRoles($episodeSlug)), 'application/json'); - } - ], - [ - 'pattern' => 'podcaster/podlove/groups/(:all)', - 'action' => function ($episodeSlug) { - $podcast = new Podcast(); - - return new Response(json_encode($podcast->getPodloveRoles($episodeSlug)), 'application/json'); - } - ], [ 'pattern' => 'podcaster/podlove/config/(:all)', 'action' => function ($episodeSlug) { @@ -158,25 +141,5 @@ return new Response(json_encode($podcast->getPodloveEpisodeJson($episode)), 'application/json'); } ], - [ - 'pattern' => 'podcaster/api/(categories|languages|podlove-clients)', - 'action' => function ($endpoint) { - if (option('mauricerenck.podcaster.useApi', true)) { - $apiCache = kirby()->cache('mauricerenck.podcaster'); - $$endpoint = $apiCache->get($endpoint); - - if ($$endpoint === null) { - $response = new Remote('https://api.podcaster-plugin.com/' . $endpoint); - $apiCache->set($endpoint, $response->content(), 7* 24 * 60 ); - } - - return $$endpoint; - } - - $json = file_get_contents(__DIR__ . '/res/' . $endpoint . '.json'); - - return new Response(json_encode($json), 'application/json'); - } - ], ], ]);