Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • alpha
  • beta
  • develop
  • docs/fix-readme
  • docs/update-vitepress
  • draft/rss-feed
  • feat/dashboard
  • feat/episodes-page-ux
  • feat/generator-user-agent
  • feat/headliner
  • feat/new-languages
  • feat/plugins
  • fix/federation
  • fix/forms-ux
  • i18n
  • main
  • next
  • refactor/transcripts
  • v1.0.0
  • v1.0.0-alpha.1
  • v1.0.0-alpha.10
  • v1.0.0-alpha.11
  • v1.0.0-alpha.12
  • v1.0.0-alpha.13
  • v1.0.0-alpha.14
  • v1.0.0-alpha.15
  • v1.0.0-alpha.16
  • v1.0.0-alpha.17
  • v1.0.0-alpha.18
  • v1.0.0-alpha.19
  • v1.0.0-alpha.2
  • v1.0.0-alpha.20
  • v1.0.0-alpha.21
  • v1.0.0-alpha.22
  • v1.0.0-alpha.23
  • v1.0.0-alpha.24
  • v1.0.0-alpha.25
  • v1.0.0-alpha.26
  • v1.0.0-alpha.27
  • v1.0.0-alpha.28
  • v1.0.0-alpha.29
  • v1.0.0-alpha.3
  • v1.0.0-alpha.30
  • v1.0.0-alpha.31
  • v1.0.0-alpha.32
  • v1.0.0-alpha.33
  • v1.0.0-alpha.34
  • v1.0.0-alpha.35
  • v1.0.0-alpha.36
  • v1.0.0-alpha.37
  • v1.0.0-alpha.38
  • v1.0.0-alpha.39
  • v1.0.0-alpha.4
  • v1.0.0-alpha.40
  • v1.0.0-alpha.41
  • v1.0.0-alpha.42
  • v1.0.0-alpha.43
  • v1.0.0-alpha.44
  • v1.0.0-alpha.45
  • v1.0.0-alpha.46
  • v1.0.0-alpha.47
  • v1.0.0-alpha.48
  • v1.0.0-alpha.49
  • v1.0.0-alpha.5
  • v1.0.0-alpha.50
  • v1.0.0-alpha.51
  • v1.0.0-alpha.52
  • v1.0.0-alpha.53
  • v1.0.0-alpha.54
  • v1.0.0-alpha.55
  • v1.0.0-alpha.56
  • v1.0.0-alpha.57
  • v1.0.0-alpha.58
  • v1.0.0-alpha.59
  • v1.0.0-alpha.6
  • v1.0.0-alpha.60
  • v1.0.0-alpha.61
  • v1.0.0-alpha.62
  • v1.0.0-alpha.63
  • v1.0.0-alpha.64
  • v1.0.0-alpha.65
  • v1.0.0-alpha.66
  • v1.0.0-alpha.67
  • v1.0.0-alpha.68
  • v1.0.0-alpha.69
  • v1.0.0-alpha.7
  • v1.0.0-alpha.70
  • v1.0.0-alpha.71
  • v1.0.0-alpha.72
  • v1.0.0-alpha.73
  • v1.0.0-alpha.74
  • v1.0.0-alpha.75
  • v1.0.0-alpha.76
  • v1.0.0-alpha.77
  • v1.0.0-alpha.78
  • v1.0.0-alpha.79
  • v1.0.0-alpha.8
  • v1.0.0-alpha.80
  • v1.0.0-alpha.9
  • v1.0.0-beta.1
  • v1.0.0-beta.10
  • v1.0.0-beta.11
  • v1.0.0-beta.12
  • v1.0.0-beta.13
  • v1.0.0-beta.14
  • v1.0.0-beta.15
  • v1.0.0-beta.16
  • v1.0.0-beta.17
  • v1.0.0-beta.18
  • v1.0.0-beta.19
  • v1.0.0-beta.2
  • v1.0.0-beta.20
  • v1.0.0-beta.21
  • v1.0.0-beta.22
  • v1.0.0-beta.23
  • v1.0.0-beta.24
  • v1.0.0-beta.3
  • v1.0.0-beta.4
118 results

Target

Select target project
  • adaures/castopod
  • mkljczk/castopod-host
  • spaetz/castopod-host
  • PatrykMis/castopod
  • jonas/castopod
  • ajeremias/castopod
  • misuzu/castopod
  • KrzysztofDomanczyk/castopod
  • Behel/castopod
  • nebulon/castopod
  • ewen/castopod
  • NeoluxConsulting/castopod
  • nateritter/castopod-og
  • prcutler/castopod
14 results
Select Git revision
  • alpha
  • beta
  • develop
  • docs/update-vitepress
  • feat/dashboard
  • feat/op3
  • i18n
  • main
  • v1.0.0
  • v1.0.0-alpha.1
  • v1.0.0-alpha.10
  • v1.0.0-alpha.11
  • v1.0.0-alpha.12
  • v1.0.0-alpha.13
  • v1.0.0-alpha.14
  • v1.0.0-alpha.15
  • v1.0.0-alpha.16
  • v1.0.0-alpha.17
  • v1.0.0-alpha.18
  • v1.0.0-alpha.19
  • v1.0.0-alpha.2
  • v1.0.0-alpha.20
  • v1.0.0-alpha.21
  • v1.0.0-alpha.22
  • v1.0.0-alpha.23
  • v1.0.0-alpha.24
  • v1.0.0-alpha.25
  • v1.0.0-alpha.26
  • v1.0.0-alpha.27
  • v1.0.0-alpha.28
  • v1.0.0-alpha.29
  • v1.0.0-alpha.3
  • v1.0.0-alpha.30
  • v1.0.0-alpha.31
  • v1.0.0-alpha.32
  • v1.0.0-alpha.33
  • v1.0.0-alpha.34
  • v1.0.0-alpha.35
  • v1.0.0-alpha.36
  • v1.0.0-alpha.37
  • v1.0.0-alpha.38
  • v1.0.0-alpha.39
  • v1.0.0-alpha.4
  • v1.0.0-alpha.40
  • v1.0.0-alpha.41
  • v1.0.0-alpha.42
  • v1.0.0-alpha.43
  • v1.0.0-alpha.44
  • v1.0.0-alpha.45
  • v1.0.0-alpha.46
  • v1.0.0-alpha.47
  • v1.0.0-alpha.48
  • v1.0.0-alpha.49
  • v1.0.0-alpha.5
  • v1.0.0-alpha.50
  • v1.0.0-alpha.51
  • v1.0.0-alpha.52
  • v1.0.0-alpha.53
  • v1.0.0-alpha.54
  • v1.0.0-alpha.55
  • v1.0.0-alpha.56
  • v1.0.0-alpha.57
  • v1.0.0-alpha.58
  • v1.0.0-alpha.59
  • v1.0.0-alpha.6
  • v1.0.0-alpha.60
  • v1.0.0-alpha.61
  • v1.0.0-alpha.62
  • v1.0.0-alpha.63
  • v1.0.0-alpha.64
  • v1.0.0-alpha.65
  • v1.0.0-alpha.66
  • v1.0.0-alpha.67
  • v1.0.0-alpha.68
  • v1.0.0-alpha.69
  • v1.0.0-alpha.7
  • v1.0.0-alpha.70
  • v1.0.0-alpha.71
  • v1.0.0-alpha.72
  • v1.0.0-alpha.73
  • v1.0.0-alpha.74
  • v1.0.0-alpha.75
  • v1.0.0-alpha.76
  • v1.0.0-alpha.77
  • v1.0.0-alpha.78
  • v1.0.0-alpha.79
  • v1.0.0-alpha.8
  • v1.0.0-alpha.80
  • v1.0.0-alpha.9
  • v1.0.0-beta.1
  • v1.0.0-beta.10
  • v1.0.0-beta.11
  • v1.0.0-beta.12
  • v1.0.0-beta.13
  • v1.0.0-beta.14
  • v1.0.0-beta.15
  • v1.0.0-beta.16
  • v1.0.0-beta.17
  • v1.0.0-beta.18
  • v1.0.0-beta.19
  • v1.0.0-beta.2
  • v1.0.0-beta.20
  • v1.0.0-beta.21
  • v1.0.0-beta.22
  • v1.0.0-beta.23
  • v1.0.0-beta.24
  • v1.0.0-beta.3
  • v1.0.0-beta.4
108 results
Show changes
Showing
with 1171 additions and 2198 deletions
<?php
declare(strict_types=1);
/**
* Class PermissionSeeder Inserts permissions
*
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
namespace App\Database\Seeds;
use CodeIgniter\Database\Seeder;
class AuthSeeder extends Seeder
{
/**
* @var array<string, string>[]
*/
protected array $groups = [
[
'name' => 'superadmin',
'description' =>
'Somebody who has access to all the castopod instance features',
],
[
'name' => 'podcast_admin',
'description' =>
'Somebody who has access to all the features within a given podcast',
],
];
/**
* Build permissions array as a list of:
*
* ``` context => [ [action, description], [action, description], ... ] ```
*
* @var array<string, array<string, string|string[]>[]>
*/
protected array $permissions = [
'settings' => [
[
'name' => 'view',
'description' => 'View settings options',
'has_permission' => ['superadmin'],
],
[
'name' => 'manage',
'description' => 'Update general settings',
'has_permission' => ['superadmin'],
],
],
'users' => [
[
'name' => 'create',
'description' => 'Create a user',
'has_permission' => ['superadmin'],
],
[
'name' => 'list',
'description' => 'List all users',
'has_permission' => ['superadmin'],
],
[
'name' => 'view',
'description' => 'View any user info',
'has_permission' => ['superadmin'],
],
[
'name' => 'manage_authorizations',
'description' => 'Add or remove roles/permissions to a user',
'has_permission' => ['superadmin'],
],
[
'name' => 'manage_bans',
'description' => 'Ban / unban a user',
'has_permission' => ['superadmin'],
],
[
'name' => 'force_pass_reset',
'description' =>
'Force a user to update his password upon next login',
'has_permission' => ['superadmin'],
],
[
'name' => 'delete',
'description' =>
'Delete user without removing him from database',
'has_permission' => ['superadmin'],
],
[
'name' => 'delete_permanently',
'description' =>
'Delete all occurrences of a user from the database',
'has_permission' => ['superadmin'],
],
],
'pages' => [
[
'name' => 'manage',
'description' => 'List / create / edit / delete pages',
'has_permission' => ['superadmin'],
],
],
'podcasts' => [
[
'name' => 'create',
'description' => 'Add a new podcast',
'has_permission' => ['superadmin'],
],
[
'name' => 'import',
'description' => 'Import a new podcast from an external feed',
'has_permission' => ['superadmin'],
],
[
'name' => 'list',
'description' => 'List all podcasts and their episodes',
'has_permission' => ['superadmin'],
],
[
'name' => 'view',
'description' => 'View any podcast and their contributors list',
'has_permission' => ['superadmin'],
],
[
'name' => 'delete',
'description' =>
'Delete a podcast without removing it from database',
'has_permission' => ['superadmin'],
],
[
'name' => 'delete_permanently',
'description' => 'Delete any podcast from the database',
'has_permission' => ['superadmin'],
],
],
'episodes' => [
[
'name' => 'list',
'description' => 'List all episodes of any podcast',
'has_permission' => ['superadmin'],
],
[
'name' => 'view',
'description' => 'View any episode of any podcast',
'has_permission' => ['superadmin'],
],
],
'podcast' => [
[
'name' => 'view',
'description' => 'View a podcast',
'has_permission' => ['podcast_admin'],
],
[
'name' => 'edit',
'description' => 'Edit a podcast',
'has_permission' => ['podcast_admin'],
],
[
'name' => 'manage_contributors',
'description' =>
'Add / remove contributors to a podcast and edit their roles',
'has_permission' => ['podcast_admin'],
],
[
'name' => 'manage_platforms',
'description' => 'Set / remove platform links of a podcast',
'has_permission' => ['podcast_admin'],
],
[
'name' => 'manage_publications',
'description' =>
'Publish / unpublish episodes & posts of a podcast',
'has_permission' => ['podcast_admin'],
],
[
'name' => 'interact_as',
'description' =>
'Interact as the podcast to favourite / share or reply to posts.',
'has_permission' => ['podcast_admin'],
],
],
'podcast_episodes' => [
[
'name' => 'list',
'description' => 'List all episodes of a podcast',
'has_permission' => ['podcast_admin'],
],
[
'name' => 'view',
'description' => 'View any episode of a podcast',
'has_permission' => ['podcast_admin'],
],
[
'name' => 'create',
'description' => 'Add new episodes for a podcast',
'has_permission' => ['podcast_admin'],
],
[
'name' => 'edit',
'description' => 'Edit an episode of a podcast',
'has_permission' => ['podcast_admin'],
],
[
'name' => 'delete',
'description' =>
'Delete an episode of a podcast without removing it from the database',
'has_permission' => ['podcast_admin'],
],
[
'name' => 'delete_permanently',
'description' =>
'Delete all occurrences of an episode of a podcast from the database',
'has_permission' => ['podcast_admin'],
],
],
'person' => [
[
'name' => 'create',
'description' => 'Add a new person',
'has_permission' => ['superadmin'],
],
[
'name' => 'list',
'description' => 'List all persons',
'has_permission' => ['superadmin'],
],
[
'name' => 'view',
'description' => 'View any person',
'has_permission' => ['superadmin'],
],
[
'name' => 'edit',
'description' => 'Edit a person',
'has_permission' => ['superadmin'],
],
[
'name' => 'delete',
'description' =>
'Delete permanently any person from the database',
'has_permission' => ['superadmin'],
],
],
'fediverse' => [
[
'name' => 'block_actors',
'description' =>
'Block fediverse actors from interacting with the instance.',
'has_permission' => ['superadmin'],
],
[
'name' => 'block_domains',
'description' =>
'Block fediverse domains from interacting with the instance.',
'has_permission' => ['superadmin'],
],
],
];
public function run(): void
{
$groupId = 0;
$dataGroups = [];
foreach ($this->groups as $group) {
$dataGroups[] = [
'id' => ++$groupId,
'name' => $group['name'],
'description' => $group['description'],
];
}
// Map permissions to a format the `auth_permissions` table expects
$dataPermissions = [];
$dataGroupsPermissions = [];
$permissionId = 0;
foreach ($this->permissions as $context => $actions) {
foreach ($actions as $action) {
$dataPermissions[] = [
'id' => ++$permissionId,
'name' => $context . '-' . $action['name'],
'description' => $action['description'],
];
foreach ($action['has_permission'] as $role) {
// link permission to specified groups
$dataGroupsPermissions[] = [
'group_id' => $this->getGroupIdByName($role, $dataGroups),
'permission_id' => $permissionId,
];
}
}
}
if ($this->db->table('auth_groups')->countAll() < count($dataPermissions)) {
$this->db
->table('auth_permissions')
->ignore(true)
->insertBatch($dataPermissions);
}
if ($this->db->table('auth_groups')->countAll() < count($dataGroups)) {
$this->db
->table('auth_groups')
->ignore(true)
->insertBatch($dataGroups);
}
if ($this->db->table('auth_groups_permissions')->countAll() < count($dataGroupsPermissions)) {
$this->db
->table('auth_groups_permissions')
->ignore(true)
->insertBatch($dataGroupsPermissions);
}
}
/**
* @param array<string, string|int>[] $dataGroups
*/
public static function getGroupIdByName(string $name, array $dataGroups): ?int
{
foreach ($dataGroups as $group) {
if ($group['name'] === $name) {
return $group['id'];
}
}
return null;
}
}
...@@ -13,780 +13,782 @@ declare(strict_types=1); ...@@ -13,780 +13,782 @@ declare(strict_types=1);
namespace App\Database\Seeds; namespace App\Database\Seeds;
use CodeIgniter\Database\Seeder; use CodeIgniter\Database\Seeder;
use Override;
class CategorySeeder extends Seeder class CategorySeeder extends Seeder
{ {
#[Override]
public function run(): void public function run(): void
{ {
$data = [ $data = [
[ [
'id' => 1, 'id' => 1,
'parent_id' => null, 'parent_id' => null,
'code' => 'arts', 'code' => 'arts',
'apple_category' => 'Arts', 'apple_category' => 'Arts',
'google_category' => 'Arts', 'google_category' => 'Arts',
], ],
[ [
'id' => 2, 'id' => 2,
'parent_id' => null, 'parent_id' => null,
'code' => 'business', 'code' => 'business',
'apple_category' => 'Business', 'apple_category' => 'Business',
'google_category' => 'Business', 'google_category' => 'Business',
], ],
[ [
'id' => 3, 'id' => 3,
'parent_id' => null, 'parent_id' => null,
'code' => 'comedy', 'code' => 'comedy',
'apple_category' => 'Comedy', 'apple_category' => 'Comedy',
'google_category' => 'Comedy', 'google_category' => 'Comedy',
], ],
[ [
'id' => 4, 'id' => 4,
'parent_id' => null, 'parent_id' => null,
'code' => 'education', 'code' => 'education',
'apple_category' => 'Education', 'apple_category' => 'Education',
'google_category' => 'Education', 'google_category' => 'Education',
], ],
[ [
'id' => 5, 'id' => 5,
'parent_id' => null, 'parent_id' => null,
'code' => 'fiction', 'code' => 'fiction',
'apple_category' => 'Fiction', 'apple_category' => 'Fiction',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 6, 'id' => 6,
'parent_id' => null, 'parent_id' => null,
'code' => 'government', 'code' => 'government',
'apple_category' => 'Government', 'apple_category' => 'Government',
'google_category' => 'Government & Organizations', 'google_category' => 'Government & Organizations',
], ],
[ [
'id' => 7, 'id' => 7,
'parent_id' => null, 'parent_id' => null,
'code' => 'health_and_fitness', 'code' => 'health_and_fitness',
'apple_category' => 'Health & Fitness', 'apple_category' => 'Health & Fitness',
'google_category' => 'Health', 'google_category' => 'Health',
], ],
[ [
'id' => 8, 'id' => 8,
'parent_id' => null, 'parent_id' => null,
'code' => 'history', 'code' => 'history',
'apple_category' => 'History', 'apple_category' => 'History',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 9, 'id' => 9,
'parent_id' => null, 'parent_id' => null,
'code' => 'kids_and_family', 'code' => 'kids_and_family',
'apple_category' => 'Kids & Family', 'apple_category' => 'Kids & Family',
'google_category' => 'Kids & Family', 'google_category' => 'Kids & Family',
], ],
[ [
'id' => 10, 'id' => 10,
'parent_id' => null, 'parent_id' => null,
'code' => 'leisure', 'code' => 'leisure',
'apple_category' => 'Leisure', 'apple_category' => 'Leisure',
'google_category' => 'Games & Hobbies', 'google_category' => 'Games & Hobbies',
], ],
[ [
'id' => 11, 'id' => 11,
'parent_id' => null, 'parent_id' => null,
'code' => 'music', 'code' => 'music',
'apple_category' => 'Music', 'apple_category' => 'Music',
'google_category' => 'Music', 'google_category' => 'Music',
], ],
[ [
'id' => 12, 'id' => 12,
'parent_id' => null, 'parent_id' => null,
'code' => 'news', 'code' => 'news',
'apple_category' => 'News', 'apple_category' => 'News',
'google_category' => 'News & Politics', 'google_category' => 'News & Politics',
], ],
[ [
'id' => 13, 'id' => 13,
'parent_id' => null, 'parent_id' => null,
'code' => 'religion_and_spirituality', 'code' => 'religion_and_spirituality',
'apple_category' => 'Religion & Spirituality', 'apple_category' => 'Religion & Spirituality',
'google_category' => 'Religion & Spirituality', 'google_category' => 'Religion & Spirituality',
], ],
[ [
'id' => 14, 'id' => 14,
'parent_id' => null, 'parent_id' => null,
'code' => 'science', 'code' => 'science',
'apple_category' => 'Science', 'apple_category' => 'Science',
'google_category' => 'Science & Medicine', 'google_category' => 'Science & Medicine',
], ],
[ [
'id' => 15, 'id' => 15,
'parent_id' => null, 'parent_id' => null,
'code' => 'society_and_culture', 'code' => 'society_and_culture',
'apple_category' => 'Society & Culture', 'apple_category' => 'Society & Culture',
'google_category' => 'Society & Culture', 'google_category' => 'Society & Culture',
], ],
[ [
'id' => 16, 'id' => 16,
'parent_id' => null, 'parent_id' => null,
'code' => 'sports', 'code' => 'sports',
'apple_category' => 'Sports', 'apple_category' => 'Sports',
'google_category' => 'Sports & Recreation', 'google_category' => 'Sports & Recreation',
], ],
[ [
'id' => 17, 'id' => 17,
'parent_id' => null, 'parent_id' => null,
'code' => 'technology', 'code' => 'technology',
'apple_category' => 'Technology', 'apple_category' => 'Technology',
'google_category' => 'Technology', 'google_category' => 'Technology',
], ],
[ [
'id' => 18, 'id' => 18,
'parent_id' => null, 'parent_id' => null,
'code' => 'true_crime', 'code' => 'true_crime',
'apple_category' => 'True Crime', 'apple_category' => 'True Crime',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 19, 'id' => 19,
'parent_id' => null, 'parent_id' => null,
'code' => 'tv_and_film', 'code' => 'tv_and_film',
'apple_category' => 'TV & Film', 'apple_category' => 'TV & Film',
'google_category' => 'TV & Film', 'google_category' => 'TV & Film',
], ],
[ [
'id' => 20, 'id' => 20,
'parent_id' => 1, 'parent_id' => 1,
'code' => 'books', 'code' => 'books',
'apple_category' => 'Books', 'apple_category' => 'Books',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 21, 'id' => 21,
'parent_id' => 1, 'parent_id' => 1,
'code' => 'design', 'code' => 'design',
'apple_category' => 'Design', 'apple_category' => 'Design',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 22, 'id' => 22,
'parent_id' => 1, 'parent_id' => 1,
'code' => 'fashion_and_beauty', 'code' => 'fashion_and_beauty',
'apple_category' => 'Fashion & Beauty', 'apple_category' => 'Fashion & Beauty',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 23, 'id' => 23,
'parent_id' => 1, 'parent_id' => 1,
'code' => 'food', 'code' => 'food',
'apple_category' => 'Food', 'apple_category' => 'Food',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 24, 'id' => 24,
'parent_id' => 1, 'parent_id' => 1,
'code' => 'performing_arts', 'code' => 'performing_arts',
'apple_category' => 'Performing Arts', 'apple_category' => 'Performing Arts',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 25, 'id' => 25,
'parent_id' => 1, 'parent_id' => 1,
'code' => 'visual_arts', 'code' => 'visual_arts',
'apple_category' => 'Visual Arts', 'apple_category' => 'Visual Arts',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 26, 'id' => 26,
'parent_id' => 2, 'parent_id' => 2,
'code' => 'careers', 'code' => 'careers',
'apple_category' => 'Careers', 'apple_category' => 'Careers',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 27, 'id' => 27,
'parent_id' => 2, 'parent_id' => 2,
'code' => 'entrepreneurship', 'code' => 'entrepreneurship',
'apple_category' => 'Entrepreneurship', 'apple_category' => 'Entrepreneurship',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 28, 'id' => 28,
'parent_id' => 2, 'parent_id' => 2,
'code' => 'investing', 'code' => 'investing',
'apple_category' => 'Investing', 'apple_category' => 'Investing',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 29, 'id' => 29,
'parent_id' => 2, 'parent_id' => 2,
'code' => 'management', 'code' => 'management',
'apple_category' => 'Management', 'apple_category' => 'Management',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 30, 'id' => 30,
'parent_id' => 2, 'parent_id' => 2,
'code' => 'marketing', 'code' => 'marketing',
'apple_category' => 'Marketing', 'apple_category' => 'Marketing',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 31, 'id' => 31,
'parent_id' => 2, 'parent_id' => 2,
'code' => 'non_profit', 'code' => 'non_profit',
'apple_category' => 'Non-Profit', 'apple_category' => 'Non-Profit',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 32, 'id' => 32,
'parent_id' => 3, 'parent_id' => 3,
'code' => 'comedy_interviews', 'code' => 'comedy_interviews',
'apple_category' => 'Comedy Interviews', 'apple_category' => 'Comedy Interviews',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 33, 'id' => 33,
'parent_id' => 3, 'parent_id' => 3,
'code' => 'improv', 'code' => 'improv',
'apple_category' => 'Improv', 'apple_category' => 'Improv',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 34, 'id' => 34,
'parent_id' => 3, 'parent_id' => 3,
'code' => 'stand_up', 'code' => 'stand_up',
'apple_category' => 'Stand-Up', 'apple_category' => 'Stand-Up',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 35, 'id' => 35,
'parent_id' => 4, 'parent_id' => 4,
'code' => 'courses', 'code' => 'courses',
'apple_category' => 'Courses', 'apple_category' => 'Courses',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 36, 'id' => 36,
'parent_id' => 4, 'parent_id' => 4,
'code' => 'how_to', 'code' => 'how_to',
'apple_category' => 'How To', 'apple_category' => 'How To',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 37, 'id' => 37,
'parent_id' => 4, 'parent_id' => 4,
'code' => 'language_learning', 'code' => 'language_learning',
'apple_category' => 'Language Learning', 'apple_category' => 'Language Learning',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 38, 'id' => 38,
'parent_id' => 4, 'parent_id' => 4,
'code' => 'self_improvement', 'code' => 'self_improvement',
'apple_category' => 'Self-Improvement', 'apple_category' => 'Self-Improvement',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 39, 'id' => 39,
'parent_id' => 5, 'parent_id' => 5,
'code' => 'comedy_fiction', 'code' => 'comedy_fiction',
'apple_category' => 'Comedy Fiction', 'apple_category' => 'Comedy Fiction',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 40, 'id' => 40,
'parent_id' => 5, 'parent_id' => 5,
'code' => 'drama', 'code' => 'drama',
'apple_category' => 'Drama', 'apple_category' => 'Drama',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 41, 'id' => 41,
'parent_id' => 5, 'parent_id' => 5,
'code' => 'science_fiction', 'code' => 'science_fiction',
'apple_category' => 'Science Fiction', 'apple_category' => 'Science Fiction',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 42, 'id' => 42,
'parent_id' => 7, 'parent_id' => 7,
'code' => 'alternative_health', 'code' => 'alternative_health',
'apple_category' => 'Alternative Health', 'apple_category' => 'Alternative Health',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 43, 'id' => 43,
'parent_id' => 7, 'parent_id' => 7,
'code' => 'fitness', 'code' => 'fitness',
'apple_category' => 'Fitness', 'apple_category' => 'Fitness',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 44, 'id' => 44,
'parent_id' => 7, 'parent_id' => 7,
'code' => 'medicine', 'code' => 'medicine',
'apple_category' => 'Medicine', 'apple_category' => 'Medicine',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 45, 'id' => 45,
'parent_id' => 7, 'parent_id' => 7,
'code' => 'mental_health', 'code' => 'mental_health',
'apple_category' => 'Mental Health', 'apple_category' => 'Mental Health',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 46, 'id' => 46,
'parent_id' => 7, 'parent_id' => 7,
'code' => 'nutrition', 'code' => 'nutrition',
'apple_category' => 'Nutrition', 'apple_category' => 'Nutrition',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 47, 'id' => 47,
'parent_id' => 7, 'parent_id' => 7,
'code' => 'sexuality', 'code' => 'sexuality',
'apple_category' => 'Sexuality', 'apple_category' => 'Sexuality',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 48, 'id' => 48,
'parent_id' => 9, 'parent_id' => 9,
'code' => 'education_for_kids', 'code' => 'education_for_kids',
'apple_category' => 'Education for Kids', 'apple_category' => 'Education for Kids',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 49, 'id' => 49,
'parent_id' => 9, 'parent_id' => 9,
'code' => 'parenting', 'code' => 'parenting',
'apple_category' => 'Parenting', 'apple_category' => 'Parenting',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 50, 'id' => 50,
'parent_id' => 9, 'parent_id' => 9,
'code' => 'pets_and_animals', 'code' => 'pets_and_animals',
'apple_category' => 'Pets & Animals', 'apple_category' => 'Pets & Animals',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 51, 'id' => 51,
'parent_id' => 9, 'parent_id' => 9,
'code' => 'stories_for_kids', 'code' => 'stories_for_kids',
'apple_category' => 'Stories for Kids', 'apple_category' => 'Stories for Kids',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 52, 'id' => 52,
'parent_id' => 10, 'parent_id' => 10,
'code' => 'animation_and_manga', 'code' => 'animation_and_manga',
'apple_category' => 'Animation & Manga', 'apple_category' => 'Animation & Manga',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 53, 'id' => 53,
'parent_id' => 10, 'parent_id' => 10,
'code' => 'automotive', 'code' => 'automotive',
'apple_category' => 'Automotive', 'apple_category' => 'Automotive',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 54, 'id' => 54,
'parent_id' => 10, 'parent_id' => 10,
'code' => 'aviation', 'code' => 'aviation',
'apple_category' => 'Aviation', 'apple_category' => 'Aviation',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 55, 'id' => 55,
'parent_id' => 10, 'parent_id' => 10,
'code' => 'crafts', 'code' => 'crafts',
'apple_category' => 'Crafts', 'apple_category' => 'Crafts',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 56, 'id' => 56,
'parent_id' => 10, 'parent_id' => 10,
'code' => 'games', 'code' => 'games',
'apple_category' => 'Games', 'apple_category' => 'Games',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 57, 'id' => 57,
'parent_id' => 10, 'parent_id' => 10,
'code' => 'hobbies', 'code' => 'hobbies',
'apple_category' => 'Hobbies', 'apple_category' => 'Hobbies',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 58, 'id' => 58,
'parent_id' => 10, 'parent_id' => 10,
'code' => 'home_and_garden', 'code' => 'home_and_garden',
'apple_category' => 'Home & Garden', 'apple_category' => 'Home & Garden',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 59, 'id' => 59,
'parent_id' => 10, 'parent_id' => 10,
'code' => 'video_games', 'code' => 'video_games',
'apple_category' => 'Video Games', 'apple_category' => 'Video Games',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 60, 'id' => 60,
'parent_id' => 11, 'parent_id' => 11,
'code' => 'music_commentary', 'code' => 'music_commentary',
'apple_category' => 'Music Commentary', 'apple_category' => 'Music Commentary',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 61, 'id' => 61,
'parent_id' => 11, 'parent_id' => 11,
'code' => 'music_history', 'code' => 'music_history',
'apple_category' => 'Music History', 'apple_category' => 'Music History',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 62, 'id' => 62,
'parent_id' => 11, 'parent_id' => 11,
'code' => 'music_interviews', 'code' => 'music_interviews',
'apple_category' => 'Music Interviews', 'apple_category' => 'Music Interviews',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 63, 'id' => 63,
'parent_id' => 12, 'parent_id' => 12,
'code' => 'business_news', 'code' => 'business_news',
'apple_category' => 'Business News', 'apple_category' => 'Business News',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 64, 'id' => 64,
'parent_id' => 12, 'parent_id' => 12,
'code' => 'daily_news', 'code' => 'daily_news',
'apple_category' => 'Daily News', 'apple_category' => 'Daily News',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 65, 'id' => 65,
'parent_id' => 12, 'parent_id' => 12,
'code' => 'entertainment_news', 'code' => 'entertainment_news',
'apple_category' => 'Entertainment News', 'apple_category' => 'Entertainment News',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 66, 'id' => 66,
'parent_id' => 12, 'parent_id' => 12,
'code' => 'news_commentary', 'code' => 'news_commentary',
'apple_category' => 'News Commentary', 'apple_category' => 'News Commentary',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 67, 'id' => 67,
'parent_id' => 12, 'parent_id' => 12,
'code' => 'politics', 'code' => 'politics',
'apple_category' => 'Politics', 'apple_category' => 'Politics',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 68, 'id' => 68,
'parent_id' => 12, 'parent_id' => 12,
'code' => 'sports_news', 'code' => 'sports_news',
'apple_category' => 'Sports News', 'apple_category' => 'Sports News',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 69, 'id' => 69,
'parent_id' => 12, 'parent_id' => 12,
'code' => 'tech_news', 'code' => 'tech_news',
'apple_category' => 'Tech News', 'apple_category' => 'Tech News',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 70, 'id' => 70,
'parent_id' => 13, 'parent_id' => 13,
'code' => 'buddhism', 'code' => 'buddhism',
'apple_category' => 'Buddhism', 'apple_category' => 'Buddhism',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 71, 'id' => 71,
'parent_id' => 13, 'parent_id' => 13,
'code' => 'christianity', 'code' => 'christianity',
'apple_category' => 'Christianity', 'apple_category' => 'Christianity',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 72, 'id' => 72,
'parent_id' => 13, 'parent_id' => 13,
'code' => 'hinduism', 'code' => 'hinduism',
'apple_category' => 'Hinduism', 'apple_category' => 'Hinduism',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 73, 'id' => 73,
'parent_id' => 13, 'parent_id' => 13,
'code' => 'islam', 'code' => 'islam',
'apple_category' => 'Islam', 'apple_category' => 'Islam',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 74, 'id' => 74,
'parent_id' => 13, 'parent_id' => 13,
'code' => 'judaism', 'code' => 'judaism',
'apple_category' => 'Judaism', 'apple_category' => 'Judaism',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 75, 'id' => 75,
'parent_id' => 13, 'parent_id' => 13,
'code' => 'religion', 'code' => 'religion',
'apple_category' => 'Religion', 'apple_category' => 'Religion',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 76, 'id' => 76,
'parent_id' => 13, 'parent_id' => 13,
'code' => 'spirituality', 'code' => 'spirituality',
'apple_category' => 'Spirituality', 'apple_category' => 'Spirituality',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 77, 'id' => 77,
'parent_id' => 14, 'parent_id' => 14,
'code' => 'astronomy', 'code' => 'astronomy',
'apple_category' => 'Astronomy', 'apple_category' => 'Astronomy',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 78, 'id' => 78,
'parent_id' => 14, 'parent_id' => 14,
'code' => 'chemistry', 'code' => 'chemistry',
'apple_category' => 'Chemistry', 'apple_category' => 'Chemistry',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 79, 'id' => 79,
'parent_id' => 14, 'parent_id' => 14,
'code' => 'earth_sciences', 'code' => 'earth_sciences',
'apple_category' => 'Earth Sciences', 'apple_category' => 'Earth Sciences',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 80, 'id' => 80,
'parent_id' => 14, 'parent_id' => 14,
'code' => 'life_sciences', 'code' => 'life_sciences',
'apple_category' => 'Life Sciences', 'apple_category' => 'Life Sciences',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 81, 'id' => 81,
'parent_id' => 14, 'parent_id' => 14,
'code' => 'mathematics', 'code' => 'mathematics',
'apple_category' => 'Mathematics', 'apple_category' => 'Mathematics',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 82, 'id' => 82,
'parent_id' => 14, 'parent_id' => 14,
'code' => 'natural_sciences', 'code' => 'natural_sciences',
'apple_category' => 'Natural Sciences', 'apple_category' => 'Natural Sciences',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 83, 'id' => 83,
'parent_id' => 14, 'parent_id' => 14,
'code' => 'nature', 'code' => 'nature',
'apple_category' => 'Nature', 'apple_category' => 'Nature',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 84, 'id' => 84,
'parent_id' => 14, 'parent_id' => 14,
'code' => 'physics', 'code' => 'physics',
'apple_category' => 'Physics', 'apple_category' => 'Physics',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 85, 'id' => 85,
'parent_id' => 14, 'parent_id' => 14,
'code' => 'social_sciences', 'code' => 'social_sciences',
'apple_category' => 'Social Sciences', 'apple_category' => 'Social Sciences',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 86, 'id' => 86,
'parent_id' => 15, 'parent_id' => 15,
'code' => 'documentary', 'code' => 'documentary',
'apple_category' => 'Documentary', 'apple_category' => 'Documentary',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 87, 'id' => 87,
'parent_id' => 15, 'parent_id' => 15,
'code' => 'personal_journals', 'code' => 'personal_journals',
'apple_category' => 'Personal Journals', 'apple_category' => 'Personal Journals',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 88, 'id' => 88,
'parent_id' => 15, 'parent_id' => 15,
'code' => 'philosophy', 'code' => 'philosophy',
'apple_category' => 'Philosophy', 'apple_category' => 'Philosophy',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 89, 'id' => 89,
'parent_id' => 15, 'parent_id' => 15,
'code' => 'places_and_travel', 'code' => 'places_and_travel',
'apple_category' => 'Places & Travel', 'apple_category' => 'Places & Travel',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 90, 'id' => 90,
'parent_id' => 15, 'parent_id' => 15,
'code' => 'relationships', 'code' => 'relationships',
'apple_category' => 'Relationships', 'apple_category' => 'Relationships',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 91, 'id' => 91,
'parent_id' => 16, 'parent_id' => 16,
'code' => 'baseball', 'code' => 'baseball',
'apple_category' => 'Baseball', 'apple_category' => 'Baseball',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 92, 'id' => 92,
'parent_id' => 16, 'parent_id' => 16,
'code' => 'basketball', 'code' => 'basketball',
'apple_category' => 'Basketball', 'apple_category' => 'Basketball',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 93, 'id' => 93,
'parent_id' => 16, 'parent_id' => 16,
'code' => 'cricket', 'code' => 'cricket',
'apple_category' => 'Cricket', 'apple_category' => 'Cricket',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 94, 'id' => 94,
'parent_id' => 16, 'parent_id' => 16,
'code' => 'fantasy_sports', 'code' => 'fantasy_sports',
'apple_category' => 'Fantasy Sports', 'apple_category' => 'Fantasy Sports',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 95, 'id' => 95,
'parent_id' => 16, 'parent_id' => 16,
'code' => 'football', 'code' => 'football',
'apple_category' => 'Football', 'apple_category' => 'Football',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 96, 'id' => 96,
'parent_id' => 16, 'parent_id' => 16,
'code' => 'golf', 'code' => 'golf',
'apple_category' => 'Golf', 'apple_category' => 'Golf',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 97, 'id' => 97,
'parent_id' => 16, 'parent_id' => 16,
'code' => 'hockey', 'code' => 'hockey',
'apple_category' => 'Hockey', 'apple_category' => 'Hockey',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 98, 'id' => 98,
'parent_id' => 16, 'parent_id' => 16,
'code' => 'rugby', 'code' => 'rugby',
'apple_category' => 'Rugby', 'apple_category' => 'Rugby',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 99, 'id' => 99,
'parent_id' => 16, 'parent_id' => 16,
'code' => 'running', 'code' => 'running',
'apple_category' => 'Running', 'apple_category' => 'Running',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 100, 'id' => 100,
'parent_id' => 16, 'parent_id' => 16,
'code' => 'soccer', 'code' => 'soccer',
'apple_category' => 'Soccer', 'apple_category' => 'Soccer',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 101, 'id' => 101,
'parent_id' => 16, 'parent_id' => 16,
'code' => 'swimming', 'code' => 'swimming',
'apple_category' => 'Swimming', 'apple_category' => 'Swimming',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 102, 'id' => 102,
'parent_id' => 16, 'parent_id' => 16,
'code' => 'tennis', 'code' => 'tennis',
'apple_category' => 'Tennis', 'apple_category' => 'Tennis',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 103, 'id' => 103,
'parent_id' => 16, 'parent_id' => 16,
'code' => 'volleyball', 'code' => 'volleyball',
'apple_category' => 'Volleyball', 'apple_category' => 'Volleyball',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 104, 'id' => 104,
'parent_id' => 16, 'parent_id' => 16,
'code' => 'wilderness', 'code' => 'wilderness',
'apple_category' => 'Wilderness', 'apple_category' => 'Wilderness',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 105, 'id' => 105,
'parent_id' => 16, 'parent_id' => 16,
'code' => 'wrestling', 'code' => 'wrestling',
'apple_category' => 'Wrestling', 'apple_category' => 'Wrestling',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 106, 'id' => 106,
'parent_id' => 19, 'parent_id' => 19,
'code' => 'after_shows', 'code' => 'after_shows',
'apple_category' => 'After Shows', 'apple_category' => 'After Shows',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 107, 'id' => 107,
'parent_id' => 19, 'parent_id' => 19,
'code' => 'film_history', 'code' => 'film_history',
'apple_category' => 'Film History', 'apple_category' => 'Film History',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 108, 'id' => 108,
'parent_id' => 19, 'parent_id' => 19,
'code' => 'film_interviews', 'code' => 'film_interviews',
'apple_category' => 'Film Interviews', 'apple_category' => 'Film Interviews',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 109, 'id' => 109,
'parent_id' => 19, 'parent_id' => 19,
'code' => 'film_reviews', 'code' => 'film_reviews',
'apple_category' => 'Film Reviews', 'apple_category' => 'Film Reviews',
'google_category' => '', 'google_category' => '',
], ],
[ [
'id' => 110, 'id' => 110,
'parent_id' => 19, 'parent_id' => 19,
'code' => 'tv_reviews', 'code' => 'tv_reviews',
'apple_category' => 'TV Reviews', 'apple_category' => 'TV Reviews',
'google_category' => '', 'google_category' => '',
], ],
]; ];
......
...@@ -3,20 +3,25 @@ ...@@ -3,20 +3,25 @@
declare(strict_types=1); declare(strict_types=1);
/** /**
* Class AppSeeder Calls all required seeders for castopod to work properly
*
* @copyright 2020 Ad Aures * @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/ * @link https://castopod.org/
*/ */
namespace Modules\Admin\Controllers; namespace App\Database\Seeds;
use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\Database\Seeder;
use Override;
class HomeController extends BaseController class DevSeeder extends Seeder
{ {
public function index(): RedirectResponse #[Override]
public function run(): void
{ {
session()->keepFlashdata('message'); $this->call('CategorySeeder');
return redirect()->route('podcast-list'); $this->call('LanguageSeeder');
$this->call('DevSuperadminSeeder');
} }
} }
<?php
declare(strict_types=1);
/**
* Class TestSeeder Inserts a superadmin user in the database
*
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
namespace App\Database\Seeds;
use CodeIgniter\Database\Seeder;
use CodeIgniter\Shield\Entities\User;
use Modules\Auth\Models\UserModel;
use Override;
class DevSuperadminSeeder extends Seeder
{
#[Override]
public function run(): void
{
if ((new UserModel())->where('is_owner', true)->first() instanceof User) {
return;
}
/**
* Inserts an owner with the following credentials: admin: `admin@example.com` password: `castopod`
*/
// Get the User Provider (UserModel by default)
$users = auth()
->getProvider();
$user = new User([
'username' => 'admin',
'email' => 'admin@castopod.local',
'password' => 'castopod',
'is_owner' => true,
]);
$users->save($user);
// To get the complete user object with ID, we need to get from the database
$user = $users->findById($users->getInsertID());
$user->addGroup(setting('AuthGroups.mostPowerfulGroup'));
}
}
...@@ -12,15 +12,19 @@ declare(strict_types=1); ...@@ -12,15 +12,19 @@ declare(strict_types=1);
namespace App\Database\Seeds; namespace App\Database\Seeds;
use App\Entities\Episode;
use App\Entities\Podcast;
use App\Models\EpisodeModel; use App\Models\EpisodeModel;
use App\Models\PodcastModel; use App\Models\PodcastModel;
use CodeIgniter\Database\Seeder; use CodeIgniter\Database\Seeder;
use Exception;
use GeoIp2\Database\Reader; use GeoIp2\Database\Reader;
use GeoIp2\Exception\AddressNotFoundException; use GeoIp2\Exception\AddressNotFoundException;
use Override;
class FakePodcastsAnalyticsSeeder extends Seeder class FakePodcastsAnalyticsSeeder extends Seeder
{ {
#[Override]
public function run(): void public function run(): void
{ {
$jsonUserAgents = json_decode( $jsonUserAgents = json_decode(
...@@ -41,162 +45,162 @@ class FakePodcastsAnalyticsSeeder extends Seeder ...@@ -41,162 +45,162 @@ class FakePodcastsAnalyticsSeeder extends Seeder
$podcast = (new PodcastModel())->first(); $podcast = (new PodcastModel())->first();
if ($podcast !== null) { if (! $podcast instanceof Podcast) {
$firstEpisode = (new EpisodeModel()) throw new Exception("COULD NOT POPULATE DATABASE:\n\tCreate a podcast with episodes first.\n");
->selectMin('published_at') }
->first();
$firstEpisode = (new EpisodeModel())
for ( ->selectMin('published_at')
$date = strtotime((string) $firstEpisode->published_at); ->first();
$date < strtotime('now');
$date = strtotime(date('Y-m-d', $date) . ' +1 day') if (! $firstEpisode instanceof Episode) {
) { throw new Exception("COULD NOT POPULATE DATABASE:\n\tCreate an episode first.");
$analyticsPodcasts = []; }
$analyticsPodcastsByHour = [];
$analyticsPodcastsByCountry = []; for (
$analyticsPodcastsByEpisode = []; $date = strtotime((string) $firstEpisode->published_at);
$analyticsPodcastsByPlayer = []; $date < strtotime('now');
$analyticsPodcastsByRegion = []; $date = strtotime(date('Y-m-d', $date) . ' +1 day')
) {
$episodes = (new EpisodeModel()) $analyticsPodcasts = [];
->where('podcast_id', $podcast->id) $analyticsPodcastsByHour = [];
->where('`published_at` <= UTC_TIMESTAMP()', null, false) $analyticsPodcastsByCountry = [];
->findAll(); $analyticsPodcastsByEpisode = [];
foreach ($episodes as $episode) { $analyticsPodcastsByPlayer = [];
$age = floor(($date - strtotime((string) $episode->published_at)) / 86400); $analyticsPodcastsByRegion = [];
$probability1 = floor(exp(3 - $age / 40)) + 1;
$episodes = (new EpisodeModel())
for ( ->where('podcast_id', $podcast->id)
$lineNumber = 0; ->where('`published_at` <= UTC_TIMESTAMP()', null, false)
$lineNumber < rand(1, (int) $probability1); ->findAll();
++$lineNumber foreach ($episodes as $episode) {
) { $age = floor(($date - strtotime((string) $episode->published_at)) / 86400);
$probability2 = floor(exp(6 - $age / 20)) + 10; $probability1 = floor(exp(3 - $age / 40)) + 1;
$player = for (
$jsonUserAgents[ $lineNumber = 0;
rand(1, count($jsonUserAgents) - 1) $lineNumber < random_int(1, (int) $probability1);
]; ++$lineNumber
$service = ) {
$jsonRSSUserAgents[ $probability2 = floor(exp(6 - $age / 20)) + 10;
rand(1, count($jsonRSSUserAgents) - 1)
]['slug']; $player =
$app = isset($player['app']) ? $player['app'] : ''; $jsonUserAgents[
$device = isset($player['device']) random_int(1, count($jsonUserAgents) - 1)
? $player['device']
: '';
$os = isset($player['os']) ? $player['os'] : '';
$isBot = isset($player['bot']) ? $player['bot'] : 0;
$fakeIp =
rand(0, 255) .
'.' .
rand(0, 255) .
'.' .
rand(0, 255) .
'.' .
rand(0, 255);
$cityReader = new Reader(WRITEPATH . 'uploads/GeoLite2-City/GeoLite2-City.mmdb');
$countryCode = 'N/A';
$regionCode = 'N/A';
$latitude = null;
$longitude = null;
try {
$city = $cityReader->city($fakeIp);
$countryCode = $city->country->isoCode === null
? 'N/A'
: $city->country->isoCode;
$regionCode = $city->subdivisions === []
? 'N/A'
: $city->subdivisions[0]->isoCode;
$latitude = round((float) $city->location->latitude, 3);
$longitude = round((float) $city->location->longitude, 3);
} catch (AddressNotFoundException) {
//Bad luck, bad IP, nothing to do.
}
$hits = rand(0, (int) $probability2);
$analyticsPodcasts[] = [
'podcast_id' => $podcast->id,
'date' => date('Y-m-d', $date),
'duration' => rand(60, 3600),
'bandwidth' => rand(1000000, 10000000),
'hits' => $hits,
'unique_listeners' => $hits,
];
$analyticsPodcastsByHour[] = [
'podcast_id' => $podcast->id,
'date' => date('Y-m-d', $date),
'hour' => rand(0, 23),
'hits' => $hits,
];
$analyticsPodcastsByCountry[] = [
'podcast_id' => $podcast->id,
'date' => date('Y-m-d', $date),
'country_code' => $countryCode,
'hits' => $hits,
];
$analyticsPodcastsByEpisode[] = [
'podcast_id' => $podcast->id,
'date' => date('Y-m-d', $date),
'episode_id' => $episode->id,
'age' => $age,
'hits' => $hits,
];
$analyticsPodcastsByPlayer[] = [
'podcast_id' => $podcast->id,
'date' => date('Y-m-d', $date),
'service' => $service,
'app' => $app,
'device' => $device,
'os' => $os,
'is_bot' => $isBot,
'hits' => $hits,
];
$analyticsPodcastsByRegion[] = [
'podcast_id' => $podcast->id,
'date' => date('Y-m-d', $date),
'country_code' => $countryCode,
'region_code' => $regionCode,
'latitude' => $latitude,
'longitude' => $longitude,
'hits' => $hits,
]; ];
$service =
$jsonRSSUserAgents[
random_int(1, count($jsonRSSUserAgents) - 1)
]['slug'];
$app = $player['app'] ?? '';
$device = $player['device'] ?? '';
$os = $player['os'] ?? '';
$isBot = $player['bot'] ?? 0;
$fakeIp =
random_int(0, 255) .
'.' .
random_int(0, 255) .
'.' .
random_int(0, 255) .
'.' .
random_int(0, 255);
$cityReader = new Reader(WRITEPATH . 'uploads/GeoLite2-City/GeoLite2-City.mmdb');
$countryCode = 'N/A';
$regionCode = 'N/A';
$latitude = null;
$longitude = null;
try {
$city = $cityReader->city($fakeIp);
$countryCode = $city->country->isoCode ?? 'N/A';
$regionCode = $city->subdivisions === []
? 'N/A'
: $city->subdivisions[0]->isoCode;
$latitude = round((float) $city->location->latitude, 3);
$longitude = round((float) $city->location->longitude, 3);
} catch (AddressNotFoundException) {
//Bad luck, bad IP, nothing to do.
} }
}
$this->db $hits = random_int(0, (int) $probability2);
->table('analytics_podcasts')
->ignore(true) $analyticsPodcasts[] = [
->insertBatch($analyticsPodcasts); 'podcast_id' => $podcast->id,
$this->db 'date' => date('Y-m-d', $date),
->table('analytics_podcasts_by_hour') 'duration' => random_int(60, 3600),
->ignore(true) 'bandwidth' => random_int(1000000, 10000000),
->insertBatch($analyticsPodcastsByHour); 'hits' => $hits,
$this->db 'unique_listeners' => $hits,
->table('analytics_podcasts_by_country') ];
->ignore(true) $analyticsPodcastsByHour[] = [
->insertBatch($analyticsPodcastsByCountry); 'podcast_id' => $podcast->id,
$this->db 'date' => date('Y-m-d', $date),
->table('analytics_podcasts_by_episode') 'hour' => random_int(0, 23),
->ignore(true) 'hits' => $hits,
->insertBatch($analyticsPodcastsByEpisode); ];
$this->db $analyticsPodcastsByCountry[] = [
->table('analytics_podcasts_by_player') 'podcast_id' => $podcast->id,
->ignore(true) 'date' => date('Y-m-d', $date),
->insertBatch($analyticsPodcastsByPlayer); 'country_code' => $countryCode,
$this->db 'hits' => $hits,
->table('analytics_podcasts_by_region') ];
->ignore(true) $analyticsPodcastsByEpisode[] = [
->insertBatch($analyticsPodcastsByRegion); 'podcast_id' => $podcast->id,
'date' => date('Y-m-d', $date),
'episode_id' => $episode->id,
'age' => $age,
'hits' => $hits,
];
$analyticsPodcastsByPlayer[] = [
'podcast_id' => $podcast->id,
'date' => date('Y-m-d', $date),
'service' => $service,
'app' => $app,
'device' => $device,
'os' => $os,
'is_bot' => $isBot,
'hits' => $hits,
];
$analyticsPodcastsByRegion[] = [
'podcast_id' => $podcast->id,
'date' => date('Y-m-d', $date),
'country_code' => $countryCode,
'region_code' => $regionCode,
'latitude' => $latitude,
'longitude' => $longitude,
'hits' => $hits,
];
}
} }
} else {
echo "COULD NOT POPULATE DATABASE:\n\tCreate a podcast with episodes first.\n"; $this->db
->table('analytics_podcasts')
->ignore(true)
->insertBatch($analyticsPodcasts);
$this->db
->table('analytics_podcasts_by_hour')
->ignore(true)
->insertBatch($analyticsPodcastsByHour);
$this->db
->table('analytics_podcasts_by_country')
->ignore(true)
->insertBatch($analyticsPodcastsByCountry);
$this->db
->table('analytics_podcasts_by_episode')
->ignore(true)
->insertBatch($analyticsPodcastsByEpisode);
$this->db
->table('analytics_podcasts_by_player')
->ignore(true)
->insertBatch($analyticsPodcastsByPlayer);
$this->db
->table('analytics_podcasts_by_region')
->ignore(true)
->insertBatch($analyticsPodcastsByRegion);
} }
} }
} }
...@@ -12,10 +12,13 @@ declare(strict_types=1); ...@@ -12,10 +12,13 @@ declare(strict_types=1);
namespace App\Database\Seeds; namespace App\Database\Seeds;
use App\Entities\Episode;
use App\Entities\Podcast;
use App\Models\EpisodeModel; use App\Models\EpisodeModel;
use App\Models\PodcastModel; use App\Models\PodcastModel;
use CodeIgniter\Database\Seeder; use CodeIgniter\Database\Seeder;
use Exception;
use Override;
class FakeWebsiteAnalyticsSeeder extends Seeder class FakeWebsiteAnalyticsSeeder extends Seeder
{ {
...@@ -179,91 +182,95 @@ class FakeWebsiteAnalyticsSeeder extends Seeder ...@@ -179,91 +182,95 @@ class FakeWebsiteAnalyticsSeeder extends Seeder
'WOSBrowser', 'WOSBrowser',
]; ];
#[Override]
public function run(): void public function run(): void
{ {
$podcast = (new PodcastModel())->first(); $podcast = (new PodcastModel())->first();
if ($podcast) { if (! $podcast instanceof Podcast) {
$firstEpisode = (new EpisodeModel()) throw new Exception("COULD NOT POPULATE DATABASE:\n\tCreate a podcast with episodes first.\n");
->selectMin('published_at') }
->first();
for ( $firstEpisode = (new EpisodeModel())
$date = strtotime((string) $firstEpisode->published_at); ->selectMin('published_at')
$date < strtotime('now'); ->first();
$date = strtotime(date('Y-m-d', $date) . ' +1 day')
) {
$websiteByBrowser = [];
$websiteByEntryPage = [];
$websiteByReferer = [];
$episodes = (new EpisodeModel()) if (! $firstEpisode instanceof Episode) {
->where('podcast_id', $podcast->id) throw new Exception("COULD NOT POPULATE DATABASE:\n\tCreate an episode first.");
->where('`published_at` <= UTC_TIMESTAMP()', null, false) }
->findAll();
foreach ($episodes as $episode) {
$age = floor(($date - strtotime((string) $episode->published_at)) / 86400);
$probability1 = (int) floor(exp(3 - $age / 40)) + 1;
for ( for (
$lineNumber = 0; $date = strtotime((string) $firstEpisode->published_at);
$lineNumber < rand(1, $probability1); $date < strtotime('now');
++$lineNumber $date = strtotime(date('Y-m-d', $date) . ' +1 day')
) { ) {
$probability2 = (int) floor(exp(6 - $age / 20)) + 10; $websiteByBrowser = [];
$websiteByEntryPage = [];
$websiteByReferer = [];
$domain = $episodes = (new EpisodeModel())
$this->domains[rand(0, count($this->domains) - 1)]; ->where('podcast_id', $podcast->id)
$keyword = ->where('`published_at` <= UTC_TIMESTAMP()', null, false)
$this->keywords[ ->findAll();
rand(0, count($this->keywords) - 1) foreach ($episodes as $episode) {
]; $age = floor(($date - strtotime((string) $episode->published_at)) / 86400);
$browser = $probability1 = (int) floor(exp(3 - $age / 40)) + 1;
$this->browsers[
rand(0, count($this->browsers) - 1)
];
$hits = rand(0, $probability2); for (
$lineNumber = 0;
$lineNumber < random_int(1, $probability1);
++$lineNumber
) {
$probability2 = (int) floor(exp(6 - $age / 20)) + 10;
$websiteByBrowser[] = [ $domain =
'podcast_id' => $podcast->id, $this->domains[random_int(0, count($this->domains) - 1)];
'date' => date('Y-m-d', $date), $keyword =
'browser' => $browser, $this->keywords[
'hits' => $hits, random_int(0, count($this->keywords) - 1)
];
$websiteByEntryPage[] = [
'podcast_id' => $podcast->id,
'date' => date('Y-m-d', $date),
'entry_page_url' => $episode->link,
'hits' => $hits,
]; ];
$websiteByReferer[] = [ $browser =
'podcast_id' => $podcast->id, $this->browsers[
'date' => date('Y-m-d', $date), random_int(0, count($this->browsers) - 1)
'referer_url' =>
'http://' . $domain . '/?q=' . $keyword,
'domain' => $domain,
'keywords' => $keyword,
'hits' => $hits,
]; ];
}
}
$this->db $hits = random_int(0, $probability2);
->table('analytics_website_by_browser')
->ignore(true) $websiteByBrowser[] = [
->insertBatch($websiteByBrowser); 'podcast_id' => $podcast->id,
$this->db 'date' => date('Y-m-d', $date),
->table('analytics_website_by_entry_page') 'browser' => $browser,
->ignore(true) 'hits' => $hits,
->insertBatch($websiteByEntryPage); ];
$this->db $websiteByEntryPage[] = [
->table('analytics_website_by_referer') 'podcast_id' => $podcast->id,
->ignore(true) 'date' => date('Y-m-d', $date),
->insertBatch($websiteByReferer); 'entry_page_url' => $episode->link,
'hits' => $hits,
];
$websiteByReferer[] = [
'podcast_id' => $podcast->id,
'date' => date('Y-m-d', $date),
'referer_url' => 'http://' . $domain . '/?q=' . $keyword,
'domain' => $domain,
'keywords' => $keyword,
'hits' => $hits,
];
}
} }
} else {
echo "COULD NOT POPULATE DATABASE:\n\tCreate a podcast with episodes first.\n"; $this->db
->table('analytics_website_by_browser')
->ignore(true)
->insertBatch($websiteByBrowser);
$this->db
->table('analytics_website_by_entry_page')
->ignore(true)
->insertBatch($websiteByEntryPage);
$this->db
->table('analytics_website_by_referer')
->ignore(true)
->insertBatch($websiteByReferer);
} }
} }
} }
...@@ -18,747 +18,748 @@ declare(strict_types=1); ...@@ -18,747 +18,748 @@ declare(strict_types=1);
namespace App\Database\Seeds; namespace App\Database\Seeds;
use CodeIgniter\Database\Seeder; use CodeIgniter\Database\Seeder;
use Override;
class LanguageSeeder extends Seeder class LanguageSeeder extends Seeder
{ {
#[Override]
public function run(): void public function run(): void
{ {
$data = [ $data = [
[ [
'code' => 'aa', 'code' => 'aa',
'native_name' => 'Afaraf', 'native_name' => 'Afaraf',
], ],
[ [
'code' => 'ab', 'code' => 'ab',
'native_name' => 'аҧсуа бызшәа, аҧсшәа', 'native_name' => 'аҧсуа бызшәа, аҧсшәа',
], ],
[ [
'code' => 'ae', 'code' => 'ae',
'native_name' => 'Avesta', 'native_name' => 'Avesta',
], ],
[ [
'code' => 'af', 'code' => 'af',
'native_name' => 'Afrikaans', 'native_name' => 'Afrikaans',
], ],
[ [
'code' => 'ak', 'code' => 'ak',
'native_name' => 'Akan', 'native_name' => 'Akan',
], ],
[ [
'code' => 'am', 'code' => 'am',
'native_name' => 'አማርኛ', 'native_name' => 'አማርኛ',
], ],
[ [
'code' => 'an', 'code' => 'an',
'native_name' => 'Aragonés', 'native_name' => 'Aragonés',
], ],
[ [
'code' => 'ar', 'code' => 'ar',
'native_name' => 'العربية', 'native_name' => 'العربية',
], ],
[ [
'code' => 'as', 'code' => 'as',
'native_name' => 'অসমীয়া', 'native_name' => 'অসমীয়া',
], ],
[ [
'code' => 'av', 'code' => 'av',
'native_name' => 'авар мацӀ, магӀарул мацӀ', 'native_name' => 'авар мацӀ, магӀарул мацӀ',
], ],
[ [
'code' => 'ay', 'code' => 'ay',
'native_name' => 'Aymar aru', 'native_name' => 'Aymar aru',
], ],
[ [
'code' => 'az', 'code' => 'az',
'native_name' => 'azərbaycan dili', 'native_name' => 'azərbaycan dili',
], ],
[ [
'code' => 'ba', 'code' => 'ba',
'native_name' => 'башҡорт теле', 'native_name' => 'башҡорт теле',
], ],
[ [
'code' => 'be', 'code' => 'be',
'native_name' => 'беларуская мова', 'native_name' => 'беларуская мова',
], ],
[ [
'code' => 'bg', 'code' => 'bg',
'native_name' => 'български език', 'native_name' => 'български език',
], ],
[ [
'code' => 'bh', 'code' => 'bh',
'native_name' => 'भोजपुरी', 'native_name' => 'भोजपुरी',
], ],
[ [
'code' => 'bi', 'code' => 'bi',
'native_name' => 'Bislama', 'native_name' => 'Bislama',
], ],
[ [
'code' => 'bm', 'code' => 'bm',
'native_name' => 'Bamanankan', 'native_name' => 'Bamanankan',
], ],
[ [
'code' => 'bn', 'code' => 'bn',
'native_name' => 'বাংলা', 'native_name' => 'বাংলা',
], ],
[ [
'code' => 'bo', 'code' => 'bo',
'native_name' => 'བོད་ཡིག', 'native_name' => 'བོད་ཡིག',
], ],
[ [
'code' => 'br', 'code' => 'br',
'native_name' => 'Brezhoneg', 'native_name' => 'Brezhoneg',
], ],
[ [
'code' => 'bs', 'code' => 'bs',
'native_name' => 'Bosanski jezik', 'native_name' => 'Bosanski jezik',
], ],
[ [
'code' => 'ca', 'code' => 'ca',
'native_name' => 'Català, valencià', 'native_name' => 'Català, valencià',
], ],
[ [
'code' => 'ce', 'code' => 'ce',
'native_name' => 'нохчийн мотт', 'native_name' => 'нохчийн мотт',
], ],
[ [
'code' => 'ch', 'code' => 'ch',
'native_name' => 'Chamoru', 'native_name' => 'Chamoru',
], ],
[ [
'code' => 'co', 'code' => 'co',
'native_name' => 'Corsu, lingua corsa', 'native_name' => 'Corsu, lingua corsa',
], ],
[ [
'code' => 'cr', 'code' => 'cr',
'native_name' => 'ᓀᐦᐃᔭᐍᐏᐣ', 'native_name' => 'ᓀᐦᐃᔭᐍᐏᐣ',
], ],
[ [
'code' => 'cs', 'code' => 'cs',
'native_name' => 'čeština, český jazyk', 'native_name' => 'čeština, český jazyk',
], ],
[ [
'code' => 'cu', 'code' => 'cu',
'native_name' => 'ѩзыкъ словѣньскъ', 'native_name' => 'ѩзыкъ словѣньскъ',
], ],
[ [
'code' => 'cv', 'code' => 'cv',
'native_name' => 'чӑваш чӗлхи', 'native_name' => 'чӑваш чӗлхи',
], ],
[ [
'code' => 'cy', 'code' => 'cy',
'native_name' => 'Cymraeg', 'native_name' => 'Cymraeg',
], ],
[ [
'code' => 'da', 'code' => 'da',
'native_name' => 'Dansk', 'native_name' => 'Dansk',
], ],
[ [
'code' => 'de', 'code' => 'de',
'native_name' => 'Deutsch', 'native_name' => 'Deutsch',
], ],
[ [
'code' => 'dv', 'code' => 'dv',
'native_name' => 'ދިވެހި', 'native_name' => 'ދިވެހި',
], ],
[ [
'code' => 'dz', 'code' => 'dz',
'native_name' => 'རྫོང་ཁ', 'native_name' => 'རྫོང་ཁ',
], ],
[ [
'code' => 'ee', 'code' => 'ee',
'native_name' => 'Eʋegbe', 'native_name' => 'Eʋegbe',
], ],
[ [
'code' => 'el', 'code' => 'el',
'native_name' => 'ελληνικά', 'native_name' => 'ελληνικά',
], ],
[ [
'code' => 'en', 'code' => 'en',
'native_name' => 'English', 'native_name' => 'English',
], ],
[ [
'code' => 'eo', 'code' => 'eo',
'native_name' => 'Esperanto', 'native_name' => 'Esperanto',
], ],
[ [
'code' => 'es', 'code' => 'es',
'native_name' => 'Español', 'native_name' => 'Español',
], ],
[ [
'code' => 'et', 'code' => 'et',
'native_name' => 'eesti, eesti keel', 'native_name' => 'eesti, eesti keel',
], ],
[ [
'code' => 'eu', 'code' => 'eu',
'native_name' => 'Euskara, euskera', 'native_name' => 'Euskara, euskera',
], ],
[ [
'code' => 'fa', 'code' => 'fa',
'native_name' => 'فارسی', 'native_name' => 'فارسی',
], ],
[ [
'code' => 'ff', 'code' => 'ff',
'native_name' => 'Fulfulde, Pulaar, Pular', 'native_name' => 'Fulfulde, Pulaar, Pular',
], ],
[ [
'code' => 'fi', 'code' => 'fi',
'native_name' => 'Suomi, suomen kieli', 'native_name' => 'Suomi, suomen kieli',
], ],
[ [
'code' => 'fj', 'code' => 'fj',
'native_name' => 'Vosa Vakaviti', 'native_name' => 'Vosa Vakaviti',
], ],
[ [
'code' => 'fo', 'code' => 'fo',
'native_name' => 'Føroyskt', 'native_name' => 'Føroyskt',
], ],
[ [
'code' => 'fr', 'code' => 'fr',
'native_name' => 'Français, langue française', 'native_name' => 'Français, langue française',
], ],
[ [
'code' => 'fy', 'code' => 'fy',
'native_name' => 'Frysk', 'native_name' => 'Frysk',
], ],
[ [
'code' => 'ga', 'code' => 'ga',
'native_name' => 'Gaeilge', 'native_name' => 'Gaeilge',
], ],
[ [
'code' => 'gd', 'code' => 'gd',
'native_name' => 'Gàidhlig', 'native_name' => 'Gàidhlig',
], ],
[ [
'code' => 'gl', 'code' => 'gl',
'native_name' => 'Galego', 'native_name' => 'Galego',
], ],
[ [
'code' => 'gn', 'code' => 'gn',
'native_name' => "Avañe'ẽ", 'native_name' => "Avañe'ẽ",
], ],
[ [
'code' => 'gu', 'code' => 'gu',
'native_name' => 'ગુજરાતી', 'native_name' => 'ગુજરાતી',
], ],
[ [
'code' => 'gv', 'code' => 'gv',
'native_name' => 'Gaelg, Gailck', 'native_name' => 'Gaelg, Gailck',
], ],
[ [
'code' => 'ha', 'code' => 'ha',
'native_name' => '(Hausa) هَوُسَ', 'native_name' => '(Hausa) هَوُسَ',
], ],
[ [
'code' => 'he', 'code' => 'he',
'native_name' => 'עברית', 'native_name' => 'עברית',
], ],
[ [
'code' => 'hi', 'code' => 'hi',
'native_name' => 'हिन्दी, हिंदी', 'native_name' => 'हिन्दी, हिंदी',
], ],
[ [
'code' => 'ho', 'code' => 'ho',
'native_name' => 'Hiri Motu', 'native_name' => 'Hiri Motu',
], ],
[ [
'code' => 'hr', 'code' => 'hr',
'native_name' => 'Hrvatski jezik', 'native_name' => 'Hrvatski jezik',
], ],
[ [
'code' => 'ht', 'code' => 'ht',
'native_name' => 'Kreyòl ayisyen', 'native_name' => 'Kreyòl ayisyen',
], ],
[ [
'code' => 'hu', 'code' => 'hu',
'native_name' => 'Magyar', 'native_name' => 'Magyar',
], ],
[ [
'code' => 'hy', 'code' => 'hy',
'native_name' => 'Հայերեն', 'native_name' => 'Հայերեն',
], ],
[ [
'code' => 'hz', 'code' => 'hz',
'native_name' => 'Otjiherero', 'native_name' => 'Otjiherero',
], ],
[ [
'code' => 'ia', 'code' => 'ia',
'native_name' => 'Interlingua', 'native_name' => 'Interlingua',
], ],
[ [
'code' => 'id', 'code' => 'id',
'native_name' => 'Bahasa Indonesia', 'native_name' => 'Bahasa Indonesia',
], ],
[ [
'code' => 'ie', 'code' => 'ie',
'native_name' => 'native_name' => 'Interlingue, formerly Occidental',
'Interlingue, formerly Occidental',
], ],
[ [
'code' => 'ig', 'code' => 'ig',
'native_name' => 'Asụsụ Igbo', 'native_name' => 'Asụsụ Igbo',
], ],
[ [
'code' => 'ii', 'code' => 'ii',
'native_name' => 'ꆈꌠ꒿ Nuosuhxop', 'native_name' => 'ꆈꌠ꒿ Nuosuhxop',
], ],
[ [
'code' => 'ik', 'code' => 'ik',
'native_name' => 'Iñupiaq, Iñupiatun', 'native_name' => 'Iñupiaq, Iñupiatun',
], ],
[ [
'code' => 'io', 'code' => 'io',
'native_name' => 'Ido', 'native_name' => 'Ido',
], ],
[ [
'code' => 'is', 'code' => 'is',
'native_name' => 'Íslenska', 'native_name' => 'Íslenska',
], ],
[ [
'code' => 'it', 'code' => 'it',
'native_name' => 'Italiano', 'native_name' => 'Italiano',
], ],
[ [
'code' => 'iu', 'code' => 'iu',
'native_name' => 'ᐃᓄᒃᑎᑐᑦ', 'native_name' => 'ᐃᓄᒃᑎᑐᑦ',
], ],
[ [
'code' => 'ja', 'code' => 'ja',
'native_name' => '日本語 (にほんご)', 'native_name' => '日本語 (にほんご)',
], ],
[ [
'code' => 'jv', 'code' => 'jv',
'native_name' => 'ꦧꦱꦗꦮ, Basa Jawa', 'native_name' => 'ꦧꦱꦗꦮ, Basa Jawa',
], ],
[ [
'code' => 'ka', 'code' => 'ka',
'native_name' => 'ქართული', 'native_name' => 'ქართული',
], ],
[ [
'code' => 'kg', 'code' => 'kg',
'native_name' => 'Kikongo', 'native_name' => 'Kikongo',
], ],
[ [
'code' => 'ki', 'code' => 'ki',
'native_name' => 'Gĩkũyũ', 'native_name' => 'Gĩkũyũ',
], ],
[ [
'code' => 'kj', 'code' => 'kj',
'native_name' => 'Kuanyama', 'native_name' => 'Kuanyama',
], ],
[ [
'code' => 'kk', 'code' => 'kk',
'native_name' => 'қазақ тілі', 'native_name' => 'қазақ тілі',
], ],
[ [
'code' => 'kl', 'code' => 'kl',
'native_name' => 'Kalaallisut, kalaallit oqaasii', 'native_name' => 'Kalaallisut, kalaallit oqaasii',
], ],
[ [
'code' => 'km', 'code' => 'km',
'native_name' => 'ខ្មែរ, ខេមរភាសា, ភាសាខ្មែរ', 'native_name' => 'ខ្មែរ, ខេមរភាសា, ភាសាខ្មែរ',
], ],
[ [
'code' => 'kn', 'code' => 'kn',
'native_name' => 'ಕನ್ನಡ', 'native_name' => 'ಕನ್ನಡ',
], ],
[ [
'code' => 'ko', 'code' => 'ko',
'native_name' => '한국어', 'native_name' => '한국어',
], ],
[ [
'code' => 'kr', 'code' => 'kr',
'native_name' => 'Kanuri', 'native_name' => 'Kanuri',
], ],
[ [
'code' => 'ks', 'code' => 'ks',
'native_name' => 'कश्मीरी, كشميري', 'native_name' => 'कश्मीरी, كشميري',
], ],
[ [
'code' => 'ku', 'code' => 'ku',
'native_name' => 'Kurdî, کوردی', 'native_name' => 'Kurdî, کوردی',
], ],
[ [
'code' => 'kv', 'code' => 'kv',
'native_name' => 'коми кыв', 'native_name' => 'коми кыв',
], ],
[ [
'code' => 'kw', 'code' => 'kw',
'native_name' => 'Kernewek', 'native_name' => 'Kernewek',
], ],
[ [
'code' => 'ky', 'code' => 'ky',
'native_name' => 'Кыргызча, Кыргыз тили', 'native_name' => 'Кыргызча, Кыргыз тили',
], ],
[ [
'code' => 'la', 'code' => 'la',
'native_name' => 'Latine, lingua latina', 'native_name' => 'Latine, lingua latina',
], ],
[ [
'code' => 'lb', 'code' => 'lb',
'native_name' => 'Lëtzebuergesch', 'native_name' => 'Lëtzebuergesch',
], ],
[ [
'code' => 'lg', 'code' => 'lg',
'native_name' => 'Luganda', 'native_name' => 'Luganda',
], ],
[ [
'code' => 'li', 'code' => 'li',
'native_name' => 'Limburgs', 'native_name' => 'Limburgs',
], ],
[ [
'code' => 'ln', 'code' => 'ln',
'native_name' => 'Lingála', 'native_name' => 'Lingála',
], ],
[ [
'code' => 'lo', 'code' => 'lo',
'native_name' => 'ພາສາລາວ', 'native_name' => 'ພາສາລາວ',
], ],
[ [
'code' => 'lt', 'code' => 'lt',
'native_name' => 'Lietuvių kalba', 'native_name' => 'Lietuvių kalba',
], ],
[ [
'code' => 'lu', 'code' => 'lu',
'native_name' => 'Kiluba', 'native_name' => 'Kiluba',
], ],
[ [
'code' => 'lv', 'code' => 'lv',
'native_name' => 'Latviešu valoda', 'native_name' => 'Latviešu valoda',
], ],
[ [
'code' => 'mg', 'code' => 'mg',
'native_name' => 'Fiteny malagasy', 'native_name' => 'Fiteny malagasy',
], ],
[ [
'code' => 'mh', 'code' => 'mh',
'native_name' => 'Kajin M̧ajeļ', 'native_name' => 'Kajin M̧ajeļ',
], ],
[ [
'code' => 'mi', 'code' => 'mi',
'native_name' => 'Te reo Māori', 'native_name' => 'Te reo Māori',
], ],
[ [
'code' => 'mk', 'code' => 'mk',
'native_name' => 'македонски јазик', 'native_name' => 'македонски јазик',
], ],
[ [
'code' => 'ml', 'code' => 'ml',
'native_name' => 'മലയാളം', 'native_name' => 'മലയാളം',
], ],
[ [
'code' => 'mn', 'code' => 'mn',
'native_name' => 'Монгол хэл', 'native_name' => 'Монгол хэл',
], ],
[ [
'code' => 'mr', 'code' => 'mr',
'native_name' => 'मराठी', 'native_name' => 'मराठी',
], ],
[ [
'code' => 'ms', 'code' => 'ms',
'native_name' => 'Bahasa Melayu, بهاس ملايو', 'native_name' => 'Bahasa Melayu, بهاس ملايو',
], ],
[ [
'code' => 'mt', 'code' => 'mt',
'native_name' => 'Malti', 'native_name' => 'Malti',
], ],
[ [
'code' => 'my', 'code' => 'my',
'native_name' => 'ဗမာစာ', 'native_name' => 'ဗမာစာ',
], ],
[ [
'code' => 'na', 'code' => 'na',
'native_name' => 'Dorerin Naoero', 'native_name' => 'Dorerin Naoero',
], ],
[ [
'code' => 'nb', 'code' => 'nb',
'native_name' => 'Norsk Bokmål', 'native_name' => 'Norsk Bokmål',
], ],
[ [
'code' => 'nd', 'code' => 'nd',
'native_name' => 'isiNdebele', 'native_name' => 'isiNdebele',
], ],
[ [
'code' => 'ne', 'code' => 'ne',
'native_name' => 'नेपाली', 'native_name' => 'नेपाली',
], ],
[ [
'code' => 'ng', 'code' => 'ng',
'native_name' => 'Owambo', 'native_name' => 'Owambo',
], ],
[ [
'code' => 'nl', 'code' => 'nl',
'native_name' => 'Nederlands, Vlaams', 'native_name' => 'Nederlands, Vlaams',
], ],
[ [
'code' => 'nn', 'code' => 'nn',
'native_name' => 'Norsk Nynorsk', 'native_name' => 'Norsk Nynorsk',
], ],
[ [
'code' => 'no', 'code' => 'no',
'native_name' => 'Norsk', 'native_name' => 'Norsk',
], ],
[ [
'code' => 'nr', 'code' => 'nr',
'native_name' => 'isiNdebele', 'native_name' => 'isiNdebele',
], ],
[ [
'code' => 'nv', 'code' => 'nv',
'native_name' => 'Diné bizaad', 'native_name' => 'Diné bizaad',
], ],
[ [
'code' => 'ny', 'code' => 'ny',
'native_name' => 'Chicheŵa, chinyanja', 'native_name' => 'Chicheŵa, chinyanja',
], ],
[ [
'code' => 'oc', 'code' => 'oc',
'native_name' => 'Occitan, lenga d’òc', 'native_name' => 'Occitan, lenga d’òc',
], ],
[ [
'code' => 'oj', 'code' => 'oj',
'native_name' => 'ᐊᓂᔑᓈᐯᒧᐎᓐ', 'native_name' => 'ᐊᓂᔑᓈᐯᒧᐎᓐ',
], ],
[ [
'code' => 'om', 'code' => 'om',
'native_name' => 'Afaan Oromoo', 'native_name' => 'Afaan Oromoo',
], ],
[ [
'code' => 'or', 'code' => 'or',
'native_name' => 'ଓଡ଼ିଆ', 'native_name' => 'ଓଡ଼ିଆ',
], ],
[ [
'code' => 'os', 'code' => 'os',
'native_name' => 'ирон æвзаг', 'native_name' => 'ирон æвзаг',
], ],
[ [
'code' => 'pa', 'code' => 'pa',
'native_name' => 'ਪੰਜਾਬੀ, پنجابی', 'native_name' => 'ਪੰਜਾਬੀ, پنجابی',
], ],
[ [
'code' => 'pi', 'code' => 'pi',
'native_name' => 'पालि, पाळि', 'native_name' => 'पालि, पाळि',
], ],
[ [
'code' => 'pl', 'code' => 'pl',
'native_name' => 'język polski, polszczyzna', 'native_name' => 'język polski, polszczyzna',
], ],
[ [
'code' => 'ps', 'code' => 'ps',
'native_name' => 'پښتو', 'native_name' => 'پښتو',
], ],
[ [
'code' => 'pt', 'code' => 'pt',
'native_name' => 'Português', 'native_name' => 'Português',
], ],
[ [
'code' => 'qu', 'code' => 'qu',
'native_name' => 'Runa Simi, Kichwa', 'native_name' => 'Runa Simi, Kichwa',
], ],
[ [
'code' => 'rm', 'code' => 'rm',
'native_name' => 'Rumantsch Grischun', 'native_name' => 'Rumantsch Grischun',
], ],
[ [
'code' => 'rn', 'code' => 'rn',
'native_name' => 'Ikirundi', 'native_name' => 'Ikirundi',
], ],
[ [
'code' => 'ro', 'code' => 'ro',
'native_name' => 'Română', 'native_name' => 'Română',
], ],
[ [
'code' => 'ru', 'code' => 'ru',
'native_name' => 'Pусский', 'native_name' => 'Pусский',
], ],
[ [
'code' => 'rw', 'code' => 'rw',
'native_name' => 'Ikinyarwanda', 'native_name' => 'Ikinyarwanda',
], ],
[ [
'code' => 'sa', 'code' => 'sa',
'native_name' => 'संस्कृतम्', 'native_name' => 'संस्कृतम्',
], ],
[ [
'code' => 'sc', 'code' => 'sc',
'native_name' => 'Sardu', 'native_name' => 'Sardu',
], ],
[ [
'code' => 'sd', 'code' => 'sd',
'native_name' => 'सिन्धी, سنڌي، سندھی', 'native_name' => 'सिन्धी, سنڌي، سندھی',
], ],
[ [
'code' => 'se', 'code' => 'se',
'native_name' => 'Davvisámegiella', 'native_name' => 'Davvisámegiella',
], ],
[ [
'code' => 'sg', 'code' => 'sg',
'native_name' => 'Yângâ tî sängö', 'native_name' => 'Yângâ tî sängö',
], ],
[ [
'code' => 'si', 'code' => 'si',
'native_name' => 'සිංහල', 'native_name' => 'සිංහල',
], ],
[ [
'code' => 'sk', 'code' => 'sk',
'native_name' => 'Slovenčina, Slovenský Jazyk', 'native_name' => 'Slovenčina, Slovenský Jazyk',
], ],
[ [
'code' => 'sl', 'code' => 'sl',
'native_name' => 'Slovenski Jezik, Slovenščina', 'native_name' => 'Slovenski Jezik, Slovenščina',
], ],
[ [
'code' => 'sm', 'code' => 'sm',
'native_name' => "Gagana fa'a Samoa", 'native_name' => "Gagana fa'a Samoa",
], ],
[ [
'code' => 'sn', 'code' => 'sn',
'native_name' => 'chiShona', 'native_name' => 'chiShona',
], ],
[ [
'code' => 'so', 'code' => 'so',
'native_name' => 'Soomaaliga, af Soomaali', 'native_name' => 'Soomaaliga, af Soomaali',
], ],
[ [
'code' => 'sq', 'code' => 'sq',
'native_name' => 'Shqip', 'native_name' => 'Shqip',
], ],
[ [
'code' => 'sr', 'code' => 'sr',
'native_name' => 'српски језик', 'native_name' => 'српски језик',
], ],
[ [
'code' => 'ss', 'code' => 'ss',
'native_name' => 'SiSwati', 'native_name' => 'SiSwati',
], ],
[ [
'code' => 'st', 'code' => 'st',
'native_name' => 'Sesotho', 'native_name' => 'Sesotho',
], ],
[ [
'code' => 'su', 'code' => 'su',
'native_name' => 'Basa Sunda', 'native_name' => 'Basa Sunda',
], ],
[ [
'code' => 'sv', 'code' => 'sv',
'native_name' => 'Svenska', 'native_name' => 'Svenska',
], ],
[ [
'code' => 'sw', 'code' => 'sw',
'native_name' => 'Kiswahili', 'native_name' => 'Kiswahili',
], ],
[ [
'code' => 'ta', 'code' => 'ta',
'native_name' => 'தமிழ்', 'native_name' => 'தமிழ்',
], ],
[ [
'code' => 'te', 'code' => 'te',
'native_name' => 'తెలుగు', 'native_name' => 'తెలుగు',
], ],
[ [
'code' => 'tg', 'code' => 'tg',
'native_name' => 'тоҷикӣ, toçikī, تاجیکی', 'native_name' => 'тоҷикӣ, toçikī, تاجیکی',
], ],
[ [
'code' => 'th', 'code' => 'th',
'native_name' => 'ไทย', 'native_name' => 'ไทย',
], ],
[ [
'code' => 'ti', 'code' => 'ti',
'native_name' => 'ትግርኛ', 'native_name' => 'ትግርኛ',
], ],
[ [
'code' => 'tk', 'code' => 'tk',
'native_name' => 'Türkmen, Түркмен', 'native_name' => 'Türkmen, Түркмен',
], ],
[ [
'code' => 'tl', 'code' => 'tl',
'native_name' => 'Wikang Tagalog', 'native_name' => 'Wikang Tagalog',
], ],
[ [
'code' => 'tn', 'code' => 'tn',
'native_name' => 'Setswana', 'native_name' => 'Setswana',
], ],
[ [
'code' => 'to', 'code' => 'to',
'native_name' => 'Faka Tonga', 'native_name' => 'Faka Tonga',
], ],
[ [
'code' => 'tr', 'code' => 'tr',
'native_name' => 'Türkçe', 'native_name' => 'Türkçe',
], ],
[ [
'code' => 'ts', 'code' => 'ts',
'native_name' => 'Xitsonga', 'native_name' => 'Xitsonga',
], ],
[ [
'code' => 'tt', 'code' => 'tt',
'native_name' => 'татар теле, tatar tele', 'native_name' => 'татар теле, tatar tele',
], ],
[ [
'code' => 'tw', 'code' => 'tw',
'native_name' => 'Twi', 'native_name' => 'Twi',
], ],
[ [
'code' => 'ty', 'code' => 'ty',
'native_name' => 'Reo Tahiti', 'native_name' => 'Reo Tahiti',
], ],
[ [
'code' => 'ug', 'code' => 'ug',
'native_name' => 'ئۇيغۇرچە, Uyghurche', 'native_name' => 'ئۇيغۇرچە, Uyghurche',
], ],
[ [
'code' => 'uk', 'code' => 'uk',
'native_name' => 'Українська', 'native_name' => 'Українська',
], ],
[ [
'code' => 'ur', 'code' => 'ur',
'native_name' => 'اردو', 'native_name' => 'اردو',
], ],
[ [
'code' => 'uz', 'code' => 'uz',
'native_name' => 'Oʻzbek, Ўзбек, أۇزبېك', 'native_name' => 'Oʻzbek, Ўзбек, أۇزبېك',
], ],
[ [
'code' => 've', 'code' => 've',
'native_name' => 'Tshivenḓa', 'native_name' => 'Tshivenḓa',
], ],
[ [
'code' => 'vi', 'code' => 'vi',
'native_name' => 'Tiếng Việt', 'native_name' => 'Tiếng Việt',
], ],
[ [
'code' => 'vo', 'code' => 'vo',
'native_name' => 'Volapük', 'native_name' => 'Volapük',
], ],
[ [
'code' => 'wa', 'code' => 'wa',
'native_name' => 'Walon', 'native_name' => 'Walon',
], ],
[ [
'code' => 'wo', 'code' => 'wo',
'native_name' => 'Wollof', 'native_name' => 'Wollof',
], ],
[ [
'code' => 'xh', 'code' => 'xh',
'native_name' => 'isiXhosa', 'native_name' => 'isiXhosa',
], ],
[ [
'code' => 'yi', 'code' => 'yi',
'native_name' => 'ייִדיש', 'native_name' => 'ייִדיש',
], ],
[ [
'code' => 'yo', 'code' => 'yo',
'native_name' => 'Yorùbá', 'native_name' => 'Yorùbá',
], ],
[ [
'code' => 'za', 'code' => 'za',
'native_name' => 'Saɯ cueŋƅ, Saw cuengh', 'native_name' => 'Saɯ cueŋƅ, Saw cuengh',
], ],
[ [
'code' => 'zh', 'code' => 'zh',
'native_name' => '中文 (Zhōngwén), 汉语, 漢語', 'native_name' => '中文 (Zhōngwén), 汉语, 漢語',
], ],
[ [
'code' => 'zu', 'code' => 'zu',
'native_name' => 'isiZulu', 'native_name' => 'isiZulu',
], ],
]; ];
......
<?php
declare(strict_types=1);
/**
* Class PlatformsSeeder Inserts values in platforms table in database
*
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
namespace App\Database\Seeds;
use CodeIgniter\Database\Seeder;
class PlatformSeeder extends Seeder
{
public function run(): void
{
$podcastingData = [
[
'slug' => 'amazon',
'type' => 'podcasting',
'label' => 'Amazon Music and Audible',
'home_url' => 'https://music.amazon.com/podcasts',
'submit_url' => 'http://amazon.com/podcasters',
],
[
'slug' => 'antennapod',
'type' => 'podcasting',
'label' => 'AntennaPod',
'home_url' => 'https://antennapod.org/',
'submit_url' => 'https://api.podcastindex.org/signup',
],
[
'slug' => 'apple',
'type' => 'podcasting',
'label' => 'Apple Podcasts',
'home_url' => 'https://www.apple.com/itunes/podcasts/',
'submit_url' =>
'https://podcastsconnect.apple.com/my-podcasts/new-feed',
],
[
'slug' => 'blubrry',
'type' => 'podcasting',
'label' => 'Blubrry',
'home_url' => 'https://www.blubrry.com/',
'submit_url' => 'https://www.blubrry.com/addpodcast.php',
],
[
'slug' => 'breaker',
'type' => 'podcasting',
'label' => 'Breaker',
'home_url' => 'https://www.breaker.audio/',
'submit_url' => 'https://podcasters.breaker.audio/',
],
[
'slug' => 'castbox',
'type' => 'podcasting',
'label' => 'Castbox',
'home_url' => 'https://castbox.fm/',
'submit_url' =>
'https://helpcenter.castbox.fm/portal/kb/articles/submit-my-podcast',
],
[
'slug' => 'castopod',
'type' => 'podcasting',
'label' => 'Castopod',
'home_url' => 'https://castopod.org/',
'submit_url' => 'https://castopod.org/instances',
],
[
'slug' => 'castro',
'type' => 'podcasting',
'label' => 'Castro',
'home_url' => 'http://castro.fm/',
'submit_url' =>
'https://castro.fm/support/link-to-your-podcast-in-castro',
],
[
'slug' => 'chartable',
'type' => 'podcasting',
'label' => 'Chartable',
'home_url' => 'https://chartable.com/',
'submit_url' => 'https://chartable.com/podcasts/submit',
],
[
'slug' => 'deezer',
'type' => 'podcasting',
'label' => 'Deezer',
'home_url' => 'https://www.deezer.com/',
'submit_url' => 'https://podcasters.deezer.com/submission',
],
[
'slug' => 'fyyd',
'type' => 'podcasting',
'label' => 'fyyd',
'home_url' => 'https://fyyd.de/',
'submit_url' => 'https://fyyd.de/add-feed',
],
[
'slug' => 'google',
'type' => 'podcasting',
'label' => 'Google Podcasts',
'home_url' => 'https://podcasts.google.com/about',
'submit_url' =>
'https://search.google.com/search-console/about',
],
[
'slug' => 'ivoox',
'type' => 'podcasting',
'label' => 'Ivoox',
'home_url' => 'https://www.ivoox.com/',
'submit_url' => 'http://www.ivoox.com/upload-podcast_u.html',
],
[
'slug' => 'listennotes',
'type' => 'podcasting',
'label' => 'ListenNotes',
'home_url' => 'https://www.listennotes.com/',
'submit_url' => 'https://www.listennotes.com/submit/',
],
[
'slug' => 'overcast',
'type' => 'podcasting',
'label' => 'Overcast',
'home_url' => 'https://overcast.fm/',
'submit_url' => 'https://overcast.fm/podcasterinfo',
],
[
'slug' => 'playerfm',
'type' => 'podcasting',
'label' => 'Player.Fm',
'home_url' => 'https://player.fm/',
'submit_url' => 'https://player.fm/importer/feed',
],
[
'slug' => 'pocketcasts',
'type' => 'podcasting',
'label' => 'Pocketcasts',
'home_url' => 'https://www.pocketcasts.com/',
'submit_url' => 'https://www.pocketcasts.com/submit/',
],
[
'slug' => 'podbean',
'type' => 'podcasting',
'label' => 'Podbean',
'home_url' => 'https://www.podbean.com/',
'submit_url' => 'https://www.podbean.com/site/submitPodcast',
],
[
'slug' => 'podcastaddict',
'type' => 'podcasting',
'label' => 'Podcast Addict',
'home_url' => 'https://podcastaddict.com/',
'submit_url' => 'https://podcastaddict.com/submit',
],
[
'slug' => 'podcastindex',
'type' => 'podcasting',
'label' => 'Podcast Index',
'home_url' => 'https://podcastindex.org/',
'submit_url' => 'https://api.podcastindex.org/signup',
],
[
'slug' => 'podchaser',
'type' => 'podcasting',
'label' => 'Podchaser',
'home_url' => 'https://www.podchaser.com/',
'submit_url' => 'https://www.podchaser.com/creators/edit',
],
[
'slug' => 'podcloud',
'type' => 'podcasting',
'label' => 'podCloud',
'home_url' => 'https://podcloud.fr/',
'submit_url' => 'https://podcloud.fr/studio/podcasts/new',
],
[
'slug' => 'podinstall',
'type' => 'podcasting',
'label' => 'Podinstall',
'home_url' => 'https://www.podinstall.com/',
'submit_url' => 'https://www.podinstall.com/claim.html',
],
[
'slug' => 'podlink',
'type' => 'podcasting',
'label' => 'pod.link',
'home_url' => 'https://pod.link/',
'submit_url' => 'https://pod.link',
],
[
'slug' => 'podtail',
'type' => 'podcasting',
'label' => 'Podtail',
'home_url' => 'https://podtail.com/',
'submit_url' => 'https://podtail.com/about/faq/',
],
[
'slug' => 'podfriend',
'type' => 'podcasting',
'label' => 'Podfriend',
'home_url' => 'https://www.podfriend.com/',
'submit_url' => 'https://api.podcastindex.org/signup',
],
[
'slug' => 'podverse',
'type' => 'podcasting',
'label' => 'Podverse',
'home_url' => 'https://podverse.fm/',
'submit_url' =>
'https://docs.google.com/forms/d/e/1FAIpQLSdewKP-YrE8zGjDPrkmoJEwCxPl_gizEkmzAlTYsiWAuAk1Ng/viewform',
],
[
'slug' => 'radiopublic',
'type' => 'podcasting',
'label' => 'RadioPublic',
'home_url' => 'https://radiopublic.com/',
'submit_url' => 'https://podcasters.radiopublic.com/signup',
],
[
'slug' => 'spotify',
'type' => 'podcasting',
'label' => 'Spotify',
'home_url' => 'https://www.spotify.com/',
'submit_url' => 'https://podcasters.spotify.com/submit',
],
[
'slug' => 'spreaker',
'type' => 'podcasting',
'label' => 'Spreaker',
'home_url' => 'https://www.spreaker.com/',
'submit_url' => 'https://www.spreaker.com/cms/shows/rss-import',
],
[
'slug' => 'stitcher',
'type' => 'podcasting',
'label' => 'Stitcher',
'home_url' => 'https://www.stitcher.com/',
'submit_url' => 'https://partners.stitcher.com/join',
],
[
'slug' => 'tunein',
'type' => 'podcasting',
'label' => 'TuneIn',
'home_url' => 'https://tunein.com/',
'submit_url' =>
'https://help.tunein.com/contact/add-podcast-S19TR3Sdf',
],
[
'slug' => 'anytime',
'type' => 'podcasting',
'label' => 'Anytime Podcast Player',
'home_url' => 'https://anytimeplayer.app/',
'submit_url' => '',
],
[
'slug' => 'breez',
'type' => 'podcasting',
'label' => 'Breez',
'home_url' => 'https://breez.technology/',
'submit_url' => '',
],
[
'slug' => 'castamatic',
'type' => 'podcasting',
'label' => 'Castamatic',
'home_url' => 'https://castamatic.com/',
'submit_url' => '',
],
[
'slug' => 'castcoverage',
'type' => 'podcasting',
'label' => 'CastCoverage',
'home_url' => 'http://castcoverage.com/',
'submit_url' => '',
],
[
'slug' => 'curiocaster',
'type' => 'podcasting',
'label' => 'CurioCaster',
'home_url' => 'https://curiocaster.com/',
'submit_url' => '',
],
[
'slug' => 'escapepod',
'type' => 'podcasting',
'label' => 'Escapepod',
'home_url' => 'http://y20k.org/escapepod/',
'submit_url' => '',
],
[
'slug' => 'fountain',
'type' => 'podcasting',
'label' => 'Fountain',
'home_url' => 'https://www.fountain.fm/',
'submit_url' => '',
],
[
'slug' => 'gpodder',
'type' => 'podcasting',
'label' => 'gPodder',
'home_url' => 'https://gpodder.org/',
'submit_url' => '',
],
[
'slug' => 'hypercatcher',
'type' => 'podcasting',
'label' => 'HyperCatcher',
'home_url' => 'https://hypercatcher.com/',
'submit_url' => '',
],
[
'slug' => 'ivyfm',
'type' => 'podcasting',
'label' => 'Ivy Podcast Discovery',
'home_url' => 'https://ivy.fm/',
'submit_url' => '',
],
[
'slug' => 'jumplink',
'type' => 'podcasting',
'label' => 'JumpLink',
'home_url' => 'https://jump.link/',
'submit_url' => 'https://jump.link/a/accounts/signup/',
],
[
'slug' => 'kasts',
'type' => 'podcasting',
'label' => 'Kasts',
'home_url' => 'https://apps.kde.org/kasts/',
'submit_url' => '',
],
[
'slug' => 'playapod',
'type' => 'podcasting',
'label' => 'Playapod',
'home_url' => 'https://playapod.com/',
'submit_url' => '',
],
[
'slug' => 'plink',
'type' => 'podcasting',
'label' => 'Plink',
'home_url' => 'https://plinkhq.com/',
'submit_url' => '',
],
[
'slug' => 'podcastchapters',
'type' => 'podcasting',
'label' => 'Podcast Chapters',
'home_url' => 'https://chaptersapp.com/',
'submit_url' => '',
],
[
'slug' => 'podcastguru',
'type' => 'podcasting',
'label' => 'Podcast Guru',
'home_url' => 'https://podcastguru.io/',
'submit_url' => 'https://podcastguru.io/promote-your-podcast/',
],
[
'slug' => 'podlp',
'type' => 'podcasting',
'label' => 'PodLP',
'home_url' => 'https://podlp.com/',
'submit_url' => 'https://podlp.com/submit.html',
],
[
'slug' => 'podnews',
'type' => 'podcasting',
'label' => 'podnews',
'home_url' => 'https://podnews.net/podcast/subscribe-pages',
'submit_url' => '',
],
[
'slug' => 'podstation',
'type' => 'podcasting',
'label' => 'podStation',
'home_url' => 'https://podstation.github.io/',
'submit_url' => '',
],
[
'slug' => 'sphinxchat',
'type' => 'podcasting',
'label' => 'Sphinx',
'home_url' => 'https://sphinx.chat/',
'submit_url' => '',
],
[
'slug' => 'tsacdop',
'type' => 'podcasting',
'label' => 'Tsacdop',
'home_url' => 'https://www.tsacdop.app/',
'submit_url' => '',
],
[
'slug' => 'zion',
'type' => 'podcasting',
'label' => 'Zion',
'home_url' => 'https://getzion.com/',
'submit_url' => 'https://shop.n2n2.chat/',
],
];
$fundingData = [
[
'slug' => 'paypal',
'type' => 'funding',
'label' => 'Paypal',
'home_url' => 'https://www.paypal.com/',
'submit_url' => 'https://www.paypal.com/paypalme/my/grab',
],
[
'slug' => 'fosspay',
'type' => 'funding',
'label' => 'fosspay',
'home_url' => 'https://git.sr.ht/~sircmpwn/fosspay',
'submit_url' => '',
],
[
'slug' => 'gofundme',
'type' => 'funding',
'label' => 'GoFundMe',
'home_url' => 'https://www.gofundme.com/',
'submit_url' => 'https://www.gofundme.com/sign-up',
],
[
'slug' => 'helloasso',
'type' => 'funding',
'label' => 'helloasso',
'home_url' => 'https://www.helloasso.com/',
'submit_url' => 'https://auth.helloasso.com/inscription',
],
[
'slug' => 'indiegogo',
'type' => 'funding',
'label' => 'Indiegogo',
'home_url' => 'https://www.indiegogo.com/',
'submit_url' => 'https://www.indiegogo.com/start-a-campaign#/',
],
[
'slug' => 'kickstarter',
'type' => 'funding',
'label' => 'Kickstarter',
'home_url' => 'https://www.kickstarter.com/',
'submit_url' => 'https://www.kickstarter.com/learn',
],
[
'slug' => 'kisskissbankbank',
'type' => 'funding',
'label' => 'KissKissBankBank',
'home_url' => 'https://www.kisskissbankbank.com/',
'submit_url' =>
'https://www.kisskissbankbank.com/en/financer-mon-projet',
],
[
'slug' => 'liberapay',
'type' => 'funding',
'label' => 'Liberapay',
'home_url' => 'https://liberapay.com/',
'submit_url' => 'https://liberapay.com/sign-up',
],
[
'slug' => 'patreon',
'type' => 'funding',
'label' => 'Patreon',
'home_url' => 'https://www.patreon.com/',
'submit_url' => 'https://www.patreon.com/create',
],
[
'slug' => 'tipeee',
'type' => 'funding',
'label' => 'Tipeee',
'home_url' => 'https://tipeee.com/',
'submit_url' => 'https://tipeee.com/register/',
],
[
'slug' => 'ulule',
'type' => 'funding',
'label' => 'Ulule',
'home_url' => 'https://www.ulule.com/',
'submit_url' => 'https://www.ulule.com/projects/create/#/',
],
];
$socialData = [
[
'slug' => 'discord',
'type' => 'social',
'label' => 'Discord',
'home_url' => 'https://discord.com/',
'submit_url' => 'https://discord.com/register',
],
[
'slug' => 'facebook',
'type' => 'social',
'label' => 'Facebook',
'home_url' => 'https://www.facebook.com/',
'submit_url' =>
'https://www.facebook.com/pages/creation/?ref_type=comet_home',
],
[
'slug' => 'funkwhale',
'type' => 'social',
'label' => 'Funkwhale',
'home_url' => 'https://funkwhale.audio/',
'submit_url' => 'https://network.funkwhale.audio/dashboards/',
],
[
'slug' => 'instagram',
'type' => 'social',
'label' => 'Instagram',
'home_url' => 'https://www.instagram.com/',
'submit_url' =>
'https://www.instagram.com/accounts/emailsignup/',
],
[
'slug' => 'linkedin',
'type' => 'social',
'label' => 'LinkedIn',
'home_url' => 'https://www.linkedin.com/',
'submit_url' => 'https://www.linkedin.com/company/setup/new/',
],
[
'slug' => 'mastodon',
'type' => 'social',
'label' => 'Mastodon',
'home_url' => 'https://joinmastodon.org/',
'submit_url' => 'https://joinmastodon.org/communities',
],
[
'slug' => 'misskey',
'type' => 'social',
'label' => 'Misskey',
'home_url' => 'https://join.misskey.page/',
'submit_url' => 'https://join.misskey.page/en-US/instances',
],
[
'slug' => 'mobilizon',
'type' => 'social',
'label' => 'Mobilizon',
'home_url' => 'https://joinmobilizon.org/',
'submit_url' => 'https://instances.joinmobilizon.org/instances',
],
[
'slug' => 'peertube',
'type' => 'social',
'label' => 'PeerTube',
'home_url' => 'https://joinpeertube.org/',
'submit_url' => 'https://joinpeertube.org/instances',
],
[
'slug' => 'pixelfed',
'type' => 'social',
'label' => 'Pixelfed',
'home_url' => 'https://pixelfed.org/',
'submit_url' => 'https://beta.joinpixelfed.org/',
],
[
'slug' => 'pleroma',
'type' => 'social',
'label' => 'Pleroma',
'home_url' => 'https://pleroma.social/',
'submit_url' => 'https://pleroma.social/#featured-instances',
],
[
'slug' => 'plume',
'type' => 'social',
'label' => 'Plume',
'home_url' => 'https://joinplu.me/',
'submit_url' => 'https://joinplu.me/#instances',
],
[
'slug' => 'slack',
'type' => 'social',
'label' => 'Slack',
'home_url' => 'https://slack.com/',
'submit_url' => 'https://slack.com/get-started#/create',
],
[
'slug' => 'twitch',
'type' => 'social',
'label' => 'Twitch',
'home_url' => 'https://www.twitch.tv/',
'submit_url' => 'https://www.twitch.tv/signup',
],
[
'slug' => 'twitter',
'type' => 'social',
'label' => 'Twitter',
'home_url' => 'https://twitter.com/',
'submit_url' => 'https://twitter.com/i/flow/signup',
],
[
'slug' => 'writefreely',
'type' => 'social',
'label' => 'WriteFreely',
'home_url' => 'https://writefreely.org/',
'submit_url' => 'https://writefreely.org/instances',
],
[
'slug' => 'youtube',
'type' => 'social',
'label' => 'Youtube',
'home_url' => 'https://www.youtube.com/',
'submit_url' => 'https://creatoracademy.youtube.com/page/home',
],
];
$data = array_merge($podcastingData, $fundingData, $socialData);
$this->db
->table('platforms')
->ignore(true)
->insertBatch($data);
}
}
<?php
declare(strict_types=1);
/**
* Class TestSeeder Inserts a superadmin user in the database
*
* @copyright 2020 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
namespace App\Database\Seeds;
use CodeIgniter\Database\Seeder;
class TestSeeder extends Seeder
{
public function run(): void
{
/**
* Inserts an active user with the following credentials: username: admin password: AGUehL3P
*/
$this->db->table('users')
->insert([
'id' => 1,
'username' => 'admin',
'email' => 'admin@example.com',
'password_hash' =>
'$2y$10$TXJEHX/djW8jtzgpDVf7dOOCGo5rv1uqtAYWdwwwkttQcDkAeB2.6',
'active' => 1,
]);
$this->db
->table('auth_groups_users')
->insert([
'group_id' => 1,
'user_id' => 1,
]);
}
}
...@@ -12,6 +12,7 @@ namespace App\Entities; ...@@ -12,6 +12,7 @@ namespace App\Entities;
use App\Models\PodcastModel; use App\Models\PodcastModel;
use Modules\Fediverse\Entities\Actor as FediverseActor; use Modules\Fediverse\Entities\Actor as FediverseActor;
use Override;
use RuntimeException; use RuntimeException;
/** /**
...@@ -26,7 +27,7 @@ class Actor extends FediverseActor ...@@ -26,7 +27,7 @@ class Actor extends FediverseActor
public function getIsPodcast(): bool public function getIsPodcast(): bool
{ {
return $this->getPodcast() !== null; return $this->getPodcast() instanceof Podcast;
} }
public function getPodcast(): ?Podcast public function getPodcast(): ?Podcast
...@@ -42,21 +43,23 @@ class Actor extends FediverseActor ...@@ -42,21 +43,23 @@ class Actor extends FediverseActor
return $this->podcast; return $this->podcast;
} }
#[Override]
public function getAvatarImageUrl(): string public function getAvatarImageUrl(): string
{ {
if ($this->podcast !== null) { if ($this->podcast instanceof Podcast) {
return $this->podcast->cover->thumbnail_url; return $this->podcast->cover->thumbnail_url;
} }
return $this->attributes['avatar_image_url']; return parent::getAvatarImageUrl();
} }
#[Override]
public function getAvatarImageMimetype(): string public function getAvatarImageMimetype(): string
{ {
if ($this->podcast !== null) { if ($this->podcast instanceof Podcast) {
return $this->podcast->cover->thumbnail_mimetype; return $this->podcast->cover->thumbnail_mimetype;
} }
return $this->attributes['avatar_image_mimetype']; return parent::getAvatarImageMimetype();
} }
} }
...@@ -29,16 +29,13 @@ class Category extends Entity ...@@ -29,16 +29,13 @@ class Category extends Entity
* @var array<string, string> * @var array<string, string>
*/ */
protected $casts = [ protected $casts = [
'id' => 'integer', 'id' => 'integer',
'parent_id' => '?integer', 'parent_id' => '?integer',
'code' => 'string', 'code' => 'string',
'apple_category' => 'string', 'apple_category' => 'string',
'google_category' => 'string', 'google_category' => 'string',
]; ];
/**
* @noRector ReturnTypeDeclarationRector
*/
public function getParent(): ?self public function getParent(): ?self
{ {
if ($this->parent_id === null) { if ($this->parent_id === null) {
......
...@@ -11,17 +11,17 @@ declare(strict_types=1); ...@@ -11,17 +11,17 @@ declare(strict_types=1);
namespace App\Entities\Clip; namespace App\Entities\Clip;
use App\Entities\Episode; use App\Entities\Episode;
use App\Entities\Media\Audio;
use App\Entities\Media\Video;
use App\Entities\Podcast; use App\Entities\Podcast;
use App\Models\EpisodeModel; use App\Models\EpisodeModel;
use App\Models\MediaModel;
use App\Models\PodcastModel; use App\Models\PodcastModel;
use App\Models\UserModel;
use CodeIgniter\Entity\Entity; use CodeIgniter\Entity\Entity;
use CodeIgniter\Files\File; use CodeIgniter\Files\File;
use CodeIgniter\I18n\Time; use CodeIgniter\I18n\Time;
use Modules\Auth\Entities\User; use CodeIgniter\Shield\Entities\User;
use Modules\Auth\Models\UserModel;
use Modules\Media\Entities\Audio;
use Modules\Media\Entities\Video;
use Modules\Media\Models\MediaModel;
/** /**
* @property int $id * @property int $id
...@@ -36,7 +36,7 @@ use Modules\Auth\Entities\User; ...@@ -36,7 +36,7 @@ use Modules\Auth\Entities\User;
* @property string $type * @property string $type
* @property int|null $media_id * @property int|null $media_id
* @property Video|Audio|null $media * @property Video|Audio|null $media
* @property array|null $metadata * @property array<mixed>|null $metadata
* @property string $status * @property string $status
* @property string $logs * @property string $logs
* @property User $user * @property User $user
...@@ -57,7 +57,8 @@ class BaseClip extends Entity ...@@ -57,7 +57,8 @@ class BaseClip extends Entity
protected ?float $end_time = null; protected ?float $end_time = null;
/** /**
* @var string[] * @var array<int, string>
* @phpstan-var list<string>
*/ */
protected $dates = ['created_at', 'updated_at', 'job_started_at', 'job_ended_at']; protected $dates = ['created_at', 'updated_at', 'job_started_at', 'job_ended_at'];
...@@ -65,17 +66,17 @@ class BaseClip extends Entity ...@@ -65,17 +66,17 @@ class BaseClip extends Entity
* @var array<string, string> * @var array<string, string>
*/ */
protected $casts = [ protected $casts = [
'id' => 'integer', 'id' => 'integer',
'podcast_id' => 'integer', 'podcast_id' => 'integer',
'episode_id' => 'integer', 'episode_id' => 'integer',
'title' => 'string', 'title' => 'string',
'start_time' => 'double', 'start_time' => 'double',
'duration' => 'double', 'duration' => 'double',
'type' => 'string', 'type' => 'string',
'media_id' => '?integer', 'media_id' => '?integer',
'metadata' => '?json-array', 'metadata' => '?json-array',
'status' => 'string', 'status' => 'string',
'logs' => 'string', 'logs' => 'string',
'created_by' => 'integer', 'created_by' => 'integer',
'updated_by' => 'integer', 'updated_by' => 'integer',
]; ];
...@@ -83,7 +84,7 @@ class BaseClip extends Entity ...@@ -83,7 +84,7 @@ class BaseClip extends Entity
/** /**
* @param array<string, mixed>|null $data * @param array<string, mixed>|null $data
*/ */
public function __construct(array $data = null) public function __construct(?array $data = null)
{ {
parent::__construct($data); parent::__construct($data);
} }
...@@ -119,30 +120,25 @@ class BaseClip extends Entity ...@@ -119,30 +120,25 @@ class BaseClip extends Entity
public function getUser(): ?User public function getUser(): ?User
{ {
/** @var ?User */
return (new UserModel())->find($this->created_by); return (new UserModel())->find($this->created_by);
} }
public function setMedia(string $filePath = null): static public function setMedia(File $file, string $fileKey): static
{ {
if ($filePath === null) {
return $this;
}
$file = new File($filePath);
if ($this->media_id !== null) { if ($this->media_id !== null) {
$this->getMedia() $this->getMedia()
->setFile($file); ->setFile($file);
$this->getMedia() $this->getMedia()
->updated_by = (int) user_id(); ->updated_by = $this->attributes['updated_by'];
(new MediaModel('audio'))->updateMedia($this->getMedia()); (new MediaModel('audio'))->updateMedia($this->getMedia());
} else { } else {
$media = new Audio([ $media = new Audio([
'file_path' => $filePath, 'file_key' => $fileKey,
'language_code' => $this->getPodcast() 'language_code' => $this->getPodcast()
->language_code, ->language_code,
'uploaded_by' => $this->attributes['created_by'], 'uploaded_by' => $this->attributes['updated_by'],
'updated_by' => $this->attributes['created_by'], 'updated_by' => $this->attributes['updated_by'],
]); ]);
$media->setFile($file); $media->setFile($file);
......
...@@ -10,12 +10,13 @@ declare(strict_types=1); ...@@ -10,12 +10,13 @@ declare(strict_types=1);
namespace App\Entities\Clip; namespace App\Entities\Clip;
use App\Entities\Media\Video;
use App\Models\MediaModel;
use CodeIgniter\Files\File; use CodeIgniter\Files\File;
use Modules\Media\Entities\Video;
use Modules\Media\Models\MediaModel;
use Override;
/** /**
* @property array $theme * @property array{name:string,preview:string} $theme
* @property string $format * @property string $format
*/ */
class VideoClip extends BaseClip class VideoClip extends BaseClip
...@@ -25,7 +26,7 @@ class VideoClip extends BaseClip ...@@ -25,7 +26,7 @@ class VideoClip extends BaseClip
/** /**
* @param array<string, mixed>|null $data * @param array<string, mixed>|null $data
*/ */
public function __construct(array $data = null) public function __construct(?array $data = null)
{ {
parent::__construct($data); parent::__construct($data);
...@@ -36,7 +37,7 @@ class VideoClip extends BaseClip ...@@ -36,7 +37,7 @@ class VideoClip extends BaseClip
} }
/** /**
* @param array<string, string> $theme * @param array{name:string,preview:string} $theme
*/ */
public function setTheme(array $theme): self public function setTheme(array $theme): self
{ {
...@@ -53,7 +54,7 @@ class VideoClip extends BaseClip ...@@ -53,7 +54,7 @@ class VideoClip extends BaseClip
public function setFormat(string $format): self public function setFormat(string $format): self
{ {
$this->attributes['metadata'] = json_decode($this->attributes['metadata'], true); $this->attributes['metadata'] = json_decode((string) $this->attributes['metadata'], true);
$this->attributes['format'] = $format; $this->attributes['format'] = $format;
$this->attributes['metadata']['format'] = $format; $this->attributes['metadata']['format'] = $format;
...@@ -63,30 +64,24 @@ class VideoClip extends BaseClip ...@@ -63,30 +64,24 @@ class VideoClip extends BaseClip
return $this; return $this;
} }
public function setMedia(string $filePath = null): static #[Override]
public function setMedia(File $file, string $fileKey): static
{ {
if ($filePath === null) {
return $this;
}
if ($this->attributes['media_id'] !== null) { if ($this->attributes['media_id'] !== null) {
// media is already set, do nothing // media is already set, do nothing
return $this; return $this;
} }
helper('media');
$file = new File(media_path($filePath));
$video = new Video([ $video = new Video([
'file_path' => $filePath, 'file_key' => $fileKey,
'language_code' => $this->getPodcast() 'language_code' => $this->getPodcast()
->language_code, ->language_code,
'uploaded_by' => $this->attributes['created_by'], 'uploaded_by' => $this->attributes['created_by'],
'updated_by' => $this->attributes['created_by'], 'updated_by' => $this->attributes['created_by'],
]); ]);
$video->setFile($file); $video->setFile($file);
$this->attributes['media_id'] = (new MediaModel())->saveMedia($video); $this->attributes['media_id'] = (new MediaModel('video'))->saveMedia($video);
return $this; return $this;
} }
......
...@@ -45,12 +45,12 @@ class Credit extends Entity ...@@ -45,12 +45,12 @@ class Credit extends Entity
* @var array<string, string> * @var array<string, string>
*/ */
protected $casts = [ protected $casts = [
'podcast_id' => 'integer', 'podcast_id' => 'integer',
'episode_id' => '?integer', 'episode_id' => '?integer',
'person_id' => 'integer', 'person_id' => 'integer',
'full_name' => 'string', 'full_name' => 'string',
'person_group' => 'string', 'person_group' => 'string',
'person_role' => 'string', 'person_role' => 'string',
]; ];
public function getPerson(): ?Person public function getPerson(): ?Person
...@@ -92,21 +92,16 @@ class Credit extends Entity ...@@ -92,21 +92,16 @@ class Credit extends Entity
return $this->episode; return $this->episode;
} }
/**
* @noRector ReturnTypeDeclarationRector
*/
public function getGroupLabel(): string public function getGroupLabel(): string
{ {
if ($this->person_group === null) { if ($this->person_group === null) {
return ''; return '';
} }
/** @var string */
return lang("PersonsTaxonomy.persons.{$this->person_group}.label"); return lang("PersonsTaxonomy.persons.{$this->person_group}.label");
} }
/**
* @noRector ReturnTypeDeclarationRector
*/
public function getRoleLabel(): string public function getRoleLabel(): string
{ {
if ($this->person_group === '') { if ($this->person_group === '') {
...@@ -117,6 +112,7 @@ class Credit extends Entity ...@@ -117,6 +112,7 @@ class Credit extends Entity
return ''; return '';
} }
/** @var string */
return lang("PersonsTaxonomy.persons.{$this->person_group}.roles.{$this->person_role}.label"); return lang("PersonsTaxonomy.persons.{$this->person_group}.roles.{$this->person_role}.label");
} }
} }
...@@ -11,14 +11,9 @@ declare(strict_types=1); ...@@ -11,14 +11,9 @@ declare(strict_types=1);
namespace App\Entities; namespace App\Entities;
use App\Entities\Clip\Soundbite; use App\Entities\Clip\Soundbite;
use App\Entities\Media\Audio;
use App\Entities\Media\Chapters;
use App\Entities\Media\Image;
use App\Entities\Media\Transcript;
use App\Libraries\SimpleRSSElement;
use App\Models\ClipModel; use App\Models\ClipModel;
use App\Models\EpisodeCommentModel; use App\Models\EpisodeCommentModel;
use App\Models\MediaModel; use App\Models\EpisodeModel;
use App\Models\PersonModel; use App\Models\PersonModel;
use App\Models\PodcastModel; use App\Models\PodcastModel;
use App\Models\PostModel; use App\Models\PostModel;
...@@ -26,32 +21,41 @@ use CodeIgniter\Entity\Entity; ...@@ -26,32 +21,41 @@ use CodeIgniter\Entity\Entity;
use CodeIgniter\Files\File; use CodeIgniter\Files\File;
use CodeIgniter\HTTP\Files\UploadedFile; use CodeIgniter\HTTP\Files\UploadedFile;
use CodeIgniter\I18n\Time; use CodeIgniter\I18n\Time;
use Exception;
use League\CommonMark\Environment\Environment; use League\CommonMark\Environment\Environment;
use League\CommonMark\Extension\Autolink\AutolinkExtension; use League\CommonMark\Extension\Autolink\AutolinkExtension;
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension; use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
use League\CommonMark\Extension\DisallowedRawHtml\DisallowedRawHtmlExtension; use League\CommonMark\Extension\DisallowedRawHtml\DisallowedRawHtmlExtension;
use League\CommonMark\Extension\SmartPunct\SmartPunctExtension; use League\CommonMark\Extension\SmartPunct\SmartPunctExtension;
use League\CommonMark\MarkdownConverter; use League\CommonMark\MarkdownConverter;
use Modules\Media\Entities\Audio;
use Modules\Media\Entities\Chapters;
use Modules\Media\Entities\Image;
use Modules\Media\Entities\Transcript;
use Modules\Media\Models\MediaModel;
use Override;
use RuntimeException; use RuntimeException;
/** /**
* @property int $id * @property int $id
* @property int $podcast_id * @property int $podcast_id
* @property Podcast $podcast * @property Podcast $podcast
* @property ?string $preview_id
* @property string $preview_link
* @property string $link * @property string $link
* @property string $guid * @property string $guid
* @property string $slug * @property string $slug
* @property string $title * @property string $title
* @property int $audio_id * @property int $audio_id
* @property Audio $audio * @property ?Audio $audio
* @property string $audio_analytics_url * @property string $audio_url
* @property string $audio_web_url * @property string $audio_web_url
* @property string $audio_opengraph_url * @property string $audio_opengraph_url
* @property string|null $description Holds text only description, striped of any markdown or html special characters * @property string|null $description Holds text only description, striped of any markdown or html special characters
* @property string $description_markdown * @property string $description_markdown
* @property string $description_html * @property string $description_html
* @property int $cover_id * @property ?int $cover_id
* @property Image $cover * @property ?Image $cover
* @property int|null $transcript_id * @property int|null $transcript_id
* @property Transcript|null $transcript * @property Transcript|null $transcript
* @property string|null $transcript_remote_url * @property string|null $transcript_remote_url
...@@ -67,38 +71,38 @@ use RuntimeException; ...@@ -67,38 +71,38 @@ use RuntimeException;
* @property string|null $location_name * @property string|null $location_name
* @property string|null $location_geo * @property string|null $location_geo
* @property string|null $location_osm * @property string|null $location_osm
* @property array|null $custom_rss
* @property string $custom_rss_string
* @property bool $is_published_on_hubs * @property bool $is_published_on_hubs
* @property int $downloads_count
* @property int $posts_count * @property int $posts_count
* @property int $comments_count * @property int $comments_count
* @property EpisodeComment[]|null $comments
* @property bool $is_premium
* @property int $created_by * @property int $created_by
* @property int $updated_by * @property int $updated_by
* @property string $publication_status; * @property string $publication_status
* @property Time|null $published_at; * @property Time|null $published_at
* @property Time $created_at; * @property Time $created_at
* @property Time $updated_at; * @property Time $updated_at
* @property Time|null $deleted_at;
* *
* @property Person[] $persons; * @property Person[] $persons
* @property Soundbite[] $soundbites; * @property Soundbite[] $soundbites
* @property string $embed_url; * @property string $embed_url
*/ */
class Episode extends Entity class Episode extends Entity
{ {
protected Podcast $podcast; public string $link = '';
protected string $link; public string $audio_url = '';
protected ?Audio $audio = null; public string $audio_web_url = '';
protected string $audio_analytics_url; public string $audio_opengraph_url = '';
protected string $audio_web_url; protected Podcast $podcast;
protected string $audio_opengraph_url; protected ?Audio $audio = null;
protected string $embed_url; protected string $embed_url = '';
protected ?Image $cover = null; protected ?Image $cover = null;
...@@ -130,51 +134,77 @@ class Episode extends Entity ...@@ -130,51 +134,77 @@ class Episode extends Entity
protected ?Location $location = null; protected ?Location $location = null;
protected string $custom_rss_string;
protected ?string $publication_status = null; protected ?string $publication_status = null;
/** /**
* @var string[] * @var array<int, string>
* @phpstan-var list<string>
*/ */
protected $dates = ['published_at', 'created_at', 'updated_at', 'deleted_at']; protected $dates = ['published_at', 'created_at', 'updated_at'];
/** /**
* @var array<string, string> * @var array<string, string>
*/ */
protected $casts = [ protected $casts = [
'id' => 'integer', 'id' => 'integer',
'podcast_id' => 'integer', 'podcast_id' => 'integer',
'guid' => 'string', 'preview_id' => '?string',
'slug' => 'string', 'guid' => 'string',
'title' => 'string', 'slug' => 'string',
'audio_id' => 'integer', 'title' => 'string',
'description_markdown' => 'string', 'audio_id' => 'integer',
'description_html' => 'string', 'description_markdown' => 'string',
'cover_id' => '?integer', 'description_html' => 'string',
'transcript_id' => '?integer', 'cover_id' => '?integer',
'transcript_id' => '?integer',
'transcript_remote_url' => '?string', 'transcript_remote_url' => '?string',
'chapters_id' => '?integer', 'chapters_id' => '?integer',
'chapters_remote_url' => '?string', 'chapters_remote_url' => '?string',
'parental_advisory' => '?string', 'parental_advisory' => '?string',
'number' => '?integer', 'number' => '?integer',
'season_number' => '?integer', 'season_number' => '?integer',
'type' => 'string', 'type' => 'string',
'is_blocked' => 'boolean', 'is_blocked' => 'boolean',
'location_name' => '?string', 'location_name' => '?string',
'location_geo' => '?string', 'location_geo' => '?string',
'location_osm' => '?string', 'location_osm' => '?string',
'custom_rss' => '?json-array', 'is_published_on_hubs' => 'boolean',
'is_published_on_hubs' => 'boolean', 'downloads_count' => 'integer',
'posts_count' => 'integer', 'posts_count' => 'integer',
'comments_count' => 'integer', 'comments_count' => 'integer',
'created_by' => 'integer', 'is_premium' => 'boolean',
'updated_by' => 'integer', 'created_by' => 'integer',
'updated_by' => 'integer',
]; ];
public function setCover(UploadedFile | File $file = null): self /**
* @param array<string, mixed> $data
*/
#[Override]
public function injectRawData(array $data): static
{
parent::injectRawData($data);
$this->link = url_to('episode', esc($this->getPodcast()->handle, 'url'), esc($this->attributes['slug'], 'url'));
$this->audio_url = url_to(
'episode-audio',
$this->getPodcast()
->handle,
$this->slug,
$this->getAudio()
->file_extension,
);
$this->audio_opengraph_url = $this->audio_url . '?_from=-+Open+Graph+-';
$this->audio_web_url = $this->audio_url . '?_from=-+Website+-';
return $this;
}
public function setCover(UploadedFile | File|null $file = null): self
{ {
if ($file === null || ($file instanceof UploadedFile && ! $file->isValid())) { if (! $file instanceof File || ($file instanceof UploadedFile && ! $file->isValid())) {
return $this; return $this;
} }
...@@ -182,16 +212,15 @@ class Episode extends Entity ...@@ -182,16 +212,15 @@ class Episode extends Entity
$this->getCover() $this->getCover()
->setFile($file); ->setFile($file);
$this->getCover() $this->getCover()
->updated_by = (int) user_id(); ->updated_by = $this->attributes['updated_by'];
(new MediaModel('image'))->updateMedia($this->getCover()); (new MediaModel('image'))->updateMedia($this->getCover());
} else { } else {
$cover = new Image([ $cover = new Image([
'file_name' => $this->attributes['slug'], 'file_key' => 'podcasts/' . $this->getPodcast()->handle . '/' . $this->attributes['slug'] . '.' . $file->getExtension(),
'file_directory' => 'podcasts/' . $this->getPodcast()->handle, 'sizes' => config('Images')
'sizes' => config('Images')
->podcastCoverSizes, ->podcastCoverSizes,
'uploaded_by' => user_id(), 'uploaded_by' => $this->attributes['updated_by'],
'updated_by' => user_id(), 'updated_by' => $this->attributes['updated_by'],
]); ]);
$cover->setFile($file); $cover->setFile($file);
...@@ -219,9 +248,9 @@ class Episode extends Entity ...@@ -219,9 +248,9 @@ class Episode extends Entity
return $this->cover; return $this->cover;
} }
public function setAudio(UploadedFile | File $file = null): self public function setAudio(UploadedFile | File|null $file = null): self
{ {
if ($file === null || ($file instanceof UploadedFile && ! $file->isValid())) { if (! $file instanceof File || ($file instanceof UploadedFile && ! $file->isValid())) {
return $this; return $this;
} }
...@@ -229,16 +258,15 @@ class Episode extends Entity ...@@ -229,16 +258,15 @@ class Episode extends Entity
$this->getAudio() $this->getAudio()
->setFile($file); ->setFile($file);
$this->getAudio() $this->getAudio()
->updated_by = (int) user_id(); ->updated_by = $this->attributes['updated_by'];
(new MediaModel('audio'))->updateMedia($this->getAudio()); (new MediaModel('audio'))->updateMedia($this->getAudio());
} else { } else {
$audio = new Audio([ $audio = new Audio([
'file_name' => $this->attributes['slug'], 'file_key' => 'podcasts/' . $this->getPodcast()->handle . '/' . $file->getRandomName(),
'file_directory' => 'podcasts/' . $this->getPodcast()->handle,
'language_code' => $this->getPodcast() 'language_code' => $this->getPodcast()
->language_code, ->language_code,
'uploaded_by' => user_id(), 'uploaded_by' => $this->attributes['updated_by'],
'updated_by' => user_id(), 'updated_by' => $this->attributes['updated_by'],
]); ]);
$audio->setFile($file); $audio->setFile($file);
...@@ -257,26 +285,25 @@ class Episode extends Entity ...@@ -257,26 +285,25 @@ class Episode extends Entity
return $this->audio; return $this->audio;
} }
public function setTranscript(UploadedFile | File $file = null): self public function setTranscript(UploadedFile | File|null $file = null): self
{ {
if ($file === null || ($file instanceof UploadedFile && ! $file->isValid())) { if (! $file instanceof File || ($file instanceof UploadedFile && ! $file->isValid())) {
return $this; return $this;
} }
if ($this->getTranscript() !== null) { if ($this->getTranscript() instanceof Transcript) {
$this->getTranscript() $this->getTranscript()
->setFile($file); ->setFile($file);
$this->getTranscript() $this->getTranscript()
->updated_by = (int) user_id(); ->updated_by = $this->attributes['updated_by'];
(new MediaModel('transcript'))->updateMedia($this->getTranscript()); (new MediaModel('transcript'))->updateMedia($this->getTranscript());
} else { } else {
$transcript = new Transcript([ $transcript = new Transcript([
'file_name' => $this->attributes['slug'] . '-transcript', 'file_key' => 'podcasts/' . $this->getPodcast()->handle . '/' . $this->attributes['slug'] . '-transcript.' . $file->getExtension(),
'file_directory' => 'podcasts/' . $this->getPodcast()->handle,
'language_code' => $this->getPodcast() 'language_code' => $this->getPodcast()
->language_code, ->language_code,
'uploaded_by' => user_id(), 'uploaded_by' => $this->attributes['updated_by'],
'updated_by' => user_id(), 'updated_by' => $this->attributes['updated_by'],
]); ]);
$transcript->setFile($file); $transcript->setFile($file);
...@@ -288,33 +315,32 @@ class Episode extends Entity ...@@ -288,33 +315,32 @@ class Episode extends Entity
public function getTranscript(): ?Transcript public function getTranscript(): ?Transcript
{ {
if ($this->transcript_id !== null && $this->transcript === null) { if ($this->transcript_id !== null && ! $this->transcript instanceof Transcript) {
$this->transcript = (new MediaModel('transcript'))->getMediaById($this->transcript_id); $this->transcript = (new MediaModel('transcript'))->getMediaById($this->transcript_id);
} }
return $this->transcript; return $this->transcript;
} }
public function setChapters(UploadedFile | File $file = null): self public function setChapters(UploadedFile | File|null $file = null): self
{ {
if ($file === null || ($file instanceof UploadedFile && ! $file->isValid())) { if (! $file instanceof File || ($file instanceof UploadedFile && ! $file->isValid())) {
return $this; return $this;
} }
if ($this->getChapters() !== null) { if ($this->getChapters() instanceof Chapters) {
$this->getChapters() $this->getChapters()
->setFile($file); ->setFile($file);
$this->getChapters() $this->getChapters()
->updated_by = (int) user_id(); ->updated_by = $this->attributes['updated_by'];
(new MediaModel('chapters'))->updateMedia($this->getChapters()); (new MediaModel('chapters'))->updateMedia($this->getChapters());
} else { } else {
$chapters = new Chapters([ $chapters = new Chapters([
'file_name' => $this->attributes['slug'] . '-chapters', 'file_key' => 'podcasts/' . $this->getPodcast()->handle . '/' . $this->attributes['slug'] . '-chapters' . '.' . $file->getExtension(),
'file_directory' => 'podcasts/' . $this->getPodcast()->handle,
'language_code' => $this->getPodcast() 'language_code' => $this->getPodcast()
->language_code, ->language_code,
'uploaded_by' => user_id(), 'uploaded_by' => $this->attributes['updated_by'],
'updated_by' => user_id(), 'updated_by' => $this->attributes['updated_by'],
]); ]);
$chapters->setFile($file); $chapters->setFile($file);
...@@ -326,47 +352,19 @@ class Episode extends Entity ...@@ -326,47 +352,19 @@ class Episode extends Entity
public function getChapters(): ?Chapters public function getChapters(): ?Chapters
{ {
if ($this->chapters_id !== null && $this->chapters === null) { if ($this->chapters_id !== null && ! $this->chapters instanceof Chapters) {
$this->chapters = (new MediaModel('chapters'))->getMediaById($this->chapters_id); $this->chapters = (new MediaModel('chapters'))->getMediaById($this->chapters_id);
} }
return $this->chapters; return $this->chapters;
} }
public function getAudioAnalyticsUrl(): string
{
helper('analytics');
// remove 'podcasts/' from audio file path
$strippedAudioPath = substr($this->getAudio()->file_path, 9);
return generate_episode_analytics_url(
$this->podcast_id,
$this->id,
$strippedAudioPath,
$this->audio->duration,
$this->audio->file_size,
$this->audio->header_size,
$this->published_at,
);
}
public function getAudioWebUrl(): string
{
return $this->getAudioAnalyticsUrl() . '?_from=-+Website+-';
}
public function getAudioOpengraphUrl(): string
{
return $this->getAudioAnalyticsUrl() . '?_from=-+Open+Graph+-';
}
/** /**
* Gets transcript url from transcript file uri if it exists or returns the transcript_remote_url which can be null. * Gets transcript url from transcript file uri if it exists or returns the transcript_remote_url which can be null.
*/ */
public function getTranscriptUrl(): ?string public function getTranscriptUrl(): ?string
{ {
if ($this->transcript !== null) { if ($this->transcript instanceof Transcript) {
return $this->transcript->file_url; return $this->transcript->file_url;
} }
...@@ -378,7 +376,7 @@ class Episode extends Entity ...@@ -378,7 +376,7 @@ class Episode extends Entity
*/ */
public function getChaptersFileUrl(): ?string public function getChaptersFileUrl(): ?string
{ {
if ($this->chapters !== null) { if ($this->chapters instanceof Chapters) {
return $this->chapters->file_url; return $this->chapters->file_url;
} }
...@@ -453,21 +451,16 @@ class Episode extends Entity ...@@ -453,21 +451,16 @@ class Episode extends Entity
return $this->comments; return $this->comments;
} }
public function getLink(): string public function getEmbedUrl(?string $theme = null): string
{
return url_to('episode', esc($this->getPodcast()->handle), esc($this->attributes['slug']));
}
public function getEmbedUrl(string $theme = null): string
{ {
return $theme return $theme
? url_to('embed-theme', esc($this->getPodcast()->handle), esc($this->attributes['slug']), $theme,) ? url_to('embed-theme', esc($this->getPodcast()->handle), esc($this->attributes['slug']), $theme)
: url_to('embed', esc($this->getPodcast()->handle), esc($this->attributes['slug'])); : url_to('embed', esc($this->getPodcast()->handle), esc($this->attributes['slug']));
} }
public function setGuid(?string $guid = null): static public function setGuid(?string $guid = null): static
{ {
$this->attributes['guid'] = $guid === null ? $this->getLink() : $guid; $this->attributes['guid'] = $guid ?? $this->link;
return $this; return $this;
} }
...@@ -480,7 +473,7 @@ class Episode extends Entity ...@@ -480,7 +473,7 @@ class Episode extends Entity
public function setDescriptionMarkdown(string $descriptionMarkdown): static public function setDescriptionMarkdown(string $descriptionMarkdown): static
{ {
$config = [ $config = [
'html_input' => 'escape', 'html_input' => 'escape',
'allow_unsafe_links' => false, 'allow_unsafe_links' => false,
]; ];
...@@ -498,39 +491,11 @@ class Episode extends Entity ...@@ -498,39 +491,11 @@ class Episode extends Entity
return $this; return $this;
} }
public function getDescriptionHtml(?string $serviceSlug = null): string
{
$descriptionHtml = '';
if (
$this->getPodcast()
->partner_id !== null &&
$this->getPodcast()
->partner_link_url !== null &&
$this->getPodcast()
->partner_image_url !== null
) {
$descriptionHtml .= "<div><a href=\"{$this->getPartnerLink(
$serviceSlug,
)}\" rel=\"sponsored noopener noreferrer\" target=\"_blank\"><img src=\"{$this->getPartnerImageUrl(
$serviceSlug,
)}\" alt=\"Partner image\" /></a></div>";
}
$descriptionHtml .= $this->attributes['description_html'];
if ($this->getPodcast()->episode_description_footer_html) {
$descriptionHtml .= "<footer>{$this->getPodcast()
->episode_description_footer_html}</footer>";
}
return $descriptionHtml;
}
public function getDescription(): string public function getDescription(): string
{ {
if ($this->description === null) { if ($this->description === null) {
$this->description = trim( $this->description = trim(
preg_replace('~\s+~', ' ', strip_tags($this->attributes['description_html'])), (string) preg_replace('~\s+~', ' ', strip_tags((string) $this->attributes['description_html'])),
); );
} }
...@@ -540,8 +505,10 @@ class Episode extends Entity ...@@ -540,8 +505,10 @@ class Episode extends Entity
public function getPublicationStatus(): string public function getPublicationStatus(): string
{ {
if ($this->publication_status === null) { if ($this->publication_status === null) {
if ($this->published_at === null) { if (! $this->published_at instanceof Time) {
$this->publication_status = 'not_published'; $this->publication_status = 'not_published';
} elseif ($this->getPodcast()->publication_status !== 'published') {
$this->publication_status = 'with_podcast';
} elseif ($this->published_at->isBefore(Time::now())) { } elseif ($this->published_at->isBefore(Time::now())) {
$this->publication_status = 'published'; $this->publication_status = 'published';
} else { } else {
...@@ -557,7 +524,7 @@ class Episode extends Entity ...@@ -557,7 +524,7 @@ class Episode extends Entity
*/ */
public function setLocation(?Location $location = null): static public function setLocation(?Location $location = null): static
{ {
if ($location === null) { if (! $location instanceof Location) {
$this->attributes['location_name'] = null; $this->attributes['location_name'] = null;
$this->attributes['location_geo'] = null; $this->attributes['location_geo'] = null;
$this->attributes['location_osm'] = null; $this->attributes['location_osm'] = null;
...@@ -585,89 +552,36 @@ class Episode extends Entity ...@@ -585,89 +552,36 @@ class Episode extends Entity
return null; return null;
} }
if ($this->location === null) { if (! $this->location instanceof Location) {
$this->location = new Location($this->location_name, $this->location_geo, $this->location_osm); $this->location = new Location($this->location_name, $this->location_geo, $this->location_osm);
} }
return $this->location; return $this->location;
} }
/** public function getPreviewLink(): string
* Get custom rss tag as XML String
*/
public function getCustomRssString(): string
{ {
if ($this->custom_rss === null) { if ($this->preview_id === null) {
return ''; // generate preview id
} if (! $previewUUID = (new EpisodeModel())->setEpisodePreviewId($this->id)) {
throw new Exception('Could not set episode preview id');
helper('rss'); }
$xmlNode = (new SimpleRSSElement( $this->preview_id = $previewUUID;
'<?xml version="1.0" encoding="utf-8"?><rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:podcast="https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0"/>', }
))
->addChild('channel')
->addChild('item');
array_to_rss([
'elements' => $this->custom_rss,
], $xmlNode);
return (string) str_replace(['<item>', '</item>'], '', $xmlNode->asXML()); return url_to('episode-preview', (string) $this->preview_id);
} }
/** /**
* Saves custom rss tag into json * Returns the episode's clip count
*/ */
public function setCustomRssString(?string $customRssString = null): static public function getClipCount(): int|string
{ {
if ($customRssString === '') { if ($this->id === null) {
$this->attributes['custom_rss'] = null; throw new RuntimeException('Episode must be created before getting number of video clips.');
return $this;
}
helper('rss');
$customRssArray = rss_to_array(
simplexml_load_string(
'<?xml version="1.0" encoding="utf-8"?><rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:podcast="https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0"><channel><item>' .
$customRssString .
'</item></channel></rss>',
),
)['elements'][0]['elements'][0];
if (array_key_exists('elements', $customRssArray)) {
$this->attributes['custom_rss'] = json_encode($customRssArray['elements']);
} else {
$this->attributes['custom_rss'] = null;
}
return $this;
}
public function getPartnerLink(?string $serviceSlug = null): string
{
$partnerLink =
rtrim($this->getPodcast()->partner_link_url, '/') .
'?pid=' .
$this->getPodcast()
->partner_id .
'&guid=' .
urlencode($this->attributes['guid']);
if ($serviceSlug !== null) {
$partnerLink .= '&_from=' . $serviceSlug;
} }
return $partnerLink; return (new ClipModel())->getClipCount($this->podcast_id, $this->id);
}
public function getPartnerImageUrl(string $serviceSlug = null): string
{
return rtrim($this->getPodcast()->partner_image_url, '/') .
'?pid=' .
$this->getPodcast()
->partner_id .
'&guid=' .
urlencode($this->attributes['guid']) .
($serviceSlug !== null ? '&_from=' . $serviceSlug : '');
} }
} }
...@@ -51,7 +51,8 @@ class EpisodeComment extends UuidEntity ...@@ -51,7 +51,8 @@ class EpisodeComment extends UuidEntity
protected bool $has_replies = false; protected bool $has_replies = false;
/** /**
* @var string[] * @var array<int, string>
* @phpstan-var list<string>
*/ */
protected $dates = ['created_at']; protected $dates = ['created_at'];
...@@ -59,17 +60,17 @@ class EpisodeComment extends UuidEntity ...@@ -59,17 +60,17 @@ class EpisodeComment extends UuidEntity
* @var array<string, string> * @var array<string, string>
*/ */
protected $casts = [ protected $casts = [
'id' => 'string', 'id' => 'string',
'uri' => 'string', 'uri' => 'string',
'episode_id' => 'integer', 'episode_id' => 'integer',
'actor_id' => 'integer', 'actor_id' => 'integer',
'in_reply_to_id' => '?string', 'in_reply_to_id' => '?string',
'message' => 'string', 'message' => 'string',
'message_html' => 'string', 'message_html' => 'string',
'likes_count' => 'integer', 'likes_count' => 'integer',
'replies_count' => 'integer', 'replies_count' => 'integer',
'created_by' => 'integer', 'created_by' => 'integer',
'is_from_post' => 'boolean', 'is_from_post' => 'boolean',
]; ];
public function getEpisode(): ?Episode public function getEpisode(): ?Episode
...@@ -87,8 +88,6 @@ class EpisodeComment extends UuidEntity ...@@ -87,8 +88,6 @@ class EpisodeComment extends UuidEntity
/** /**
* Returns the comment's actor * Returns the comment's actor
*
* @noRector ReturnTypeDeclarationRector
*/ */
public function getActor(): ?Actor public function getActor(): ?Actor
{ {
...@@ -96,8 +95,7 @@ class EpisodeComment extends UuidEntity ...@@ -96,8 +95,7 @@ class EpisodeComment extends UuidEntity
throw new RuntimeException('Comment must have an actor_id before getting actor.'); throw new RuntimeException('Comment must have an actor_id before getting actor.');
} }
if ($this->actor === null) { if (! $this->actor instanceof Actor) {
// @phpstan-ignore-next-line
$this->actor = model(ActorModel::class, false) $this->actor = model(ActorModel::class, false)
->getActorById($this->actor_id); ->getActorById($this->actor_id);
} }
...@@ -126,16 +124,13 @@ class EpisodeComment extends UuidEntity ...@@ -126,16 +124,13 @@ class EpisodeComment extends UuidEntity
return $this->getReplies() !== []; return $this->getReplies() !== [];
} }
/**
* @noRector ReturnTypeDeclarationRector
*/
public function getReplyToComment(): ?self public function getReplyToComment(): ?self
{ {
if ($this->in_reply_to_id === null) { if ($this->in_reply_to_id === null) {
throw new RuntimeException('Comment is not a reply.'); throw new RuntimeException('Comment is not a reply.');
} }
if ($this->reply_to_comment === null) { if (! $this->reply_to_comment instanceof self) {
$this->reply_to_comment = model(EpisodeCommentModel::class, false) $this->reply_to_comment = model(EpisodeCommentModel::class, false)
->getCommentById($this->in_reply_to_id); ->getCommentById($this->in_reply_to_id);
} }
......
...@@ -22,7 +22,7 @@ class Language extends Entity ...@@ -22,7 +22,7 @@ class Language extends Entity
* @var array<string, string> * @var array<string, string>
*/ */
protected $casts = [ protected $casts = [
'code' => 'string', 'code' => 'string',
'native_name' => 'string', 'native_name' => 'string',
]; ];
} }
...@@ -27,7 +27,7 @@ class Like extends UuidEntity ...@@ -27,7 +27,7 @@ class Like extends UuidEntity
* @var array<string, string> * @var array<string, string>
*/ */
protected $casts = [ protected $casts = [
'actor_id' => 'integer', 'actor_id' => 'integer',
'comment_id' => 'string', 'comment_id' => 'string',
]; ];
} }
...@@ -11,7 +11,6 @@ declare(strict_types=1); ...@@ -11,7 +11,6 @@ declare(strict_types=1);
namespace App\Entities; namespace App\Entities;
use CodeIgniter\Entity\Entity; use CodeIgniter\Entity\Entity;
use Config\Services;
/** /**
* @property string $url * @property string $url
...@@ -23,15 +22,9 @@ use Config\Services; ...@@ -23,15 +22,9 @@ use Config\Services;
*/ */
class Location extends Entity class Location extends Entity
{ {
/** private const string OSM_URL = 'https://www.openstreetmap.org/';
* @var string
*/
private const OSM_URL = 'https://www.openstreetmap.org/';
/** private const string NOMINATIM_URL = 'https://nominatim.openstreetmap.org/';
* @var string
*/
private const NOMINATIM_URL = 'https://nominatim.openstreetmap.org/';
public function __construct( public function __construct(
protected string $name, protected string $name,
...@@ -42,15 +35,18 @@ class Location extends Entity ...@@ -42,15 +35,18 @@ class Location extends Entity
$longitude = null; $longitude = null;
if ($geo !== null) { if ($geo !== null) {
$geoArray = explode(',', substr($geo, 4)); $geoArray = explode(',', substr($geo, 4));
$latitude = floatval($geoArray[0]);
$longitude = floatval($geoArray[1]); if (count($geoArray) === 2) {
$latitude = (float) $geoArray[0];
$longitude = (float) $geoArray[1];
}
} }
parent::__construct([ parent::__construct([
'name' => $name, 'name' => $name,
'geo' => $geo, 'geo' => $geo,
'osm' => $osm, 'osm' => $osm,
'latitude' => $latitude, 'latitude' => $latitude,
'longitude' => $longitude, 'longitude' => $longitude,
]); ]);
} }
...@@ -82,7 +78,7 @@ class Location extends Entity ...@@ -82,7 +78,7 @@ class Location extends Entity
*/ */
public function fetchOsmLocation(): static public function fetchOsmLocation(): static
{ {
$client = Services::curlrequest(); $client = service('curlrequest');
$response = $client->request( $response = $client->request(
'GET', 'GET',
...@@ -93,12 +89,12 @@ class Location extends Entity ...@@ -93,12 +89,12 @@ class Location extends Entity
[ [
'headers' => [ 'headers' => [
'User-Agent' => 'Castopod/' . CP_VERSION, 'User-Agent' => 'Castopod/' . CP_VERSION,
'Accept' => 'application/json', 'Accept' => 'application/json',
], ],
], ],
); );
$places = json_decode($response->getBody(), false, 512, JSON_THROW_ON_ERROR); $places = json_decode((string) $response->getBody(), false, 512, JSON_THROW_ON_ERROR);
if ($places === []) { if ($places === []) {
return $this; return $this;
...@@ -106,16 +102,16 @@ class Location extends Entity ...@@ -106,16 +102,16 @@ class Location extends Entity
if (property_exists($places[0], 'lat') && $places[0]->lat !== null && (property_exists( if (property_exists($places[0], 'lat') && $places[0]->lat !== null && (property_exists(
$places[0], $places[0],
'lon' 'lon',
) && $places[0]->lon !== null)) { ) && $places[0]->lon !== null)) {
$this->attributes['geo'] = "geo:{$places[0]->lat},{$places[0]->lon}"; $this->attributes['geo'] = "geo:{$places[0]->lat},{$places[0]->lon}";
} }
if (property_exists($places[0], 'osm_type') && $places[0]->osm_type !== null && (property_exists( if (property_exists($places[0], 'osm_type') && $places[0]->osm_type !== null && (property_exists(
$places[0], $places[0],
'osm_id' 'osm_id',
) && $places[0]->osm_id !== null)) { ) && $places[0]->osm_id !== null)) {
$this->attributes['osm'] = strtoupper(substr($places[0]->osm_type, 0, 1)) . $places[0]->osm_id; $this->attributes['osm'] = strtoupper(substr((string) $places[0]->osm_type, 0, 1)) . $places[0]->osm_id;
} }
return $this; return $this;
......
<?php
declare(strict_types=1);
/**
* @copyright 2021 Ad Aures
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
namespace App\Entities\Media;
class Chapters extends BaseMedia
{
protected string $type = 'chapters';
}