diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index beb4929c..ab03fd17 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -7,13 +7,17 @@ "workspaceFolder": "/castopod-host", "postCreateCommand": "cron && php spark serve --host 0.0.0.0", "settings": { - "terminal.integrated.shell.linux": "/bin/bash", + "terminal.integrated.defaultProfile.linux": "/bin/bash", "editor.formatOnSave": true, "[php]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, "phpSniffer.autoDetect": true, - "color-highlight.markerType": "dot-before" + "color-highlight.markerType": "dot-before", + "files.associations": { + "*.xml.dist": "xml", + "spark": "php" + } }, "extensions": [ "mikestead.dotenv", @@ -28,6 +32,8 @@ "dbaeumer.vscode-eslint", "stylelint.vscode-stylelint", "wongjn.php-sniffer", - "eamodio.gitlens" + "eamodio.gitlens", + "breezelin.phpstan", + "kasik96.latte" ] } diff --git a/app/Authorization/FlatAuthorization.php b/app/Authorization/FlatAuthorization.php index 5c4a7f89..b5af66d5 100644 --- a/app/Authorization/FlatAuthorization.php +++ b/app/Authorization/FlatAuthorization.php @@ -2,8 +2,19 @@ namespace App\Authorization; -class FlatAuthorization extends \Myth\Auth\Authorization\FlatAuthorization +use Myth\Auth\Authorization\FlatAuthorization as MythAuthFlatAuthorization; + +class FlatAuthorization extends MythAuthFlatAuthorization { + /** + * The group model to use. Usually the class noted + * below (or an extension thereof) but can be any + * compatible CodeIgniter Model. + * + * @var PermissionModel + */ + protected $permissionModel; + /** * Checks a group to see if they have the specified permission. * @@ -18,7 +29,7 @@ class FlatAuthorization extends \Myth\Auth\Authorization\FlatAuthorization return false; } - return (bool) $this->permissionModel->doesGroupHavePermission( + return $this->permissionModel->doesGroupHavePermission( $groupId, $permissionId, ); @@ -27,14 +38,14 @@ class FlatAuthorization extends \Myth\Auth\Authorization\FlatAuthorization /** * Makes user part of given groups. * - * @param array $groups Either collection of ID or names + * @param array $groups Either collection of ID or names */ public function setUserGroups(int $userId, array $groups = []): bool { // remove user from all groups before resetting it in new groups $this->groupModel->removeUserFromAllGroups($userId); - if ($groups = []) { + if ($groups === []) { return true; } diff --git a/app/Authorization/GroupModel.php b/app/Authorization/GroupModel.php index 4c7da3f6..f48ab40c 100644 --- a/app/Authorization/GroupModel.php +++ b/app/Authorization/GroupModel.php @@ -2,7 +2,9 @@ namespace App\Authorization; -class GroupModel extends \Myth\Auth\Authorization\GroupModel +use Myth\Auth\Authorization\GroupModel as MythAuthGroupModel; + +class GroupModel extends MythAuthGroupModel { /** * @return mixed[] diff --git a/app/Authorization/PermissionModel.php b/app/Authorization/PermissionModel.php index 254265e9..d2e2c9bd 100644 --- a/app/Authorization/PermissionModel.php +++ b/app/Authorization/PermissionModel.php @@ -2,7 +2,9 @@ namespace App\Authorization; -class PermissionModel extends \Myth\Auth\Authorization\PermissionModel +use Myth\Auth\Authorization\PermissionModel as MythAuthPermissionModel; + +class PermissionModel extends MythAuthPermissionModel { /** * Checks to see if a user, or one of their groups, diff --git a/app/Config/Analytics.php b/app/Config/Analytics.php index 19b75559..df73c9a9 100644 --- a/app/Config/Analytics.php +++ b/app/Config/Analytics.php @@ -28,8 +28,10 @@ class Analytics extends AnalyticsBase /** * get the full audio file url + * + * @param string|string[] $audioFilePath */ - public function getAudioFileUrl(string $audioFilePath): string + public function getAudioFileUrl($audioFilePath): string { helper('media'); diff --git a/app/Config/Auth.php b/app/Config/Auth.php index db08a27a..20e5303d 100644 --- a/app/Config/Auth.php +++ b/app/Config/Auth.php @@ -2,7 +2,9 @@ namespace Config; -class Auth extends \Myth\Auth\Config\Auth +use Myth\Auth\Config\Auth as MythAuthConfig; + +class Auth extends MythAuthConfig { /** * -------------------------------------------------------------------------- diff --git a/app/Config/Events.php b/app/Config/Events.php index 6a994450..24af525c 100644 --- a/app/Config/Events.php +++ b/app/Config/Events.php @@ -2,6 +2,9 @@ namespace Config; +use App\Entities\Actor; +use App\Entities\Note; +use App\Entities\User; use CodeIgniter\Events\Events; use CodeIgniter\Exceptions\FrameworkException; @@ -23,6 +26,7 @@ use CodeIgniter\Exceptions\FrameworkException; */ Events::on('pre_system', function () { + // @phpstan-ignore-next-line if (ENVIRONMENT !== 'testing') { if (ini_get('zlib.output_compression')) { throw FrameworkException::forEnabledZlibOutputCompression(); @@ -42,6 +46,8 @@ Events::on('pre_system', function () { * Debug Toolbar Listeners. * -------------------------------------------------------------------- * If you delete, they will no longer be collected. + * + * @phpstan-ignore-next-line */ if (CI_DEBUG) { Events::on( @@ -52,7 +58,7 @@ Events::on('pre_system', function () { } }); -Events::on('login', function ($user): void { +Events::on('login', function (User $user): void { helper('auth'); // set interact_as_actor_id value @@ -62,7 +68,7 @@ Events::on('login', function ($user): void { } }); -Events::on('logout', function ($user): void { +Events::on('logout', function (User $user): void { helper('auth'); // remove user's interact_as_actor session @@ -75,7 +81,7 @@ Events::on('logout', function ($user): void { * -------------------------------------------------------------------- * Update episode metadata counts */ -Events::on('on_note_add', function ($note): void { +Events::on('on_note_add', function (Note $note): void { if ($note->episode_id) { model('EpisodeModel') ->where('id', $note->episode_id) @@ -87,7 +93,7 @@ Events::on('on_note_add', function ($note): void { cache()->deleteMatching("page_podcast#{$note->actor->podcast->id}*"); }); -Events::on('on_note_remove', function ($note): void { +Events::on('on_note_remove', function (Note $note): void { if ($note->episode_id) { model('EpisodeModel') ->where('id', $note->episode_id) @@ -106,7 +112,7 @@ Events::on('on_note_remove', function ($note): void { cache()->deleteMatching("page_note#{$note->id}*"); }); -Events::on('on_note_reblog', function ($actor, $note): void { +Events::on('on_note_reblog', function (Actor $actor, Note $note): void { if ($episodeId = $note->episode_id) { model('EpisodeModel') ->where('id', $episodeId) @@ -125,7 +131,7 @@ Events::on('on_note_reblog', function ($actor, $note): void { } }); -Events::on('on_note_undo_reblog', function ($reblogNote): void { +Events::on('on_note_undo_reblog', function (Note $reblogNote): void { $note = $reblogNote->reblog_of_note; if ($episodeId = $note->episode_id) { model('EpisodeModel') @@ -147,21 +153,21 @@ Events::on('on_note_undo_reblog', function ($reblogNote): void { } }); -Events::on('on_note_reply', function ($reply): void { +Events::on('on_note_reply', function (Note $reply): void { $note = $reply->reply_to_note; cache()->deleteMatching("page_podcast#{$note->actor->podcast->id}*"); cache()->deleteMatching("page_note#{$note->id}*"); }); -Events::on('on_reply_remove', function ($reply): void { +Events::on('on_reply_remove', function (Note $reply): void { $note = $reply->reply_to_note; cache()->deleteMatching("page_podcast#{$note->actor->podcast->id}*"); cache()->deleteMatching("page_note#{$note->id}*"); }); -Events::on('on_note_favourite', function ($actor, $note): void { +Events::on('on_note_favourite', function (Actor $actor, Note $note): void { if ($note->episode_id) { model('EpisodeModel') ->where('id', $note->episode_id) @@ -176,7 +182,7 @@ Events::on('on_note_favourite', function ($actor, $note): void { } }); -Events::on('on_note_undo_favourite', function ($actor, $note): void { +Events::on('on_note_undo_favourite', function (Actor $actor, Note $note): void { if ($note->episode_id) { model('EpisodeModel') ->where('id', $note->episode_id) @@ -191,22 +197,22 @@ Events::on('on_note_undo_favourite', function ($actor, $note): void { } }); -Events::on('on_block_actor', function ($actorId): void { +Events::on('on_block_actor', function (int $actorId): void { cache()->deleteMatching('page_podcast*'); cache()->deleteMatching('page_note*'); }); -Events::on('on_unblock_actor', function ($actorId): void { +Events::on('on_unblock_actor', function (int $actorId): void { cache()->deleteMatching('page_podcast*'); cache()->deleteMatching('page_note*'); }); -Events::on('on_block_domain', function ($domainName): void { +Events::on('on_block_domain', function (string $domainName): void { cache()->deleteMatching('page_podcast*'); cache()->deleteMatching('page_note*'); }); -Events::on('on_unblock_domain', function ($domainName): void { +Events::on('on_unblock_domain', function (string $domainName): void { cache()->deleteMatching('page_podcast*'); cache()->deleteMatching('page_note*'); }); diff --git a/app/Config/Images.php b/app/Config/Images.php index db5ef185..e1067cb6 100644 --- a/app/Config/Images.php +++ b/app/Config/Images.php @@ -80,25 +80,25 @@ class Images extends BaseConfig /** * @var string */ - public $thumbnailExtension = '_thumbnail'; + public $thumbnailSuffix = '_thumbnail'; /** * @var string */ - public $mediumExtension = '_medium'; + public $mediumSuffix = '_medium'; /** * @var string */ - public $largeExtension = '_large'; + public $largeSuffix = '_large'; /** * @var string */ - public $feedExtension = '_feed'; + public $feedSuffix = '_feed'; /** * @var string */ - public $id3Extension = '_id3'; + public $id3Suffix = '_id3'; } diff --git a/app/Config/Mimes.php b/app/Config/Mimes.php index 39c2aace..48e1b58d 100644 --- a/app/Config/Mimes.php +++ b/app/Config/Mimes.php @@ -22,7 +22,7 @@ class Mimes /** * Map of extensions to mime types. * - * @var array + * @var array */ public static $mimes = [ 'hqx' => [ @@ -350,25 +350,25 @@ class Mimes $proposedExtension = trim(strtolower($proposedExtension)); - if ($proposedExtension !== '') { - if ( - array_key_exists($proposedExtension, static::$mimes) && - in_array( - $type, - is_string(static::$mimes[$proposedExtension]) - ? [static::$mimes[$proposedExtension]] - : static::$mimes[$proposedExtension], - true, - ) - ) { - // The detected mime type matches with the proposed extension. - return $proposedExtension; - } - + if ($proposedExtension === '') { // An extension was proposed, but the media type does not match the mime type list. return null; } + if ( + array_key_exists($proposedExtension, static::$mimes) && + in_array( + $type, + is_string(static::$mimes[$proposedExtension]) + ? [static::$mimes[$proposedExtension]] + : static::$mimes[$proposedExtension], + true, + ) + ) { + // The detected mime type matches with the proposed extension. + return $proposedExtension; + } + // Reverse check the mime type list if no extension was proposed. // This search is order sensitive! foreach (static::$mimes as $ext => $types) { diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 2bc5d9bc..4539867c 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -51,23 +51,35 @@ $routes->addPlaceholder( // We get a performance increase by specifying the default // route since we don't have to scan directories. -$routes->get('/', 'Home::index', ['as' => 'home']); +$routes->get('/', 'HomeController::index', ['as' => 'home']); // Install Wizard route $routes->group(config('App')->installGateway, function ($routes): void { - $routes->get('/', 'Install', ['as' => 'install']); - $routes->post('instance-config', 'Install::attemptInstanceConfig', [ - 'as' => 'instance-config', - ]); - $routes->post('database-config', 'Install::attemptDatabaseConfig', [ - 'as' => 'database-config', - ]); - $routes->post('cache-config', 'Install::attemptCacheConfig', [ + $routes->get('/', 'InstallController', ['as' => 'install']); + $routes->post( + 'instance-config', + 'InstallController::attemptInstanceConfig', + [ + 'as' => 'instance-config', + ], + ); + $routes->post( + 'database-config', + 'InstallController::attemptDatabaseConfig', + [ + 'as' => 'database-config', + ], + ); + $routes->post('cache-config', 'InstallController::attemptCacheConfig', [ 'as' => 'cache-config', ]); - $routes->post('create-superadmin', 'Install::attemptCreateSuperAdmin', [ - 'as' => 'create-superadmin', - ]); + $routes->post( + 'create-superadmin', + 'InstallController::attemptCreateSuperAdmin', + [ + 'as' => 'create-superadmin', + ], + ); }); $routes->get('.well-known/platforms', 'Platform'); @@ -77,35 +89,35 @@ $routes->group( config('App')->adminGateway, ['namespace' => 'App\Controllers\Admin'], function ($routes): void { - $routes->get('/', 'Home', [ + $routes->get('/', 'HomeController', [ 'as' => 'admin', ]); $routes->group('persons', function ($routes): void { - $routes->get('/', 'Person', [ + $routes->get('/', 'PersonController', [ 'as' => 'person-list', 'filter' => 'permission:person-list', ]); - $routes->get('new', 'Person::create', [ + $routes->get('new', 'PersonController::create', [ 'as' => 'person-create', 'filter' => 'permission:person-create', ]); - $routes->post('new', 'Person::attemptCreate', [ + $routes->post('new', 'PersonController::attemptCreate', [ 'filter' => 'permission:person-create', ]); $routes->group('(:num)', function ($routes): void { - $routes->get('/', 'Person::view/$1', [ + $routes->get('/', 'PersonController::view/$1', [ 'as' => 'person-view', 'filter' => 'permission:person-view', ]); - $routes->get('edit', 'Person::edit/$1', [ + $routes->get('edit', 'PersonController::edit/$1', [ 'as' => 'person-edit', 'filter' => 'permission:person-edit', ]); - $routes->post('edit', 'Person::attemptEdit/$1', [ + $routes->post('edit', 'PersonController::attemptEdit/$1', [ 'filter' => 'permission:person-edit', ]); - $routes->add('delete', 'Person::delete/$1', [ + $routes->add('delete', 'PersonController::delete/$1', [ 'as' => 'person-delete', 'filter' => 'permission:person-delete', ]); @@ -114,55 +126,59 @@ $routes->group( // Podcasts $routes->group('podcasts', function ($routes): void { - $routes->get('/', 'Podcast::list', [ + $routes->get('/', 'PodcastController::list', [ 'as' => 'podcast-list', ]); - $routes->get('new', 'Podcast::create', [ + $routes->get('new', 'PodcastController::create', [ 'as' => 'podcast-create', 'filter' => 'permission:podcasts-create', ]); - $routes->post('new', 'Podcast::attemptCreate', [ + $routes->post('new', 'PodcastController::attemptCreate', [ 'filter' => 'permission:podcasts-create', ]); - $routes->get('import', 'PodcastImport', [ + $routes->get('import', 'PodcastImportController', [ 'as' => 'podcast-import', 'filter' => 'permission:podcasts-import', ]); - $routes->post('import', 'PodcastImport::attemptImport', [ + $routes->post('import', 'PodcastImportController::attemptImport', [ 'filter' => 'permission:podcasts-import', ]); // Podcast // Use ids in admin area to help permission and group lookups $routes->group('(:num)', function ($routes): void { - $routes->get('/', 'Podcast::view/$1', [ + $routes->get('/', 'PodcastController::view/$1', [ 'as' => 'podcast-view', 'filter' => 'permission:podcasts-view,podcast-view', ]); - $routes->get('edit', 'Podcast::edit/$1', [ + $routes->get('edit', 'PodcastController::edit/$1', [ 'as' => 'podcast-edit', 'filter' => 'permission:podcast-edit', ]); - $routes->post('edit', 'Podcast::attemptEdit/$1', [ + $routes->post('edit', 'PodcastController::attemptEdit/$1', [ 'filter' => 'permission:podcast-edit', ]); - $routes->get('delete', 'Podcast::delete/$1', [ + $routes->get('delete', 'PodcastController::delete/$1', [ 'as' => 'podcast-delete', 'filter' => 'permission:podcasts-delete', ]); $routes->group('persons', function ($routes): void { - $routes->get('/', 'PodcastPerson/$1', [ + $routes->get('/', 'PodcastPersonController/$1', [ 'as' => 'podcast-person-manage', 'filter' => 'permission:podcast-edit', ]); - $routes->post('/', 'PodcastPerson::attemptAdd/$1', [ - 'filter' => 'permission:podcast-edit', - ]); + $routes->post( + '/', + 'PodcastPersonController::attemptAdd/$1', + [ + 'filter' => 'permission:podcast-edit', + ], + ); $routes->get( '(:num)/remove', - 'PodcastPerson::remove/$1/$2', + 'PodcastPersonController::remove/$1/$2', [ 'as' => 'podcast-person-remove', 'filter' => 'permission:podcast-edit', @@ -171,13 +187,13 @@ $routes->group( }); $routes->group('analytics', function ($routes): void { - $routes->get('/', 'Podcast::viewAnalytics/$1', [ + $routes->get('/', 'PodcastController::viewAnalytics/$1', [ 'as' => 'podcast-analytics', 'filter' => 'permission:podcasts-view,podcast-view', ]); $routes->get( 'webpages', - 'Podcast::viewAnalyticsWebpages/$1', + 'PodcastController::viewAnalyticsWebpages/$1', [ 'as' => 'podcast-analytics-webpages', 'filter' => 'permission:podcasts-view,podcast-view', @@ -185,7 +201,7 @@ $routes->group( ); $routes->get( 'locations', - 'Podcast::viewAnalyticsLocations/$1', + 'PodcastController::viewAnalyticsLocations/$1', [ 'as' => 'podcast-analytics-locations', 'filter' => 'permission:podcasts-view,podcast-view', @@ -193,7 +209,7 @@ $routes->group( ); $routes->get( 'unique-listeners', - 'Podcast::viewAnalyticsUniqueListeners/$1', + 'PodcastController::viewAnalyticsUniqueListeners/$1', [ 'as' => 'podcast-analytics-unique-listeners', 'filter' => 'permission:podcasts-view,podcast-view', @@ -201,7 +217,7 @@ $routes->group( ); $routes->get( 'listening-time', - 'Podcast::viewAnalyticsListeningTime/$1', + 'PodcastController::viewAnalyticsListeningTime/$1', [ 'as' => 'podcast-analytics-listening-time', 'filter' => 'permission:podcasts-view,podcast-view', @@ -209,7 +225,7 @@ $routes->group( ); $routes->get( 'time-periods', - 'Podcast::viewAnalyticsTimePeriods/$1', + 'PodcastController::viewAnalyticsTimePeriods/$1', [ 'as' => 'podcast-analytics-time-periods', 'filter' => 'permission:podcasts-view,podcast-view', @@ -217,7 +233,7 @@ $routes->group( ); $routes->get( 'players', - 'Podcast::viewAnalyticsPlayers/$1', + 'PodcastController::viewAnalyticsPlayers/$1', [ 'as' => 'podcast-analytics-players', 'filter' => 'permission:podcasts-view,podcast-view', @@ -227,41 +243,53 @@ $routes->group( // Podcast episodes $routes->group('episodes', function ($routes): void { - $routes->get('/', 'Episode::list/$1', [ + $routes->get('/', 'EpisodeController::list/$1', [ 'as' => 'episode-list', 'filter' => 'permission:episodes-list,podcast_episodes-list', ]); - $routes->get('new', 'Episode::create/$1', [ + $routes->get('new', 'EpisodeController::create/$1', [ 'as' => 'episode-create', 'filter' => 'permission:podcast_episodes-create', ]); - $routes->post('new', 'Episode::attemptCreate/$1', [ - 'filter' => 'permission:podcast_episodes-create', - ]); + $routes->post( + 'new', + 'EpisodeController::attemptCreate/$1', + [ + 'filter' => 'permission:podcast_episodes-create', + ], + ); // Episode $routes->group('(:num)', function ($routes): void { - $routes->get('/', 'Episode::view/$1/$2', [ + $routes->get('/', 'EpisodeController::view/$1/$2', [ 'as' => 'episode-view', 'filter' => 'permission:episodes-view,podcast_episodes-view', ]); - $routes->get('edit', 'Episode::edit/$1/$2', [ + $routes->get('edit', 'EpisodeController::edit/$1/$2', [ 'as' => 'episode-edit', 'filter' => 'permission:podcast_episodes-edit', ]); - $routes->post('edit', 'Episode::attemptEdit/$1/$2', [ - 'filter' => 'permission:podcast_episodes-edit', - ]); - $routes->get('publish', 'Episode::publish/$1/$2', [ - 'as' => 'episode-publish', - 'filter' => - 'permission:podcast-manage_publications', - ]); + $routes->post( + 'edit', + 'EpisodeController::attemptEdit/$1/$2', + [ + 'filter' => 'permission:podcast_episodes-edit', + ], + ); + $routes->get( + 'publish', + 'EpisodeController::publish/$1/$2', + [ + 'as' => 'episode-publish', + 'filter' => + 'permission:podcast-manage_publications', + ], + ); $routes->post( 'publish', - 'Episode::attemptPublish/$1/$2', + 'EpisodeController::attemptPublish/$1/$2', [ 'filter' => 'permission:podcast-manage_publications', @@ -269,7 +297,7 @@ $routes->group( ); $routes->get( 'publish-edit', - 'Episode::publishEdit/$1/$2', + 'EpisodeController::publishEdit/$1/$2', [ 'as' => 'episode-publish_edit', 'filter' => @@ -278,32 +306,41 @@ $routes->group( ); $routes->post( 'publish-edit', - 'Episode::attemptPublishEdit/$1/$2', + 'EpisodeController::attemptPublishEdit/$1/$2', [ 'filter' => 'permission:podcast-manage_publications', ], ); - $routes->get('unpublish', 'Episode::unpublish/$1/$2', [ - 'as' => 'episode-unpublish', - 'filter' => - 'permission:podcast-manage_publications', - ]); + $routes->get( + 'unpublish', + 'EpisodeController::unpublish/$1/$2', + [ + 'as' => 'episode-unpublish', + 'filter' => + 'permission:podcast-manage_publications', + ], + ); $routes->post( 'unpublish', - 'Episode::attemptUnpublish/$1/$2', + 'EpisodeController::attemptUnpublish/$1/$2', [ 'filter' => 'permission:podcast-manage_publications', ], ); - $routes->get('delete', 'Episode::delete/$1/$2', [ - 'as' => 'episode-delete', - 'filter' => 'permission:podcast_episodes-delete', - ]); + $routes->get( + 'delete', + 'EpisodeController::delete/$1/$2', + [ + 'as' => 'episode-delete', + 'filter' => + 'permission:podcast_episodes-delete', + ], + ); $routes->get( 'transcript-delete', - 'Episode::transcriptDelete/$1/$2', + 'EpisodeController::transcriptDelete/$1/$2', [ 'as' => 'transcript-delete', 'filter' => 'permission:podcast_episodes-edit', @@ -311,7 +348,7 @@ $routes->group( ); $routes->get( 'chapters-delete', - 'Episode::chaptersDelete/$1/$2', + 'EpisodeController::chaptersDelete/$1/$2', [ 'as' => 'chapters-delete', 'filter' => 'permission:podcast_episodes-edit', @@ -319,7 +356,7 @@ $routes->group( ); $routes->get( 'soundbites', - 'Episode::soundbitesEdit/$1/$2', + 'EpisodeController::soundbitesEdit/$1/$2', [ 'as' => 'soundbites-edit', 'filter' => 'permission:podcast_episodes-edit', @@ -327,14 +364,14 @@ $routes->group( ); $routes->post( 'soundbites', - 'Episode::soundbitesAttemptEdit/$1/$2', + 'EpisodeController::soundbitesAttemptEdit/$1/$2', [ 'filter' => 'permission:podcast_episodes-edit', ], ); $routes->get( 'soundbites/(:num)/delete', - 'Episode::soundbiteDelete/$1/$2/$3', + 'EpisodeController::soundbiteDelete/$1/$2/$3', [ 'as' => 'soundbite-delete', 'filter' => 'permission:podcast_episodes-edit', @@ -342,7 +379,7 @@ $routes->group( ); $routes->get( 'embeddable-player', - 'Episode::embeddablePlayer/$1/$2', + 'EpisodeController::embeddablePlayer/$1/$2', [ 'as' => 'embeddable-player-add', 'filter' => 'permission:podcast_episodes-edit', @@ -350,13 +387,13 @@ $routes->group( ); $routes->group('persons', function ($routes): void { - $routes->get('/', 'EpisodePerson/$1/$2', [ + $routes->get('/', 'EpisodePersonController/$1/$2', [ 'as' => 'episode-person-manage', 'filter' => 'permission:podcast_episodes-edit', ]); $routes->post( '/', - 'EpisodePerson::attemptAdd/$1/$2', + 'EpisodePersonController::attemptAdd/$1/$2', [ 'filter' => 'permission:podcast_episodes-edit', @@ -364,7 +401,7 @@ $routes->group( ); $routes->get( '(:num)/remove', - 'EpisodePerson::remove/$1/$2/$3', + 'EpisodePersonController::remove/$1/$2/$3', [ 'as' => 'episode-person-remove', 'filter' => @@ -377,51 +414,64 @@ $routes->group( // Podcast contributors $routes->group('contributors', function ($routes): void { - $routes->get('/', 'Contributor::list/$1', [ + $routes->get('/', 'ContributorController::list/$1', [ 'as' => 'contributor-list', 'filter' => 'permission:podcasts-view,podcast-manage_contributors', ]); - $routes->get('add', 'Contributor::add/$1', [ + $routes->get('add', 'ContributorController::add/$1', [ 'as' => 'contributor-add', 'filter' => 'permission:podcast-manage_contributors', ]); - $routes->post('add', 'Contributor::attemptAdd/$1', [ - 'filter' => 'permission:podcast-manage_contributors', - ]); + $routes->post( + 'add', + 'ContributorController::attemptAdd/$1', + [ + 'filter' => + 'permission:podcast-manage_contributors', + ], + ); // Contributor $routes->group('(:num)', function ($routes): void { - $routes->get('/', 'Contributor::view/$1/$2', [ + $routes->get('/', 'ContributorController::view/$1/$2', [ 'as' => 'contributor-view', 'filter' => 'permission:podcast-manage_contributors', ]); - $routes->get('edit', 'Contributor::edit/$1/$2', [ - 'as' => 'contributor-edit', - 'filter' => - 'permission:podcast-manage_contributors', - ]); + $routes->get( + 'edit', + 'ContributorController::edit/$1/$2', + [ + 'as' => 'contributor-edit', + 'filter' => + 'permission:podcast-manage_contributors', + ], + ); $routes->post( 'edit', - 'Contributor::attemptEdit/$1/$2', + 'ContributorController::attemptEdit/$1/$2', [ 'filter' => 'permission:podcast-manage_contributors', ], ); - $routes->get('remove', 'Contributor::remove/$1/$2', [ - 'as' => 'contributor-remove', - 'filter' => - 'permission:podcast-manage_contributors', - ]); + $routes->get( + 'remove', + 'ContributorController::remove/$1/$2', + [ + 'as' => 'contributor-remove', + 'filter' => + 'permission:podcast-manage_contributors', + ], + ); }); }); $routes->group('platforms', function ($routes): void { $routes->get( '/', - 'PodcastPlatform::platforms/$1/podcasting', + 'PodcastPlatformController::platforms/$1/podcasting', [ 'as' => 'platforms-podcasting', 'filter' => 'permission:podcast-manage_platforms', @@ -429,7 +479,7 @@ $routes->group( ); $routes->get( 'social', - 'PodcastPlatform::platforms/$1/social', + 'PodcastPlatformController::platforms/$1/social', [ 'as' => 'platforms-social', 'filter' => 'permission:podcast-manage_platforms', @@ -437,7 +487,7 @@ $routes->group( ); $routes->get( 'funding', - 'PodcastPlatform::platforms/$1/funding', + 'PodcastPlatformController::platforms/$1/funding', [ 'as' => 'platforms-funding', 'filter' => 'permission:podcast-manage_platforms', @@ -445,7 +495,7 @@ $routes->group( ); $routes->post( 'save/(:platformType)', - 'PodcastPlatform::attemptPlatformsUpdate/$1/$2', + 'PodcastPlatformController::attemptPlatformsUpdate/$1/$2', [ 'as' => 'platforms-save', 'filter' => 'permission:podcast-manage_platforms', @@ -453,7 +503,7 @@ $routes->group( ); $routes->get( '(:slug)/podcast-platform-remove', - 'PodcastPlatform::removePodcastPlatform/$1/$2', + 'PodcastPlatformController::removePodcastPlatform/$1/$2', [ 'as' => 'podcast-platform-remove', 'filter' => 'permission:podcast-manage_platforms', @@ -465,41 +515,51 @@ $routes->group( // Instance wide Fediverse config $routes->group('fediverse', function ($routes): void { - $routes->get('/', 'Fediverse::dashboard', [ + $routes->get('/', 'FediverseController::dashboard', [ 'as' => 'fediverse-dashboard', ]); - $routes->get('blocked-actors', 'Fediverse::blockedActors', [ - 'as' => 'fediverse-blocked-actors', - 'filter' => 'permission:fediverse-block_actors', - ]); - $routes->get('blocked-domains', 'Fediverse::blockedDomains', [ - 'as' => 'fediverse-blocked-domains', - 'filter' => 'permission:fediverse-block_domains', - ]); + $routes->get( + 'blocked-actors', + 'FediverseController::blockedActors', + [ + 'as' => 'fediverse-blocked-actors', + 'filter' => 'permission:fediverse-block_actors', + ], + ); + $routes->get( + 'blocked-domains', + 'FediverseController::blockedDomains', + [ + 'as' => 'fediverse-blocked-domains', + 'filter' => 'permission:fediverse-block_domains', + ], + ); }); // Pages $routes->group('pages', function ($routes): void { - $routes->get('/', 'Page::list', ['as' => 'page-list']); - $routes->get('new', 'Page::create', [ + $routes->get('/', 'PageController::list', ['as' => 'page-list']); + $routes->get('new', 'PageController::create', [ 'as' => 'page-create', 'filter' => 'permission:pages-manage', ]); - $routes->post('new', 'Page::attemptCreate', [ + $routes->post('new', 'PageController::attemptCreate', [ 'filter' => 'permission:pages-manage', ]); $routes->group('(:num)', function ($routes): void { - $routes->get('/', 'Page::view/$1', ['as' => 'page-view']); - $routes->get('edit', 'Page::edit/$1', [ + $routes->get('/', 'PageController::view/$1', [ + 'as' => 'page-view', + ]); + $routes->get('edit', 'PageController::edit/$1', [ 'as' => 'page-edit', 'filter' => 'permission:pages-manage', ]); - $routes->post('edit', 'Page::attemptEdit/$1', [ + $routes->post('edit', 'PageController::attemptEdit/$1', [ 'filter' => 'permission:pages-manage', ]); - $routes->get('delete', 'Page::delete/$1', [ + $routes->get('delete', 'PageController::delete/$1', [ 'as' => 'page-delete', 'filter' => 'permission:pages-manage', ]); @@ -508,44 +568,48 @@ $routes->group( // Users $routes->group('users', function ($routes): void { - $routes->get('/', 'User::list', [ + $routes->get('/', 'UserController::list', [ 'as' => 'user-list', 'filter' => 'permission:users-list', ]); - $routes->get('new', 'User::create', [ + $routes->get('new', 'UserController::create', [ 'as' => 'user-create', 'filter' => 'permission:users-create', ]); - $routes->post('new', 'User::attemptCreate', [ + $routes->post('new', 'UserController::attemptCreate', [ 'filter' => 'permission:users-create', ]); // User $routes->group('(:num)', function ($routes): void { - $routes->get('/', 'User::view/$1', [ + $routes->get('/', 'UserController::view/$1', [ 'as' => 'user-view', 'filter' => 'permission:users-view', ]); - $routes->get('edit', 'User::edit/$1', [ + $routes->get('edit', 'UserController::edit/$1', [ 'as' => 'user-edit', 'filter' => 'permission:users-manage_authorizations', ]); - $routes->post('edit', 'User::attemptEdit/$1', [ + $routes->post('edit', 'UserController::attemptEdit/$1', [ 'filter' => 'permission:users-manage_authorizations', ]); - $routes->get('ban', 'User::ban/$1', [ + $routes->get('ban', 'UserController::ban/$1', [ 'as' => 'user-ban', 'filter' => 'permission:users-manage_bans', ]); - $routes->get('unban', 'User::unBan/$1', [ + $routes->get('unban', 'UserController::unBan/$1', [ 'as' => 'user-unban', 'filter' => 'permission:users-manage_bans', ]); - $routes->get('force-pass-reset', 'User::forcePassReset/$1', [ - 'as' => 'user-force_pass_reset', - 'filter' => 'permission:users-force_pass_reset', - ]); - $routes->get('delete', 'User::delete/$1', [ + $routes->get( + 'force-pass-reset', + 'UserController::forcePassReset/$1', + [ + 'as' => 'user-force_pass_reset', + 'filter' => 'permission:users-force_pass_reset', + ], + ); + $routes->get('delete', 'UserController::delete/$1', [ 'as' => 'user-delete', 'filter' => 'permission:users-delete', ]); @@ -554,13 +618,20 @@ $routes->group( // My account $routes->group('my-account', function ($routes): void { - $routes->get('/', 'MyAccount', [ + $routes->get('/', 'MyAccountController', [ 'as' => 'my-account', ]); - $routes->get('change-password', 'MyAccount::changePassword/$1', [ - 'as' => 'change-password', - ]); - $routes->post('change-password', 'MyAccount::attemptChange/$1'); + $routes->get( + 'change-password', + 'MyAccountController::changePassword/$1', + [ + 'as' => 'change-password', + ], + ); + $routes->post( + 'change-password', + 'MyAccountController::attemptChange/$1', + ); }); }, ); @@ -570,42 +641,48 @@ $routes->group( */ $routes->group(config('App')->authGateway, function ($routes): void { // Login/out - $routes->get('login', 'Auth::login', ['as' => 'login']); - $routes->post('login', 'Auth::attemptLogin'); - $routes->get('logout', 'Auth::logout', ['as' => 'logout']); + $routes->get('login', 'AuthController::login', ['as' => 'login']); + $routes->post('login', 'AuthController::attemptLogin'); + $routes->get('logout', 'AuthController::logout', [ + 'as' => 'logout', + ]); // Registration - $routes->get('register', 'Auth::register', [ + $routes->get('register', 'AuthController::register', [ 'as' => 'register', ]); - $routes->post('register', 'Auth::attemptRegister'); + $routes->post('register', 'AuthController::attemptRegister'); // Activation - $routes->get('activate-account', 'Auth::activateAccount', [ + $routes->get('activate-account', 'AuthController::activateAccount', [ 'as' => 'activate-account', ]); - $routes->get('resend-activate-account', 'Auth::resendActivateAccount', [ - 'as' => 'resend-activate-account', - ]); + $routes->get( + 'resend-activate-account', + 'AuthController::resendActivateAccount', + [ + 'as' => 'resend-activate-account', + ], + ); // Forgot/Resets - $routes->get('forgot', 'Auth::forgotPassword', [ + $routes->get('forgot', 'AuthController::forgotPassword', [ 'as' => 'forgot', ]); - $routes->post('forgot', 'Auth::attemptForgot'); - $routes->get('reset-password', 'Auth::resetPassword', [ + $routes->post('forgot', 'AuthController::attemptForgot'); + $routes->get('reset-password', 'AuthController::resetPassword', [ 'as' => 'reset-password', ]); - $routes->post('reset-password', 'Auth::attemptReset'); + $routes->post('reset-password', 'AuthController::attemptReset'); }); // Podcast's Public routes $routes->group('@(:podcastName)', function ($routes): void { - $routes->get('/', 'Podcast::activity/$1', [ + $routes->get('/', 'PodcastController::activity/$1', [ 'as' => 'podcast-activity', ]); // override default ActivityPub Library's actor route - $routes->get('/', 'Podcast::activity/$1', [ + $routes->get('/', 'PodcastController::activity/$1', [ 'as' => 'actor', 'alternate-content' => [ 'application/activity+json' => [ @@ -618,26 +695,26 @@ $routes->group('@(:podcastName)', function ($routes): void { ], ], ]); - $routes->get('episodes', 'Podcast::episodes/$1', [ + $routes->get('episodes', 'PodcastController::episodes/$1', [ 'as' => 'podcast-episodes', ]); $routes->group('episodes/(:slug)', function ($routes): void { - $routes->get('/', 'Episode/$1/$2', [ + $routes->get('/', 'EpisodeController/$1/$2', [ 'as' => 'episode', ]); - $routes->get('oembed.json', 'Episode::oembedJSON/$1/$2', [ + $routes->get('oembed.json', 'EpisodeController::oembedJSON/$1/$2', [ 'as' => 'episode-oembed-json', ]); - $routes->get('oembed.xml', 'Episode::oembedXML/$1/$2', [ + $routes->get('oembed.xml', 'EpisodeController::oembedXML/$1/$2', [ 'as' => 'episode-oembed-xml', ]); $routes->group('embeddable-player', function ($routes): void { - $routes->get('/', 'Episode::embeddablePlayer/$1/$2', [ + $routes->get('/', 'EpisodeController::embeddablePlayer/$1/$2', [ 'as' => 'embeddable-player', ]); $routes->get( '(:embeddablePlayerTheme)', - 'Episode::embeddablePlayer/$1/$2/$3', + 'EpisodeController::embeddablePlayer/$1/$2/$3', [ 'as' => 'embeddable-player-theme', ], @@ -645,16 +722,16 @@ $routes->group('@(:podcastName)', function ($routes): void { }); }); - $routes->head('feed.xml', 'Feed/$1', ['as' => 'podcast_feed']); - $routes->get('feed.xml', 'Feed/$1', ['as' => 'podcast_feed']); + $routes->head('feed.xml', 'FeedController/$1', ['as' => 'podcast_feed']); + $routes->get('feed.xml', 'FeedController/$1', ['as' => 'podcast_feed']); }); // Other pages -$routes->get('/credits', 'Page::credits', ['as' => 'credits']); +$routes->get('/credits', 'PageController::credits', ['as' => 'credits']); $routes->get('/pages/(:slug)', 'Page/$1', ['as' => 'page']); // interacting as an actor -$routes->post('interact-as-actor', 'Auth::attemptInteractAsActor', [ +$routes->post('interact-as-actor', 'AuthController::attemptInteractAsActor', [ 'as' => 'interact-as-actor', ]); @@ -662,13 +739,13 @@ $routes->post('interact-as-actor', 'Auth::attemptInteractAsActor', [ * Overwriting ActivityPub routes file */ $routes->group('@(:podcastName)', function ($routes): void { - $routes->post('notes/new', 'Note::attemptCreate/$1', [ + $routes->post('notes/new', 'NoteController::attemptCreate/$1', [ 'as' => 'note-attempt-create', 'filter' => 'permission:podcast-manage_publications', ]); // Note $routes->group('notes/(:uuid)', function ($routes): void { - $routes->get('/', 'Note/$1/$2', [ + $routes->get('/', 'NoteController::view/$1/$2', [ 'as' => 'note', 'alternate-content' => [ 'application/activity+json' => [ @@ -681,7 +758,7 @@ $routes->group('@(:podcastName)', function ($routes): void { ], ], ]); - $routes->get('replies', 'Note/$1/$2', [ + $routes->get('replies', 'NoteController/$1/$2', [ 'as' => 'note-replies', 'alternate-content' => [ 'application/activity+json' => [ @@ -696,33 +773,45 @@ $routes->group('@(:podcastName)', function ($routes): void { ]); // Actions - $routes->post('action', 'Note::attemptAction/$1/$2', [ + $routes->post('action', 'NoteController::attemptAction/$1/$2', [ 'as' => 'note-attempt-action', 'filter' => 'permission:podcast-interact_as', ]); - $routes->post('block-actor', 'Note::attemptBlockActor/$1/$2', [ - 'as' => 'note-attempt-block-actor', - 'filter' => 'permission:fediverse-block_actors', - ]); - $routes->post('block-domain', 'Note::attemptBlockDomain/$1/$2', [ - 'as' => 'note-attempt-block-domain', - 'filter' => 'permission:fediverse-block_domains', - ]); - $routes->post('delete', 'Note::attemptDelete/$1/$2', [ + $routes->post( + 'block-actor', + 'NoteController::attemptBlockActor/$1/$2', + [ + 'as' => 'note-attempt-block-actor', + 'filter' => 'permission:fediverse-block_actors', + ], + ); + $routes->post( + 'block-domain', + 'NoteController::attemptBlockDomain/$1/$2', + [ + 'as' => 'note-attempt-block-domain', + 'filter' => 'permission:fediverse-block_domains', + ], + ); + $routes->post('delete', 'NoteController::attemptDelete/$1/$2', [ 'as' => 'note-attempt-delete', 'filter' => 'permission:podcast-manage_publications', ]); - $routes->get('remote/(:noteAction)', 'Note::remoteAction/$1/$2/$3', [ - 'as' => 'note-remote-action', - ]); + $routes->get( + 'remote/(:noteAction)', + 'NoteController::remoteAction/$1/$2/$3', + [ + 'as' => 'note-remote-action', + ], + ); }); - $routes->get('follow', 'Actor::follow/$1', [ + $routes->get('follow', 'ActorController::follow/$1', [ 'as' => 'follow', ]); - $routes->get('outbox', 'Actor::outbox/$1', [ + $routes->get('outbox', 'ActorController::outbox/$1', [ 'as' => 'outbox', 'filter' => 'activity-pub:verify-activitystream', ]); diff --git a/app/Config/Services.php b/app/Config/Services.php index d6c711bd..7ea9a3dd 100644 --- a/app/Config/Services.php +++ b/app/Config/Services.php @@ -101,11 +101,11 @@ class Services extends BaseService $instance = new $class($config); - if (empty($userModel)) { + if ($userModel === null) { $userModel = new UserModel(); } - if (empty($loginModel)) { + if ($loginModel === null) { $loginModel = new LoginModel(); } diff --git a/app/Controllers/Actor.php b/app/Controllers/ActorController.php similarity index 87% rename from app/Controllers/Actor.php rename to app/Controllers/ActorController.php index 16bd68ca..cbc27c1c 100644 --- a/app/Controllers/Actor.php +++ b/app/Controllers/ActorController.php @@ -8,9 +8,10 @@ namespace App\Controllers; +use ActivityPub\Controllers\ActorController as ActivityPubActorController; use Analytics\AnalyticsTrait; -class Actor extends \ActivityPub\Controllers\ActorController +class ActorController extends ActivityPubActorController { use AnalyticsTrait; diff --git a/app/Controllers/Admin/Contributor.php b/app/Controllers/Admin/ContributorController.php similarity index 97% rename from app/Controllers/Admin/Contributor.php rename to app/Controllers/Admin/ContributorController.php index 9ae1e21b..2726abb1 100644 --- a/app/Controllers/Admin/Contributor.php +++ b/app/Controllers/Admin/ContributorController.php @@ -16,7 +16,7 @@ use App\Authorization\GroupModel; use App\Models\PodcastModel; use App\Models\UserModel; -class Contributor extends BaseController +class ContributorController extends BaseController { /** * @var Podcast @@ -172,7 +172,7 @@ class Contributor extends BaseController public function remove() { - if ($this->podcast->created_by == $this->user->id) { + if ($this->podcast->created_by === $this->user->id) { return redirect() ->back() ->with('errors', [ diff --git a/app/Controllers/Admin/Episode.php b/app/Controllers/Admin/EpisodeController.php similarity index 97% rename from app/Controllers/Admin/Episode.php rename to app/Controllers/Admin/EpisodeController.php index bbd3318d..ed81106e 100644 --- a/app/Controllers/Admin/Episode.php +++ b/app/Controllers/Admin/EpisodeController.php @@ -8,15 +8,16 @@ namespace App\Controllers\Admin; -use App\Entities\Episode as EpisodeEntity; +use App\Entities\Episode; use App\Entities\Note; +use App\Entities\Podcast; use App\Models\EpisodeModel; use App\Models\NoteModel; use App\Models\PodcastModel; use App\Models\SoundbiteModel; use CodeIgniter\I18n\Time; -class Episode extends BaseController +class EpisodeController extends BaseController { /** * @var Podcast @@ -28,12 +29,7 @@ class Episode extends BaseController */ protected $episode; - /** - * @var Soundbite|null - */ - protected $soundbites; - - public function _remap($method, ...$params) + public function _remap(string $method, ...$params) { if ( !($this->podcast = (new PodcastModel())->getPodcastById($params[0])) @@ -124,7 +120,7 @@ class Episode extends BaseController ->with('errors', $this->validator->getErrors()); } - $newEpisode = new EpisodeEntity([ + $newEpisode = new Episode([ 'podcast_id' => $this->podcast->id, 'title' => $this->request->getPost('title'), 'slug' => $this->request->getPost('slug'), @@ -148,8 +144,8 @@ class Episode extends BaseController 'type' => $this->request->getPost('type'), 'is_blocked' => $this->request->getPost('block') == 'yes', 'custom_rss_string' => $this->request->getPost('custom_rss'), - 'created_by' => user()->id, - 'updated_by' => user()->id, + 'created_by' => user_id(), + 'updated_by' => user_id(), 'published_at' => null, ]); @@ -265,14 +261,15 @@ class Episode extends BaseController 'custom_rss', ); - $this->episode->updated_by = user()->id; + $this->episode->updated_by = user_id(); $audioFile = $this->request->getFile('audio_file'); - if ($audioFile) { + if ($audioFile !== null && $audioFile->isValid()) { $this->episode->audio_file = $audioFile; } + $image = $this->request->getFile('image'); - if ($image) { + if ($image !== null && $image->isValid()) { $this->episode->image = $image; } @@ -291,7 +288,7 @@ class Episode extends BaseController ) { if ( ($transcriptFile = $this->episode->transcript_file) && - !empty($transcriptFile) + $transcriptFile !== null ) { unlink($transcriptFile); $this->episode->transcript_file_path = null; @@ -315,7 +312,7 @@ class Episode extends BaseController ) { if ( ($chaptersFile = $this->episode->chapters_file) && - !empty($chaptersFile) + $chaptersFile !== null ) { unlink($chaptersFile); $this->episode->chapters_file_path = null; @@ -700,8 +697,8 @@ class Episode extends BaseController foreach ($soundbites_array as $soundbite_id => $soundbite) { if ( - !empty($soundbite['start_time']) && - !empty($soundbite['duration']) + $soundbite['start_time'] !== null && + $soundbite['duration'] !== null ) { $data = [ 'podcast_id' => $this->podcast->id, @@ -709,10 +706,10 @@ class Episode extends BaseController 'start_time' => $soundbite['start_time'], 'duration' => $soundbite['duration'], 'label' => $soundbite['label'], - 'updated_by' => user()->id, + 'updated_by' => user_id(), ]; if ($soundbite_id == 0) { - $data += ['created_by' => user()->id]; + $data += ['created_by' => user_id()]; } else { $data += ['id' => $soundbite_id]; } diff --git a/app/Controllers/Admin/EpisodePerson.php b/app/Controllers/Admin/EpisodePersonController.php similarity index 98% rename from app/Controllers/Admin/EpisodePerson.php rename to app/Controllers/Admin/EpisodePersonController.php index 420efb8f..7c882513 100644 --- a/app/Controllers/Admin/EpisodePerson.php +++ b/app/Controllers/Admin/EpisodePersonController.php @@ -16,7 +16,7 @@ use App\Models\PodcastModel; use App\Models\EpisodeModel; use App\Models\PersonModel; -class EpisodePerson extends BaseController +class EpisodePersonController extends BaseController { /** * @var Podcast diff --git a/app/Controllers/Admin/Fediverse.php b/app/Controllers/Admin/FediverseController.php similarity index 94% rename from app/Controllers/Admin/Fediverse.php rename to app/Controllers/Admin/FediverseController.php index 75084575..fd54d103 100644 --- a/app/Controllers/Admin/Fediverse.php +++ b/app/Controllers/Admin/FediverseController.php @@ -8,7 +8,7 @@ namespace App\Controllers\Admin; -class Fediverse extends BaseController +class FediverseController extends BaseController { public function dashboard() { diff --git a/app/Controllers/Admin/Home.php b/app/Controllers/Admin/HomeController.php similarity index 87% rename from app/Controllers/Admin/Home.php rename to app/Controllers/Admin/HomeController.php index 42e633db..d2b973f9 100644 --- a/app/Controllers/Admin/Home.php +++ b/app/Controllers/Admin/HomeController.php @@ -8,7 +8,7 @@ namespace App\Controllers\Admin; -class Home extends BaseController +class HomeController extends BaseController { public function index() { diff --git a/app/Controllers/Admin/MyAccount.php b/app/Controllers/Admin/MyAccountController.php similarity index 94% rename from app/Controllers/Admin/MyAccount.php rename to app/Controllers/Admin/MyAccountController.php index 50f2fb45..e482e214 100644 --- a/app/Controllers/Admin/MyAccount.php +++ b/app/Controllers/Admin/MyAccountController.php @@ -11,7 +11,7 @@ namespace App\Controllers\Admin; use Config\Services; use App\Models\UserModel; -class MyAccount extends BaseController +class MyAccountController extends BaseController { public function index() { @@ -58,7 +58,7 @@ class MyAccount extends BaseController user()->password = $this->request->getPost('new_password'); - if (!$userModel->update(user()->id, user())) { + if (!$userModel->update(user_id(), user())) { return redirect() ->back() ->withInput() diff --git a/app/Controllers/Admin/Page.php b/app/Controllers/Admin/PageController.php similarity index 91% rename from app/Controllers/Admin/Page.php rename to app/Controllers/Admin/PageController.php index d62855d5..520ce08d 100644 --- a/app/Controllers/Admin/Page.php +++ b/app/Controllers/Admin/PageController.php @@ -8,11 +8,11 @@ namespace App\Controllers\Admin; -use App\Entities\Page as EntitiesPage; +use App\Entities\Page; use CodeIgniter\Exceptions\PageNotFoundException; use App\Models\PageModel; -class Page extends BaseController +class PageController extends BaseController { /** * @var Page|null @@ -55,10 +55,10 @@ class Page extends BaseController function attemptCreate() { - $page = new EntitiesPage([ + $page = new Page([ 'title' => $this->request->getPost('title'), 'slug' => $this->request->getPost('slug'), - 'content' => $this->request->getPost('content'), + 'content_markdown' => $this->request->getPost('content'), ]); $pageModel = new PageModel(); @@ -92,7 +92,7 @@ class Page extends BaseController { $this->page->title = $this->request->getPost('title'); $this->page->slug = $this->request->getPost('slug'); - $this->page->content = $this->request->getPost('content'); + $this->page->content_markdown = $this->request->getPost('content'); $pageModel = new PageModel(); diff --git a/app/Controllers/Admin/Person.php b/app/Controllers/Admin/PersonController.php similarity index 93% rename from app/Controllers/Admin/Person.php rename to app/Controllers/Admin/PersonController.php index 8a2f33b5..513d521d 100644 --- a/app/Controllers/Admin/Person.php +++ b/app/Controllers/Admin/PersonController.php @@ -8,11 +8,11 @@ namespace App\Controllers\Admin; -use App\Entities\Person as EntitiesPerson; +use App\Entities\Person; use CodeIgniter\Exceptions\PageNotFoundException; use App\Models\PersonModel; -class Person extends BaseController +class PersonController extends BaseController { /** * @var Person|null @@ -68,13 +68,13 @@ class Person extends BaseController ->with('errors', $this->validator->getErrors()); } - $person = new EntitiesPerson([ + $person = new Person([ 'full_name' => $this->request->getPost('full_name'), 'unique_name' => $this->request->getPost('unique_name'), 'information_url' => $this->request->getPost('information_url'), 'image' => $this->request->getFile('image'), - 'created_by' => user()->id, - 'updated_by' => user()->id, + 'created_by' => user_id(), + 'updated_by' => user_id(), ]); $personModel = new PersonModel(); @@ -125,7 +125,7 @@ class Person extends BaseController $this->person->image = $image; } - $this->person->updated_by = user()->id; + $this->person->updated_by = user_id(); $personModel = new PersonModel(); if (!$personModel->update($this->person->id, $this->person)) { diff --git a/app/Controllers/Admin/Podcast.php b/app/Controllers/Admin/PodcastController.php similarity index 86% rename from app/Controllers/Admin/Podcast.php rename to app/Controllers/Admin/PodcastController.php index 7919ae4c..2fdcdc1b 100644 --- a/app/Controllers/Admin/Podcast.php +++ b/app/Controllers/Admin/PodcastController.php @@ -8,23 +8,30 @@ namespace App\Controllers\Admin; -use App\Entities\Podcast as EntitiesPodcast; +use App\Entities\Image; +use App\Entities\Podcast; use CodeIgniter\Exceptions\PageNotFoundException; use Config\Database; use App\Models\CategoryModel; use App\Models\LanguageModel; use App\Models\PodcastModel; use App\Models\EpisodeModel; +use CodeIgniter\HTTP\RedirectResponse; use Config\Services; -class Podcast extends BaseController +class PodcastController extends BaseController { /** - * @var Podcast|null + * @var Podcast */ protected $podcast; - public function _remap($method, ...$params) + /** + * + * @param array $params + * @return static|string + */ + public function _remap(string $method, ...$params) { if (count($params) === 0) { return $this->$method(); @@ -37,11 +44,13 @@ class Podcast extends BaseController throw PageNotFoundException::forPageNotFound(); } - public function list() + public function list(): string { if (!has_permission('podcasts-list')) { $data = [ - 'podcasts' => (new PodcastModel())->getUserPodcasts(user()->id), + 'podcasts' => (new PodcastModel())->getUserPodcasts( + (int) user_id(), + ), ]; } else { $data = ['podcasts' => (new PodcastModel())->findAll()]; @@ -50,7 +59,7 @@ class Podcast extends BaseController return view('admin/podcast/list', $data); } - public function view() + public function view(): string { $data = ['podcast' => $this->podcast]; @@ -58,7 +67,7 @@ class Podcast extends BaseController return view('admin/podcast/view', $data); } - public function viewAnalytics() + public function viewAnalytics(): string { $data = ['podcast' => $this->podcast]; @@ -66,7 +75,7 @@ class Podcast extends BaseController return view('admin/podcast/analytics/index', $data); } - public function viewAnalyticsWebpages() + public function viewAnalyticsWebpages(): string { $data = ['podcast' => $this->podcast]; @@ -74,7 +83,7 @@ class Podcast extends BaseController return view('admin/podcast/analytics/webpages', $data); } - public function viewAnalyticsLocations() + public function viewAnalyticsLocations(): string { $data = ['podcast' => $this->podcast]; @@ -82,7 +91,7 @@ class Podcast extends BaseController return view('admin/podcast/analytics/locations', $data); } - public function viewAnalyticsUniqueListeners() + public function viewAnalyticsUniqueListeners(): string { $data = ['podcast' => $this->podcast]; @@ -90,7 +99,7 @@ class Podcast extends BaseController return view('admin/podcast/analytics/unique_listeners', $data); } - public function viewAnalyticsListeningTime() + public function viewAnalyticsListeningTime(): string { $data = ['podcast' => $this->podcast]; @@ -98,7 +107,7 @@ class Podcast extends BaseController return view('admin/podcast/analytics/listening_time', $data); } - public function viewAnalyticsTimePeriods() + public function viewAnalyticsTimePeriods(): string { $data = ['podcast' => $this->podcast]; @@ -106,7 +115,7 @@ class Podcast extends BaseController return view('admin/podcast/analytics/time_periods', $data); } - public function viewAnalyticsPlayers() + public function viewAnalyticsPlayers(): string { $data = ['podcast' => $this->podcast]; @@ -114,7 +123,7 @@ class Podcast extends BaseController return view('admin/podcast/analytics/players', $data); } - public function create() + public function create(): string { helper(['form', 'misc']); @@ -132,7 +141,7 @@ class Podcast extends BaseController return view('admin/podcast/create', $data); } - public function attemptCreate() + public function attemptCreate(): RedirectResponse { $rules = [ 'image' => @@ -146,11 +155,11 @@ class Podcast extends BaseController ->with('errors', $this->validator->getErrors()); } - $podcast = new EntitiesPodcast([ + $podcast = new Podcast([ 'title' => $this->request->getPost('title'), 'name' => $this->request->getPost('name'), 'description_markdown' => $this->request->getPost('description'), - 'image' => $this->request->getFile('image'), + 'image' => new Image($this->request->getFile('image')), 'language_code' => $this->request->getPost('language'), 'category_id' => $this->request->getPost('category'), 'parental_advisory' => @@ -171,8 +180,8 @@ class Podcast extends BaseController 'is_blocked' => $this->request->getPost('block') === 'yes', 'is_completed' => $this->request->getPost('complete') === 'yes', 'is_locked' => $this->request->getPost('lock') === 'yes', - 'created_by' => user()->id, - 'updated_by' => user()->id, + 'created_by' => user_id(), + 'updated_by' => user_id(), ]); $podcastModel = new PodcastModel(); @@ -192,14 +201,14 @@ class Podcast extends BaseController $podcastAdminGroup = $authorize->group('podcast_admin'); $podcastModel->addPodcastContributor( - user()->id, + user_id(), $newPodcastId, $podcastAdminGroup->id, ); // set Podcast categories (new CategoryModel())->setPodcastCategories( - $newPodcastId, + (int) $newPodcastId, $this->request->getPost('other_categories'), ); @@ -212,7 +221,7 @@ class Podcast extends BaseController return redirect()->route('podcast-view', [$newPodcastId]); } - public function edit() + public function edit(): string { helper('form'); @@ -229,7 +238,7 @@ class Podcast extends BaseController return view('admin/podcast/edit', $data); } - public function attemptEdit() + public function attemptEdit(): RedirectResponse { $rules = [ 'image' => @@ -249,8 +258,8 @@ class Podcast extends BaseController ); $image = $this->request->getFile('image'); - if ($image->isValid()) { - $this->podcast->image = $image; + if ($image !== null && $image->isValid()) { + $this->podcast->image = new Image($image); } $this->podcast->language_code = $this->request->getPost('language'); $this->podcast->category_id = $this->request->getPost('category'); @@ -281,7 +290,7 @@ class Podcast extends BaseController $this->podcast->is_completed = $this->request->getPost('complete') === 'yes'; $this->podcast->is_locked = $this->request->getPost('lock') === 'yes'; - $this->podcast->updated_by = user()->id; + $this->podcast->updated_by = (int) user_id(); $db = Database::connect(); $db->transStart(); @@ -306,7 +315,7 @@ class Podcast extends BaseController return redirect()->route('podcast-view', [$this->podcast->id]); } - public function latestEpisodes(int $limit, int $podcast_id) + public function latestEpisodes(int $limit, int $podcast_id): string { $episodes = (new EpisodeModel()) ->where('podcast_id', $podcast_id) @@ -316,7 +325,7 @@ class Podcast extends BaseController return view('admin/podcast/latest_episodes', ['episodes' => $episodes]); } - public function delete() + public function delete(): RedirectResponse { (new PodcastModel())->delete($this->podcast->id); diff --git a/app/Controllers/Admin/PodcastImport.php b/app/Controllers/Admin/PodcastImportController.php similarity index 77% rename from app/Controllers/Admin/PodcastImport.php rename to app/Controllers/Admin/PodcastImportController.php index 230e6db5..82356dae 100644 --- a/app/Controllers/Admin/PodcastImport.php +++ b/app/Controllers/Admin/PodcastImportController.php @@ -15,6 +15,7 @@ use Config\Database; use Podlibre\PodcastNamespace\ReversedTaxonomy; use App\Entities\PodcastPerson; use App\Entities\Episode; +use App\Entities\Image; use App\Models\CategoryModel; use App\Models\LanguageModel; use App\Models\PodcastModel; @@ -26,14 +27,14 @@ use App\Models\EpisodePersonModel; use Config\Services; use League\HTMLToMarkdown\HtmlConverter; -class PodcastImport extends BaseController +class PodcastImportController extends BaseController { /** * @var Podcast|null */ protected $podcast; - public function _remap($method, ...$params) + public function _remap(string $method, string ...$params) { if (count($params) === 0) { return $this->$method(); @@ -120,6 +121,19 @@ class PodcastImport extends BaseController $channelDescriptionHtml = (string) $feed->channel[0]->description; try { + if ( + $nsItunes->image !== null && + $nsItunes->image->attributes()['href'] !== null + ) { + $imageFile = download_file( + (string) $nsItunes->image->attributes()['href'], + ); + } else { + $imageFile = download_file( + (string) $feed->channel[0]->image->url, + ); + } + $podcast = new Podcast([ 'name' => $this->request->getPost('name'), 'imported_feed_url' => $this->request->getPost( @@ -133,50 +147,46 @@ class PodcastImport extends BaseController $channelDescriptionHtml, ), 'description_html' => $channelDescriptionHtml, - 'image' => - $nsItunes->image && !empty($nsItunes->image->attributes()) - ? download_file((string) $nsItunes->image->attributes()) - : ($feed->channel[0]->image && - !empty($feed->channel[0]->image->url) - ? download_file( - (string) $feed->channel[0]->image->url, - ) - : null), + 'image' => new Image($imageFile), 'language_code' => $this->request->getPost('language'), 'category_id' => $this->request->getPost('category'), - 'parental_advisory' => empty($nsItunes->explicit) - ? null - : (in_array($nsItunes->explicit, ['yes', 'true']) - ? 'explicit' - : (in_array($nsItunes->explicit, ['no', 'false']) - ? 'clean' - : null)), + 'parental_advisory' => + $nsItunes->explicit === null + ? null + : (in_array($nsItunes->explicit, ['yes', 'true']) + ? 'explicit' + : (in_array($nsItunes->explicit, ['no', 'false']) + ? 'clean' + : null)), 'owner_name' => (string) $nsItunes->owner->name, 'owner_email' => (string) $nsItunes->owner->email, 'publisher' => (string) $nsItunes->author, - 'type' => empty($nsItunes->type) ? 'episodic' : $nsItunes->type, + 'type' => + $nsItunes->type === null ? 'episodic' : $nsItunes->type, 'copyright' => (string) $feed->channel[0]->copyright, - 'is_blocked' => empty($nsItunes->block) - ? false - : $nsItunes->block === 'yes', - 'is_completed' => empty($nsItunes->complete) - ? false - : $nsItunes->complete === 'yes', + 'is_blocked' => + $nsItunes->block === null + ? false + : $nsItunes->block === 'yes', + 'is_completed' => + $nsItunes->complete === null + ? false + : $nsItunes->complete === 'yes', 'location_name' => $nsPodcast->location ? (string) $nsPodcast->location : null, 'location_geo' => !$nsPodcast->location || - empty($nsPodcast->location->attributes()['geo']) + $nsPodcast->location->attributes()['geo'] === null ? null : (string) $nsPodcast->location->attributes()['geo'], - 'location_osmid' => + 'location_osm_id' => !$nsPodcast->location || - empty($nsPodcast->location->attributes()['osm']) + $nsPodcast->location->attributes()['osm'] === null ? null : (string) $nsPodcast->location->attributes()['osm'], - 'created_by' => user()->id, - 'updated_by' => user()->id, + 'created_by' => user_id(), + 'updated_by' => user_id(), ]); } catch (ErrorException $ex) { return redirect() @@ -209,7 +219,7 @@ class PodcastImport extends BaseController $podcastAdminGroup = $authorize->group('podcast_admin'); $podcastModel->addPodcastContributor( - user()->id, + user_id(), $newPodcastId, $podcastAdminGroup->id, ); @@ -236,6 +246,7 @@ class PodcastImport extends BaseController } } } + if (count($podcastsPlatformsData) > 1) { $platformModel->createPodcastPlatforms( $newPodcastId, @@ -261,14 +272,15 @@ class PodcastImport extends BaseController ->with('errors', $personModel->errors()); } - $personGroup = empty($podcastPerson->attributes()['group']) - ? ['slug' => ''] - : ReversedTaxonomy::$taxonomy[ - (string) $podcastPerson->attributes()['group'] - ]; + $personGroup = + $podcastPerson->attributes()['group'] === null + ? ['slug' => ''] + : ReversedTaxonomy::$taxonomy[ + (string) $podcastPerson->attributes()['group'] + ]; $personRole = - empty($podcastPerson->attributes()['role']) || - empty($personGroup) + $podcastPerson->attributes()['role'] === null || + $personGroup === null ? ['slug' => ''] : $personGroup['roles'][ strval($podcastPerson->attributes()['role']) @@ -291,7 +303,7 @@ class PodcastImport extends BaseController $numberItems = $feed->channel[0]->item->count(); $lastItem = - !empty($this->request->getPost('max_episodes')) && + $this->request->getPost('max_episodes') !== null && $this->request->getPost('max_episodes') < $numberItems ? $this->request->getPost('max_episodes') : $numberItems; @@ -343,63 +355,71 @@ class PodcastImport extends BaseController $itemDescriptionHtml = $item->description; } + if ( + $nsItunes->image !== null && + $nsItunes->image->attributes()['href'] !== null + ) { + $episodeImage = new Image( + download_file( + (string) $nsItunes->image->attributes()['href'], + ), + ); + } else { + $episodeImage = null; + } + $newEpisode = new Episode([ 'podcast_id' => $newPodcastId, - 'guid' => empty($item->guid) ? null : $item->guid, + 'guid' => $item->guid ?? null, 'title' => $item->title, 'slug' => $slug, - 'audio_file' => download_file($item->enclosure->attributes()), + 'audio_file' => download_file( + $item->enclosure->attributes()['url'], + ), 'description_markdown' => $converter->convert( $itemDescriptionHtml, ), 'description_html' => $itemDescriptionHtml, - 'image' => - !$nsItunes->image || empty($nsItunes->image->attributes()) + 'image' => $episodeImage, + 'parental_advisory' => + $nsItunes->explicit === null ? null - : download_file( - (string) $nsItunes->image->attributes(), - ), - 'parental_advisory' => empty($nsItunes->explicit) - ? null - : (in_array($nsItunes->explicit, ['yes', 'true']) - ? 'explicit' - : (in_array($nsItunes->explicit, ['no', 'false']) - ? 'clean' - : null)), + : (in_array($nsItunes->explicit, ['yes', 'true']) + ? 'explicit' + : (in_array($nsItunes->explicit, ['no', 'false']) + ? 'clean' + : null)), 'number' => $this->request->getPost('force_renumber') === 'yes' ? $itemNumber - : (empty($nsItunes->episode) - ? null - : $nsItunes->episode), - 'season_number' => empty( - $this->request->getPost('season_number') - ) - ? (empty($nsItunes->season) - ? null - : $nsItunes->season) - : $this->request->getPost('season_number'), - 'type' => empty($nsItunes->episodeType) - ? 'full' - : $nsItunes->episodeType, - 'is_blocked' => empty($nsItunes->block) - ? false - : $nsItunes->block === 'yes', + : $nsItunes->episode, + 'season_number' => + $this->request->getPost('season_number') === null + ? $nsItunes->season + : $this->request->getPost('season_number'), + 'type' => + $nsItunes->episodeType === null + ? 'full' + : $nsItunes->episodeType, + 'is_blocked' => + $nsItunes->block === null + ? false + : $nsItunes->block === 'yes', 'location_name' => $nsPodcast->location ? $nsPodcast->location : null, 'location_geo' => !$nsPodcast->location || - empty($nsPodcast->location->attributes()['geo']) + $nsPodcast->location->attributes()['geo'] === null ? null : $nsPodcast->location->attributes()['geo'], - 'location_osmid' => + 'location_osm_id' => !$nsPodcast->location || - empty($nsPodcast->location->attributes()['osm']) + $nsPodcast->location->attributes()['osm'] === null ? null : $nsPodcast->location->attributes()['osm'], - 'created_by' => user()->id, - 'updated_by' => user()->id, + 'created_by' => user_id(), + 'updated_by' => user_id(), 'published_at' => strtotime($item->pubDate), ]); @@ -431,14 +451,15 @@ class PodcastImport extends BaseController ->with('errors', $personModel->errors()); } - $personGroup = empty($episodePerson->attributes()['group']) - ? ['slug' => ''] - : ReversedTaxonomy::$taxonomy[ - strval($episodePerson->attributes()['group']) - ]; + $personGroup = + $episodePerson->attributes()['group'] === null + ? ['slug' => ''] + : ReversedTaxonomy::$taxonomy[ + strval($episodePerson->attributes()['group']) + ]; $personRole = - empty($episodePerson->attributes()['role']) || - empty($personGroup) + $episodePerson->attributes()['role'] === null || + $personGroup === null ? ['slug' => ''] : $personGroup['roles'][ strval($episodePerson->attributes()['role']) diff --git a/app/Controllers/Admin/PodcastPerson.php b/app/Controllers/Admin/PodcastPersonController.php similarity index 97% rename from app/Controllers/Admin/PodcastPerson.php rename to app/Controllers/Admin/PodcastPersonController.php index 9a9e4474..894555c2 100644 --- a/app/Controllers/Admin/PodcastPerson.php +++ b/app/Controllers/Admin/PodcastPersonController.php @@ -14,7 +14,7 @@ use App\Models\PodcastPersonModel; use App\Models\PodcastModel; use App\Models\PersonModel; -class PodcastPerson extends BaseController +class PodcastPersonController extends BaseController { /** * @var Podcast diff --git a/app/Controllers/Admin/PodcastPlatform.php b/app/Controllers/Admin/PodcastPlatformController.php similarity index 96% rename from app/Controllers/Admin/PodcastPlatform.php rename to app/Controllers/Admin/PodcastPlatformController.php index 55d2ab98..27b1deab 100644 --- a/app/Controllers/Admin/PodcastPlatform.php +++ b/app/Controllers/Admin/PodcastPlatformController.php @@ -14,7 +14,7 @@ use App\Models\PlatformModel; use App\Models\PodcastModel; use Config\Services; -class PodcastPlatform extends BaseController +class PodcastPlatformController extends BaseController { /** * @var Podcast|null @@ -69,7 +69,7 @@ class PodcastPlatform extends BaseController as $platformSlug => $podcastPlatform ) { $podcastPlatformUrl = $podcastPlatform['url']; - if (empty($podcastPlatformUrl)) { + if ($podcastPlatformUrl === null) { continue; } if (!$validation->check($podcastPlatformUrl, 'validate_url')) { diff --git a/app/Controllers/Admin/User.php b/app/Controllers/Admin/UserController.php similarity index 97% rename from app/Controllers/Admin/User.php rename to app/Controllers/Admin/UserController.php index 1b456eac..3446e28f 100644 --- a/app/Controllers/Admin/User.php +++ b/app/Controllers/Admin/UserController.php @@ -10,11 +10,11 @@ namespace App\Controllers\Admin; use CodeIgniter\Exceptions\PageNotFoundException; use App\Authorization\GroupModel; -use App\Entities\User as EntitiesUser; +use App\Entities\User; use App\Models\UserModel; use Config\Services; -class User extends BaseController +class UserController extends BaseController { /** * @var User|null @@ -82,7 +82,7 @@ class User extends BaseController } // Save the user - $user = new EntitiesUser($this->request->getPost()); + $user = new User($this->request->getPost()); // Activate user $user->activate(); diff --git a/app/Controllers/Auth.php b/app/Controllers/AuthController.php similarity index 96% rename from app/Controllers/Auth.php rename to app/Controllers/AuthController.php index 0ac069f1..20129e87 100644 --- a/app/Controllers/Auth.php +++ b/app/Controllers/AuthController.php @@ -8,11 +8,11 @@ namespace App\Controllers; -use Myth\Auth\Controllers\AuthController; +use Myth\Auth\Controllers\AuthController as MythAuthController; use App\Entities\User; use CodeIgniter\HTTP\RedirectResponse; -class Auth extends AuthController +class AuthController extends MythAuthController { /** * An array of helpers to be automatically loaded @@ -66,7 +66,7 @@ class Auth extends AuthController : $user->activate(); // Ensure default group gets assigned if set - if (!empty($this->config->defaultUserGroup)) { + if ($this->config->defaultUserGroup !== null) { $users = $users->withGroup($this->config->defaultUserGroup); } @@ -151,7 +151,7 @@ class Auth extends AuthController // Reset token still valid? if ( - !empty($user->reset_expires) && + $user->reset_expires !== null && time() > $user->reset_expires->getTimestamp() ) { return redirect() diff --git a/app/Controllers/Episode.php b/app/Controllers/EpisodeController.php similarity index 95% rename from app/Controllers/Episode.php rename to app/Controllers/EpisodeController.php index 98050652..55404eae 100644 --- a/app/Controllers/Episode.php +++ b/app/Controllers/EpisodeController.php @@ -9,12 +9,14 @@ namespace App\Controllers; use Analytics\AnalyticsTrait; +use App\Entities\Episode; +use App\Entities\Podcast; use App\Models\EpisodeModel; use App\Models\PodcastModel; use CodeIgniter\Exceptions\PageNotFoundException; use SimpleXMLElement; -class Episode extends BaseController +class EpisodeController extends BaseController { use AnalyticsTrait; @@ -162,7 +164,7 @@ class Episode extends BaseController 'author_url' => $this->podcast->link, 'html' => '', 'width' => 600, 'height' => 200, @@ -192,12 +194,12 @@ class Episode extends BaseController 'html', htmlentities( '', ), ); - $oembed->addChild('width', 600); - $oembed->addChild('height', 200); + $oembed->addChild('width', '600'); + $oembed->addChild('height', '200'); return $this->response->setXML($oembed); } diff --git a/app/Controllers/Feed.php b/app/Controllers/FeedController.php similarity index 87% rename from app/Controllers/Feed.php rename to app/Controllers/FeedController.php index 1844f205..b227dc67 100644 --- a/app/Controllers/Feed.php +++ b/app/Controllers/FeedController.php @@ -16,9 +16,9 @@ use App\Models\EpisodeModel; use App\Models\PodcastModel; use CodeIgniter\Controller; -class Feed extends Controller +class FeedController extends Controller { - public function index($podcastName): ResponseInterface + public function index(string $podcastName): ResponseInterface { helper('rss'); @@ -27,17 +27,19 @@ class Feed extends Controller throw PageNotFoundException::forPageNotFound(); } - $serviceSlug = ''; + $service = null; try { $service = UserAgentsRSS::find($_SERVER['HTTP_USER_AGENT']); - if ($service) { - $serviceSlug = $service['slug']; - } } catch (Exception $exception) { // If things go wrong the show must go on and the user must be able to download the file log_message('critical', $exception); } + $serviceSlug = null; + if ($service) { + $serviceSlug = $service['slug']; + } + $cacheName = "podcast#{$podcast->id}_feed" . ($service ? "_{$serviceSlug}" : ''); @@ -57,6 +59,7 @@ class Feed extends Controller : DECADE, ); } + return $this->response->setXML($found); } } diff --git a/app/Controllers/Home.php b/app/Controllers/HomeController.php similarity index 94% rename from app/Controllers/Home.php rename to app/Controllers/HomeController.php index 3e107c79..251f7eb3 100644 --- a/app/Controllers/Home.php +++ b/app/Controllers/HomeController.php @@ -10,7 +10,7 @@ namespace App\Controllers; use App\Models\PodcastModel; -class Home extends BaseController +class HomeController extends BaseController { /** * @return mixed diff --git a/app/Controllers/Install.php b/app/Controllers/InstallController.php similarity index 94% rename from app/Controllers/Install.php rename to app/Controllers/InstallController.php index 3fbb2ba0..6fb02e01 100644 --- a/app/Controllers/Install.php +++ b/app/Controllers/InstallController.php @@ -22,7 +22,7 @@ use CodeIgniter\Controller; use Config\Services; use Dotenv\Dotenv; -class Install extends Controller +class InstallController extends Controller { /** * @var string[] @@ -50,15 +50,14 @@ class Install extends Controller */ public function index(): string { - try { - // Check if .env is created and has all required fields - $dotenv = Dotenv::createUnsafeImmutable(ROOTPATH); - - $dotenv->load(); - } catch (Throwable $e) { + if (!file_exists(ROOTPATH . '.env')) { $this->createEnv(); } + // Check if .env has all required fields + $dotenv = Dotenv::createUnsafeImmutable(ROOTPATH); + $dotenv->load(); + // Check if the created .env file is writable to continue install process if (is_really_writable(ROOTPATH . '.env')) { try { @@ -171,8 +170,9 @@ class Install extends Controller if (!$this->validate($rules)) { return redirect() ->to( - (empty(host_url()) ? config('App')->baseURL : host_url()) . - config('App')->installGateway, + (host_url() === null + ? config('App')->baseURL + : host_url()) . config('App')->installGateway, ) ->withInput() ->with('errors', $this->validator->getErrors()); @@ -182,9 +182,8 @@ class Install extends Controller $mediaBaseUrl = $this->request->getPost('media_base_url'); self::writeEnv([ 'app.baseURL' => $baseUrl, - 'app.mediaBaseURL' => empty($mediaBaseUrl) - ? $baseUrl - : $mediaBaseUrl, + 'app.mediaBaseURL' => + $mediaBaseUrl === null ? $baseUrl : $mediaBaseUrl, 'app.adminGateway' => $this->request->getPost('admin_gateway'), 'app.authGateway' => $this->request->getPost('auth_gateway'), ]); @@ -192,7 +191,7 @@ class Install extends Controller helper('text'); // redirect to full install url with new baseUrl input - return redirect(0)->to( + return redirect()->to( reduce_double_slashes( $baseUrl . '/' . config('App')->installGateway, ), @@ -357,9 +356,9 @@ class Install extends Controller * writes config values in .env file * overwrites any existing key and appends new ones * - * @param array $data key/value config pairs + * @param array $configData key/value config pairs */ - public static function writeEnv($configData): void + public static function writeEnv(array $configData): void { $envData = file(ROOTPATH . '.env'); // reads an array of lines diff --git a/app/Controllers/Note.php b/app/Controllers/NoteController.php similarity index 88% rename from app/Controllers/Note.php rename to app/Controllers/NoteController.php index 6c0ff328..41e94ae1 100644 --- a/app/Controllers/Note.php +++ b/app/Controllers/NoteController.php @@ -8,17 +8,19 @@ namespace App\Controllers; -use ActivityPub\Controllers\NoteController; +use ActivityPub\Controllers\NoteController as ActivityPubNoteController; use ActivityPub\Entities\Note as ActivityPubNote; use Analytics\AnalyticsTrait; +use App\Entities\Actor; use App\Entities\Note as CastopodNote; +use App\Entities\Podcast; use App\Models\EpisodeModel; use App\Models\PodcastModel; use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\URI; use CodeIgniter\I18n\Time; -class Note extends NoteController +class NoteController extends ActivityPubNoteController { use AnalyticsTrait; @@ -27,6 +29,11 @@ class Note extends NoteController */ protected $podcast; + /** + * @var Actor + */ + protected $actor; + protected $helpers = ['auth', 'activitypub', 'svg', 'components', 'misc']; public function _remap($method, ...$params) @@ -52,7 +59,7 @@ class Note extends NoteController return $this->$method(...$params); } - public function index(): RedirectResponse + public function view(): string { // Prevent analytics hit when authenticated if (!can_user_interact()) { @@ -96,7 +103,7 @@ class Note extends NoteController return $cachedView; } - public function attemptCreate() + public function attemptCreate(): RedirectResponse { $rules = [ 'message' => 'required|max_length[500]', @@ -153,7 +160,7 @@ class Note extends NoteController return redirect()->back(); } - public function attemptReply() + public function attemptReply(): RedirectResponse { $rules = [ 'message' => 'required|max_length[500]', @@ -185,7 +192,7 @@ class Note extends NoteController return redirect()->back(); } - public function attemptFavourite() + public function attemptFavourite(): RedirectResponse { model('FavouriteModel')->toggleFavourite( interact_as_actor(), @@ -195,14 +202,14 @@ class Note extends NoteController return redirect()->back(); } - public function attemptReblog() + public function attemptReblog(): RedirectResponse { model('NoteModel')->toggleReblog(interact_as_actor(), $this->note); return redirect()->back(); } - public function attemptAction() + public function attemptAction(): RedirectResponse { $rules = [ 'action' => 'required|in_list[favourite,reblog,reply]', @@ -215,17 +222,23 @@ class Note extends NoteController ->with('errors', $this->validator->getErrors()); } - switch ($this->request->getPost('action')) { + $action = $this->request->getPost('action'); + switch ($action) { case 'favourite': return $this->attemptFavourite(); case 'reblog': return $this->attemptReblog(); case 'reply': return $this->attemptReply(); + default: + return redirect() + ->back() + ->withInput() + ->with('errors', 'error'); } } - public function remoteAction($action) + public function remoteAction(string $action): string { // Prevent analytics hit when authenticated if (!can_user_interact()) { @@ -258,6 +271,6 @@ class Note extends NoteController ]); } - return $cachedView; + return (string) $cachedView; } } diff --git a/app/Controllers/Page.php b/app/Controllers/PageController.php similarity index 98% rename from app/Controllers/Page.php rename to app/Controllers/PageController.php index b547a4ca..c2bbd741 100644 --- a/app/Controllers/Page.php +++ b/app/Controllers/PageController.php @@ -8,13 +8,13 @@ namespace App\Controllers; -use App\Entities\Page as PageEntity; +use App\Entities\Page; use CodeIgniter\Exceptions\PageNotFoundException; use App\Models\PageModel; use App\Models\CreditModel; use App\Models\PodcastModel; -class Page extends BaseController +class PageController extends BaseController { /** * @var Page|null @@ -60,10 +60,10 @@ class Page extends BaseController $cacheName = "page_credits_{$locale}"; if (!($found = cache($cacheName))) { - $page = new PageEntity([ + $page = new Page([ 'title' => lang('Person.credits', [], $locale), 'slug' => 'credits', - 'content' => '', + 'content_markdown' => '', ]); $allCredits = (new CreditModel())->findAll(); diff --git a/app/Controllers/Platform.php b/app/Controllers/PlatformController.php similarity index 92% rename from app/Controllers/Platform.php rename to app/Controllers/PlatformController.php index b4ba11de..89d37467 100644 --- a/app/Controllers/Platform.php +++ b/app/Controllers/PlatformController.php @@ -15,7 +15,7 @@ use CodeIgniter\Controller; /* * Provide public access to all platforms so that they can be exported */ -class Platform extends Controller +class PlatformController extends Controller { public function index(): ResponseInterface { diff --git a/app/Controllers/Podcast.php b/app/Controllers/PodcastController.php similarity index 98% rename from app/Controllers/Podcast.php rename to app/Controllers/PodcastController.php index 0144e144..4057218a 100644 --- a/app/Controllers/Podcast.php +++ b/app/Controllers/PodcastController.php @@ -9,11 +9,12 @@ namespace App\Controllers; use Analytics\AnalyticsTrait; +use App\Entities\Podcast; use App\Models\EpisodeModel; use App\Models\PodcastModel; use App\Models\NoteModel; -class Podcast extends BaseController +class PodcastController extends BaseController { use AnalyticsTrait; diff --git a/app/Libraries/Analytics/Database/Migrations/2017-12-01-160000_add_podcasts_platforms.php b/app/Database/Migrations/2017-12-01-160000_add_podcasts_platforms.php similarity index 100% rename from app/Libraries/Analytics/Database/Migrations/2017-12-01-160000_add_podcasts_platforms.php rename to app/Database/Migrations/2017-12-01-160000_add_podcasts_platforms.php diff --git a/app/Database/Migrations/2020-05-30-101500_add_podcasts.php b/app/Database/Migrations/2020-05-30-101500_add_podcasts.php index 772d5127..aa32c889 100644 --- a/app/Database/Migrations/2020-05-30-101500_add_podcasts.php +++ b/app/Database/Migrations/2020-05-30-101500_add_podcasts.php @@ -142,7 +142,7 @@ class AddPodcasts extends Migration 'constraint' => 32, 'null' => true, ], - 'location_osmid' => [ + 'location_osm_id' => [ 'type' => 'VARCHAR', 'constraint' => 12, 'null' => true, @@ -194,7 +194,7 @@ class AddPodcasts extends Migration 'actor_id', 'activitypub_actors', 'id', - false, + '', 'CASCADE', ); $this->forge->addForeignKey('category_id', 'categories', 'id'); diff --git a/app/Database/Migrations/2020-06-05-170000_add_episodes.php b/app/Database/Migrations/2020-06-05-170000_add_episodes.php index c8d55e71..83ee1e4a 100644 --- a/app/Database/Migrations/2020-06-05-170000_add_episodes.php +++ b/app/Database/Migrations/2020-06-05-170000_add_episodes.php @@ -44,7 +44,8 @@ class AddEpisodes extends Migration 'constraint' => 255, ], 'audio_file_duration' => [ - 'type' => 'INT', + // exact value for duration with max 99999,999 ~ 27.7 hours + 'type' => 'DECIMAL(8,3)', 'unsigned' => true, 'comment' => 'Playtime in seconds', ], @@ -136,7 +137,7 @@ class AddEpisodes extends Migration 'constraint' => 32, 'null' => true, ], - 'location_osmid' => [ + 'location_osm_id' => [ 'type' => 'VARCHAR', 'constraint' => 12, 'null' => true, @@ -189,7 +190,7 @@ class AddEpisodes extends Migration 'podcast_id', 'podcasts', 'id', - false, + '', 'CASCADE', ); $this->forge->addForeignKey('created_by', 'users', 'id'); diff --git a/app/Database/Migrations/2020-06-05-180000_add_soundbites.php b/app/Database/Migrations/2020-06-05-180000_add_soundbites.php index a448d630..43b3126a 100644 --- a/app/Database/Migrations/2020-06-05-180000_add_soundbites.php +++ b/app/Database/Migrations/2020-06-05-180000_add_soundbites.php @@ -32,10 +32,10 @@ class AddSoundbites extends Migration 'unsigned' => true, ], 'start_time' => [ - 'type' => 'FLOAT', + 'type' => 'DECIMAL(8,3)', ], 'duration' => [ - 'type' => 'FLOAT', + 'type' => 'DECIMAL(8,3)', ], 'label' => [ 'type' => 'VARCHAR', @@ -67,14 +67,14 @@ class AddSoundbites extends Migration 'podcast_id', 'podcasts', 'id', - false, + '', 'CASCADE', ); $this->forge->addForeignKey( 'episode_id', 'episodes', 'id', - false, + '', 'CASCADE', ); $this->forge->addForeignKey('created_by', 'users', 'id'); diff --git a/app/Database/Migrations/2020-07-03-191500_add_podcasts_users.php b/app/Database/Migrations/2020-07-03-191500_add_podcasts_users.php index 90d2ab1a..85a90f0d 100644 --- a/app/Database/Migrations/2020-07-03-191500_add_podcasts_users.php +++ b/app/Database/Migrations/2020-07-03-191500_add_podcasts_users.php @@ -32,19 +32,19 @@ class AddPodcastsUsers extends Migration ], ]); $this->forge->addPrimaryKey(['user_id', 'podcast_id']); - $this->forge->addForeignKey('user_id', 'users', 'id', false, 'CASCADE'); + $this->forge->addForeignKey('user_id', 'users', 'id', '', 'CASCADE'); $this->forge->addForeignKey( 'podcast_id', 'podcasts', 'id', - false, + '', 'CASCADE', ); $this->forge->addForeignKey( 'group_id', 'auth_groups', 'id', - false, + '', 'CASCADE', ); $this->forge->createTable('podcasts_users'); diff --git a/app/Database/Migrations/2020-08-17-150000_add_pages.php b/app/Database/Migrations/2020-08-17-150000_add_pages.php index fda65e2a..c54d5720 100644 --- a/app/Database/Migrations/2020-08-17-150000_add_pages.php +++ b/app/Database/Migrations/2020-08-17-150000_add_pages.php @@ -32,7 +32,10 @@ class AddPages extends Migration 'constraint' => 191, 'unique' => true, ], - 'content' => [ + 'content_markdown' => [ + 'type' => 'TEXT', + ], + 'content_html' => [ 'type' => 'TEXT', ], 'created_at' => [ diff --git a/app/Database/Migrations/2020-09-29-150000_add_podcasts_categories.php b/app/Database/Migrations/2020-09-29-150000_add_podcasts_categories.php index 4d8b73ee..49b7bc56 100644 --- a/app/Database/Migrations/2020-09-29-150000_add_podcasts_categories.php +++ b/app/Database/Migrations/2020-09-29-150000_add_podcasts_categories.php @@ -32,14 +32,14 @@ class AddPodcastsCategories extends Migration 'podcast_id', 'podcasts', 'id', - false, + '', 'CASCADE', ); $this->forge->addForeignKey( 'category_id', 'categories', 'id', - false, + '', 'CASCADE', ); $this->forge->createTable('podcasts_categories'); diff --git a/app/Database/Migrations/2020-12-25-130000_add_podcasts_persons.php b/app/Database/Migrations/2020-12-25-130000_add_podcasts_persons.php index 5a714efa..2507a815 100644 --- a/app/Database/Migrations/2020-12-25-130000_add_podcasts_persons.php +++ b/app/Database/Migrations/2020-12-25-130000_add_podcasts_persons.php @@ -51,14 +51,14 @@ class AddPodcastsPersons extends Migration 'podcast_id', 'podcasts', 'id', - false, + '', 'CASCADE', ); $this->forge->addForeignKey( 'person_id', 'persons', 'id', - false, + '', 'CASCADE', ); $this->forge->createTable('podcasts_persons'); diff --git a/app/Database/Migrations/2020-12-25-140000_add_episodes_persons.php b/app/Database/Migrations/2020-12-25-140000_add_episodes_persons.php index 512756b5..1bff6c1d 100644 --- a/app/Database/Migrations/2020-12-25-140000_add_episodes_persons.php +++ b/app/Database/Migrations/2020-12-25-140000_add_episodes_persons.php @@ -56,21 +56,21 @@ class AddEpisodesPersons extends Migration 'podcast_id', 'podcasts', 'id', - false, + '', 'CASCADE', ); $this->forge->addForeignKey( 'episode_id', 'episodes', 'id', - false, + '', 'CASCADE', ); $this->forge->addForeignKey( 'person_id', 'persons', 'id', - false, + '', 'CASCADE', ); $this->forge->createTable('episodes_persons'); diff --git a/app/Database/Seeds/AuthSeeder.php b/app/Database/Seeds/AuthSeeder.php index 0a0bd086..24835c26 100644 --- a/app/Database/Seeds/AuthSeeder.php +++ b/app/Database/Seeds/AuthSeeder.php @@ -307,13 +307,14 @@ class AuthSeeder extends Seeder /** * @param array[] $dataGroups */ - static function getGroupIdByName(string $name, array $dataGroups): int + static function getGroupIdByName(string $name, array $dataGroups): ?int { foreach ($dataGroups as $group) { if ($group['name'] === $name) { return $group['id']; } } + return null; } } diff --git a/app/Database/Seeds/FakePodcastsAnalyticsSeeder.php b/app/Database/Seeds/FakePodcastsAnalyticsSeeder.php index 140b61ff..376877e5 100644 --- a/app/Database/Seeds/FakePodcastsAnalyticsSeeder.php +++ b/app/Database/Seeds/FakePodcastsAnalyticsSeeder.php @@ -69,14 +69,14 @@ class FakePodcastsAnalyticsSeeder extends Seeder $age = floor( ($date - strtotime($episode->published_at)) / 86400, ); - $proba1 = floor(exp(3 - $age / 40)) + 1; + $probability1 = (int) floor(exp(3 - $age / 40)) + 1; for ( $num_line = 0; - $num_line < rand(1, $proba1); + $num_line < rand(1, $probability1); ++$num_line ) { - $proba2 = floor(exp(6 - $age / 20)) + 10; + $probability2 = (int) floor(exp(6 - $age / 20)) + 10; $player = $jsonUserAgents[ @@ -127,7 +127,7 @@ class FakePodcastsAnalyticsSeeder extends Seeder //Bad luck, bad IP, nothing to do. } - $hits = rand(0, $proba2); + $hits = rand(0, $probability2); $analytics_podcasts[] = [ 'podcast_id' => $podcast->id, diff --git a/app/Database/Seeds/FakeWebsiteAnalyticsSeeder.php b/app/Database/Seeds/FakeWebsiteAnalyticsSeeder.php index 2534d968..51697c9b 100644 --- a/app/Database/Seeds/FakeWebsiteAnalyticsSeeder.php +++ b/app/Database/Seeds/FakeWebsiteAnalyticsSeeder.php @@ -206,14 +206,14 @@ class FakeWebsiteAnalyticsSeeder extends Seeder $age = floor( ($date - strtotime($episode->published_at)) / 86400, ); - $proba1 = floor(exp(3 - $age / 40)) + 1; + $probability1 = (int) floor(exp(3 - $age / 40)) + 1; for ( $num_line = 0; - $num_line < rand(1, $proba1); + $num_line < rand(1, $probability1); ++$num_line ) { - $proba2 = floor(exp(6 - $age / 20)) + 10; + $probability2 = (int) floor(exp(6 - $age / 20)) + 10; $domain = $this->domains[rand(0, count($this->domains) - 1)]; @@ -226,7 +226,7 @@ class FakeWebsiteAnalyticsSeeder extends Seeder rand(0, count($this->browsers) - 1) ]; - $hits = rand(0, $proba2); + $hits = rand(0, $probability2); $website_by_browser[] = [ 'podcast_id' => $podcast->id, diff --git a/app/Entities/Actor.php b/app/Entities/Actor.php index e19c00c1..e19892dd 100644 --- a/app/Entities/Actor.php +++ b/app/Entities/Actor.php @@ -8,13 +8,18 @@ namespace App\Entities; +use ActivityPub\Entities\Actor as ActivityPubActor; use App\Models\PodcastModel; use RuntimeException; -class Actor extends \ActivityPub\Entities\Actor +/** + * @property Podcast|null $podcast + * @property boolean $is_podcast + */ +class Actor extends ActivityPubActor { /** - * @var App\Entities\Podcast|null + * @var Podcast|null */ protected $podcast; @@ -23,20 +28,20 @@ class Actor extends \ActivityPub\Entities\Actor */ protected $is_podcast; - public function getIsPodcast() + public function getIsPodcast(): bool { - return !empty($this->podcast); + return $this->podcast !== null; } - public function getPodcast() + public function getPodcast(): ?Podcast { - if (empty($this->id)) { + if ($this->id === null) { throw new RuntimeException( - 'Actor must be created before getting associated podcast.', + 'Podcast id must be set before getting associated podcast.', ); } - if (empty($this->podcast)) { + if ($this->podcast === null) { $this->podcast = (new PodcastModel())->getPodcastByActorId( $this->id, ); diff --git a/app/Entities/Category.php b/app/Entities/Category.php index 72edbe9e..208a6962 100644 --- a/app/Entities/Category.php +++ b/app/Entities/Category.php @@ -11,6 +11,14 @@ namespace App\Entities; use App\Models\CategoryModel; use CodeIgniter\Entity\Entity; +/** + * @property int $id + * @property int $parent_id + * @property Category|null $parent + * @property string $code + * @property string $apple_category + * @property string $google_category + */ class Category extends Entity { /** @@ -23,7 +31,7 @@ class Category extends Entity */ protected $casts = [ 'id' => 'integer', - 'parent_id' => 'integer', + 'parent_id' => '?integer', 'code' => 'string', 'apple_category' => 'string', 'google_category' => 'string', diff --git a/app/Entities/Credit.php b/app/Entities/Credit.php index f323cbb1..44e07382 100644 --- a/app/Entities/Credit.php +++ b/app/Entities/Credit.php @@ -14,6 +14,19 @@ use App\Models\PodcastModel; use App\Models\EpisodeModel; use CodeIgniter\Entity\Entity; +/** + * @property int $podcast_id + * @property Podcast $podcast + * @property int|null $episode_id + * @property Episode|null $episode + * @property string $full_name + * @property string $person_group + * @property string $group_label + * @property string $person_role + * @property string $role_label + * @property int $person_id + * @property Person $person + */ class Credit extends Entity { /** @@ -45,30 +58,57 @@ class Credit extends Entity * @var array */ protected $casts = [ - 'person_group' => 'string', - 'person_role' => 'string', - 'person_id' => 'integer', - 'full_name' => 'integer', 'podcast_id' => 'integer', 'episode_id' => '?integer', + 'person_id' => 'integer', + 'full_name' => 'string', + 'person_group' => 'string', + 'person_role' => 'string', ]; + public function getPerson(): Person + { + if ($this->person_id === null) { + throw new RuntimeException( + 'Credit must have person_id before getting person.', + ); + } + + if ($this->person === null) { + $this->person = (new PersonModel())->getPersonById( + $this->person_id, + ); + } + + return $this->person; + } + public function getPodcast(): Podcast { - return (new PodcastModel())->getPodcastById( - $this->attributes['podcast_id'], - ); + if ($this->podcast_id === null) { + throw new RuntimeException( + 'Credit must have podcast_id before getting podcast.', + ); + } + + if ($this->podcast === null) { + $this->podcast = (new PodcastModel())->getPodcastById( + $this->podcast_id, + ); + } + + return $this->podcast; } public function getEpisode(): ?Episode { - if (empty($this->episode_id)) { + if ($this->episode_id === null) { throw new RuntimeException( 'Credit must have episode_id before getting episode.', ); } - if (empty($this->episode)) { + if ($this->episode === null) { $this->episode = (new EpisodeModel())->getPublishedEpisodeById( $this->podcast_id, $this->episode_id, @@ -78,40 +118,23 @@ class Credit extends Entity return $this->episode; } - public function getPerson(): Person + public function getGroupLabel(): string { - if (empty($this->person_id)) { - throw new RuntimeException( - 'Credit must have person_id before getting person.', - ); - } - - if (empty($this->person)) { - $this->person = (new PersonModel())->getPersonById( - $this->person_id, - ); - } - - return $this->person; - } - - public function getGroupLabel(): ?string - { - if (empty($this->person_group)) { - return null; + if ($this->person_group === null) { + return ''; } return lang("PersonsTaxonomy.persons.{$this->person_group}.label"); } - public function getRoleLabel(): ?string + public function getRoleLabel(): string { - if (empty($this->person_group)) { - return null; + if ($this->person_group === '') { + return ''; } - if (empty($this->person_role)) { - return null; + if ($this->person_role === '') { + return ''; } return lang( diff --git a/app/Entities/Episode.php b/app/Entities/Episode.php index d2297421..5e60ff82 100644 --- a/app/Entities/Episode.php +++ b/app/Entities/Episode.php @@ -8,21 +8,77 @@ namespace App\Entities; -use App\Libraries\Image; +use App\Entities\Location; use App\Libraries\SimpleRSSElement; use App\Models\PodcastModel; use App\Models\SoundbiteModel; use App\Models\EpisodePersonModel; use App\Models\NoteModel; use CodeIgniter\Entity\Entity; -use CodeIgniter\Files\Exceptions\FileNotFoundException; use CodeIgniter\Files\File; -use CodeIgniter\HTTP\Exceptions\HTTPException; use CodeIgniter\HTTP\Files\UploadedFile; use CodeIgniter\I18n\Time; use League\CommonMark\CommonMarkConverter; use RuntimeException; +/** + * @property int $id + * @property int $podcast_id + * @property Podcast $podcast + * @property string $link + * @property string $guid + * @property string $slug + * @property string $title + * @property File $audio_file + * @property string $audio_file_url + * @property string $audio_file_analytics_url + * @property string $audio_file_web_url + * @property string $audio_file_opengraph_url + * @property string $audio_file_path + * @property double $audio_file_duration + * @property string $audio_file_mimetype + * @property int $audio_file_size + * @property int $audio_file_header_size + * @property string $description Holds text only description, striped of any markdown or html special characters + * @property string $description_markdown + * @property string $description_html + * @property Image $image + * @property string|null $image_path + * @property string|null $image_mimetype + * @property File|null $transcript_file + * @property string|null $transcript_file_url + * @property string|null $transcript_file_path + * @property string|null $transcript_file_remote_url + * @property File|null $chapters_file + * @property string|null $chapters_file_url + * @property string|null $chapters_file_path + * @property string|null $chapters_file_remote_url + * @property string|null $parental_advisory + * @property int $number + * @property int $season_number + * @property string $type + * @property bool $is_blocked + * @property Location $location + * @property string|null $location_name + * @property string|null $location_geo + * @property string|null $location_osm_id + * @property array|null $custom_rss + * @property string $custom_rss_string + * @property int $favourites_total + * @property int $reblogs_total + * @property int $notes_total + * @property int $created_by + * @property int $updated_by + * @property string $publication_status; + * @property Time|null $published_at; + * @property Time $created_at; + * @property Time $updated_at; + * @property Time|null $deleted_at; + * + * @property EpisodePerson[] $persons; + * @property Soundbite[] $soundbites; + * @property string $embeddable_player_url; + */ class Episode extends Entity { /** @@ -35,25 +91,10 @@ class Episode extends Entity */ protected $link; - /** - * @var Image - */ - protected $image; - /** * @var File */ - protected $audioFile; - - /** - * @var File - */ - protected $transcript_file; - - /** - * @var File - */ - protected $chapters_file; + protected $audio_file; /** * @var string @@ -75,6 +116,31 @@ class Episode extends Entity */ protected $audio_file_opengraph_url; + /** + * @var string + */ + protected $embeddable_player_url; + + /** + * @var Image + */ + protected $image; + + /** + * @var string + */ + protected $description; + + /** + * @var File + */ + protected $transcript_file; + + /** + * @var File + */ + protected $chapters_file; + /** * @var EpisodePerson[] */ @@ -91,18 +157,14 @@ class Episode extends Entity protected $notes; /** - * Holds text only description, striped of any markdown or html special characters - * - * @var string + * @var Location|null */ - protected $description; + protected $location; /** - * The embeddable player URL - * * @var string */ - protected $embeddable_player; + protected $custom_rss_string; /** * @var string @@ -110,12 +172,8 @@ class Episode extends Entity protected $publication_status; /** - * Return custom rss as string - * - * @var string + * @var string[] */ - protected $custom_rss_string; - protected $dates = [ 'published_at', 'created_at', @@ -123,6 +181,9 @@ class Episode extends Entity 'deleted_at', ]; + /** + * @var array + */ protected $casts = [ 'id' => 'integer', 'podcast_id' => 'integer', @@ -130,7 +191,7 @@ class Episode extends Entity 'slug' => 'string', 'title' => 'string', 'audio_file_path' => 'string', - 'audio_file_duration' => 'integer', + 'audio_file_duration' => 'double', 'audio_file_mimetype' => 'string', 'audio_file_size' => 'integer', 'audio_file_header_size' => 'integer', @@ -149,7 +210,7 @@ class Episode extends Entity 'is_blocked' => 'boolean', 'location_name' => '?string', 'location_geo' => '?string', - 'location_osmid' => '?string', + 'location_osm_id' => '?string', 'custom_rss' => '?json-array', 'favourites_total' => 'integer', 'reblogs_total' => 'integer', @@ -161,96 +222,79 @@ class Episode extends Entity /** * Saves an episode image * - * @param UploadedFile|File $image + * @param Image|null $image */ - public function setImage($image) + public function setImage($image = null): self { - if ( - !empty($image) && - (!($image instanceof UploadedFile) || $image->isValid()) - ) { - helper('media'); - - // check whether the user has inputted an image and store - $this->attributes['image_mimetype'] = $image->getMimeType(); - $this->attributes['image_path'] = save_media( - $image, - 'podcasts/' . $this->getPodcast()->name, - $this->attributes['slug'], - ); - $this->image = new Image( - $this->attributes['image_path'], - $this->attributes['image_mimetype'], - ); - $this->image->saveSizes(); + if ($image === null) { + return $this; } + // Save image + $image->saveImage( + 'podcasts/' . $this->getPodcast()->name, + $this->attributes['slug'], + ); + + $this->attributes['image_mimetype'] = $image->mimetype; + $this->attributes['image_path'] = $image->path; + return $this; } public function getImage(): Image { if ($imagePath = $this->attributes['image_path']) { - return new Image($imagePath, $this->attributes['image_mimetype']); + return new Image( + null, + $imagePath, + $this->attributes['image_mimetype'], + ); } - return $this->getPodcast()->image; + + return $this->podcast->image; } /** * Saves an audio file * * @param UploadedFile|File $audioFile - * */ - public function setAudioFile($audioFile = null) + public function setAudioFile($audioFile) { - if ( - !empty($audioFile) && - (!($audioFile instanceof UploadedFile) || $audioFile->isValid()) - ) { - helper(['media', 'id3']); + helper(['media', 'id3']); - $audio_metadata = get_file_tags($audioFile); + $audio_metadata = get_file_tags($audioFile); - $this->attributes['audio_file_path'] = save_media( - $audioFile, - 'podcasts/' . $this->getPodcast()->name, - $this->attributes['slug'], - ); - $this->attributes['audio_file_duration'] = round( - $audio_metadata['playtime_seconds'], - ); - $this->attributes['audio_file_mimetype'] = - $audio_metadata['mime_type']; - $this->attributes['audio_file_size'] = $audio_metadata['filesize']; - $this->attributes['audio_file_header_size'] = - $audio_metadata['avdataoffset']; + $this->attributes['audio_file_path'] = save_media( + $audioFile, + 'podcasts/' . $this->getPodcast()->name, + $this->attributes['slug'], + ); + $this->attributes['audio_file_duration'] = + $audio_metadata['playtime_seconds']; + $this->attributes['audio_file_mimetype'] = $audio_metadata['mime_type']; + $this->attributes['audio_file_size'] = $audio_metadata['filesize']; + $this->attributes['audio_file_header_size'] = + $audio_metadata['avdataoffset']; - return $this; - } + return $this; } /** * Saves an episode transcript file * * @param UploadedFile|File $transcriptFile - * */ public function setTranscriptFile($transcriptFile) { - if ( - !empty($transcriptFile) && - (!($transcriptFile instanceof UploadedFile) || - $transcriptFile->isValid()) - ) { - helper('media'); + helper('media'); - $this->attributes['transcript_file_path'] = save_media( - $transcriptFile, - $this->getPodcast()->name, - $this->attributes['slug'] . '-transcript', - ); - } + $this->attributes['transcript_file_path'] = save_media( + $transcriptFile, + $this->getPodcast()->name, + $this->attributes['slug'] . '-transcript', + ); return $this; } @@ -259,35 +303,28 @@ class Episode extends Entity * Saves an episode chapters file * * @param UploadedFile|File $chaptersFile - * */ public function setChaptersFile($chaptersFile) { - if ( - !empty($chaptersFile) && - (!($chaptersFile instanceof UploadedFile) || - $chaptersFile->isValid()) - ) { - helper('media'); + helper('media'); - $this->attributes['chapters_file_path'] = save_media( - $chaptersFile, - $this->getPodcast()->name, - $this->attributes['slug'] . '-chapters', - ); - } + $this->attributes['chapters_file_path'] = save_media( + $chaptersFile, + $this->getPodcast()->name, + $this->attributes['slug'] . '-chapters', + ); return $this; } - public function getAudioFile() + public function getAudioFile(): File { helper('media'); return new File(media_path($this->audio_file_path)); } - public function getTranscriptFile() + public function getTranscriptFile(): ?File { if ($this->attributes['transcript_file_path']) { helper('media'); @@ -300,7 +337,7 @@ class Episode extends Entity return null; } - public function getChaptersFile() + public function getChaptersFile(): ?File { if ($this->attributes['chapters_file_path']) { helper('media'); @@ -313,14 +350,14 @@ class Episode extends Entity return null; } - public function getAudioFileUrl() + public function getAudioFileUrl(): string { helper('media'); return media_base_url($this->audio_file_path); } - public function getAudioFileAnalyticsUrl() + public function getAudioFileAnalyticsUrl(): string { helper('analytics'); @@ -335,12 +372,12 @@ class Episode extends Entity ); } - public function getAudioFileWebUrl() + public function getAudioFileWebUrl(): string { return $this->getAudioFileAnalyticsUrl() . '?_from=-+Website+-'; } - public function getAudioFileOpengraphUrl() + public function getAudioFileOpengraphUrl(): string { return $this->getAudioFileAnalyticsUrl() . '?_from=-+Open+Graph+-'; } @@ -348,12 +385,8 @@ class Episode extends Entity /** * Gets transcript url from transcript file uri if it exists * or returns the transcript_file_remote_url which can be null. - * - * @return string|null - * @throws FileNotFoundException - * @throws HTTPException */ - public function getTranscriptFileUrl() + public function getTranscriptFileUrl(): ?string { if ($this->attributes['transcript_file_path']) { return media_base_url($this->attributes['transcript_file_path']); @@ -378,9 +411,9 @@ class Episode extends Entity /** * Returns the episode's persons * - * @return \App\Entities\EpisodePerson[] + * @return EpisodePerson[] */ - public function getPersons() + public function getPersons(): array { if (empty($this->id)) { throw new RuntimeException( @@ -401,9 +434,9 @@ class Episode extends Entity /** * Returns the episode’s soundbites * - * @return \App\Entities\Episode[] + * @return Soundbite[] */ - public function getSoundbites() + public function getSoundbites(): array { if (empty($this->id)) { throw new RuntimeException( @@ -421,7 +454,10 @@ class Episode extends Entity return $this->soundbites; } - public function getNotes() + /** + * @return Note[] + */ + public function getNotes(): array { if (empty($this->id)) { throw new RuntimeException( @@ -436,7 +472,7 @@ class Episode extends Entity return $this->notes; } - public function getLink() + public function getLink(): string { return base_url( route_to( @@ -447,7 +483,7 @@ class Episode extends Entity ); } - public function getEmbeddablePlayer($theme = null) + public function getEmbeddablePlayerUrl($theme = null): string { return base_url( $theme @@ -465,14 +501,18 @@ class Episode extends Entity ); } - public function setGuid(string $guid) + public function setGuid(?string $guid = null) { - return $this->attributes['guid'] = empty($guid) - ? $this->getLink() - : $guid; + if ($guid === null) { + $this->attributes['guid'] = $this->getLink(); + } else { + $this->attributes['guid'] = $guid; + } + + return $this; } - public function getPodcast() + public function getPodcast(): Podcast { return (new PodcastModel())->getPodcastById( $this->attributes['podcast_id'], @@ -494,39 +534,46 @@ class Episode extends Entity return $this; } - public function getDescriptionHtml($serviceSlug = null) + public function getDescriptionHtml(?string $serviceSlug = null): string { - return (empty($this->getPodcast()->partner_id) || - empty($this->getPodcast()->partner_link_url) || - empty($this->getPodcast()->partner_image_url) - ? '' - : "
getPartnerLink( + $descriptionHtml = ''; + if ( + $this->getPodcast()->partner_id !== null && + $this->getPodcast()->partner_link_url !== null && + $this->getPodcast()->partner_image_url !== null + ) { + $descriptionHtml .= "") . - $this->attributes['description_html'] . - (empty($this->getPodcast()->episode_description_footer_html) - ? '' - : "
{$this->getPodcast()->episode_description_footer_html}
"); - } - - public function getDescription() - { - if ($this->description) { - return $this->description; + )}\" alt=\"Partner image\" />
"; } - return trim( - preg_replace( - '/\s+/', - ' ', - strip_tags($this->attributes['description_html']), - ), - ); + $descriptionHtml .= $this->attributes['description_html']; + + if ($this->getPodcast()->episode_description_footer_html) { + $descriptionHtml .= "
{$this->getPodcast()->episode_description_footer_html}
"; + } + + return $descriptionHtml; } - public function getPublicationStatus() + public function getDescription(): string + { + if ($this->description === null) { + $this->description = trim( + preg_replace( + '/\s+/', + ' ', + strip_tags($this->attributes['description_html']), + ), + ); + } + + return $this->description; + } + + public function getPublicationStatus(): string { if ($this->publication_status) { return $this->publication_status; @@ -546,41 +593,57 @@ class Episode extends Entity /** * Saves the location name and fetches OpenStreetMap info - * - * @param string $locationName - * */ - public function setLocation($locationName = null) + public function setLocation(?string $newLocationName = null) { - helper('location'); - - if ( - $locationName && - (empty($this->attributes['location_name']) || - $this->attributes['location_name'] != $locationName) - ) { - $this->attributes['location_name'] = $locationName; - if ($location = fetch_osm_location($locationName)) { - $this->attributes['location_geo'] = $location['geo']; - $this->attributes['location_osmid'] = $location['osmid']; - } - } elseif (empty($locationName)) { + if ($newLocationName === null) { $this->attributes['location_name'] = null; $this->attributes['location_geo'] = null; - $this->attributes['location_osmid'] = null; + $this->attributes['location_osm_id'] = null; } + + helper('location'); + + $oldLocationName = $this->attributes['location_name']; + + if ( + $oldLocationName === null || + $oldLocationName !== $newLocationName + ) { + $this->attributes['location_name'] = $newLocationName; + + if ($location = fetch_osm_location($newLocationName)) { + $this->attributes['location_geo'] = $location['geo']; + $this->attributes['location_osm_id'] = $location['osm_id']; + } + } + return $this; } + public function getLocation(): ?Location + { + if ($this->location_name === null) { + return null; + } + + if ($this->location === null) { + $this->location = new Location([ + 'name' => $this->location_name, + 'geo' => $this->location_geo, + 'osm_id' => $this->location_osm_id, + ]); + } + + return $this->location; + } + /** * Get custom rss tag as XML String - * - * @return string - * */ - function getCustomRssString() + function getCustomRssString(): string { - if (empty($this->custom_rss)) { + if ($this->custom_rss === null) { return ''; } @@ -597,18 +660,16 @@ class Episode extends Entity ], $xmlNode, ); + return str_replace(['', ''], '', $xmlNode->asXML()); } /** * Saves custom rss tag into json - * - * @param string $customRssString - * */ - function setCustomRssString($customRssString) + function setCustomRssString(?string $customRssString = null) { - if (empty($customRssString)) { + if ($customRssString === null) { return $this; } @@ -632,23 +693,35 @@ class Episode extends Entity return $this; } - function getPartnerLink($serviceSlug = null) + function getPartnerLink(?string $serviceSlug = null): string { - return rtrim($this->getPodcast()->partner_link_url, '/') . + $partnerLink = + rtrim($this->getPodcast()->partner_link_url, '/') . '?pid=' . $this->getPodcast()->partner_id . '&guid=' . - urlencode($this->attributes['guid']) . - (empty($serviceSlug) ? '' : '&_from=' . $serviceSlug); + urlencode($this->attributes['guid']); + + if ($serviceSlug !== null) { + $partnerLink .= '&_from=' . $serviceSlug; + } + + return $partnerLink; } - function getPartnerImage($serviceSlug = null) + function getPartnerImageUrl($serviceSlug = null): string { - return rtrim($this->getPodcast()->partner_image_url, '/') . + $partnerImageUrl = + rtrim($this->getPodcast()->partner_image_url, '/') . '?pid=' . $this->getPodcast()->partner_id . '&guid=' . - urlencode($this->attributes['guid']) . - (empty($serviceSlug) ? '' : '&_from=' . $serviceSlug); + urlencode($this->attributes['guid']); + + if ($serviceSlug !== null) { + $partnerImageUrl = '&_from=' . $serviceSlug; + } + + return $partnerImageUrl; } } diff --git a/app/Entities/EpisodePerson.php b/app/Entities/EpisodePerson.php index dff7be1b..9113d353 100644 --- a/app/Entities/EpisodePerson.php +++ b/app/Entities/EpisodePerson.php @@ -11,6 +11,15 @@ namespace App\Entities; use CodeIgniter\Entity\Entity; use App\Models\PersonModel; +/** + * @property int $id + * @property int $podcast_id + * @property int $episode_id + * @property int $person_id + * @property Person $person + * @property string|null $person_group + * @property string|null $person_role + */ class EpisodePerson extends Entity { /** @@ -30,7 +39,7 @@ class EpisodePerson extends Entity 'person_role' => '?string', ]; - public function getPerson() + public function getPerson(): Person { return (new PersonModel())->getPersonById( $this->attributes['person_id'], diff --git a/app/Entities/Image.php b/app/Entities/Image.php new file mode 100644 index 00000000..5a9fa826 --- /dev/null +++ b/app/Entities/Image.php @@ -0,0 +1,250 @@ +config = config('Images'); + + $dirname = ''; + $filename = ''; + $extension = ''; + + if ($file !== null) { + $dirname = $file->getPath(); + $filename = $file->getBasename(); + $extension = $file->getExtension(); + $mimetype = $file->getMimeType(); + } + + if ($path !== '') { + [ + 'filename' => $filename, + 'dirname' => $dirname, + 'extension' => $extension, + ] = pathinfo($path); + } + + $this->file = $file; + $this->dirname = $dirname; + $this->filename = $filename; + $this->extension = $extension; + $this->mimetype = $mimetype; + } + + function getFile(): File + { + if ($this->file === null) { + $this->file = new File($this->path); + } + + return $this->file; + } + + function getPath(): string + { + return $this->dirname . '/' . $this->filename . '.' . $this->extension; + } + + function getUrl(): string + { + helper('media'); + + return media_base_url($this->path); + } + + function getThumbnailPath(): string + { + return $this->dirname . + '/' . + $this->filename . + $this->config->thumbnailSuffix . + '.' . + $this->extension; + } + + function getThumbnailUrl(): string + { + helper('media'); + + return media_base_url($this->thumbnail_path); + } + + function getMediumPath(): string + { + return $this->dirname . + '/' . + $this->filename . + $this->config->mediumSuffix . + '.' . + $this->extension; + } + + function getMediumUrl(): string + { + helper('media'); + + return media_base_url($this->medium_path); + } + + function getLargePath(): string + { + return $this->dirname . + '/' . + $this->filename . + $this->config->largeSuffix . + '.' . + $this->extension; + } + + function getLargeUrl(): string + { + helper('media'); + + return media_base_url($this->large_path); + } + + function getFeedPath(): string + { + return $this->dirname . + '/' . + $this->filename . + $this->config->feedSuffix . + '.' . + $this->extension; + } + + function getFeedUrl(): string + { + helper('media'); + + return media_base_url($this->feed_path); + } + + function getId3Path(): string + { + return $this->dirname . + '/' . + $this->filename . + $this->config->id3Suffix . + '.' . + $this->extension; + } + + function getId3Url(): string + { + helper('media'); + + return media_base_url($this->id3_path); + } + + public function saveImage(string $dirname, string $filename): void + { + helper('media'); + + $this->dirname = $dirname; + $this->filename = $filename; + + save_media($this->file, $this->dirname, $this->filename); + + $imageService = Services::image(); + + $thumbnailSize = $this->config->thumbnailSize; + $mediumSize = $this->config->mediumSize; + $largeSize = $this->config->largeSize; + $feedSize = $this->config->feedSize; + $id3Size = $this->config->id3Size; + + $imageService + ->withFile(media_path($this->path)) + ->resize($thumbnailSize, $thumbnailSize) + ->save(media_path($this->thumbnail_path)); + + $imageService + ->withFile(media_path($this->path)) + ->resize($mediumSize, $mediumSize) + ->save(media_path($this->medium_path)); + + $imageService + ->withFile(media_path($this->path)) + ->resize($largeSize, $largeSize) + ->save(media_path($this->large_path)); + + $imageService + ->withFile(media_path($this->path)) + ->resize($feedSize, $feedSize) + ->save(media_path($this->feed_path)); + + $imageService + ->withFile(media_path($this->path)) + ->resize($id3Size, $id3Size) + ->save(media_path($this->id3_path)); + } +} diff --git a/app/Entities/Language.php b/app/Entities/Language.php index ea9b4a53..d42814b4 100644 --- a/app/Entities/Language.php +++ b/app/Entities/Language.php @@ -10,6 +10,10 @@ namespace App\Entities; use CodeIgniter\Entity\Entity; +/** + * @property string $code + * @property string $native_name + */ class Language extends Entity { /** diff --git a/app/Entities/Location.php b/app/Entities/Location.php new file mode 100644 index 00000000..bfce2ddf --- /dev/null +++ b/app/Entities/Location.php @@ -0,0 +1,45 @@ +osm_id !== null) { + return self::OSM_URL . + ['N' => 'node', 'W' => 'way', 'R' => 'relation'][ + substr($this->osm_id, 0, 1) + ] . + '/' . + substr($this->osm_id, 1); + } + + if ($this->geo !== null) { + return self::OSM_URL . + '#map=17/' . + str_replace(',', '/', substr($this->geo, 4)); + } + + return self::OSM_URL . 'search?query=' . urlencode($this->name); + } +} diff --git a/app/Entities/Note.php b/app/Entities/Note.php index 223a9c20..c6069c6e 100644 --- a/app/Entities/Note.php +++ b/app/Entities/Note.php @@ -8,10 +8,16 @@ namespace App\Entities; +use ActivityPub\Entities\Note as ActivityPubNote; +use App\Models\ActorModel; use App\Models\EpisodeModel; use RuntimeException; -class Note extends \ActivityPub\Entities\Note +/** + * @property int|null $episode_id + * @property Episode|null $episode + */ +class Note extends ActivityPubNote { /** * @var Episode|null @@ -40,13 +46,13 @@ class Note extends \ActivityPub\Entities\Note */ public function getEpisode() { - if (empty($this->episode_id)) { + if ($this->episode_id === null) { throw new RuntimeException( 'Note must have an episode_id before getting episode.', ); } - if (empty($this->episode)) { + if ($this->episode === null) { $this->episode = (new EpisodeModel())->getEpisodeById( $this->episode_id, ); diff --git a/app/Entities/Page.php b/app/Entities/Page.php index 518edf66..500e5bc7 100644 --- a/app/Entities/Page.php +++ b/app/Entities/Page.php @@ -9,8 +9,20 @@ namespace App\Entities; use CodeIgniter\Entity\Entity; +use CodeIgniter\I18n\Time; use League\CommonMark\CommonMarkConverter; +/** + * @property int $id + * @property string $title + * @property string $link + * @property string $slug + * @property string $content_markdown + * @property string $content_html + * @property Time $created_at + * @property Time $updated_at + * @property Time|null $delete_at + */ class Page extends Entity { /** @@ -30,21 +42,27 @@ class Page extends Entity 'id' => 'integer', 'title' => 'string', 'slug' => 'string', - 'content' => 'string', + 'content_markdown' => 'string', + 'content_html' => 'string', ]; - public function getLink() + public function getLink(): string { return url_to('page', $this->attributes['slug']); } - public function getContentHtml(): string + public function setContentMarkdown(string $contentMarkdown): self { $converter = new CommonMarkConverter([ 'html_input' => 'strip', 'allow_unsafe_links' => false, ]); - return $converter->convertToHtml($this->attributes['content']); + $this->attributes['content_markdown'] = $contentMarkdown; + $this->attributes['content_html'] = $converter->convertToHtml( + $contentMarkdown, + ); + + return $this; } } diff --git a/app/Entities/Person.php b/app/Entities/Person.php index 2fdfbc33..5946d95e 100644 --- a/app/Entities/Person.php +++ b/app/Entities/Person.php @@ -8,11 +8,19 @@ namespace App\Entities; -use App\Libraries\Image; -use CodeIgniter\HTTP\Files\UploadedFile; -use CodeIgniter\Files\File; use CodeIgniter\Entity\Entity; +/** + * @property int $id + * @property string $full_name + * @property string $unique_name + * @property string|null $information_url + * @property Image $image + * @property string $image_path + * @property string $image_mimetype + * @property int $created_by + * @property int $updated_by + */ class Person extends Entity { /** @@ -36,26 +44,16 @@ class Person extends Entity /** * Saves a picture in `public/media/persons/` - * - * @param UploadedFile|File|null $image */ - public function setImage($image = null): self + public function setImage(Image $image): self { - if ($image !== null) { - helper('media'); + helper('media'); - $this->attributes['image_mimetype'] = $image->getMimeType(); - $this->attributes['image_path'] = save_media( - $image, - 'persons', - $this->attributes['unique_name'], - ); - $this->image = new Image( - $this->attributes['image_path'], - $this->attributes['image_mimetype'], - ); - $this->image->saveSizes(); - } + // Save image + $image->saveImage('persons', $this->attributes['unique_name']); + + $this->attributes['image_mimetype'] = $image->mimetype; + $this->attributes['image_path'] = $image->path; return $this; } @@ -63,6 +61,7 @@ class Person extends Entity public function getImage(): Image { return new Image( + null, $this->attributes['image_path'], $this->attributes['image_mimetype'], ); diff --git a/app/Entities/Platform.php b/app/Entities/Platform.php index 9cc5662d..cfa50a52 100644 --- a/app/Entities/Platform.php +++ b/app/Entities/Platform.php @@ -10,6 +10,17 @@ namespace App\Entities; use CodeIgniter\Entity\Entity; +/** + * @property string $slug + * @property string $type + * @property string $label + * @property string $home_url + * @property string|null $submit_url + * @property string|null $link_url + * @property string|null $link_content + * @property bool|null $is_visible + * @property bool|null $is_on_embeddable_player + */ class Platform extends Entity { /** diff --git a/app/Entities/Podcast.php b/app/Entities/Podcast.php index 7bd77a15..7476e20d 100644 --- a/app/Entities/Podcast.php +++ b/app/Entities/Podcast.php @@ -8,7 +8,6 @@ namespace App\Entities; -use App\Libraries\Image; use App\Libraries\SimpleRSSElement; use App\Models\CategoryModel; use App\Models\EpisodeModel; @@ -16,11 +15,66 @@ use App\Models\PlatformModel; use App\Models\PodcastPersonModel; use CodeIgniter\Entity\Entity; use App\Models\UserModel; -use CodeIgniter\Files\File; -use CodeIgniter\HTTP\Files\UploadedFile; +use CodeIgniter\I18n\Time; use League\CommonMark\CommonMarkConverter; use RuntimeException; +/** + * @property int $id + * @property int $actor_id + * @property Actor $actor + * @property string $name + * @property string $link + * @property string $feed_url + * @property string $title + * @property string $description Holds text only description, striped of any markdown or html special characters + * @property string $description_markdown + * @property string $description_html + * @property Image $image + * @property string $image_path + * @property string $image_mimetype + * @property string $language_code + * @property int $category_id + * @property Category $category + * @property int[] $other_categories_ids + * @property Category[] $other_categories + * @property string|null $parental_advisory + * @property string|null $publisher + * @property string $owner_name + * @property string $owner_email + * @property string $type + * @property string|null $copyright + * @property string|null $episode_description_footer_markdown + * @property string|null $episode_description_footer_html + * @property bool $is_blocked + * @property bool $is_completed + * @property bool $is_locked + * @property string|null $imported_feed_url + * @property string|null $new_feed_url + * @property Location $location + * @property string|null $location_name + * @property string|null $location_geo + * @property string|null $location_osm_id + * @property string|null $payment_pointer + * @property array|null $custom_rss + * @property string $custom_rss_string + * @property string|null $partner_id + * @property string|null $partner_link_url + * @property string|null $partner_image_url + * @property int $created_by + * @property int $updated_by + * @property Time $created_at; + * @property Time $updated_at; + * @property Time|null $deleted_at; + * + * @property Episode[] $episodes + * @property PodcastPerson[] $persons + * @property User[] $contributors + * @property Platform[] $podcasting_platforms + * @property Platform[] $social_platforms + * @property Platform[] $funding_platforms + * + */ class Podcast extends Entity { /** @@ -39,14 +93,9 @@ class Podcast extends Entity protected $image; /** - * @var Episode[] + * @var string */ - protected $episodes; - - /** - * @var PodcastPerson[] - */ - protected $persons; + protected $description; /** * @var Category @@ -59,44 +108,53 @@ class Podcast extends Entity protected $other_categories; /** - * @var integer[] + * @var string[] */ protected $other_categories_ids; + /** + * @var Episode[] + */ + protected $episodes; + + /** + * @var PodcastPerson[] + */ + protected $persons; + /** * @var User[] */ protected $contributors; /** - * @var Platform + * @var Platform[] */ - protected $podcastingPlatforms; + protected $podcasting_platforms; /** - * @var Platform + * @var Platform[] */ - protected $socialPlatforms; + protected $social_platforms; /** - * @var Platform + * @var Platform[] */ - protected $fundingPlatforms; + protected $funding_platforms; /** - * Holds text only description, striped of any markdown or html special characters - * - * @var string + * @var Location|null */ - protected $description; + protected $location; /** - * Return custom rss as string - * * @var string */ protected $custom_rss_string; + /** + * @var array + */ protected $casts = [ 'id' => 'integer', 'actor_id' => 'integer', @@ -123,7 +181,7 @@ class Podcast extends Entity 'new_feed_url' => '?string', 'location_name' => '?string', 'location_geo' => '?string', - 'location_osmid' => '?string', + 'location_osm_id' => '?string', 'payment_pointer' => '?string', 'custom_rss' => '?json-array', 'partner_id' => '?string', @@ -133,20 +191,15 @@ class Podcast extends Entity 'updated_by' => 'integer', ]; - /** - * Returns the podcast actor - * - * @return Actor - */ public function getActor(): Actor { - if (!$this->attributes['actor_id']) { + if (!$this->actor_id) { throw new RuntimeException( 'Podcast must have an actor_id before getting actor.', ); } - if (empty($this->actor)) { + if ($this->actor === null) { $this->actor = model('ActorModel')->getActorById($this->actor_id); } @@ -156,36 +209,22 @@ class Podcast extends Entity /** * Saves a cover image to the corresponding podcast folder in `public/media/podcast_name/` * - * @param UploadedFile|File $image + * @param Image $image */ - public function setImage($image = null): self + public function setImage($image): self { - if ($image) { - helper('media'); + // Save image + $image->saveImage('podcasts/' . $this->attributes['name'], 'cover'); - $this->attributes['image_mimetype'] = $image->getMimeType(); - $this->attributes['image_path'] = save_media( - $image, - 'podcasts/' . $this->attributes['name'], - 'cover', - ); - - $this->image = new Image( - $this->attributes['image_path'], - $this->attributes['image_mimetype'], - ); - $this->image->saveSizes(); - } + $this->attributes['image_mimetype'] = $image->mimetype; + $this->attributes['image_path'] = $image->path; return $this; } public function getImage(): Image { - return new Image( - $this->attributes['image_path'], - $this->attributes['image_mimetype'], - ); + return new Image(null, $this->image_path, $this->image_mimetype); } public function getLink(): string @@ -350,14 +389,14 @@ class Podcast extends Entity ); } - if (empty($this->podcastingPlatforms)) { - $this->podcastingPlatforms = (new PlatformModel())->getPodcastPlatforms( + if (empty($this->podcasting_platforms)) { + $this->podcasting_platforms = (new PlatformModel())->getPodcastPlatforms( $this->id, 'podcasting', ); } - return $this->podcastingPlatforms; + return $this->podcasting_platforms; } /** @@ -373,14 +412,14 @@ class Podcast extends Entity ); } - if (empty($this->socialPlatforms)) { - $this->socialPlatforms = (new PlatformModel())->getPodcastPlatforms( + if (empty($this->social_platforms)) { + $this->social_platforms = (new PlatformModel())->getPodcastPlatforms( $this->id, 'social', ); } - return $this->socialPlatforms; + return $this->social_platforms; } /** @@ -396,14 +435,14 @@ class Podcast extends Entity ); } - if (empty($this->fundingPlatforms)) { - $this->fundingPlatforms = (new PlatformModel())->getPodcastPlatforms( + if (empty($this->funding_platforms)) { + $this->funding_platforms = (new PlatformModel())->getPodcastPlatforms( $this->id, 'funding', ); } - return $this->fundingPlatforms; + return $this->funding_platforms; } /** @@ -444,29 +483,50 @@ class Podcast extends Entity /** * Saves the location name and fetches OpenStreetMap info */ - public function setLocation(?string $locationName = null): self + public function setLocation(?string $newLocationName = null) { - helper('location'); - - if ( - $locationName && - (empty($this->attributes['location_name']) || - $this->attributes['location_name'] != $locationName) - ) { - $this->attributes['location_name'] = $locationName; - if ($location = fetch_osm_location($locationName)) { - $this->attributes['location_geo'] = $location['geo']; - $this->attributes['location_osmid'] = $location['osmid']; - } - } elseif (empty($locationName)) { + if ($newLocationName === null) { $this->attributes['location_name'] = null; $this->attributes['location_geo'] = null; - $this->attributes['location_osmid'] = null; + $this->attributes['location_osm_id'] = null; + } + + helper('location'); + + $oldLocationName = $this->attributes['location_name']; + + if ( + $oldLocationName === null || + $oldLocationName !== $newLocationName + ) { + $this->attributes['location_name'] = $newLocationName; + + if ($location = fetch_osm_location($newLocationName)) { + $this->attributes['location_geo'] = $location['geo']; + $this->attributes['location_osm_id'] = $location['osm_id']; + } } return $this; } + public function getLocation(): ?Location + { + if ($this->location_name === null) { + return null; + } + + if ($this->location === null) { + $this->location = new Location([ + 'name' => $this->location_name, + 'geo' => $this->location_geo, + 'osm_id' => $this->location_osm_id, + ]); + } + + return $this->location; + } + /** * Get custom rss tag as XML String * diff --git a/app/Entities/PodcastPerson.php b/app/Entities/PodcastPerson.php index 55481910..a3f06aec 100644 --- a/app/Entities/PodcastPerson.php +++ b/app/Entities/PodcastPerson.php @@ -11,6 +11,14 @@ namespace App\Entities; use CodeIgniter\Entity\Entity; use App\Models\PersonModel; +/** + * @property int $id + * @property int $podcast_id + * @property int $person_id + * @property Person $person + * @property string|null $person_group + * @property string|null $person_role + */ class PodcastPerson extends Entity { /** @@ -29,7 +37,7 @@ class PodcastPerson extends Entity 'person_role' => '?string', ]; - public function getPerson() + public function getPerson(): ?Person { return (new PersonModel())->getPersonById( $this->attributes['person_id'], diff --git a/app/Entities/Soundbite.php b/app/Entities/Soundbite.php index a12c13ff..081cb1a6 100644 --- a/app/Entities/Soundbite.php +++ b/app/Entities/Soundbite.php @@ -10,6 +10,16 @@ namespace App\Entities; use CodeIgniter\Entity\Entity; +/** + * @property int $id + * @property int $podcast_id + * @property int $episode_id + * @property double $start_time + * @property double $duration + * @property string|null $label + * @property int $created_by + * @property int $updated_by + */ class Soundbite extends Entity { /** @@ -19,17 +29,10 @@ class Soundbite extends Entity 'id' => 'integer', 'podcast_id' => 'integer', 'episode_id' => 'integer', - 'start_time' => 'float', - 'duration' => 'float', + 'start_time' => 'double', + 'duration' => 'double', 'label' => '?string', 'created_by' => 'integer', 'updated_by' => 'integer', ]; - - public function setUpdatedBy(User $user): self - { - $this->attributes['updated_by'] = $user->id; - - return $this; - } } diff --git a/app/Entities/User.php b/app/Entities/User.php index ca48a273..e899ff8f 100644 --- a/app/Entities/User.php +++ b/app/Entities/User.php @@ -10,22 +10,27 @@ namespace App\Entities; use RuntimeException; use App\Models\PodcastModel; +use Myth\Auth\Entities\User as MythAuthUser; -class User extends \Myth\Auth\Entities\User +/** + * @property int $id + * @property string $username + * @property string $email + * @property string $password + * @property bool $active + * @property bool $force_pass_reset + * @property int|null $podcast_id + * @property string|null $podcast_role + * + * @property Podcast[] $podcasts All podcasts the user is contributing to + */ +class User extends MythAuthUser { /** - * Per-user podcasts * @var Podcast[] */ protected $podcasts = []; - /** - * The podcast the user is contributing to - * - * @var Podcast|null - */ - protected $podcast; - /** * Array of field names and the type of value to cast them as * when they are accessed. @@ -36,8 +41,8 @@ class User extends \Myth\Auth\Entities\User 'id' => 'integer', 'active' => 'boolean', 'force_pass_reset' => 'boolean', - 'podcast_role' => '?string', 'podcast_id' => '?integer', + 'podcast_role' => '?string', ]; /** @@ -47,36 +52,16 @@ class User extends \Myth\Auth\Entities\User */ public function getPodcasts(): array { - if (empty($this->id)) { + if ($this->id === null) { throw new RuntimeException( 'Users must be created before getting podcasts.', ); } - if (empty($this->podcasts)) { + if ($this->podcasts === null) { $this->podcasts = (new PodcastModel())->getUserPodcasts($this->id); } return $this->podcasts; } - - /** - * Returns a podcast the user is contributing to - */ - public function getPodcast(): Podcast - { - if (empty($this->podcast_id)) { - throw new RuntimeException( - 'Podcast_id must be set before getting podcast.', - ); - } - - if (empty($this->podcast)) { - $this->podcast = (new PodcastModel())->getPodcastById( - $this->podcast_id, - ); - } - - return $this->podcast; - } } diff --git a/app/Filters/PermissionFilter.php b/app/Filters/PermissionFilter.php index 929bb954..f4142387 100644 --- a/app/Filters/PermissionFilter.php +++ b/app/Filters/PermissionFilter.php @@ -26,9 +26,7 @@ class PermissionFilter implements FilterInterface */ public function before(RequestInterface $request, $params = null) { - if (!function_exists('logged_in')) { - helper('auth'); - } + helper('auth'); if (empty($params)) { return; diff --git a/app/Helpers/auth_helper.php b/app/Helpers/auth_helper.php index fc07555a..b390d516 100644 --- a/app/Helpers/auth_helper.php +++ b/app/Helpers/auth_helper.php @@ -7,9 +7,22 @@ */ use ActivityPub\Entities\Actor; +use App\Entities\User; use CodeIgniter\Database\Exceptions\DataException; use Config\Services; +if (!function_exists('user')) { + /** + * Returns the User instance for the current logged in user. + */ + function user(): ?User + { + $authenticate = Services::authentication(); + $authenticate->check(); + return $authenticate->user(); + } +} + if (!function_exists('set_interact_as_actor')) { /** * Sets the actor id of which the user is acting as diff --git a/app/Helpers/components_helper.php b/app/Helpers/components_helper.php index 6b8f96c4..a156d3fd 100644 --- a/app/Helpers/components_helper.php +++ b/app/Helpers/components_helper.php @@ -6,6 +6,7 @@ * @link https://castopod.org/ */ +use App\Entities\Location; use CodeIgniter\View\Table; use CodeIgniter\I18n\Time; @@ -127,8 +128,8 @@ if (!function_exists('icon_button')) { * * Abstracts the `button()` helper to create a stylized icon button * - * @param string $label The button label - * @param string $uri URI string or array of URI segments + * @param string $icon The button icon + * @param string $title The button label * @param array $customOptions button options: variant, size, iconLeft, iconRight * @param array $customAttributes Additional attributes * @@ -252,15 +253,11 @@ if (!function_exists('publication_pill')) { * * Shows the stylized publication datetime in regards to current datetime. * - * @param Time $publicationDate publication datetime of the episode - * @param boolean $isPublished whether or not the episode has been published - * @param string $customClass css class to add to the component - * * @return string */ function publication_pill( ?Time $publicationDate, - $publicationStatus, + string $publicationStatus, string $customClass = '' ): string { if ($publicationDate === null) { @@ -336,6 +333,12 @@ if (!function_exists('publication_button')) { $variant = 'danger'; $iconLeft = 'cloud-off'; break; + default: + $label = ''; + $route = ''; + $variant = ''; + $iconLeft = ''; + break; } return button($label, $route, [ @@ -351,16 +354,13 @@ if (!function_exists('episode_numbering')) { /** * Returns relevant translated episode numbering. * - * @param string $class styling classes - * @param string $is_abbr component will show abbreviated numbering if true - * - * @return string|null + * @param bool $isAbbr component will show abbreviated numbering if true */ function episode_numbering( ?int $episodeNumber = null, ?int $seasonNumber = null, string $class = '', - $isAbbr = false + bool $isAbbr = false ): string { if (!$episodeNumber && !$seasonNumber) { return ''; @@ -368,22 +368,20 @@ if (!function_exists('episode_numbering')) { $transKey = ''; $args = []; - if ($episodeNumber && $seasonNumber) { + if ($episodeNumber !== null) { + $args['episodeNumber'] = $episodeNumber; + } + + if ($seasonNumber !== null) { + $args['seasonNumber'] = $seasonNumber; + } + + if ($episodeNumber !== null && $seasonNumber !== null) { $transKey = 'Episode.season_episode'; - $args = [ - 'seasonNumber' => $seasonNumber, - 'episodeNumber' => $episodeNumber, - ]; - } elseif ($episodeNumber && !$seasonNumber) { + } elseif ($episodeNumber !== null && $seasonNumber === null) { $transKey = 'Episode.number'; - $args = [ - 'episodeNumber' => $episodeNumber, - ]; - } elseif (!$episodeNumber && $seasonNumber) { + } elseif ($episodeNumber === null && $seasonNumber !== null) { $transKey = 'Episode.season'; - $args = [ - 'seasonNumber' => $seasonNumber, - ]; } if ($isAbbr) { @@ -408,19 +406,15 @@ if (!function_exists('location_link')) { /** * Returns link to display from location info */ - function location_link( - ?string $locationName, - ?string $locationGeo, - ?string $locationOsmid, - $class = '' - ): string { - if (empty($locationName)) { + function location_link(?Location $location, string $class = ''): string + { + if ($location === null) { return ''; } return anchor( - location_url($locationName, $locationGeo, $locationOsmid), - icon('map-pin', 'mr-2') . $locationName, + $location->url, + icon('map-pin', 'mr-2') . $location->name, [ 'class' => 'inline-flex items-baseline hover:underline' . diff --git a/app/Helpers/id3_helper.php b/app/Helpers/id3_helper.php index 06c2af7d..174dea02 100644 --- a/app/Helpers/id3_helper.php +++ b/app/Helpers/id3_helper.php @@ -15,9 +15,9 @@ if (!function_exists('get_file_tags')) { /** * Gets audio file metadata and ID3 info * - * @param UploadedFile $file + * @return array */ - function get_file_tags($file): array + function get_file_tags(File $file): array { $getID3 = new GetID3(); $FileInfo = $getID3->analyze($file); @@ -34,8 +34,6 @@ if (!function_exists('get_file_tags')) { if (!function_exists('write_audio_file_tags')) { /** * Write audio file metadata / ID3 tags - * - * @return UploadedFile */ function write_audio_file_tags(Episode $episode): void { @@ -51,7 +49,7 @@ if (!function_exists('write_audio_file_tags')) { $tagwriter->tagformats = ['id3v2.4']; $tagwriter->tag_encoding = $TextEncoding; - $cover = new File($episode->image->id3_path); + $cover = new File(media_path($episode->image->id3_path)); $APICdata = file_get_contents($cover->getRealPath()); diff --git a/app/Helpers/location_helper.php b/app/Helpers/location_helper.php index 11a0498d..1c3701d9 100644 --- a/app/Helpers/location_helper.php +++ b/app/Helpers/location_helper.php @@ -11,49 +11,46 @@ use Config\Services; if (!function_exists('fetch_osm_location')) { /** * Fetches places from Nominatim OpenStreetMap - * - * @return array|null */ function fetch_osm_location(string $locationName): ?array { $osmObject = null; - if (!empty($locationName)) { - try { - $client = Services::curlrequest(); + try { + $client = Services::curlrequest(); - $response = $client->request( - 'GET', - 'https://nominatim.openstreetmap.org/search.php?q=' . - urlencode($locationName) . - '&polygon_geojson=1&format=jsonv2', - [ - 'headers' => [ - 'User-Agent' => 'Castopod/' . CP_VERSION, - 'Accept' => 'application/json', - ], + $response = $client->request( + 'GET', + 'https://nominatim.openstreetmap.org/search.php?q=' . + urlencode($locationName) . + '&polygon_geojson=1&format=jsonv2', + [ + 'headers' => [ + 'User-Agent' => 'Castopod/' . CP_VERSION, + 'Accept' => 'application/json', ], - ); - $places = json_decode( - $response->getBody(), - true, - 512, - JSON_THROW_ON_ERROR, - ); - $osmObject = [ - 'geo' => - empty($places[0]['lat']) || empty($places[0]['lon']) - ? null - : "geo:{$places[0]['lat']},{$places[0]['lon']}", - 'osmid' => empty($places[0]['osm_type']) + ], + ); + $places = json_decode( + $response->getBody(), + true, + 512, + JSON_THROW_ON_ERROR, + ); + + $osmObject = [ + 'geo' => + empty($places[0]['lat']) || empty($places[0]['lon']) ? null - : strtoupper(substr($places[0]['osm_type'], 0, 1)) . - $places[0]['osm_id'], - ]; - } catch (Exception $exception) { - //If things go wrong the show must go on - log_message('critical', $exception); - } + : "geo:{$places[0]['lat']},{$places[0]['lon']}", + 'osm_id' => empty($places[0]['osm_type']) + ? null + : strtoupper(substr($places[0]['osm_type'], 0, 1)) . + $places[0]['osm_id'], + ]; + } catch (Exception $exception) { + //If things go wrong the show must go on + log_message('critical', $exception); } return $osmObject; diff --git a/app/Helpers/media_helper.php b/app/Helpers/media_helper.php index 7074bcb7..8491a964 100644 --- a/app/Helpers/media_helper.php +++ b/app/Helpers/media_helper.php @@ -15,14 +15,16 @@ if (!function_exists('save_media')) { /** * Saves a file to the corresponding podcast folder in `public/media` * - * @param File|UploadedFile $filePath + * @param File|UploadedFile $file */ function save_media( - File $filePath, - string $folder, - string $mediaName + File $file, + string $folder = '', + string $filename ): string { - $fileName = $mediaName . '.' . $filePath->getExtension(); + if (($extension = $file->getExtension()) !== '') { + $filename = $filename . '.' . $extension; + } $mediaRoot = config('App')->mediaRoot . '/' . $folder; @@ -31,10 +33,10 @@ if (!function_exists('save_media')) { touch($mediaRoot . '/index.html'); } - // move to media folder and overwrite file if already existing - $filePath->move($mediaRoot . '/', $fileName, true); + // move to media folder, overwrite file if already existing + $file->move($mediaRoot . '/', $filename, true); - return $folder . '/' . $fileName; + return $folder . '/' . $filename; } } @@ -107,8 +109,7 @@ if (!function_exists('media_base_url')) { /** * Return the media base URL to use in views * - * @param string|array $uri URI string or array of URI segments - * @param string $protocol + * @param string|string[] $uri URI string or array of URI segments */ function media_base_url($uri = ''): string { diff --git a/app/Helpers/misc_helper.php b/app/Helpers/misc_helper.php index 2eea0972..91983d48 100644 --- a/app/Helpers/misc_helper.php +++ b/app/Helpers/misc_helper.php @@ -127,7 +127,7 @@ if (!function_exists('slugify')) { $text = iconv('utf-8', 'us-ascii//TRANSLIT', $text); // remove unwanted characters - $text = preg_replace('~[^\\-\w]+~', '', $text); + $text = preg_replace('~[^\-\w]+~', '', $text); // trim $text = trim($text, '-'); diff --git a/app/Helpers/persons_helper.php b/app/Helpers/persons_helper.php index 29fb9461..c7863d4a 100644 --- a/app/Helpers/persons_helper.php +++ b/app/Helpers/persons_helper.php @@ -6,20 +6,24 @@ * @link https://castopod.org/ */ +use App\Entities\Person; +use App\Entities\EpisodePerson; +use App\Entities\PodcastPerson; + if (!function_exists('construct_person_array')) { /** * Fetches persons from an episode * - * @param array &$personsArray + * @param Person[]|PodcastPerson[]|EpisodePerson[] $persons */ - function construct_person_array(array $persons, &$personsArray): void + function construct_person_array(array $persons, array &$personsArray): void { foreach ($persons as $person) { - if (array_key_exists($person->person->id, $personsArray)) { - $personsArray[$person->person->id]['roles'] .= + if (array_key_exists($person->id, $personsArray)) { + $personsArray[$person->id]['roles'] .= empty($person->person_group) || empty($person->person_role) ? '' - : (empty($personsArray[$person->person->id]['roles']) + : (empty($personsArray[$person->id]['roles']) ? '' : ', ') . lang( diff --git a/app/Helpers/rss_helper.php b/app/Helpers/rss_helper.php index 314f30aa..498fee97 100644 --- a/app/Helpers/rss_helper.php +++ b/app/Helpers/rss_helper.php @@ -16,10 +16,10 @@ if (!function_exists('get_rss_feed')) { /** * Generates the rss feed for a given podcast entity * - * @param string $service The name of the service that fetches the RSS feed for future reference when the audio file is eventually downloaded + * @param string $serviceSlug The name of the service that fetches the RSS feed for future reference when the audio file is eventually downloaded * @return string rss feed as xml */ - function get_rss_feed(Podcast $podcast, $serviceSlug = ''): string + function get_rss_feed(Podcast $podcast, ?string $serviceSlug = null): string { $episodes = $podcast->episodes; @@ -43,7 +43,7 @@ if (!function_exists('get_rss_feed')) { $atom_link->addAttribute('rel', 'self'); $atom_link->addAttribute('type', 'application/rss+xml'); - if (!empty($podcast->new_feed_url)) { + if ($podcast->new_feed_url !== null) { $channel->addChild( 'new-feed-url', $podcast->new_feed_url, @@ -67,23 +67,27 @@ if (!function_exists('get_rss_feed')) { $itunes_image = $channel->addChild('image', null, $itunes_namespace); - $itunes_image->addAttribute('href', $podcast->image->original_url); + // FIXME: This should be downsized to 1400x1400 + $itunes_image->addAttribute('href', $podcast->image->url); $channel->addChild('language', $podcast->language_code); - if (!empty($podcast->location_name)) { + if ($podcast->location !== null) { $locationElement = $channel->addChild( 'location', - htmlspecialchars($podcast->location_name), + htmlspecialchars($podcast->location->name), $podcast_namespace, ); - if (!empty($podcast->location_geo)) { - $locationElement->addAttribute('geo', $podcast->location_geo); + if ($podcast->location->geo !== null) { + $locationElement->addAttribute('geo', $podcast->location->geo); } - if (!empty($podcast->location_osmid)) { - $locationElement->addAttribute('osm', $podcast->location_osmid); + if ($podcast->location->osm_id !== null) { + $locationElement->addAttribute( + 'osm', + $podcast->location->osm_id, + ); } } - if (!empty($podcast->payment_pointer)) { + if ($podcast->payment_pointer !== null) { $valueElement = $channel->addChild( 'value', null, @@ -103,7 +107,7 @@ if (!function_exists('get_rss_feed')) { 'address', $podcast->payment_pointer, ); - $recipientElement->addAttribute('split', 100); + $recipientElement->addAttribute('split', '100'); } $channel ->addChild( @@ -112,7 +116,7 @@ if (!function_exists('get_rss_feed')) { $podcast_namespace, ) ->addAttribute('owner', $podcast->owner_email); - if (!empty($podcast->imported_feed_url)) { + if ($podcast->imported_feed_url !== null) { $channel->addChild( 'previousUrl', $podcast->imported_feed_url, @@ -120,7 +124,7 @@ if (!function_exists('get_rss_feed')) { ); } - foreach ($podcast->podcastingPlatforms as $podcastingPlatform) { + foreach ($podcast->podcasting_platforms as $podcastingPlatform) { $podcastingPlatformElement = $channel->addChild( 'id', null, @@ -130,13 +134,13 @@ if (!function_exists('get_rss_feed')) { 'platform', $podcastingPlatform->slug, ); - if (!empty($podcastingPlatform->link_content)) { + if ($podcastingPlatform->link_content !== null) { $podcastingPlatformElement->addAttribute( 'id', $podcastingPlatform->link_content, ); } - if (!empty($podcastingPlatform->link_url)) { + if ($podcastingPlatform->link_url !== null) { $podcastingPlatformElement->addAttribute( 'url', htmlspecialchars($podcastingPlatform->link_url), @@ -144,7 +148,7 @@ if (!function_exists('get_rss_feed')) { } } - foreach ($podcast->socialPlatforms as $socialPlatform) { + foreach ($podcast->social_platforms as $socialPlatform) { $socialPlatformElement = $channel->addChild( 'social', $socialPlatform->link_content, @@ -154,7 +158,7 @@ if (!function_exists('get_rss_feed')) { 'platform', $socialPlatform->slug, ); - if (!empty($socialPlatform->link_url)) { + if ($socialPlatform->link_url !== null) { $socialPlatformElement->addAttribute( 'url', htmlspecialchars($socialPlatform->link_url), @@ -162,7 +166,7 @@ if (!function_exists('get_rss_feed')) { } } - foreach ($podcast->fundingPlatforms as $fundingPlatform) { + foreach ($podcast->funding_platforms as $fundingPlatform) { $fundingPlatformElement = $channel->addChild( 'funding', $fundingPlatform->link_content, @@ -172,7 +176,7 @@ if (!function_exists('get_rss_feed')) { 'platform', $fundingPlatform->slug, ); - if (!empty($socialPlatform->link_url)) { + if ($fundingPlatform->link_url !== null) { $fundingPlatformElement->addAttribute( 'url', htmlspecialchars($fundingPlatform->link_url), @@ -186,9 +190,10 @@ if (!function_exists('get_rss_feed')) { htmlspecialchars($podcastPerson->person->full_name), $podcast_namespace, ); + if ( - !empty($podcastPerson->person_role) && - !empty($podcastPerson->person_group) + $podcastPerson->person_role !== null && + $podcastPerson->person_group !== null ) { $podcastPersonElement->addAttribute( 'role', @@ -201,7 +206,8 @@ if (!function_exists('get_rss_feed')) { ), ); } - if (!empty($podcastPerson->person_group)) { + + if ($podcastPerson->person_group !== null) { $podcastPersonElement->addAttribute( 'group', htmlspecialchars( @@ -217,7 +223,8 @@ if (!function_exists('get_rss_feed')) { 'img', $podcastPerson->person->image->large_url, ); - if (!empty($podcastPerson->person->information_url)) { + + if ($podcastPerson->person->information_url !== null) { $podcastPersonElement->addAttribute( 'href', $podcastPerson->person->information_url, @@ -263,7 +270,7 @@ if (!function_exists('get_rss_feed')) { $image->addChild('title', $podcast->title); $image->addChild('link', $podcast->link); - if (!empty($podcast->custom_rss)) { + if ($podcast->custom_rss !== null) { array_to_rss( [ 'elements' => $podcast->custom_rss, @@ -280,7 +287,7 @@ if (!function_exists('get_rss_feed')) { $enclosure->addAttribute( 'url', $episode->audio_file_analytics_url . - (empty($serviceSlug) + ($serviceSlug === '' ? '' : '?_from=' . urlencode($serviceSlug)), ); @@ -292,22 +299,22 @@ if (!function_exists('get_rss_feed')) { 'pubDate', $episode->published_at->format(DATE_RFC1123), ); - if (!empty($episode->location_name)) { + if ($episode->location !== null) { $locationElement = $item->addChild( 'location', - htmlspecialchars($episode->location_name), + htmlspecialchars($episode->location->name), $podcast_namespace, ); - if (!empty($episode->location_geo)) { + if ($episode->location->geo !== null) { $locationElement->addAttribute( 'geo', - $episode->location_geo, + $episode->location->geo, ); } - if (!empty($episode->location_osmid)) { + if ($episode->location->osm_id !== null) { $locationElement->addAttribute( 'osm', - $episode->location_osmid, + $episode->location->osm_id, ); } } @@ -477,7 +484,7 @@ if (!function_exists('add_category_tag')) { { $itunes_namespace = 'http://www.itunes.com/dtds/podcast-1.0.dtd'; - $itunes_category = $node->addChild('category', null, $itunes_namespace); + $itunes_category = $node->addChild('category', '', $itunes_namespace); $itunes_category->addAttribute( 'text', $category->parent !== null @@ -488,7 +495,7 @@ if (!function_exists('add_category_tag')) { if ($category->parent !== null) { $itunes_category_child = $itunes_category->addChild( 'category', - null, + '', $itunes_namespace, ); $itunes_category_child->addAttribute( diff --git a/app/Helpers/url_helper.php b/app/Helpers/url_helper.php index 0e860743..80b4f7b5 100644 --- a/app/Helpers/url_helper.php +++ b/app/Helpers/url_helper.php @@ -6,13 +6,13 @@ * @link https://castopod.org/ */ +use CodeIgniter\HTTP\URI; + if (!function_exists('host_url')) { /** * Return the host URL to use in views - * - * @return string|false */ - function host_url() + function host_url(): ?string { if (isset($_SERVER['HTTP_HOST'])) { $protocol = @@ -23,7 +23,7 @@ if (!function_exists('host_url')) { return $protocol . $_SERVER['HTTP_HOST'] . '/'; } - return false; + return null; } } @@ -43,41 +43,13 @@ if (!function_exists('current_season_url')) { } } -if (!function_exists('location_url')) { - /** - * Returns URL to display from location info - */ - function location_url( - string $locationName, - ?string $locationGeo = null, - ?string $locationOsmid = null - ): string { - if (!empty($locationOsmid)) { - return 'https://www.openstreetmap.org/' . - ['N' => 'node', 'W' => 'way', 'R' => 'relation'][ - substr($locationOsmid, 0, 1) - ] . - '/' . - substr($locationOsmid, 1); - } - if (!empty($locationGeo)) { - return 'https://www.openstreetmap.org/#map=17/' . - str_replace(',', '/', substr($locationGeo, 4)); - } - - return 'https://www.openstreetmap.org/search?query=' . - urlencode($locationName); - } -} //-------------------------------------------------------------------- if (!function_exists('extract_params_from_episode_uri')) { /** * Returns podcast name and episode slug from episode string uri - * - * @param URI $episodeUri */ - function extract_params_from_episode_uri($episodeUri): ?array + function extract_params_from_episode_uri(URI $episodeUri): ?array { preg_match( '~@(?P[a-zA-Z0-9\_]{1,32})\/episodes\/(?P[a-zA-Z0-9\-]{1,191})~', diff --git a/app/Libraries/ActivityPub/ActivityRequest.php b/app/Libraries/ActivityPub/ActivityRequest.php index 9f8925a7..9b3accbd 100644 --- a/app/Libraries/ActivityPub/ActivityRequest.php +++ b/app/Libraries/ActivityPub/ActivityRequest.php @@ -43,15 +43,11 @@ class ActivityRequest ], ]; - /** - * @param string $uri - * @param string $activityPayload - */ - public function __construct($uri, $activityPayload = null) + public function __construct(string $uri, ?string $activityPayload = null) { $this->request = Services::curlrequest(); - if ($activityPayload) { + if ($activityPayload !== null) { $this->request->setBody($activityPayload); } diff --git a/app/Libraries/ActivityPub/Controllers/ActorController.php b/app/Libraries/ActivityPub/Controllers/ActorController.php index bdaa53df..4bc7b77e 100644 --- a/app/Libraries/ActivityPub/Controllers/ActorController.php +++ b/app/Libraries/ActivityPub/Controllers/ActorController.php @@ -8,15 +8,14 @@ namespace ActivityPub\Controllers; -use ActivityPub\Entities\Actor; use ActivityPub\Config\ActivityPub; use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\ResponseInterface; use CodeIgniter\Exceptions\PageNotFoundException; use ActivityPub\Entities\Note; -use CodeIgniter\HTTP\Exceptions\HTTPException; use ActivityPub\Objects\OrderedCollectionObject; use ActivityPub\Objects\OrderedCollectionPage; +use App\Entities\Actor; use CodeIgniter\Controller; use CodeIgniter\I18n\Time; @@ -325,13 +324,10 @@ class ActorController extends Controller // parse activityPub id to get actor and domain // check if actor and domain exist - try { - if ($parts = split_handle($this->request->getPost('handle'))) { - extract($parts); - - $data = get_webfinger_data($username, $domain); - } - } catch (HTTPException $httpException) { + if ( + !($parts = split_handle($this->request->getPost('handle'))) || + !($data = get_webfinger_data($parts['username'], $parts['domain'])) + ) { return redirect() ->back() ->withInput() diff --git a/app/Libraries/ActivityPub/Controllers/BlockController.php b/app/Libraries/ActivityPub/Controllers/BlockController.php index f38d84e1..22c2e148 100644 --- a/app/Libraries/ActivityPub/Controllers/BlockController.php +++ b/app/Libraries/ActivityPub/Controllers/BlockController.php @@ -33,9 +33,12 @@ class BlockController extends Controller $handle = $this->request->getPost('handle'); if ($parts = split_handle($handle)) { - extract($parts); - - if (($actor = get_or_create_actor($username, $domain)) === null) { + if ( + ($actor = get_or_create_actor( + $parts['username'], + $parts['domain'], + )) === null + ) { return redirect() ->back() ->withInput() diff --git a/app/Libraries/ActivityPub/Controllers/NoteController.php b/app/Libraries/ActivityPub/Controllers/NoteController.php index 708e92d7..4883acc6 100644 --- a/app/Libraries/ActivityPub/Controllers/NoteController.php +++ b/app/Libraries/ActivityPub/Controllers/NoteController.php @@ -12,8 +12,8 @@ use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\ResponseInterface; use CodeIgniter\Exceptions\PageNotFoundException; use ActivityPub\Entities\Note; -use CodeIgniter\HTTP\Exceptions\HTTPException; use ActivityPub\Config\ActivityPub; +use ActivityPub\Models\NoteModel; use ActivityPub\Objects\OrderedCollectionObject; use ActivityPub\Objects\OrderedCollectionPage; use CodeIgniter\Controller; @@ -27,7 +27,7 @@ class NoteController extends Controller protected $helpers = ['activitypub']; /** - * @var Note|null + * @var Note */ protected $note; @@ -41,7 +41,7 @@ class NoteController extends Controller $this->config = config('ActivityPub'); } - public function _remap($method, ...$params) + public function _remap(string $method, string ...$params) { if (!($this->note = model('NoteModel')->getNoteById($params[0]))) { throw PageNotFoundException::forPageNotFound(); @@ -63,7 +63,8 @@ class NoteController extends Controller public function replies(): RedirectResponse { - // get note replies + /** get note replies + * @var NoteModel */ $noteReplies = model('NoteModel') ->where( 'in_reply_to_id', @@ -90,10 +91,14 @@ class NoteController extends Controller $orderedItems = []; $noteObjectClass = $this->config->noteObject; - foreach ($paginatedReplies as $reply) { - $replyObject = new $noteObjectClass($reply); - $orderedItems[] = $replyObject->toJSON(); + + if ($paginatedReplies !== null) { + foreach ($paginatedReplies as $reply) { + $replyObject = new $noteObjectClass($reply); + $orderedItems[] = $replyObject->toJSON(); + } } + $collection = new OrderedCollectionPage($pager, $orderedItems); } @@ -102,7 +107,7 @@ class NoteController extends Controller ->setBody($collection->toJSON()); } - public function attemptCreate() + public function attemptCreate(): RedirectResponse { $rules = [ 'actor_id' => 'required|is_natural_no_zero', @@ -134,7 +139,7 @@ class NoteController extends Controller return redirect()->back(); } - public function attemptFavourite() + public function attemptFavourite(): RedirectResponse { $rules = [ 'actor_id' => 'required|is_natural_no_zero', @@ -156,7 +161,7 @@ class NoteController extends Controller return redirect()->back(); } - public function attemptReblog() + public function attemptReblog(): RedirectResponse { $rules = [ 'actor_id' => 'required|is_natural_no_zero', @@ -178,7 +183,7 @@ class NoteController extends Controller return redirect()->back(); } - public function attemptReply() + public function attemptReply(): RedirectResponse { $rules = [ 'actor_id' => 'required|is_natural_no_zero', @@ -233,13 +238,10 @@ class NoteController extends Controller // get webfinger data from actor // parse activityPub id to get actor and domain // check if actor and domain exist - try { - if ($parts = split_handle($this->request->getPost('handle'))) { - extract($parts); - - $data = get_webfinger_data($username, $domain); - } - } catch (HTTPException $httpException) { + if ( + !($parts = split_handle($this->request->getPost('handle'))) || + !($data = get_webfinger_data($parts['username'], $parts['domain'])) + ) { return redirect() ->back() ->withInput() @@ -266,21 +268,21 @@ class NoteController extends Controller ); } - public function attemptBlockActor() + public function attemptBlockActor(): RedirectResponse { model('ActorModel')->blockActor($this->note->actor->id); return redirect()->back(); } - public function attemptBlockDomain() + public function attemptBlockDomain(): RedirectResponse { model('BlockedDomainModel')->blockDomain($this->note->actor->domain); return redirect()->back(); } - public function attemptDelete() + public function attemptDelete(): RedirectResponse { model('NoteModel', false)->removeNote($this->note); diff --git a/app/Libraries/ActivityPub/Core/AbstractObject.php b/app/Libraries/ActivityPub/Core/AbstractObject.php index 4e4de802..aeca7c4a 100644 --- a/app/Libraries/ActivityPub/Core/AbstractObject.php +++ b/app/Libraries/ActivityPub/Core/AbstractObject.php @@ -15,7 +15,10 @@ namespace ActivityPub\Core; abstract class AbstractObject { - public function set($property, $value): self + /** + * @param mixed $value + */ + public function set(string $property, $value): self { $this->$property = $value; @@ -35,7 +38,7 @@ abstract class AbstractObject } $array[$key] = - is_object($value) && $value instanceof self + is_object($value) && is_subclass_of($value, self::class) ? $value->toArray() : $value; } diff --git a/app/Libraries/ActivityPub/Database/Migrations/2018-01-01-020000_add_notes.php b/app/Libraries/ActivityPub/Database/Migrations/2018-01-01-020000_add_notes.php index f6cc7cf6..1ceb9526 100644 --- a/app/Libraries/ActivityPub/Database/Migrations/2018-01-01-020000_add_notes.php +++ b/app/Libraries/ActivityPub/Database/Migrations/2018-01-01-020000_add_notes.php @@ -81,21 +81,21 @@ class AddNotes extends Migration 'actor_id', 'activitypub_actors', 'id', - false, + '', 'CASCADE', ); $this->forge->addForeignKey( 'in_reply_to_id', 'activitypub_notes', 'id', - false, + '', 'CASCADE', ); $this->forge->addForeignKey( 'reblog_of_id', 'activitypub_notes', 'id', - false, + '', 'CASCADE', ); $this->forge->createTable('activitypub_notes'); diff --git a/app/Libraries/ActivityPub/Database/Migrations/2018-01-01-100000_add_activities.php b/app/Libraries/ActivityPub/Database/Migrations/2018-01-01-100000_add_activities.php index de475d92..d3d4cc5e 100644 --- a/app/Libraries/ActivityPub/Database/Migrations/2018-01-01-100000_add_activities.php +++ b/app/Libraries/ActivityPub/Database/Migrations/2018-01-01-100000_add_activities.php @@ -63,21 +63,21 @@ class AddActivities extends Migration 'actor_id', 'activitypub_actors', 'id', - false, + '', 'CASCADE', ); $this->forge->addForeignKey( 'target_actor_id', 'activitypub_actors', 'id', - false, + '', 'CASCADE', ); $this->forge->addForeignKey( 'note_id', 'activitypub_notes', 'id', - false, + '', 'CASCADE', ); $this->forge->createTable('activitypub_activities'); diff --git a/app/Libraries/ActivityPub/Database/Migrations/2018-01-01-100000_add_favourites.php b/app/Libraries/ActivityPub/Database/Migrations/2018-01-01-100000_add_favourites.php index c7ecddcf..1959d4ef 100644 --- a/app/Libraries/ActivityPub/Database/Migrations/2018-01-01-100000_add_favourites.php +++ b/app/Libraries/ActivityPub/Database/Migrations/2018-01-01-100000_add_favourites.php @@ -35,14 +35,14 @@ class AddFavourites extends Migration 'actor_id', 'activitypub_actors', 'id', - false, + '', 'CASCADE', ); $this->forge->addForeignKey( 'note_id', 'activitypub_notes', 'id', - false, + '', 'CASCADE', ); $this->forge->createTable('activitypub_favourites'); diff --git a/app/Libraries/ActivityPub/Database/Migrations/2018-01-01-100000_add_follows.php b/app/Libraries/ActivityPub/Database/Migrations/2018-01-01-100000_add_follows.php index b7b8a809..3e6717b9 100644 --- a/app/Libraries/ActivityPub/Database/Migrations/2018-01-01-100000_add_follows.php +++ b/app/Libraries/ActivityPub/Database/Migrations/2018-01-01-100000_add_follows.php @@ -37,14 +37,14 @@ class AddFollowers extends Migration 'actor_id', 'activitypub_actors', 'id', - false, + '', 'CASCADE', ); $this->forge->addForeignKey( 'target_actor_id', 'activitypub_actors', 'id', - false, + '', 'CASCADE', ); $this->forge->createTable('activitypub_follows'); diff --git a/app/Libraries/ActivityPub/Database/Migrations/2018-01-01-110000_add_notes_preview_cards.php b/app/Libraries/ActivityPub/Database/Migrations/2018-01-01-110000_add_notes_preview_cards.php index 74ae7dbc..2b1d5e43 100644 --- a/app/Libraries/ActivityPub/Database/Migrations/2018-01-01-110000_add_notes_preview_cards.php +++ b/app/Libraries/ActivityPub/Database/Migrations/2018-01-01-110000_add_notes_preview_cards.php @@ -33,14 +33,14 @@ class AddNotesPreviewCards extends Migration 'note_id', 'activitypub_notes', 'id', - false, + '', 'CASCADE', ); $this->forge->addForeignKey( 'preview_card_id', 'activitypub_preview_cards', 'id', - false, + '', 'CASCADE', ); $this->forge->createTable('activitypub_notes_preview_cards'); diff --git a/app/Libraries/ActivityPub/Entities/Activity.php b/app/Libraries/ActivityPub/Entities/Activity.php index fa595cec..54cfc90f 100644 --- a/app/Libraries/ActivityPub/Entities/Activity.php +++ b/app/Libraries/ActivityPub/Entities/Activity.php @@ -11,28 +11,42 @@ namespace ActivityPub\Entities; use RuntimeException; use Michalsn\Uuid\UuidEntity; +/** + * @property string $id + * @property int $actor_id + * @property Actor $actor + * @property int|null $target_actor_id + * @property Actor|null $target_actor + * @property string|null $note_id + * @property Note|null $note + * @property string $type + * @property object $payload + * @property string|null $status + * @property Time|null $scheduled_at + * @property Time $created_at + */ class Activity extends UuidEntity { - /** - * @var string[] - */ - protected $uuids = ['id', 'note_id']; - /** * @var Actor */ protected $actor; /** - * @var Actor + * @var Actor|null */ protected $target_actor; /** - * @var Note + * @var Note|null */ protected $note; + /** + * @var string[] + */ + protected $uuids = ['id', 'note_id']; + /** * @var string[] */ diff --git a/app/Libraries/ActivityPub/Entities/Actor.php b/app/Libraries/ActivityPub/Entities/Actor.php index db64f837..51215ceb 100644 --- a/app/Libraries/ActivityPub/Entities/Actor.php +++ b/app/Libraries/ActivityPub/Entities/Actor.php @@ -11,12 +11,36 @@ namespace ActivityPub\Entities; use RuntimeException; use CodeIgniter\Entity\Entity; +/** + * @property int $id + * @property string $uri + * @property string $username + * @property string $domain + * @property string $display_name + * @property string|null $summary + * @property string|null $private_key + * @property string|null $public_key + * @property string|null $public_key_id + * @property string|null $avatar_image_url + * @property string|null $avatar_image_mimetype + * @property string|null $cover_image_url + * @property string|null $cover_image_mimetype + * @property string $inbox_url + * @property string|null $outbox_url + * @property string|null $followers_url + * @property int $followers_count + * @property int $notes_count + * @property bool $is_blocked + * + * @property Actor[] $followers + * @property bool $is_local + */ class Actor extends Entity { /** * @var string */ - protected $key_id; + protected $public_key_id; /** * @var Actor[] @@ -52,7 +76,7 @@ class Actor extends Entity 'is_blocked' => 'boolean', ]; - public function getKeyId(): string + public function getPublicKeyId(): string { return $this->uri . '#main-key'; } @@ -72,7 +96,7 @@ class Actor extends Entity } /** - * @return Follower[] + * @return Actor[] */ public function getFollowers(): array { diff --git a/app/Libraries/ActivityPub/Entities/BlockedDomain.php b/app/Libraries/ActivityPub/Entities/BlockedDomain.php index 8405d883..9d0009a5 100644 --- a/app/Libraries/ActivityPub/Entities/BlockedDomain.php +++ b/app/Libraries/ActivityPub/Entities/BlockedDomain.php @@ -10,6 +10,9 @@ namespace ActivityPub\Entities; use CodeIgniter\Entity\Entity; +/** + * @property string $name + */ class BlockedDomain extends Entity { /** diff --git a/app/Libraries/ActivityPub/Entities/Favourite.php b/app/Libraries/ActivityPub/Entities/Favourite.php index ea4381b2..6bc1a52e 100644 --- a/app/Libraries/ActivityPub/Entities/Favourite.php +++ b/app/Libraries/ActivityPub/Entities/Favourite.php @@ -10,6 +10,10 @@ namespace ActivityPub\Entities; use Michalsn\Uuid\UuidEntity; +/** + * @property int $actor_id + * @property string $note_id + */ class Favourite extends UuidEntity { /** @@ -22,6 +26,6 @@ class Favourite extends UuidEntity */ protected $casts = [ 'actor_id' => 'integer', - 'note_id' => 'integer', + 'note_id' => 'string', ]; } diff --git a/app/Libraries/ActivityPub/Entities/Follow.php b/app/Libraries/ActivityPub/Entities/Follow.php index fd966a17..cb5ff364 100644 --- a/app/Libraries/ActivityPub/Entities/Follow.php +++ b/app/Libraries/ActivityPub/Entities/Follow.php @@ -10,6 +10,10 @@ namespace ActivityPub\Entities; use CodeIgniter\Entity\Entity; +/** + * @property int $actor_id + * @property int $target_actor_id + */ class Follow extends Entity { /** diff --git a/app/Libraries/ActivityPub/Entities/Note.php b/app/Libraries/ActivityPub/Entities/Note.php index b6b6d858..9d68ef6c 100644 --- a/app/Libraries/ActivityPub/Entities/Note.php +++ b/app/Libraries/ActivityPub/Entities/Note.php @@ -8,16 +8,38 @@ namespace ActivityPub\Entities; +use CodeIgniter\I18n\Time; use RuntimeException; use Michalsn\Uuid\UuidEntity; +/** + * @property string $id + * @property string $uri + * @property int $actor_id + * @property Actor $actor + * @property string|null $in_reply_to_id + * @property bool $is_reply + * @property Note|null $reply_to_note + * @property string|null $reblog_of_id + * @property bool $is_reblog + * @property Note|null $reblog_of_note + * @property string $message + * @property string $message_html + * @property int $favourites_count + * @property int $reblogs_count + * @property int $replies_count + * @property Time $published_at + * @property Time $created_at + * + * @property bool $has_preview_card + * @property PreviewCard|null $preview_card + * + * @property bool $has_replies + * @property Note[] $replies + * @property Note[] $reblogs + */ class Note extends UuidEntity { - /** - * @var string[] - */ - protected $uuids = ['id', 'in_reply_to_id', 'reblog_of_id']; - /** * @var Actor */ @@ -68,6 +90,11 @@ class Note extends UuidEntity */ protected $reblogs = []; + /** + * @var string[] + */ + protected $uuids = ['id', 'in_reply_to_id', 'reblog_of_id']; + /** * @var string[] */ diff --git a/app/Libraries/ActivityPub/Entities/PreviewCard.php b/app/Libraries/ActivityPub/Entities/PreviewCard.php index 62cbcd62..35cb1973 100644 --- a/app/Libraries/ActivityPub/Entities/PreviewCard.php +++ b/app/Libraries/ActivityPub/Entities/PreviewCard.php @@ -10,6 +10,20 @@ namespace ActivityPub\Entities; use CodeIgniter\Entity\Entity; +/** + * @property int $id + * @property string $note_id + * @property string $url + * @property string $title + * @property string $description + * @property string $type + * @property string|null $author_name + * @property string|null $author_url + * @property string|null $provider_name + * @property string|null $provider_url + * @property string|null $image + * @property string|null $html + */ class PreviewCard extends Entity { /** diff --git a/app/Libraries/ActivityPub/Helpers/activitypub_helper.php b/app/Libraries/ActivityPub/Helpers/activitypub_helper.php index 8e6e6d6e..ed7931ca 100644 --- a/app/Libraries/ActivityPub/Helpers/activitypub_helper.php +++ b/app/Libraries/ActivityPub/Helpers/activitypub_helper.php @@ -26,7 +26,6 @@ if (!function_exists('get_webfinger_data')) { $webfingerUri = new URI(); $webfingerUri->setScheme('https'); $webfingerUri->setHost($domain); - isset($port) && $webfingerUri->setPort((int) $port); $webfingerUri->setPath('/.well-known/webfinger'); $webfingerUri->setQuery("resource=acct:{$username}@{$domain}"); @@ -35,7 +34,7 @@ if (!function_exists('get_webfinger_data')) { return json_decode( $webfingerResponse->getBody(), - null, + false, 512, JSON_THROW_ON_ERROR, ); @@ -106,7 +105,7 @@ if (!function_exists('accept_follow')) { $targetActor->inbox_url, $acceptActivity->toJSON(), ); - $acceptRequest->sign($actor->key_id, $actor->private_key); + $acceptRequest->sign($actor->public_key_id, $actor->private_key); $acceptRequest->post(); } catch (Exception $exception) { $db->transRollback(); @@ -119,18 +118,21 @@ if (!function_exists('accept_follow')) { if (!function_exists('send_activity_to_followers')) { /** * Sends an activity to all actor followers - * - * @param string $activity */ - function send_activity_to_followers(Actor $actor, $activityPayload): void - { + function send_activity_to_followers( + Actor $actor, + string $activityPayload + ): void { foreach ($actor->followers as $follower) { try { $acceptRequest = new ActivityRequest( $follower->inbox_url, $activityPayload, ); - $acceptRequest->sign($actor->key_id, $actor->private_key); + $acceptRequest->sign( + $actor->public_key_id, + $actor->private_key, + ); $acceptRequest->post(); } catch (Exception $e) { // log error @@ -299,7 +301,7 @@ if (!function_exists('create_actor_from_uri')) { $actorResponse = $activityRequest->get(); $actorPayload = json_decode( $actorResponse->getBody(), - null, + false, 512, JSON_THROW_ON_ERROR, ); @@ -351,9 +353,9 @@ if (!function_exists('extract_text_from_html')) { /** * Extracts the text from html content * - * @return string|string[]|null + * @return string|null */ - function extract_text_from_html(string $content) + function extract_text_from_html(string $content): ?string { return preg_replace('~\s+~', ' ', strip_tags($content)); } @@ -364,12 +366,12 @@ if (!function_exists('linkify')) { * Turn all link elements in clickable links. * Transforms urls and handles * - * @param string $value - * @param array $protocols http/https, ftp, mail, twitter - * @param array $attributes + * @param string[] $protocols http/https, twitter */ - function linkify($text, array $protocols = ['http', 'handle']): string - { + function linkify( + string $text, + array $protocols = ['http', 'handle'] + ): string { $links = []; // Extract text links for each protocol diff --git a/app/Libraries/ActivityPub/HttpSignature.php b/app/Libraries/ActivityPub/HttpSignature.php index 077233fd..30d30196 100644 --- a/app/Libraries/ActivityPub/HttpSignature.php +++ b/app/Libraries/ActivityPub/HttpSignature.php @@ -97,15 +97,17 @@ class HttpSignature throw new Exception('Malformed signature string.'); } - // extract parts as $keyId, $headers and $signature variables - extract($parts); + // set $keyId, $headers and $signature variables + $keyId = $parts['keyId']; + $headers = $parts['headers']; + $signature = $parts['signature']; // Fetch the public key linked from keyId $actorRequest = new ActivityRequest($keyId); $actorResponse = $actorRequest->get(); $actor = json_decode( $actorResponse->getBody(), - null, + false, 512, JSON_THROW_ON_ERROR, ); diff --git a/app/Libraries/ActivityPub/Models/ActivityModel.php b/app/Libraries/ActivityPub/Models/ActivityModel.php index cdd9020e..388eddb5 100644 --- a/app/Libraries/ActivityPub/Models/ActivityModel.php +++ b/app/Libraries/ActivityPub/Models/ActivityModel.php @@ -9,6 +9,7 @@ namespace ActivityPub\Models; use ActivityPub\Entities\Activity; +use CodeIgniter\Database\BaseResult; use CodeIgniter\I18n\Time; use DateTimeInterface; use Michalsn\Uuid\UuidModel; @@ -76,7 +77,7 @@ class ActivityModel extends UuidModel * * @param Time $scheduledAt * - * @return Michalsn\Uuid\BaseResult|int|string|false + * @return BaseResult|int|string|false */ public function newActivity( string $type, diff --git a/app/Libraries/ActivityPub/Models/ActorModel.php b/app/Libraries/ActivityPub/Models/ActorModel.php index c7548d8f..795d5c8f 100644 --- a/app/Libraries/ActivityPub/Models/ActorModel.php +++ b/app/Libraries/ActivityPub/Models/ActorModel.php @@ -9,6 +9,7 @@ namespace ActivityPub\Models; use ActivityPub\Entities\Actor; +use CodeIgniter\Database\Exceptions\DataException; use CodeIgniter\Events\Events; use CodeIgniter\Model; @@ -57,7 +58,7 @@ class ActorModel extends Model */ protected $useTimestamps = true; - public function getActorById($id) + public function getActorById($id): Actor { $cacheName = config('ActivityPub')->cachePrefix . "actor#{$id}"; if (!($found = cache($cacheName))) { diff --git a/app/Libraries/ActivityPub/Models/BlockedDomainModel.php b/app/Libraries/ActivityPub/Models/BlockedDomainModel.php index 60b0f203..5f67279b 100644 --- a/app/Libraries/ActivityPub/Models/BlockedDomainModel.php +++ b/app/Libraries/ActivityPub/Models/BlockedDomainModel.php @@ -49,8 +49,6 @@ class BlockedDomainModel extends Model /** * Retrieves instance or podcast domain blocks depending on whether or not $podcastId param is set. - * - * @param integer|null $podcastId */ public function getBlockedDomains() { diff --git a/app/Libraries/ActivityPub/Models/FavouriteModel.php b/app/Libraries/ActivityPub/Models/FavouriteModel.php index 8dbb292a..b61fba39 100644 --- a/app/Libraries/ActivityPub/Models/FavouriteModel.php +++ b/app/Libraries/ActivityPub/Models/FavouriteModel.php @@ -137,7 +137,8 @@ class FavouriteModel extends UuidModel ); } - $this->table('activitypub_favourites') + $this->db + ->table('activitypub_favourites') ->where([ 'actor_id' => $actor->id, 'note_id' => service('uuid') diff --git a/app/Libraries/ActivityPub/Models/NoteModel.php b/app/Libraries/ActivityPub/Models/NoteModel.php index fe33f0df..2a5e0da6 100644 --- a/app/Libraries/ActivityPub/Models/NoteModel.php +++ b/app/Libraries/ActivityPub/Models/NoteModel.php @@ -17,6 +17,7 @@ use ActivityPub\Activities\CreateActivity; use ActivityPub\Activities\DeleteActivity; use ActivityPub\Activities\UndoActivity; use ActivityPub\Objects\TombstoneObject; +use CodeIgniter\Database\BaseResult; use CodeIgniter\Events\Events; use CodeIgniter\HTTP\URI; use CodeIgniter\I18n\Time; @@ -489,7 +490,7 @@ class NoteModel extends UuidModel } /** - * @return ActivityPub\Models\BaseResult|int|string|false + * @return BaseResult|int|string|false */ public function reblog(Actor $actor, Note $note, $registerActivity = true) { diff --git a/app/Libraries/ActivityPub/Objects/ActorObject.php b/app/Libraries/ActivityPub/Objects/ActorObject.php index 819d2991..766f0946 100644 --- a/app/Libraries/ActivityPub/Objects/ActorObject.php +++ b/app/Libraries/ActivityPub/Objects/ActorObject.php @@ -72,9 +72,9 @@ class ActorObject extends ObjectType protected $icon = []; /** - * @var object + * @var array */ - protected $publicKey; + protected $publicKey = []; public function __construct(Actor $actor) { @@ -101,10 +101,12 @@ class ActorObject extends ObjectType 'url' => $actor->avatar_image_url, ]; - $this->publicKey = [ - 'id' => $actor->key_id, - 'owner' => $actor->uri, - 'publicKeyPem' => $actor->public_key, - ]; + if ($actor->public_key !== null) { + $this->publicKey = [ + 'id' => $actor->public_key_id, + 'owner' => $actor->uri, + 'publicKeyPem' => $actor->public_key, + ]; + } } } diff --git a/app/Libraries/ActivityPub/Objects/NoteObject.php b/app/Libraries/ActivityPub/Objects/NoteObject.php index 2c2f6c36..31d7556d 100644 --- a/app/Libraries/ActivityPub/Objects/NoteObject.php +++ b/app/Libraries/ActivityPub/Objects/NoteObject.php @@ -34,9 +34,9 @@ class NoteObject extends ObjectType protected $inReplyTo; /** - * @var array + * @var string */ - protected $replies = []; + protected $replies; /** * @param Note $note diff --git a/app/Libraries/ActivityPub/Objects/OrderedCollectionObject.php b/app/Libraries/ActivityPub/Objects/OrderedCollectionObject.php index 639bbc97..74e5f2d5 100644 --- a/app/Libraries/ActivityPub/Objects/OrderedCollectionObject.php +++ b/app/Libraries/ActivityPub/Objects/OrderedCollectionObject.php @@ -11,7 +11,6 @@ namespace ActivityPub\Objects; -use ActivityPub\Core\Activity; use CodeIgniter\Pager\Pager; use ActivityPub\Core\ObjectType; @@ -28,17 +27,17 @@ class OrderedCollectionObject extends ObjectType protected $totalItems; /** - * @var integer|null + * @var string|null */ protected $first; /** - * @var integer|null + * @var string|null */ protected $current; /** - * @var integer|null + * @var string|null */ protected $last; diff --git a/app/Libraries/ActivityPub/Objects/OrderedCollectionPage.php b/app/Libraries/ActivityPub/Objects/OrderedCollectionPage.php index a5a5dde4..dfa237d0 100644 --- a/app/Libraries/ActivityPub/Objects/OrderedCollectionPage.php +++ b/app/Libraries/ActivityPub/Objects/OrderedCollectionPage.php @@ -25,12 +25,12 @@ class OrderedCollectionPage extends OrderedCollectionObject protected $partOf; /** - * @var integer + * @var string|null */ protected $prev; /** - * @var integer + * @var string|null */ protected $next; diff --git a/app/Libraries/ActivityPub/WebFinger.php b/app/Libraries/ActivityPub/WebFinger.php index c273a075..85edf401 100644 --- a/app/Libraries/ActivityPub/WebFinger.php +++ b/app/Libraries/ActivityPub/WebFinger.php @@ -64,7 +64,9 @@ class WebFinger if (!$parts) { throw new Exception('Wrong WebFinger resource pattern.'); } - extract($parts); + + $username = $parts['username']; + $domain = $parts['domain']; $this->username = $username; $this->domain = $domain; diff --git a/app/Libraries/Analytics/Config/Analytics.php b/app/Libraries/Analytics/Config/Analytics.php index 28cf7379..1ab066ed 100644 --- a/app/Libraries/Analytics/Config/Analytics.php +++ b/app/Libraries/Analytics/Config/Analytics.php @@ -27,9 +27,11 @@ class Analytics extends BaseConfig ]; /** - * get the full audio file url + * get the full audio file + * + * @param string|string[] $audioFilePath */ - public function getAudioFileUrl(string $audioFilePath): string + public function getAudioFileUrl($audioFilePath): string { return base_url($audioFilePath); } diff --git a/app/Libraries/Analytics/Controllers/EpisodeAnalyticsController.php b/app/Libraries/Analytics/Controllers/EpisodeAnalyticsController.php index f2fa71f7..a8dfd1a7 100644 --- a/app/Libraries/Analytics/Controllers/EpisodeAnalyticsController.php +++ b/app/Libraries/Analytics/Controllers/EpisodeAnalyticsController.php @@ -14,6 +14,7 @@ use CodeIgniter\HTTP\ResponseInterface; use Psr\Log\LoggerInterface; use Config\Services; use CodeIgniter\Controller; +use CodeIgniter\HTTP\RedirectResponse; class EpisodeAnalyticsController extends Controller { @@ -54,9 +55,10 @@ class EpisodeAnalyticsController extends Controller $this->config = config('Analytics'); } - // Add one hit to this episode: - public function hit($base64EpisodeData, ...$audioFilePath) - { + public function hit( + string $base64EpisodeData, + string ...$audioFilePath + ): RedirectResponse { $session = Services::session(); $session->start(); diff --git a/app/Libraries/Analytics/Database/Migrations/2017-12-01-160000_add_analytics_podcasts_by_region.php b/app/Libraries/Analytics/Database/Migrations/2017-12-01-160000_add_analytics_podcasts_by_region.php index 51a60486..96fb9598 100644 --- a/app/Libraries/Analytics/Database/Migrations/2017-12-01-160000_add_analytics_podcasts_by_region.php +++ b/app/Libraries/Analytics/Database/Migrations/2017-12-01-160000_add_analytics_podcasts_by_region.php @@ -36,11 +36,11 @@ class AddAnalyticsPodcastsByRegion extends Migration 'comment' => 'ISO 3166-2 code.', ], 'latitude' => [ - 'type' => 'FLOAT', + 'type' => 'DECIMAL', 'null' => true, ], 'longitude' => [ - 'type' => 'FLOAT', + 'type' => 'DECIMAL', 'null' => true, ], 'hits' => [ diff --git a/app/Libraries/Analytics/Database/Migrations/2017-12-01-210000_add_analytics_podcasts_procedure.php b/app/Libraries/Analytics/Database/Migrations/2017-12-01-210000_add_analytics_podcasts_procedure.php index 7e2052d4..4c688f71 100644 --- a/app/Libraries/Analytics/Database/Migrations/2017-12-01-210000_add_analytics_podcasts_procedure.php +++ b/app/Libraries/Analytics/Database/Migrations/2017-12-01-210000_add_analytics_podcasts_procedure.php @@ -27,8 +27,8 @@ class AddAnalyticsPodcastsProcedure extends Migration IN `p_episode_id` INT UNSIGNED, IN `p_country_code` VARCHAR(3) CHARSET utf8mb4, IN `p_region_code` VARCHAR(3) CHARSET utf8mb4, - IN `p_latitude` FLOAT, - IN `p_longitude` FLOAT, + IN `p_latitude` DECIMAL, + IN `p_longitude` DECIMAL, IN `p_service` VARCHAR(128) CHARSET utf8mb4, IN `p_app` VARCHAR(128) CHARSET utf8mb4, IN `p_device` VARCHAR(32) CHARSET utf8mb4, diff --git a/app/Libraries/Analytics/Entities/AnalyticsPodcasts.php b/app/Libraries/Analytics/Entities/AnalyticsPodcasts.php index ef0df9a9..91c5696c 100644 --- a/app/Libraries/Analytics/Entities/AnalyticsPodcasts.php +++ b/app/Libraries/Analytics/Entities/AnalyticsPodcasts.php @@ -10,17 +10,30 @@ namespace Analytics\Entities; -use datetime; use CodeIgniter\Entity\Entity; +/** + * @property int $podcast_id + * @property Time $date + * @property int $duration + * @property int $bandwidth + * @property int $unique_listeners + * @property int $hits + * @property Time $created_at + * @property Time $updated_at + */ class AnalyticsPodcasts extends Entity { + /** + * @var string[] + */ + protected $dates = ['date', 'created_at', 'updated_at']; + /** * @var array */ protected $casts = [ 'podcast_id' => 'integer', - 'date' => 'datetime', 'duration' => 'integer', 'bandwidth' => 'integer', 'unique_listeners' => 'integer', diff --git a/app/Libraries/Analytics/Entities/AnalyticsPodcastsByCountry.php b/app/Libraries/Analytics/Entities/AnalyticsPodcastsByCountry.php index b02876dc..6744b9ac 100644 --- a/app/Libraries/Analytics/Entities/AnalyticsPodcastsByCountry.php +++ b/app/Libraries/Analytics/Entities/AnalyticsPodcastsByCountry.php @@ -10,15 +10,23 @@ namespace Analytics\Entities; -use datetime; use CodeIgniter\Entity\Entity; +/** + * @property int $podcast_id + * @property string $country_code + * @property string $labels + * @property Time $date + * @property int $hits + * @property Time $created_at + * @property Time $updated_at + */ class AnalyticsPodcastsByCountry extends Entity { /** - * @var string + * @var string[] */ - protected $labels; + protected $dates = ['date', 'created_at', 'updated_at']; /** * @var array @@ -26,7 +34,6 @@ class AnalyticsPodcastsByCountry extends Entity protected $casts = [ 'podcast_id' => 'integer', 'country_code' => 'string', - 'date' => 'datetime', 'hits' => 'integer', ]; diff --git a/app/Libraries/Analytics/Entities/AnalyticsPodcastsByEpisode.php b/app/Libraries/Analytics/Entities/AnalyticsPodcastsByEpisode.php index b512a945..8cf66c1e 100644 --- a/app/Libraries/Analytics/Entities/AnalyticsPodcastsByEpisode.php +++ b/app/Libraries/Analytics/Entities/AnalyticsPodcastsByEpisode.php @@ -10,18 +10,29 @@ namespace Analytics\Entities; -use datetime; use CodeIgniter\Entity\Entity; +/** + * @property int $podcast_id + * @property int $episode_id + * @property Time $date + * @property int $hits + * @property Time $created_at + * @property Time $updated_at + */ class AnalyticsPodcastsByEpisode extends Entity { + /** + * @var string[] + */ + protected $dates = ['date', 'created_at', 'updated_at']; + /** * @var array */ protected $casts = [ 'podcast_id' => 'integer', 'episode_id' => 'integer', - 'date' => 'datetime', 'hits' => 'integer', ]; } diff --git a/app/Libraries/Analytics/Entities/AnalyticsPodcastsByHour.php b/app/Libraries/Analytics/Entities/AnalyticsPodcastsByHour.php index 7794e5a3..f609ddb7 100644 --- a/app/Libraries/Analytics/Entities/AnalyticsPodcastsByHour.php +++ b/app/Libraries/Analytics/Entities/AnalyticsPodcastsByHour.php @@ -10,17 +10,28 @@ namespace Analytics\Entities; -use datetime; use CodeIgniter\Entity\Entity; +/** + * @property int $podcast_id + * @property Time $date + * @property int $hour + * @property int $hits + * @property Time $created_at + * @property Time $updated_at + */ class AnalyticsPodcastsByHour extends Entity { + /** + * @var string[] + */ + protected $dates = ['date', 'created_at', 'updated_at']; + /** * @var array */ protected $casts = [ 'podcast_id' => 'integer', - 'date' => 'datetime', 'hour' => 'integer', 'hits' => 'integer', ]; diff --git a/app/Libraries/Analytics/Entities/AnalyticsPodcastsByPlayer.php b/app/Libraries/Analytics/Entities/AnalyticsPodcastsByPlayer.php index 7bec2f40..ed67b984 100644 --- a/app/Libraries/Analytics/Entities/AnalyticsPodcastsByPlayer.php +++ b/app/Libraries/Analytics/Entities/AnalyticsPodcastsByPlayer.php @@ -10,11 +10,26 @@ namespace Analytics\Entities; -use datetime; use CodeIgniter\Entity\Entity; +/** + * @property int $podcast_id + * @property string|null $app + * @property string|null $device + * @property string|null $os + * @property bool $is_bot + * @property Time $date + * @property int $hits + * @property Time $created_at + * @property Time $updated_at + */ class AnalyticsPodcastsByPlayer extends Entity { + /** + * @var string[] + */ + protected $dates = ['date', 'created_at', 'updated_at']; + /** * @var array */ @@ -24,7 +39,6 @@ class AnalyticsPodcastsByPlayer extends Entity 'device' => '?string', 'os' => '?string', 'is_bot' => 'boolean', - 'date' => 'datetime', 'hits' => 'integer', ]; } diff --git a/app/Libraries/Analytics/Entities/AnalyticsPodcastsByRegion.php b/app/Libraries/Analytics/Entities/AnalyticsPodcastsByRegion.php index 6afa1944..dad55121 100644 --- a/app/Libraries/Analytics/Entities/AnalyticsPodcastsByRegion.php +++ b/app/Libraries/Analytics/Entities/AnalyticsPodcastsByRegion.php @@ -10,11 +10,26 @@ namespace Analytics\Entities; -use datetime; use CodeIgniter\Entity\Entity; +/** + * @property int $podcast_id + * @property string $country_code + * @property string|null $region_code + * @property double|null $latitude + * @property double|null $longitude + * @property Time $date + * @property int $hits + * @property Time $created_at + * @property Time $updated_at + */ class AnalyticsPodcastsByRegion extends Entity { + /** + * @var string[] + */ + protected $dates = ['date', 'created_at', 'updated_at']; + /** * @var array */ @@ -22,9 +37,8 @@ class AnalyticsPodcastsByRegion extends Entity 'podcast_id' => 'integer', 'country_code' => 'string', 'region_code' => '?string', - 'latitude' => '?float', - 'longitude' => '?float', - 'date' => 'datetime', + 'latitude' => '?double', + 'longitude' => '?double', 'hits' => 'integer', ]; diff --git a/app/Libraries/Analytics/Entities/AnalyticsPodcastsByService.php b/app/Libraries/Analytics/Entities/AnalyticsPodcastsByService.php index e17fe504..2022f283 100644 --- a/app/Libraries/Analytics/Entities/AnalyticsPodcastsByService.php +++ b/app/Libraries/Analytics/Entities/AnalyticsPodcastsByService.php @@ -10,16 +10,27 @@ namespace Analytics\Entities; -use datetime; use Opawg\UserAgentsPhp\UserAgentsRSS; use CodeIgniter\Entity\Entity; +/** + * @property int $podcast_id + * @property string $app + * @property string|null $device + * @property string|null $os + * @property bool $is_bot + * @property Time $date + * @property int $hits + * @property string $labels + * @property Time $created_at + * @property Time $updated_at + */ class AnalyticsPodcastsByService extends Entity { /** - * @var string + * @var string[] */ - protected $labels; + protected $dates = ['date', 'created_at', 'updated_at']; /** * @var array @@ -30,7 +41,6 @@ class AnalyticsPodcastsByService extends Entity 'device' => '?string', 'os' => '?string', 'is_bot' => 'boolean', - 'date' => 'datetime', 'hits' => 'integer', ]; diff --git a/app/Libraries/Analytics/Entities/AnalyticsUnknownUseragents.php b/app/Libraries/Analytics/Entities/AnalyticsUnknownUseragents.php index 4a843ab2..b4428491 100644 --- a/app/Libraries/Analytics/Entities/AnalyticsUnknownUseragents.php +++ b/app/Libraries/Analytics/Entities/AnalyticsUnknownUseragents.php @@ -12,6 +12,12 @@ namespace Analytics\Entities; use CodeIgniter\Entity\Entity; +/** + * @property int $useragent + * @property int $hits + * @property Time $created_at + * @property Time $updated_at + */ class AnalyticsUnknownUseragents extends Entity { /** diff --git a/app/Libraries/Analytics/Entities/AnalyticsWebsiteByBrowser.php b/app/Libraries/Analytics/Entities/AnalyticsWebsiteByBrowser.php index 0ca6734c..84e969ea 100644 --- a/app/Libraries/Analytics/Entities/AnalyticsWebsiteByBrowser.php +++ b/app/Libraries/Analytics/Entities/AnalyticsWebsiteByBrowser.php @@ -10,18 +10,29 @@ namespace Analytics\Entities; -use datetime; use CodeIgniter\Entity\Entity; +/** + * @property int $podcast_id + * @property string $browser + * @property Time $date + * @property int $hits + * @property Time $created_at + * @property Time $updated_at + */ class AnalyticsWebsiteByBrowser extends Entity { + /** + * @var string[] + */ + protected $dates = ['date', 'created_at', 'updated_at']; + /** * @var array */ protected $casts = [ 'podcast_id' => 'integer', 'browser' => 'string', - 'date' => 'datetime', 'hits' => 'integer', ]; } diff --git a/app/Libraries/Analytics/Entities/AnalyticsWebsiteByEntryPage.php b/app/Libraries/Analytics/Entities/AnalyticsWebsiteByEntryPage.php index f70fcbb3..37592067 100644 --- a/app/Libraries/Analytics/Entities/AnalyticsWebsiteByEntryPage.php +++ b/app/Libraries/Analytics/Entities/AnalyticsWebsiteByEntryPage.php @@ -10,18 +10,29 @@ namespace Analytics\Entities; -use datetime; use CodeIgniter\Entity\Entity; +/** + * @property int $podcast_id + * @property string $entry_page_url + * @property Time $date + * @property int $hits + * @property Time $created_at + * @property Time $updated_at + */ class AnalyticsWebsiteByEntryPage extends Entity { + /** + * @var string[] + */ + protected $dates = ['date', 'created_at', 'updated_at']; + /** * @var array */ protected $casts = [ 'podcast_id' => 'integer', 'entry_page_url' => 'string', - 'date' => 'datetime', 'hits' => 'integer', ]; } diff --git a/app/Libraries/Analytics/Entities/AnalyticsWebsiteByReferer.php b/app/Libraries/Analytics/Entities/AnalyticsWebsiteByReferer.php index 980fe575..bfd7f8fe 100644 --- a/app/Libraries/Analytics/Entities/AnalyticsWebsiteByReferer.php +++ b/app/Libraries/Analytics/Entities/AnalyticsWebsiteByReferer.php @@ -10,18 +10,29 @@ namespace Analytics\Entities; -use datetime; use CodeIgniter\Entity\Entity; +/** + * @property int $podcast_id + * @property string $referer_url + * @property Time $date + * @property int $hits + * @property Time $created_at + * @property Time $updated_at + */ class AnalyticsWebsiteByReferer extends Entity { + /** + * @var string[] + */ + protected $dates = ['date', 'created_at', 'updated_at']; + /** * @var array */ protected $casts = [ 'podcast_id' => 'integer', 'referer_url' => 'string', - 'date' => 'datetime', 'hits' => 'integer', ]; } diff --git a/app/Libraries/Analytics/Helpers/analytics_helper.php b/app/Libraries/Analytics/Helpers/analytics_helper.php index d5d44f94..364eab1c 100644 --- a/app/Libraries/Analytics/Helpers/analytics_helper.php +++ b/app/Libraries/Analytics/Helpers/analytics_helper.php @@ -45,7 +45,7 @@ if (!function_exists('generate_episode_analytics_url')) { int $podcastId, int $episodeId, string $audioFilePath, - int $audioFileDuration, + float $audioFileDuration, int $audioFileSize, int $audioFileHeaderSize, \CodeIgniter\I18n\Time $publicationDate @@ -329,7 +329,8 @@ if (!function_exists('podcast_hit')) { $parts = explode('-', $range); $downloadedBytes += empty($parts[1]) ? $fileSize - : $parts[1] - (empty($parts[0]) ? 0 : $parts[0]); + : (int) $parts[1] - + (empty($parts[0]) ? 0 : (int) $parts[0]); } } // We save the number of downloaded bytes for this user and this episode: diff --git a/app/Libraries/Image.php b/app/Libraries/Image.php deleted file mode 100644 index 572c1564..00000000 --- a/app/Libraries/Image.php +++ /dev/null @@ -1,155 +0,0 @@ - $filename, - 'dirname' => $dirname, - 'extension' => $extension, - ] = pathinfo($originalMediaPath); - - // load images extensions from config - $this->config = config('Images'); - - $thumbnailExtension = $this->config->thumbnailExtension; - $mediumExtension = $this->config->mediumExtension; - $largeExtension = $this->config->largeExtension; - $feedExtension = $this->config->feedExtension; - $id3Extension = $this->config->id3Extension; - - $thumbnail = - $dirname . '/' . $filename . $thumbnailExtension . '.' . $extension; - $medium = - $dirname . '/' . $filename . $mediumExtension . '.' . $extension; - $large = - $dirname . '/' . $filename . $largeExtension . '.' . $extension; - $feed = $dirname . '/' . $filename . $feedExtension . '.' . $extension; - $id3 = $dirname . '/' . $filename . $id3Extension . '.' . $extension; - - $this->original_path = $originalMediaPath; - $this->original_url = media_url($originalPath); - $this->thumbnail_path = $thumbnail; - $this->thumbnail_url = base_url($thumbnail); - $this->medium_path = $medium; - $this->medium_url = base_url($medium); - $this->large_path = $large; - $this->large_url = base_url($large); - $this->feed_path = $feed; - $this->feed_url = base_url($feed); - $this->id3_path = $id3; - - $this->mimetype = $mimetype; - } - - public function saveSizes(): void - { - $thumbnailSize = $this->config->thumbnailSize; - $mediumSize = $this->config->mediumSize; - $largeSize = $this->config->largeSize; - $feedSize = $this->config->feedSize; - $id3Size = $this->config->id3Size; - - $imageService = Services::image(); - - $imageService - ->withFile($this->original_path) - ->resize($thumbnailSize, $thumbnailSize) - ->save($this->thumbnail_path); - - $imageService - ->withFile($this->original_path) - ->resize($mediumSize, $mediumSize) - ->save($this->medium_path); - - $imageService - ->withFile($this->original_path) - ->resize($largeSize, $largeSize) - ->save($this->large_path); - - $imageService - ->withFile($this->original_path) - ->resize($feedSize, $feedSize) - ->save($this->feed_path); - - $imageService - ->withFile($this->original_path) - ->resize($id3Size, $id3Size) - ->save($this->id3_path); - } -} diff --git a/app/Libraries/Negotiate.php b/app/Libraries/Negotiate.php index 8e52ca03..22827dc5 100644 --- a/app/Libraries/Negotiate.php +++ b/app/Libraries/Negotiate.php @@ -2,7 +2,9 @@ namespace App\Libraries; -class Negotiate extends \CodeIgniter\HTTP\Negotiate +use CodeIgniter\HTTP\Negotiate as CodeIgniterHTTPNegotiate; + +class Negotiate extends CodeIgniterHTTPNegotiate { public function callMatch( array $acceptable, diff --git a/app/Libraries/NoteObject.php b/app/Libraries/NoteObject.php index f02c9275..48905df6 100644 --- a/app/Libraries/NoteObject.php +++ b/app/Libraries/NoteObject.php @@ -8,12 +8,12 @@ namespace App\Libraries; -class NoteObject extends \ActivityPub\Objects\NoteObject +use ActivityPub\Objects\NoteObject as ActivityPubNoteObject; +use App\Entities\Note; + +class NoteObject extends ActivityPubNoteObject { - /** - * @param Note $note - */ - public function __construct($note) + public function __construct(Note $note) { parent::__construct($note); diff --git a/app/Libraries/PodcastActor.php b/app/Libraries/PodcastActor.php index 5f6351e1..e926e823 100644 --- a/app/Libraries/PodcastActor.php +++ b/app/Libraries/PodcastActor.php @@ -9,9 +9,10 @@ namespace App\Libraries; use ActivityPub\Entities\Actor; +use ActivityPub\Objects\ActorObject; use App\Models\PodcastModel; -class PodcastActor extends \ActivityPub\Objects\ActorObject +class PodcastActor extends ActorObject { /** * @var string diff --git a/app/Libraries/Router.php b/app/Libraries/Router.php index d8202b5c..e9ac8b49 100644 --- a/app/Libraries/Router.php +++ b/app/Libraries/Router.php @@ -14,8 +14,9 @@ namespace App\Libraries; use Config\Services; use CodeIgniter\Router\Exceptions\RedirectException; +use CodeIgniter\Router\Router as CodeIgniterRouter; -class Router extends \CodeIgniter\Router\Router +class Router extends CodeIgniterRouter { /** * Compares the uri string against the routes that the diff --git a/app/Libraries/SimpleRSSElement.php b/app/Libraries/SimpleRSSElement.php index e39c0359..1bb2517b 100644 --- a/app/Libraries/SimpleRSSElement.php +++ b/app/Libraries/SimpleRSSElement.php @@ -16,17 +16,17 @@ class SimpleRSSElement extends SimpleXMLElement * Adds a child with $value inside CDATA * * @param string $name — The name of the child element to add. - * @param string|null $value — [optional] If specified, the value of the child element. + * @param string $value — [optional] If specified, the value of the child element. * @param string|null $namespace [optional] If specified, the namespace to which the child element belongs. * - * @return $this + * @return static The addChild method returns a SimpleXMLElement object representing the child added to the XML node. */ public function addChildWithCDATA( string $name, - ?string $value = null, + string $value = '', ?string $namespace = null ) { - $new_child = parent::addChild($name, null, $namespace); + $new_child = parent::addChild($name, '', $namespace); if ($new_child !== null) { $node = dom_import_simplexml($new_child); @@ -44,11 +44,12 @@ class SimpleRSSElement extends SimpleXMLElement * @param string $name — The name of the child element to add. * @param string $value — [optional] If specified, the value of the child element. * @param string $namespace [optional] If specified, the namespace to which the child element belongs. - * @return $this + * + * @return static The addChild method returns a SimpleXMLElement object representing the child added to the XML node. */ public function addChild($name, $value = null, $namespace = null) { - $new_child = parent::addChild($name, null, $namespace); + $new_child = parent::addChild($name, '', $namespace); if ($new_child !== null) { $node = dom_import_simplexml($new_child); diff --git a/app/Models/ActorModel.php b/app/Models/ActorModel.php index 694c7db6..37a70b04 100644 --- a/app/Models/ActorModel.php +++ b/app/Models/ActorModel.php @@ -8,7 +8,10 @@ namespace App\Models; -class ActorModel extends \ActivityPub\Models\ActorModel +use ActivityPub\Models\ActorModel as ActivityPubActorModel; +use App\Entities\Actor; + +class ActorModel extends ActivityPubActorModel { - protected $returnType = \App\Entities\Actor::class; + protected $returnType = Actor::class; } diff --git a/app/Models/EpisodeModel.php b/app/Models/EpisodeModel.php index c76aaa20..7bf66147 100644 --- a/app/Models/EpisodeModel.php +++ b/app/Models/EpisodeModel.php @@ -83,7 +83,7 @@ class EpisodeModel extends Model 'is_blocked', 'location_name', 'location_geo', - 'location_osmid', + 'location_osm_id', 'custom_rss', 'favourites_total', 'reblogs_total', @@ -146,10 +146,11 @@ class EpisodeModel extends Model */ protected $beforeDelete = ['clearCache']; - public function getEpisodeBySlug( - int $podcastId, - string $episodeSlug - ): ?Episode { + /** + * @param int|string $podcastId may be the id or podcast name + */ + public function getEpisodeBySlug($podcastId, string $episodeSlug): ?Episode + { $cacheName = "podcast#{$podcastId}_episode-{$episodeSlug}"; if (!($found = cache($cacheName))) { $builder = $this->select('episodes.*') @@ -275,7 +276,7 @@ class EpisodeModel extends Model * Returns the timestamp difference in seconds between the next episode to publish and the current timestamp * Returns false if there's no episode to publish * - * @return int|false seconds + * @return int|bool seconds */ public function getSecondsToNextUnpublishedEpisode(int $podcastId) { @@ -290,7 +291,9 @@ class EpisodeModel extends Model ->get() ->getResultArray(); - return (int) $result !== 0 ? $result[0]['timestamp_diff'] : false; + return count($result) !== 0 + ? (int) $result[0]['timestamp_diff'] + : false; } /** diff --git a/app/Models/EpisodePersonModel.php b/app/Models/EpisodePersonModel.php index 1fd56a53..bec23995 100644 --- a/app/Models/EpisodePersonModel.php +++ b/app/Models/EpisodePersonModel.php @@ -84,12 +84,10 @@ class EpisodePersonModel extends Model /** * Add persons to episode * - * @param int podcastId - * * @return bool|int Number of rows inserted or FALSE on failure */ public function addEpisodePersons( - $podcastId, + int $podcastId, int $episodeId, array $persons, array $groups_roles diff --git a/app/Models/NoteModel.php b/app/Models/NoteModel.php index 981e1591..819df9a5 100644 --- a/app/Models/NoteModel.php +++ b/app/Models/NoteModel.php @@ -8,7 +8,9 @@ namespace App\Models; -class NoteModel extends \ActivityPub\Models\NoteModel +use ActivityPub\Models\NoteModel as ActivityPubNoteModel; + +class NoteModel extends ActivityPubNoteModel { protected $returnType = \App\Entities\Note::class; diff --git a/app/Models/PersonModel.php b/app/Models/PersonModel.php index 94054790..be18d6f5 100644 --- a/app/Models/PersonModel.php +++ b/app/Models/PersonModel.php @@ -8,6 +8,7 @@ namespace App\Models; +use App\Entities\Image; use App\Entities\Person; use CodeIgniter\Model; @@ -102,9 +103,9 @@ class PersonModel extends Model 'full_name' => $fullName, 'unique_name' => slugify($fullName), 'information_url' => $informationUrl, - 'image' => download_file($image), - 'created_by' => user()->id, - 'updated_by' => user()->id, + 'image' => new Image(download_file($image)), + 'created_by' => user_id(), + 'updated_by' => user_id(), ]); return $this->insert($person); } @@ -135,11 +136,12 @@ class PersonModel extends Model $options = []; $locale = service('request')->getLocale(); $cacheName = "taxonomy_options_{$locale}"; + + /** @var array */ + $personsTaxonomy = lang('PersonsTaxonomy.persons'); + if (!($options = cache($cacheName))) { - foreach ( - (array) lang('PersonsTaxonomy.persons') - as $group_key => $group - ) { + foreach ($personsTaxonomy as $group_key => $group) { foreach ($group['roles'] as $role_key => $role) { $options[ "{$group_key},{$role_key}" diff --git a/app/Models/PodcastModel.php b/app/Models/PodcastModel.php index 98a7d939..7eaf25ec 100644 --- a/app/Models/PodcastModel.php +++ b/app/Models/PodcastModel.php @@ -17,6 +17,9 @@ class PodcastModel extends Model protected $table = 'podcasts'; protected $primaryKey = 'id'; + /** + * @var string[] + */ protected $allowedFields = [ 'id', 'title', @@ -42,7 +45,7 @@ class PodcastModel extends Model 'is_locked', 'location_name', 'location_geo', - 'location_osmid', + 'location_osm_id', 'payment_pointer', 'custom_rss', 'partner_id', @@ -185,7 +188,7 @@ class PodcastModel extends Model // identifier is the podcast name, request must be a join $user_podcast = $this->db ->table('podcasts_users') - ->select('group_id', 'user_id') + ->select('group_id, user_id') ->join('podcasts', 'podcasts.id = podcasts_users.podcast_id') ->where([ 'user_id' => $userId, @@ -323,7 +326,9 @@ class PodcastModel extends Model $rsa->setHash('sha256'); // extracts $privatekey and $publickey variables - extract($rsa->createKey(2048)); + $rsaKey = $rsa->createKey(2048); + $privatekey = $rsaKey['privatekey']; + $publickey = $rsaKey['publickey']; $url = new URI(base_url()); $username = $data['data']['name']; diff --git a/app/Models/PodcastPersonModel.php b/app/Models/PodcastPersonModel.php index eedb85c9..94904b90 100644 --- a/app/Models/PodcastPersonModel.php +++ b/app/Models/PodcastPersonModel.php @@ -66,7 +66,10 @@ class PodcastPersonModel extends Model */ protected $beforeDelete = ['clearCache']; - public function getPodcastPersons($podcastId) + /** + * @return PodcastPerson[] + */ + public function getPodcastPersons(int $podcastId): array { $cacheName = "podcast#{$podcastId}_persons"; if (!($found = cache($cacheName))) { @@ -85,37 +88,42 @@ class PodcastPersonModel extends Model /** * Add persons to podcast * + * @param array $persons + * @param array $groupsRoles + * * @return bool|int Number of rows inserted or FALSE on failure */ public function addPodcastPersons( int $podcastId, - array $persons, - array $groups_roles + array $persons = [], + array $groupsRoles = [] ) { - if (!empty($persons)) { - $this->clearCache(['podcast_id' => $podcastId]); - $data = []; - foreach ($persons as $person) { - if ($groups_roles !== []) { - foreach ($groups_roles as $group_role) { - $group_role = explode(',', $group_role); - $data[] = [ - 'podcast_id' => $podcastId, - 'person_id' => $person, - 'person_group' => $group_role[0], - 'person_role' => $group_role[1], - ]; - } - } else { - $data[] = [ - 'podcast_id' => $podcastId, - 'person_id' => $person, - ]; - } - } - return $this->insertBatch($data); + if ($persons === []) { + return 0; } - return 0; + + $this->clearCache(['podcast_id' => $podcastId]); + $data = []; + foreach ($persons as $person) { + if ($groupsRoles === []) { + $data[] = [ + 'podcast_id' => $podcastId, + 'person_id' => $person, + ]; + } + + foreach ($groupsRoles as $group_role) { + $group_role = explode(',', $group_role); + $data[] = [ + 'podcast_id' => $podcastId, + 'person_id' => $person, + 'person_group' => $group_role[0], + 'person_role' => $group_role[1], + ]; + } + } + + return $this->insertBatch($data); } /** diff --git a/app/Models/UserModel.php b/app/Models/UserModel.php index db7a3074..3cc6d285 100644 --- a/app/Models/UserModel.php +++ b/app/Models/UserModel.php @@ -9,7 +9,9 @@ namespace App\Models; use App\Entities\User; -class UserModel extends \Myth\Auth\Models\UserModel +use Myth\Auth\Models\UserModel as MythAuthUserModel; + +class UserModel extends MythAuthUserModel { /** * @var string diff --git a/app/Validation/Rules.php b/app/Validation/Rules.php index ac352ba0..431d463c 100644 --- a/app/Validation/Rules.php +++ b/app/Validation/Rules.php @@ -16,7 +16,7 @@ class Rules */ public function validate_url(string $str = null): bool { - if (empty($str)) { + if ($str === null) { return false; } diff --git a/app/Views/admin/episode/embeddable_player.php b/app/Views/admin/episode/embeddable_player.php index ebb99e24..bb42a4a3 100644 --- a/app/Views/admin/episode/embeddable_player.php +++ b/app/Views/admin/episode/embeddable_player.php @@ -18,13 +18,13 @@ 'style' ] ?>" class="w-12 h-12 mr-1 border-2 border-gray-400 rounded-lg hover:border-white" title="" data-type="theme-picker" data-url="getEmbeddablePlayer( +) ?>" data-type="theme-picker" data-url="getEmbeddablePlayerUrl( $themeKey, ) ?>"> - +
'iframe', 'class' => 'form-textarea w-full h-20 mr-2', ], - "", + "", ) ?> 'url', 'class' => 'form-textarea w-full h-10 mr-2', ], - $episode->embeddable_player, + $episode->embeddable_player_url, ) ?>
- location_name, - $episode->location_geo, - $episode->location_osmid, - 'text-sm', - ) ?> + location, 'text-sm') ?> description_html ?>
diff --git a/app/Views/admin/podcast/edit.php b/app/Views/admin/podcast/edit.php index c0ca9e64..28df6e4d 100644 --- a/app/Views/admin/podcast/edit.php +++ b/app/Views/admin/podcast/edit.php @@ -254,7 +254,7 @@ 'id' => 'location_name', 'name' => 'location_name', 'class' => 'form-input mb-4', - 'value' => old('location_name', $podcast->location_name), + 'value' => old('location_name', $podcast->location->name), ]) ?> diff --git a/app/Views/admin/podcast/view.php b/app/Views/admin/podcast/view.php index cc7d4865..8bf1c6f0 100644 --- a/app/Views/admin/podcast/view.php +++ b/app/Views/admin/podcast/view.php @@ -9,12 +9,7 @@ endSection() ?> section('headerLeft') ?> -location_name, - $podcast->location_geo, - $podcast->location_osmid, - 'ml-4 text-sm', -) ?> +location, 'ml-4 text-sm') ?> endSection() ?> section('headerRight') ?> @@ -32,7 +27,7 @@ section('content') ?> - 5, 'podcast_id' => $podcast->id, ]) ?> diff --git a/app/Views/podcast/_partials/header.php b/app/Views/podcast/_partials/header.php index 7924defe..2273053a 100644 --- a/app/Views/podcast/_partials/header.php +++ b/app/Views/podcast/_partials/header.php @@ -27,14 +27,7 @@ : '') ?>

@name ?>

description_html ?>
- location_name): ?> - location_name, - $podcast->location_geo, - $podcast->location_osmid, - 'text-sm mb-4', - ) ?> - + location, 'text-sm mb-4') ?>
- @@ -111,13 +111,8 @@ ], ) ?>
- location_name): ?> - location_name, - $episode->location_geo, - $episode->location_osmid, - 'text-sm mb-4', - ) ?> + location !== null): ?> + location, 'text-sm mb-4') ?>
diff --git a/app/Views/podcast/episode_authenticated.php b/app/Views/podcast/episode_authenticated.php index ddedfbc7..524caead 100644 --- a/app/Views/podcast/episode_authenticated.php +++ b/app/Views/podcast/episode_authenticated.php @@ -31,7 +31,7 @@ - @@ -111,13 +111,8 @@ ], ) ?>
- location_name): ?> - location_name, - $episode->location_geo, - $episode->location_osmid, - 'text-sm mb-4', - ) ?> + location !== null): ?> + location, 'text-sm mb-4') ?>
diff --git a/captainhook.json b/captainhook.json index cdc877e7..7c166378 100644 --- a/captainhook.json +++ b/captainhook.json @@ -27,6 +27,11 @@ "options": [], "conditions": [] }, + { + "action": "composer analyse", + "options": [], + "conditions": [] + }, { "action": "composer rector", "options": [], diff --git a/composer.json b/composer.json index 39fec8a9..958cdad1 100644 --- a/composer.json +++ b/composer.json @@ -19,15 +19,19 @@ "podlibre/ipcat": "^v1.0", "podlibre/podcast-namespace": "^v1.0.6", "phpseclib/phpseclib": "~2.0.30", - "michalsn/codeigniter4-uuid": "^v1.0.0", + "michalsn/codeigniter4-uuid": "dev-develop", "essence/essence": "^3.5.4" }, "require-dev": { "mikey179/vfsstream": "^v1.6.8", "phpunit/phpunit": "^9.5.1", - "squizlabs/php_codesniffer": "3.5.8", + "squizlabs/php_codesniffer": "^3.6.0", "rector/rector": "^0.10.17", - "captainhook/captainhook": "^5.9" + "captainhook/captainhook": "^5.9", + "captainhook/plugin-composer": "^5.2", + "phpstan/phpstan": "^0.12.85", + "phpstan/extension-installer": "^1.1", + "rector/rector-phpstan-rules": "^0.2.1" }, "autoload": { "psr-4": { @@ -45,6 +49,7 @@ }, "scripts": { "test": "vendor/bin/phpunit", + "analyse": "vendor/bin/phpstan analyse", "rector": "vendor/bin/rector process --dry-run --ansi", "rector:fix": "vendor/bin/rector process --ansi", "phpcs": "vendor/bin/phpcbf --standard=.phpcs.xml --encoding=utf-8 -n -p", @@ -64,8 +69,12 @@ "@php vendor/podlibre/podcast-namespace/src/TaxonomyGenerate.php https://raw.githubusercontent.com/Podcastindex-org/podcast-namespace/main/taxonomy-en.json > app/Language/en/PersonsTaxonomy.php", "@php vendor/podlibre/podcast-namespace/src/TaxonomyGenerate.php https://raw.githubusercontent.com/Podcastindex-org/podcast-namespace/main/taxonomy-fr.json > app/Language/fr/PersonsTaxonomy.php", "@php vendor/podlibre/podcast-namespace/src/ReversedTaxonomyGenerate.php https://raw.githubusercontent.com/Podcastindex-org/podcast-namespace/main/taxonomy-en.json > vendor/podlibre/podcast-namespace/src/ReversedTaxonomy.php" - ], - "post-autoload-dump": "vendor/bin/captainhook install -f -s" + ] + }, + "extra": { + "captainhook": { + "force-install": true + } }, "support": { "source": "https://code.podlibre.org/podlibre/castopod-host.git", diff --git a/composer.lock b/composer.lock index d6949995..be9d77fa 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4873e8d92c9c1829e6f02d8db590a786", + "content-hash": "cdbc538742689916718b17f15ba7d875", "packages": [ { "name": "brick/math", @@ -68,12 +68,12 @@ "source": { "type": "git", "url": "https://github.com/codeigniter4/CodeIgniter4.git", - "reference": "7546ee04a55071d4731c77346deb47843f397c87" + "reference": "5713da574bfaa4d73949d84330ccf80758cd6ae4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/codeigniter4/CodeIgniter4/zipball/7546ee04a55071d4731c77346deb47843f397c87", - "reference": "7546ee04a55071d4731c77346deb47843f397c87", + "url": "https://api.github.com/repos/codeigniter4/CodeIgniter4/zipball/5713da574bfaa4d73949d84330ccf80758cd6ae4", + "reference": "5713da574bfaa4d73949d84330ccf80758cd6ae4", "shasum": "" }, "require": { @@ -84,9 +84,16 @@ "kint-php/kint": "^3.3", "laminas/laminas-escaper": "^2.6", "php": "^7.3 || ^8.0", - "psr/log": "^1.1" + "psr/cache": "^1.0", + "psr/log": "^1.1", + "psr/simple-cache": "^1.0" + }, + "provide": { + "psr/cache-implementation": "^1.0", + "psr/simple-cache-implementation": "^1.0" }, "require-dev": { + "cache/integration-tests": "^0.17.0", "codeigniter4/codeigniter4-standard": "^1.0", "fakerphp/faker": "^1.9", "mikey179/vfsstream": "^1.6", @@ -95,7 +102,7 @@ "phpstan/phpstan": "0.12.85", "phpunit/phpunit": "^9.1", "predis/predis": "^1.1", - "rector/rector": "0.10.19", + "rector/rector": "0.10.22", "squizlabs/php_codesniffer": "^3.3" }, "suggest": { @@ -103,6 +110,11 @@ }, "default-branch": true, "type": "project", + "extra": { + "branch-alias": { + "dev-develop": "4.x-dev" + } + }, "autoload": { "psr-4": { "CodeIgniter\\": "system/" @@ -120,7 +132,7 @@ "scripts": { "post-update-cmd": [ "CodeIgniter\\ComposerScripts::postUpdate", - "bash admin/setup.sh" + "bash -c \"if [ -f admin/setup.sh ]; then bash admin/setup.sh; fi\"" ], "analyze": [ "phpstan analyze" @@ -140,7 +152,7 @@ "slack": "https://codeigniterchat.slack.com", "issues": "https://github.com/codeigniter4/CodeIgniter4/issues" }, - "time": "2021-05-06T01:16:55+00:00" + "time": "2021-05-12T10:19:48+00:00" }, { "name": "composer/ca-bundle", @@ -824,16 +836,16 @@ }, { "name": "league/commonmark", - "version": "1.6.0", + "version": "1.6.2", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "19a9673b833cc37770439097b381d86cd125bfe8" + "reference": "7d70d2f19c84bcc16275ea47edabee24747352eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/19a9673b833cc37770439097b381d86cd125bfe8", - "reference": "19a9673b833cc37770439097b381d86cd125bfe8", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/7d70d2f19c84bcc16275ea47edabee24747352eb", + "reference": "7d70d2f19c84bcc16275ea47edabee24747352eb", "shasum": "" }, "require": { @@ -921,7 +933,7 @@ "type": "tidelift" } ], - "time": "2021-05-01T19:00:49+00:00" + "time": "2021-05-12T11:39:41+00:00" }, { "name": "league/html-to-markdown", @@ -1126,16 +1138,16 @@ }, { "name": "michalsn/codeigniter4-uuid", - "version": "v1.0.1", + "version": "dev-develop", "source": { "type": "git", "url": "https://github.com/michalsn/codeigniter4-uuid.git", - "reference": "c8bbd961401015307bc72f6f6aa93509ffac1d5f" + "reference": "b26512ac4f3f0c772fbfa2c3317346d3c17e2d44" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/michalsn/codeigniter4-uuid/zipball/c8bbd961401015307bc72f6f6aa93509ffac1d5f", - "reference": "c8bbd961401015307bc72f6f6aa93509ffac1d5f", + "url": "https://api.github.com/repos/michalsn/codeigniter4-uuid/zipball/b26512ac4f3f0c772fbfa2c3317346d3c17e2d44", + "reference": "b26512ac4f3f0c772fbfa2c3317346d3c17e2d44", "shasum": "" }, "require": { @@ -1146,6 +1158,7 @@ "codeigniter4/codeigniter4": "dev-develop", "phpunit/phpunit": "8.5.*" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -1173,9 +1186,9 @@ ], "support": { "issues": "https://github.com/michalsn/codeigniter4-uuid/issues", - "source": "https://github.com/michalsn/codeigniter4-uuid/tree/v1.0.1" + "source": "https://github.com/michalsn/codeigniter4-uuid/tree/develop" }, - "time": "2021-05-03T12:47:44+00:00" + "time": "2021-05-10T16:28:01+00:00" }, { "name": "myth/auth", @@ -1633,6 +1646,57 @@ }, "time": "2021-05-03T11:20:27+00:00" }, + { + "name": "psr/simple-cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/master" + }, + "time": "2017-10-23T01:57:42+00:00" + }, { "name": "ramsey/collection", "version": "1.1.3", @@ -2126,16 +2190,16 @@ }, { "name": "whichbrowser/parser", - "version": "v2.1.1", + "version": "v2.1.2", "source": { "type": "git", "url": "https://github.com/WhichBrowser/Parser-PHP.git", - "reference": "da24adc4f4f26002673d236e69b91a10f2fd594c" + "reference": "bcf642a1891032de16a5ab976fd352753dd7f9a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/WhichBrowser/Parser-PHP/zipball/da24adc4f4f26002673d236e69b91a10f2fd594c", - "reference": "da24adc4f4f26002673d236e69b91a10f2fd594c", + "url": "https://api.github.com/repos/WhichBrowser/Parser-PHP/zipball/bcf642a1891032de16a5ab976fd352753dd7f9a0", + "reference": "bcf642a1891032de16a5ab976fd352753dd7f9a0", "shasum": "" }, "require": { @@ -2184,9 +2248,9 @@ ], "support": { "issues": "https://github.com/WhichBrowser/Parser-PHP/issues", - "source": "https://github.com/WhichBrowser/Parser-PHP/tree/v2.1.1" + "source": "https://github.com/WhichBrowser/Parser-PHP/tree/v2.1.2" }, - "time": "2021-01-04T16:36:15+00:00" + "time": "2021-05-10T10:18:11+00:00" } ], "packages-dev": [ @@ -2273,6 +2337,61 @@ ], "time": "2021-05-05T12:43:16+00:00" }, + { + "name": "captainhook/plugin-composer", + "version": "5.3.0", + "source": { + "type": "git", + "url": "https://github.com/captainhookphp/plugin-composer.git", + "reference": "def8812945e0767a45fe0e4db5ed255b7093600a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/captainhookphp/plugin-composer/zipball/def8812945e0767a45fe0e4db5ed255b7093600a", + "reference": "def8812945e0767a45fe0e4db5ed255b7093600a", + "shasum": "" + }, + "require": { + "captainhook/captainhook": "^5.0", + "composer-plugin-api": "^1.1|^2.0", + "php": ">=7.1" + }, + "require-dev": { + "composer/composer": "*" + }, + "type": "composer-plugin", + "extra": { + "class": "CaptainHook\\Plugin\\Composer\\ComposerPlugin", + "branch-alias": { + "dev-fluffy_hedgehog": "5.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "CaptainHook\\Plugin\\Composer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andreas Heigl", + "email": "andreas@heigl.org" + }, + { + "name": "Sebastian Feldmann", + "email": "sf@sebastian-feldmann.info" + } + ], + "description": "Composer-Plugin handling your git-hooks", + "support": { + "issues": "https://github.com/captainhookphp/plugin-composer/issues", + "source": "https://github.com/captainhookphp/plugin-composer/tree/5.3.0" + }, + "time": "2021-05-06T15:55:15+00:00" + }, { "name": "composer/package-versions-deprecated", "version": "1.11.99.1", @@ -2715,6 +2834,118 @@ ], "time": "2020-11-10T18:47:58+00:00" }, + { + "name": "ergebnis/json-printer", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/ergebnis/json-printer.git", + "reference": "e4190dadd9937a77d8afcaf2b6c42a528ab367d6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ergebnis/json-printer/zipball/e4190dadd9937a77d8afcaf2b6c42a528ab367d6", + "reference": "e4190dadd9937a77d8afcaf2b6c42a528ab367d6", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "ergebnis/license": "^1.0.0", + "ergebnis/php-cs-fixer-config": "^2.2.1", + "ergebnis/phpstan-rules": "~0.15.2", + "ergebnis/test-util": "^1.1.0", + "infection/infection": "~0.15.3", + "phpstan/extension-installer": "^1.0.4", + "phpstan/phpstan": "~0.12.40", + "phpstan/phpstan-deprecation-rules": "~0.12.5", + "phpstan/phpstan-phpunit": "~0.12.16", + "phpstan/phpstan-strict-rules": "~0.12.4", + "phpunit/phpunit": "^8.5.8", + "psalm/plugin-phpunit": "~0.11.0", + "vimeo/psalm": "^3.14.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Ergebnis\\Json\\Printer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andreas Möller", + "email": "am@localheinz.com" + } + ], + "description": "Provides a JSON printer, allowing for flexible indentation.", + "homepage": "https://github.com/ergebnis/json-printer", + "keywords": [ + "formatter", + "json", + "printer" + ], + "support": { + "issues": "https://github.com/ergebnis/json-printer/issues", + "source": "https://github.com/ergebnis/json-printer" + }, + "funding": [ + { + "url": "https://github.com/localheinz", + "type": "github" + } + ], + "time": "2020-08-30T12:17:03+00:00" + }, + { + "name": "idiosyncratic/editorconfig", + "version": "0.1.1", + "source": { + "type": "git", + "url": "https://github.com/idiosyncratic-code/editorconfig-php.git", + "reference": "50f742daee8b7a632b795f5927d8d88c43dd3a4f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/idiosyncratic-code/editorconfig-php/zipball/50f742daee8b7a632b795f5927d8d88c43dd3a4f", + "reference": "50f742daee8b7a632b795f5927d8d88c43dd3a4f", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "idiosyncratic/devtools": "^0.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Idiosyncratic\\EditorConfig\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Jason Silkey", + "email": "jason@jasonsilkey.com" + } + ], + "description": "PHP implementation of EditorConfig", + "support": { + "issues": "https://github.com/idiosyncratic-code/editorconfig-php/issues", + "source": "https://github.com/idiosyncratic-code/editorconfig-php/tree/0.1.1" + }, + "time": "2021-05-03T15:39:40+00:00" + }, { "name": "jean85/pretty-package-versions", "version": "1.6.0", @@ -3082,73 +3313,6 @@ }, "time": "2021-02-28T12:30:32+00:00" }, - { - "name": "nette/robot-loader", - "version": "v3.4.0", - "source": { - "type": "git", - "url": "https://github.com/nette/robot-loader.git", - "reference": "3973cf3970d1de7b30888fd10b92dac9e0c2fd82" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/robot-loader/zipball/3973cf3970d1de7b30888fd10b92dac9e0c2fd82", - "reference": "3973cf3970d1de7b30888fd10b92dac9e0c2fd82", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "nette/finder": "^2.5 || ^3.0", - "nette/utils": "^3.0", - "php": ">=7.1" - }, - "require-dev": { - "nette/tester": "^2.0", - "phpstan/phpstan": "^0.12", - "tracy/tracy": "^2.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0-only", - "GPL-3.0-only" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "🍀 Nette RobotLoader: high performance and comfortable autoloader that will search and autoload classes within your application.", - "homepage": "https://nette.org", - "keywords": [ - "autoload", - "class", - "interface", - "nette", - "trait" - ], - "support": { - "issues": "https://github.com/nette/robot-loader/issues", - "source": "https://github.com/nette/robot-loader/tree/v3.4.0" - }, - "time": "2021-03-07T15:12:01+00:00" - }, { "name": "nette/utils", "version": "v3.2.2", @@ -3626,6 +3790,51 @@ }, "time": "2021-03-17T13:42:18+00:00" }, + { + "name": "phpstan/extension-installer", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/extension-installer.git", + "reference": "66c7adc9dfa38b6b5838a9fb728b68a7d8348051" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/66c7adc9dfa38b6b5838a9fb728b68a7d8348051", + "reference": "66c7adc9dfa38b6b5838a9fb728b68a7d8348051", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.1 || ^2.0", + "php": "^7.1 || ^8.0", + "phpstan/phpstan": ">=0.11.6" + }, + "require-dev": { + "composer/composer": "^1.8", + "phing/phing": "^2.16.3", + "php-parallel-lint/php-parallel-lint": "^1.2.0", + "phpstan/phpstan-strict-rules": "^0.11 || ^0.12" + }, + "type": "composer-plugin", + "extra": { + "class": "PHPStan\\ExtensionInstaller\\Plugin" + }, + "autoload": { + "psr-4": { + "PHPStan\\ExtensionInstaller\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Composer plugin for automatic installation of PHPStan extensions", + "support": { + "issues": "https://github.com/phpstan/extension-installer/issues", + "source": "https://github.com/phpstan/extension-installer/tree/1.1.0" + }, + "time": "2020-12-13T13:06:13+00:00" + }, { "name": "phpstan/phpdoc-parser", "version": "0.5.4", @@ -4311,48 +4520,101 @@ "time": "2019-01-08T18:20:26+00:00" }, { - "name": "rector/rector", - "version": "0.10.19", + "name": "rector/extension-installer", + "version": "0.10.2", "source": { "type": "git", - "url": "https://github.com/rectorphp/rector.git", - "reference": "efb19e74e60347b1280369e19b26b29ac22199d5" + "url": "https://github.com/rectorphp/extension-installer.git", + "reference": "56c97630fca170b5586b2f08e76348f924ebb8dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/efb19e74e60347b1280369e19b26b29ac22199d5", - "reference": "efb19e74e60347b1280369e19b26b29ac22199d5", + "url": "https://api.github.com/repos/rectorphp/extension-installer/zipball/56c97630fca170b5586b2f08e76348f924ebb8dd", + "reference": "56c97630fca170b5586b2f08e76348f924ebb8dd", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.1 || ^2.0", + "php": "^7.3 || ^8.0" + }, + "require-dev": { + "composer/composer": "^2.0", + "composer/xdebug-handler": "2.0 as 1.4", + "friendsofphp/php-cs-fixer": "^3.0", + "jangregor/phpstan-prophecy": "^0.8.1", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/extension-installer": "^1.1", + "phpunit/phpunit": "^9.5", + "rector/rector-phpstan-rules": "^0.1", + "symplify/easy-coding-standard": "^9.3.1", + "symplify/phpstan-extensions": "^9.3", + "symplify/phpstan-rules": "^9.3" + }, + "type": "composer-plugin", + "extra": { + "class": "Rector\\RectorInstaller\\Plugin" + }, + "autoload": { + "psr-4": { + "Rector\\RectorInstaller\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Composer plugin for automatic installation of Rector extensions", + "support": { + "issues": "https://github.com/rectorphp/extension-installer/issues", + "source": "https://github.com/rectorphp/extension-installer/tree/0.10.2" + }, + "time": "2021-05-06T21:14:19+00:00" + }, + { + "name": "rector/rector", + "version": "0.10.22", + "source": { + "type": "git", + "url": "https://github.com/rectorphp/rector-src.git", + "reference": "d2b8907ce6fb86dd4d8fe2dd661f348b97e812e3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rectorphp/rector-src/zipball/d2b8907ce6fb86dd4d8fe2dd661f348b97e812e3", + "reference": "d2b8907ce6fb86dd4d8fe2dd661f348b97e812e3", "shasum": "" }, "require": { "composer/semver": "^3.2", - "composer/xdebug-handler": "^2.0", + "composer/xdebug-handler": "^1.3|^2.0", "danielstjules/stringy": "^3.1", "doctrine/inflector": "^2.0", + "ergebnis/json-printer": "^3.1", "ext-dom": "*", "ext-json": "*", + "idiosyncratic/editorconfig": "^0.1.0", "jean85/pretty-package-versions": "^1.6", "nette/caching": "^3.1", - "nette/robot-loader": "^3.4", "nette/utils": "^3.2", "nikic/php-parser": "4.10.4", "php": "^7.3|^8.0", "phpstan/phpdoc-parser": "^0.5.4", "phpstan/phpstan": "0.12.85", "phpstan/phpstan-phpunit": "^0.12.18", + "rector/extension-installer": "^0.10.2", "rector/rector-cakephp": "^0.10.4", "rector/rector-doctrine": "^0.10.6", - "rector/rector-installer": "^0.10.0", "rector/rector-laravel": "^0.10.2", - "rector/rector-nette": "^0.10.8", + "rector/rector-nette": "^0.10.9", + "rector/rector-nette-to-symfony": "^0.10.0", "rector/rector-phpunit": "^0.10.8", "rector/rector-symfony": "^0.10.5", "sebastian/diff": "^4.0.4", + "shanethehat/pretty-xml": "^1.0", "symfony/console": "^4.4.8|^5.1", "symfony/dependency-injection": "^5.1", "symfony/finder": "^4.4.8|^5.1", "symfony/http-kernel": "^4.4.8|^5.1", - "symfony/process": "^4.4.8|^5.1", "symplify/astral": "^9.3", "symplify/autowire-array-parameter": "^9.3", "symplify/console-color-diff": "^9.3", @@ -4370,16 +4632,13 @@ "rector/rector-prefixed": "self.version" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.0", - "nette/application": "^3.0.7", - "nette/di": "^3.0", - "nette/forms": "^3.0", "phpstan/extension-installer": "^1.1", "phpstan/phpstan-nette": "^0.12.16", "phpunit/phpunit": "^9.5", "rector/rector-generator": "^0.1.7", "rector/rector-phpstan-rules": "^0.1", "symplify/coding-standard": "^9.3", + "symplify/composer-json-manipulator": "^9.3", "symplify/easy-ci": "^9.3", "symplify/easy-coding-standard": "^9.3", "symplify/easy-testing": "^9.3", @@ -4414,29 +4673,10 @@ "license": [ "MIT" ], - "authors": [ - { - "name": "Tomas Votruba", - "email": "tomas.vot@gmail.com", - "homepage": "https://tomasvotruba.com" - }, - { - "name": "Jan Mikes", - "email": "j.mikes@me.com", - "homepage": "https://janmikes.cz" - } - ], "description": "Instant upgrade and refactoring of your PHP code", "homepage": "https://getrector.org", - "keywords": [ - "ast", - "automated refactoring", - "instant refactoring", - "instant upgrades" - ], "support": { - "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/0.10.19" + "source": "https://github.com/rectorphp/rector-src/tree/0.10.22" }, "funding": [ { @@ -4444,7 +4684,7 @@ "type": "github" } ], - "time": "2021-05-04T18:40:08+00:00" + "time": "2021-05-11T22:28:39+00:00" }, { "name": "rector/rector-cakephp", @@ -4558,55 +4798,6 @@ }, "time": "2021-04-24T12:17:00+00:00" }, - { - "name": "rector/rector-installer", - "version": "0.10.1", - "source": { - "type": "git", - "url": "https://github.com/rectorphp/rector-installer.git", - "reference": "2e8df01aac6a3dedd113ba57ea6f129b6a9872c9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector-installer/zipball/2e8df01aac6a3dedd113ba57ea6f129b6a9872c9", - "reference": "2e8df01aac6a3dedd113ba57ea6f129b6a9872c9", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.1 || ^2.0", - "php": "^7.3 || ^8.0" - }, - "require-dev": { - "composer/composer": "^2.0", - "jangregor/phpstan-prophecy": "^0.8.1", - "phpspec/prophecy-phpunit": "^2.0", - "phpstan/extension-installer": "^1.1", - "phpunit/phpunit": "^9.5", - "rector/rector-phpstan-rules": "^0.1.0", - "symplify/easy-coding-standard": "^9.2.24", - "symplify/phpstan-extensions": "^9.2.24", - "symplify/phpstan-rules": "^9.2.24" - }, - "type": "composer-plugin", - "extra": { - "class": "Rector\\RectorInstaller\\Plugin" - }, - "autoload": { - "psr-4": { - "Rector\\RectorInstaller\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Composer plugin for automatic installation of rector extensions", - "support": { - "issues": "https://github.com/rectorphp/rector-installer/issues", - "source": "https://github.com/rectorphp/rector-installer/tree/0.10.1" - }, - "time": "2021-04-26T14:25:12+00:00" - }, { "name": "rector/rector-laravel", "version": "0.10.2", @@ -4665,22 +4856,22 @@ }, { "name": "rector/rector-nette", - "version": "0.10.9", + "version": "0.10.10", "source": { "type": "git", "url": "https://github.com/rectorphp/rector-nette.git", - "reference": "19c85c870f9a7a90d1f2e9be9b3e048b4db69697" + "reference": "e9f0de1ffb3ba1eecdaa281fcd64fda1d3515e6f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector-nette/zipball/19c85c870f9a7a90d1f2e9be9b3e048b4db69697", - "reference": "19c85c870f9a7a90d1f2e9be9b3e048b4db69697", + "url": "https://api.github.com/repos/rectorphp/rector-nette/zipball/e9f0de1ffb3ba1eecdaa281fcd64fda1d3515e6f", + "reference": "e9f0de1ffb3ba1eecdaa281fcd64fda1d3515e6f", "shasum": "" }, "require": { "ext-xml": "*", "php": ">=7.3", - "rector/rector": "^0.10.12" + "rector/rector": "^0.10.19" }, "conflict": { "rector/rector": "<=0.10.3" @@ -4690,13 +4881,14 @@ "nette/di": "^3.0", "nette/forms": "3.0.*", "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^0.12.85", "phpstan/phpstan-nette": "^0.12.16", "phpunit/phpunit": "^9.5", - "rector/rector-phpstan-rules": "^0.1", - "symplify/easy-coding-standard": "^9.2", - "symplify/phpstan-extensions": "^9.2", - "symplify/phpstan-rules": "^9.2", - "symplify/rule-doc-generator": "^9.2" + "rector/rector-phpstan-rules": "^0.2", + "symplify/easy-coding-standard": "^9.3", + "symplify/phpstan-extensions": "^9.3", + "symplify/phpstan-rules": "^9.3", + "symplify/rule-doc-generator": "^9.3" }, "type": "rector-extension", "extra": { @@ -4721,9 +4913,121 @@ "description": "Rector upgrades rules for Nette Framework", "support": { "issues": "https://github.com/rectorphp/rector-nette/issues", - "source": "https://github.com/rectorphp/rector-nette/tree/0.10.9" + "source": "https://github.com/rectorphp/rector-nette/tree/0.10.10" }, - "time": "2021-04-26T10:35:59+00:00" + "time": "2021-05-06T23:55:02+00:00" + }, + { + "name": "rector/rector-nette-to-symfony", + "version": "0.10.0", + "source": { + "type": "git", + "url": "https://github.com/rectorphp/rector-nette-to-symfony.git", + "reference": "27be9cb982ac7ad3799e0ac7fd45be0a46d7fb0b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rectorphp/rector-nette-to-symfony/zipball/27be9cb982ac7ad3799e0ac7fd45be0a46d7fb0b", + "reference": "27be9cb982ac7ad3799e0ac7fd45be0a46d7fb0b", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "rector/rector": "^0.10.19", + "rector/rector-nette": "^0.10.9" + }, + "require-dev": { + "nette/application": "^3.1", + "nette/forms": "^3.1", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan-nette": "^0.12.16", + "phpunit/phpunit": "^9.5", + "rector/rector-phpstan-rules": "^0.1", + "symfony/form": "^5.2", + "symplify/easy-coding-standard": "^9.3", + "symplify/phpstan-extensions": "^9.3", + "symplify/phpstan-rules": "^9.3", + "symplify/rule-doc-generator": "^9.3" + }, + "type": "rector-extension", + "extra": { + "rector": { + "includes": [ + "config/config.php" + ] + } + }, + "autoload": { + "psr-4": { + "Rector\\NetteToSymfony\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Generate Rector rules from command line", + "support": { + "issues": "https://github.com/rectorphp/rector-nette-to-symfony/issues", + "source": "https://github.com/rectorphp/rector-nette-to-symfony/tree/0.10.0" + }, + "funding": [ + { + "url": "https://github.com/tomasvotruba", + "type": "github" + } + ], + "time": "2021-05-05T21:07:31+00:00" + }, + { + "name": "rector/rector-phpstan-rules", + "version": "0.2.1", + "source": { + "type": "git", + "url": "https://github.com/rectorphp/phpstan-rules.git", + "reference": "6f43a35676463c4688e120194d56928c4be523bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rectorphp/phpstan-rules/zipball/6f43a35676463c4688e120194d56928c4be523bb", + "reference": "6f43a35676463c4688e120194d56928c4be523bb", + "shasum": "" + }, + "require": { + "nette/utils": "^3.2", + "php": ">=7.3", + "phpstan/phpstan": "^0.12.84", + "symplify/phpstan-rules": "^9.2.22" + }, + "require-dev": { + "phpstan/extension-installer": "^1.1", + "phpunit/phpunit": "^9.5", + "symplify/easy-coding-standard": "^9.2.22", + "symplify/phpstan-extensions": "^9.2.22" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "config/config.neon" + ] + } + }, + "autoload": { + "psr-4": { + "Rector\\RectorPHPStanRules\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan rules for Rector projects - with focus on static reflection, constant re-use and Rector design patterns", + "support": { + "issues": "https://github.com/rectorphp/phpstan-rules/issues", + "source": "https://github.com/rectorphp/phpstan-rules/tree/0.2.1" + }, + "time": "2021-05-06T23:51:11+00:00" }, { "name": "rector/rector-phpunit", @@ -5978,17 +6282,64 @@ "time": "2021-04-10T08:31:02+00:00" }, { - "name": "squizlabs/php_codesniffer", - "version": "3.5.8", + "name": "shanethehat/pretty-xml", + "version": "1.0.2", "source": { "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "9d583721a7157ee997f235f327de038e7ea6dac4" + "url": "https://github.com/shanethehat/pretty-xml.git", + "reference": "2b063c6544c8dc9563c53cb72eb06d1d74c9e75f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/9d583721a7157ee997f235f327de038e7ea6dac4", - "reference": "9d583721a7157ee997f235f327de038e7ea6dac4", + "url": "https://api.github.com/repos/shanethehat/pretty-xml/zipball/2b063c6544c8dc9563c53cb72eb06d1d74c9e75f", + "reference": "2b063c6544c8dc9563c53cb72eb06d1d74c9e75f", + "shasum": "" + }, + "require-dev": { + "behat/behat": "~3.0", + "bossa/phpspec2-expect": "*", + "phpspec/phpspec": "~2.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "PrettyXml": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Shane Auckland", + "email": "shane.auckland@gmail.com", + "homepage": "http://shaneauckland.co.uk" + } + ], + "description": "Library for pretty-printing XML", + "keywords": [ + "pretty", + "xml" + ], + "support": { + "issues": "https://github.com/shanethehat/pretty-xml/issues", + "source": "https://github.com/shanethehat/pretty-xml/tree/master" + }, + "time": "2015-08-10T14:22:54+00:00" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "3.6.0", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ffced0d2c8fa8e6cdc4d695a743271fab6c38625", + "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625", "shasum": "" }, "require": { @@ -6031,7 +6382,7 @@ "source": "https://github.com/squizlabs/PHP_CodeSniffer", "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" }, - "time": "2020-10-23T02:01:07+00:00" + "time": "2021-04-09T00:54:41+00:00" }, { "name": "symfony/config", @@ -7539,16 +7890,16 @@ }, { "name": "symplify/astral", - "version": "v9.3.1", + "version": "v9.3.4", "source": { "type": "git", "url": "https://github.com/symplify/astral.git", - "reference": "4347ac8b82c7abc46007850147bdd48f2dd9f511" + "reference": "2ec71b4aad8995c526eee88c3d040bd7a03523e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symplify/astral/zipball/4347ac8b82c7abc46007850147bdd48f2dd9f511", - "reference": "4347ac8b82c7abc46007850147bdd48f2dd9f511", + "url": "https://api.github.com/repos/symplify/astral/zipball/2ec71b4aad8995c526eee88c3d040bd7a03523e7", + "reference": "2ec71b4aad8995c526eee88c3d040bd7a03523e7", "shasum": "" }, "require": { @@ -7557,12 +7908,12 @@ "php": ">=7.3", "symfony/dependency-injection": "^5.2", "symfony/http-kernel": "^4.4|^5.2", - "symplify/autowire-array-parameter": "^9.3.1", - "symplify/package-builder": "^9.3.1" + "symplify/autowire-array-parameter": "^9.3.4", + "symplify/package-builder": "^9.3.4" }, "require-dev": { "phpunit/phpunit": "^9.5", - "symplify/easy-testing": "^9.3.1" + "symplify/easy-testing": "^9.3.4" }, "type": "library", "extra": { @@ -7581,7 +7932,7 @@ ], "description": "Toolking for smart daily work with AST", "support": { - "source": "https://github.com/symplify/astral/tree/v9.3.1" + "source": "https://github.com/symplify/astral/tree/v9.3.4" }, "funding": [ { @@ -7593,27 +7944,27 @@ "type": "github" } ], - "time": "2021-05-04T18:51:08+00:00" + "time": "2021-05-11T13:35:47+00:00" }, { "name": "symplify/autowire-array-parameter", - "version": "v9.3.1", + "version": "v9.3.6", "source": { "type": "git", "url": "https://github.com/symplify/autowire-array-parameter.git", - "reference": "130fff4f734e752dee5d14da26038e9c213d1381" + "reference": "00044807ab4b8ae7df610f80d54360a49b253146" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symplify/autowire-array-parameter/zipball/130fff4f734e752dee5d14da26038e9c213d1381", - "reference": "130fff4f734e752dee5d14da26038e9c213d1381", + "url": "https://api.github.com/repos/symplify/autowire-array-parameter/zipball/00044807ab4b8ae7df610f80d54360a49b253146", + "reference": "00044807ab4b8ae7df610f80d54360a49b253146", "shasum": "" }, "require": { "nette/utils": "^3.2", "php": ">=7.3", "symfony/dependency-injection": "^5.2", - "symplify/package-builder": "^9.3.1" + "symplify/package-builder": "^9.3.6" }, "require-dev": { "phpunit/phpunit": "^9.5" @@ -7635,7 +7986,7 @@ ], "description": "Autowire array parameters for your Symfony applications", "support": { - "source": "https://github.com/symplify/autowire-array-parameter/tree/v9.3.1" + "source": "https://github.com/symplify/autowire-array-parameter/tree/v9.3.6" }, "funding": [ { @@ -7647,20 +7998,20 @@ "type": "github" } ], - "time": "2021-05-04T18:51:07+00:00" + "time": "2021-05-11T22:44:31+00:00" }, { "name": "symplify/composer-json-manipulator", - "version": "v9.3.1", + "version": "v9.3.6", "source": { "type": "git", "url": "https://github.com/symplify/composer-json-manipulator.git", - "reference": "3669e146cb16d990cb33c1dcd321e462aeb63209" + "reference": "c5218020d999c775f5bcc625c7e3d46f7bd21e81" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symplify/composer-json-manipulator/zipball/3669e146cb16d990cb33c1dcd321e462aeb63209", - "reference": "3669e146cb16d990cb33c1dcd321e462aeb63209", + "url": "https://api.github.com/repos/symplify/composer-json-manipulator/zipball/c5218020d999c775f5bcc625c7e3d46f7bd21e81", + "reference": "c5218020d999c775f5bcc625c7e3d46f7bd21e81", "shasum": "" }, "require": { @@ -7670,8 +8021,8 @@ "symfony/dependency-injection": "^5.2", "symfony/filesystem": "^4.4|^5.2", "symfony/http-kernel": "^4.4|^5.2", - "symplify/package-builder": "^9.3.1", - "symplify/smart-file-system": "^9.3.1" + "symplify/package-builder": "^9.3.6", + "symplify/smart-file-system": "^9.3.6" }, "require-dev": { "phpunit/phpunit": "^9.5" @@ -7693,7 +8044,7 @@ ], "description": "Package to load, merge and save composer.json file(s)", "support": { - "source": "https://github.com/symplify/composer-json-manipulator/tree/v9.3.1" + "source": "https://github.com/symplify/composer-json-manipulator/tree/v9.3.6" }, "funding": [ { @@ -7705,20 +8056,20 @@ "type": "github" } ], - "time": "2021-05-04T18:51:09+00:00" + "time": "2021-05-11T22:44:23+00:00" }, { "name": "symplify/console-color-diff", - "version": "v9.3.1", + "version": "v9.3.6", "source": { "type": "git", "url": "https://github.com/symplify/console-color-diff.git", - "reference": "4be4c9a5951bc4e06138099582143ce965f4e63c" + "reference": "8f25607a0b05754bbf6ac8f06d6662adf201e1cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symplify/console-color-diff/zipball/4be4c9a5951bc4e06138099582143ce965f4e63c", - "reference": "4be4c9a5951bc4e06138099582143ce965f4e63c", + "url": "https://api.github.com/repos/symplify/console-color-diff/zipball/8f25607a0b05754bbf6ac8f06d6662adf201e1cb", + "reference": "8f25607a0b05754bbf6ac8f06d6662adf201e1cb", "shasum": "" }, "require": { @@ -7728,7 +8079,7 @@ "symfony/console": "^4.4|^5.2", "symfony/dependency-injection": "^5.2", "symfony/http-kernel": "^4.4|^5.2", - "symplify/package-builder": "^9.3.1" + "symplify/package-builder": "^9.3.6" }, "require-dev": { "phpunit/phpunit": "^9.5" @@ -7750,7 +8101,7 @@ ], "description": "Package to print diffs in console with colors", "support": { - "source": "https://github.com/symplify/console-color-diff/tree/v9.3.1" + "source": "https://github.com/symplify/console-color-diff/tree/v9.3.6" }, "funding": [ { @@ -7762,32 +8113,32 @@ "type": "github" } ], - "time": "2021-05-04T18:51:06+00:00" + "time": "2021-05-11T22:44:55+00:00" }, { "name": "symplify/console-package-builder", - "version": "v9.3.1", + "version": "v9.3.6", "source": { "type": "git", "url": "https://github.com/symplify/console-package-builder.git", - "reference": "6b3c83944b8c094c5a4b80356316d2348a9056c7" + "reference": "4a7d5d412e2bdf805c4603a02c69ef16183521c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symplify/console-package-builder/zipball/6b3c83944b8c094c5a4b80356316d2348a9056c7", - "reference": "6b3c83944b8c094c5a4b80356316d2348a9056c7", + "url": "https://api.github.com/repos/symplify/console-package-builder/zipball/4a7d5d412e2bdf805c4603a02c69ef16183521c9", + "reference": "4a7d5d412e2bdf805c4603a02c69ef16183521c9", "shasum": "" }, "require": { "php": ">=7.3", "symfony/console": "^4.4|^5.2", "symfony/dependency-injection": "^5.2", - "symplify/symplify-kernel": "^9.3.1" + "symplify/symplify-kernel": "^9.3.6" }, "require-dev": { "phpunit/phpunit": "^9.5", "symfony/http-kernel": "^4.4|^5.2", - "symplify/package-builder": "^9.3.1" + "symplify/package-builder": "^9.3.6" }, "type": "library", "extra": { @@ -7806,22 +8157,22 @@ ], "description": "Package to speed up building command line applications", "support": { - "source": "https://github.com/symplify/console-package-builder/tree/v9.3.1" + "source": "https://github.com/symplify/console-package-builder/tree/v9.3.6" }, - "time": "2021-05-04T18:51:09+00:00" + "time": "2021-05-11T22:45:10+00:00" }, { "name": "symplify/easy-testing", - "version": "v9.3.1", + "version": "v9.3.6", "source": { "type": "git", "url": "https://github.com/symplify/easy-testing.git", - "reference": "0bde7c1c45d80a6ff9587a0b960984d9dc9b9700" + "reference": "f8b617e6c0df1c76acb3150af40bd256bf2c0aba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symplify/easy-testing/zipball/0bde7c1c45d80a6ff9587a0b960984d9dc9b9700", - "reference": "0bde7c1c45d80a6ff9587a0b960984d9dc9b9700", + "url": "https://api.github.com/repos/symplify/easy-testing/zipball/f8b617e6c0df1c76acb3150af40bd256bf2c0aba", + "reference": "f8b617e6c0df1c76acb3150af40bd256bf2c0aba", "shasum": "" }, "require": { @@ -7831,10 +8182,10 @@ "symfony/dependency-injection": "^5.2", "symfony/finder": "^4.4|^5.2", "symfony/http-kernel": "^4.4|^5.2", - "symplify/console-package-builder": "^9.3.1", - "symplify/package-builder": "^9.3.1", - "symplify/smart-file-system": "^9.3.1", - "symplify/symplify-kernel": "^9.3.1" + "symplify/console-package-builder": "^9.3.6", + "symplify/package-builder": "^9.3.6", + "symplify/smart-file-system": "^9.3.6", + "symplify/symplify-kernel": "^9.3.6" }, "require-dev": { "phpunit/phpunit": "^9.5" @@ -7859,7 +8210,7 @@ ], "description": "Testing made easy", "support": { - "source": "https://github.com/symplify/easy-testing/tree/v9.3.1" + "source": "https://github.com/symplify/easy-testing/tree/v9.3.6" }, "funding": [ { @@ -7871,20 +8222,20 @@ "type": "github" } ], - "time": "2021-05-04T18:51:21+00:00" + "time": "2021-05-11T22:44:47+00:00" }, { "name": "symplify/package-builder", - "version": "v9.3.1", + "version": "v9.3.6", "source": { "type": "git", "url": "https://github.com/symplify/package-builder.git", - "reference": "126c7b9e3c13fb44c581fced4c5355bd51466d55" + "reference": "9d572946f2483150aae1f7b7d5afe75c5206ffda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symplify/package-builder/zipball/126c7b9e3c13fb44c581fced4c5355bd51466d55", - "reference": "126c7b9e3c13fb44c581fced4c5355bd51466d55", + "url": "https://api.github.com/repos/symplify/package-builder/zipball/9d572946f2483150aae1f7b7d5afe75c5206ffda", + "reference": "9d572946f2483150aae1f7b7d5afe75c5206ffda", "shasum": "" }, "require": { @@ -7896,8 +8247,8 @@ "symfony/dependency-injection": "^5.2", "symfony/finder": "^4.4|^5.2", "symfony/http-kernel": "^4.4|^5.2", - "symplify/easy-testing": "^9.3.1", - "symplify/symplify-kernel": "^9.3.1" + "symplify/easy-testing": "^9.3.6", + "symplify/symplify-kernel": "^9.3.6" }, "require-dev": { "phpunit/phpunit": "^9.5" @@ -7919,7 +8270,7 @@ ], "description": "Dependency Injection, Console and Kernel toolkit for Symplify packages.", "support": { - "source": "https://github.com/symplify/package-builder/tree/v9.3.1" + "source": "https://github.com/symplify/package-builder/tree/v9.3.6" }, "funding": [ { @@ -7931,20 +8282,96 @@ "type": "github" } ], - "time": "2021-05-04T18:51:32+00:00" + "time": "2021-05-11T22:45:02+00:00" }, { - "name": "symplify/rule-doc-generator-contracts", - "version": "v9.3.1", + "name": "symplify/phpstan-rules", + "version": "v9.3.4", "source": { "type": "git", - "url": "https://github.com/symplify/rule-doc-generator-contracts.git", - "reference": "0f04552a1fad5beff718935086177ef2a4de5ca6" + "url": "https://github.com/symplify/phpstan-rules.git", + "reference": "4856ef701dcb0823f7455441201f11f378b99c97" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symplify/rule-doc-generator-contracts/zipball/0f04552a1fad5beff718935086177ef2a4de5ca6", - "reference": "0f04552a1fad5beff718935086177ef2a4de5ca6", + "url": "https://api.github.com/repos/symplify/phpstan-rules/zipball/4856ef701dcb0823f7455441201f11f378b99c97", + "reference": "4856ef701dcb0823f7455441201f11f378b99c97", + "shasum": "" + }, + "require": { + "nette/utils": "^3.2", + "nikic/php-parser": "4.10.4", + "php": ">=7.3", + "phpstan/phpdoc-parser": "^0.5", + "phpstan/phpstan": "0.12.85", + "symplify/astral": "^9.3.4", + "symplify/composer-json-manipulator": "^9.3.4", + "symplify/package-builder": "^9.3.4", + "symplify/rule-doc-generator-contracts": "^9.3.4", + "symplify/smart-file-system": "^9.3.4", + "webmozart/assert": "^1.9" + }, + "require-dev": { + "nette/application": "^3.1", + "nette/forms": "^3.1", + "phpunit/phpunit": "^9.5", + "symfony/framework-bundle": "^4.4|^5.2", + "symplify/easy-testing": "^9.3.4", + "symplify/phpstan-extensions": "^9.3.4", + "symplify/rule-doc-generator": "^9.3.4" + }, + "type": "phpstan-extension", + "extra": { + "branch-alias": { + "dev-main": "9.4-dev" + }, + "phpstan": { + "includes": [ + "config/services/services.neon", + "packages/cognitive-complexity/config/cognitive-complexity-services.neon", + "packages/object-calisthenics/config/object-calisthenics-services.neon" + ] + } + }, + "autoload": { + "psr-4": { + "Symplify\\PHPStanRules\\": "src", + "Symplify\\PHPStanRules\\CognitiveComplexity\\": "packages/cognitive-complexity/src", + "Symplify\\PHPStanRules\\ObjectCalisthenics\\": "packages/object-calisthenics/src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Set of Symplify rules for PHPStan", + "support": { + "source": "https://github.com/symplify/phpstan-rules/tree/v9.3.4" + }, + "funding": [ + { + "url": "https://www.paypal.me/rectorphp", + "type": "custom" + }, + { + "url": "https://github.com/tomasvotruba", + "type": "github" + } + ], + "time": "2021-05-11T13:36:44+00:00" + }, + { + "name": "symplify/rule-doc-generator-contracts", + "version": "v9.3.6", + "source": { + "type": "git", + "url": "https://github.com/symplify/rule-doc-generator-contracts.git", + "reference": "06f23a3bfe1426030c4032e99665472a229d5b43" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symplify/rule-doc-generator-contracts/zipball/06f23a3bfe1426030c4032e99665472a229d5b43", + "reference": "06f23a3bfe1426030c4032e99665472a229d5b43", "shasum": "" }, "require": { @@ -7968,7 +8395,7 @@ ], "description": "Contracts for production code of RuleDocGenerator", "support": { - "source": "https://github.com/symplify/rule-doc-generator-contracts/tree/v9.3.1" + "source": "https://github.com/symplify/rule-doc-generator-contracts/tree/v9.3.6" }, "funding": [ { @@ -7980,20 +8407,20 @@ "type": "github" } ], - "time": "2021-04-28T07:48:39+00:00" + "time": "2021-05-11T13:31:15+00:00" }, { "name": "symplify/set-config-resolver", - "version": "v9.3.1", + "version": "v9.3.6", "source": { "type": "git", "url": "https://github.com/symplify/set-config-resolver.git", - "reference": "00a96e094b2c4e784b74797a07a2ca562d14a3b3" + "reference": "7da336c9144b3bfea439e8335680c2abe57cdca1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symplify/set-config-resolver/zipball/00a96e094b2c4e784b74797a07a2ca562d14a3b3", - "reference": "00a96e094b2c4e784b74797a07a2ca562d14a3b3", + "url": "https://api.github.com/repos/symplify/set-config-resolver/zipball/7da336c9144b3bfea439e8335680c2abe57cdca1", + "reference": "7da336c9144b3bfea439e8335680c2abe57cdca1", "shasum": "" }, "require": { @@ -8004,8 +8431,8 @@ "symfony/dependency-injection": "^5.2", "symfony/filesystem": "^4.4|^5.2", "symfony/finder": "^4.4|^5.2", - "symplify/smart-file-system": "^9.3.1", - "symplify/symplify-kernel": "^9.3.1" + "symplify/smart-file-system": "^9.3.6", + "symplify/symplify-kernel": "^9.3.6" }, "require-dev": { "phpunit/phpunit": "^9.5" @@ -8027,7 +8454,7 @@ ], "description": "Resolve config and sets from configs and cli opptions for CLI applications", "support": { - "source": "https://github.com/symplify/set-config-resolver/tree/v9.3.1" + "source": "https://github.com/symplify/set-config-resolver/tree/v9.3.6" }, "funding": [ { @@ -8039,20 +8466,20 @@ "type": "github" } ], - "time": "2021-05-04T18:52:01+00:00" + "time": "2021-05-11T22:45:21+00:00" }, { "name": "symplify/simple-php-doc-parser", - "version": "v9.3.1", + "version": "v9.3.6", "source": { "type": "git", "url": "https://github.com/symplify/simple-php-doc-parser.git", - "reference": "c3e9dfc3a33dc2d16c3beff7fefa27a3b4cf421b" + "reference": "cea820fa5a20d2fa8a240e2e0fcd7b063ce21b9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symplify/simple-php-doc-parser/zipball/c3e9dfc3a33dc2d16c3beff7fefa27a3b4cf421b", - "reference": "c3e9dfc3a33dc2d16c3beff7fefa27a3b4cf421b", + "url": "https://api.github.com/repos/symplify/simple-php-doc-parser/zipball/cea820fa5a20d2fa8a240e2e0fcd7b063ce21b9d", + "reference": "cea820fa5a20d2fa8a240e2e0fcd7b063ce21b9d", "shasum": "" }, "require": { @@ -8061,11 +8488,11 @@ "symfony/config": "^4.4|^5.2", "symfony/dependency-injection": "^5.2", "symfony/http-kernel": "^4.4|^5.2", - "symplify/package-builder": "^9.3.1" + "symplify/package-builder": "^9.3.6" }, "require-dev": { "phpunit/phpunit": "^9.5", - "symplify/easy-testing": "^9.3.1" + "symplify/easy-testing": "^9.3.6" }, "type": "library", "extra": { @@ -8084,7 +8511,7 @@ ], "description": "Service integration of phpstan/phpdoc-parser, with few extra goodies for practical simple use", "support": { - "source": "https://github.com/symplify/simple-php-doc-parser/tree/v9.3.1" + "source": "https://github.com/symplify/simple-php-doc-parser/tree/v9.3.6" }, "funding": [ { @@ -8096,20 +8523,20 @@ "type": "github" } ], - "time": "2021-05-04T18:52:01+00:00" + "time": "2021-05-11T22:45:32+00:00" }, { "name": "symplify/skipper", - "version": "v9.3.1", + "version": "v9.3.6", "source": { "type": "git", "url": "https://github.com/symplify/skipper.git", - "reference": "cd166ddf714cfdc120fb44bc1338865b2f59b889" + "reference": "67417fd44b4ddc3796df5c699ecd076b8c71927e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symplify/skipper/zipball/cd166ddf714cfdc120fb44bc1338865b2f59b889", - "reference": "cd166ddf714cfdc120fb44bc1338865b2f59b889", + "url": "https://api.github.com/repos/symplify/skipper/zipball/67417fd44b4ddc3796df5c699ecd076b8c71927e", + "reference": "67417fd44b4ddc3796df5c699ecd076b8c71927e", "shasum": "" }, "require": { @@ -8119,9 +8546,9 @@ "symfony/dependency-injection": "^5.2", "symfony/filesystem": "^4.4|^5.2", "symfony/finder": "^4.4|^5.2", - "symplify/package-builder": "^9.3.1", - "symplify/smart-file-system": "^9.3.1", - "symplify/symplify-kernel": "^9.3.1" + "symplify/package-builder": "^9.3.6", + "symplify/smart-file-system": "^9.3.6", + "symplify/symplify-kernel": "^9.3.6" }, "require-dev": { "phpunit/phpunit": "^9.5" @@ -8143,7 +8570,7 @@ ], "description": "Skip files by rule class, directory, file or fnmatch", "support": { - "source": "https://github.com/symplify/skipper/tree/v9.3.1" + "source": "https://github.com/symplify/skipper/tree/v9.3.6" }, "funding": [ { @@ -8155,20 +8582,20 @@ "type": "github" } ], - "time": "2021-05-04T18:52:00+00:00" + "time": "2021-05-11T22:45:36+00:00" }, { "name": "symplify/smart-file-system", - "version": "v9.3.1", + "version": "v9.3.6", "source": { "type": "git", "url": "https://github.com/symplify/smart-file-system.git", - "reference": "2721d9eb56b43726307d42a4b64f2cee5b2534b5" + "reference": "aafc000f17d9f4b2d1274115095e3cbc2c32d63d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symplify/smart-file-system/zipball/2721d9eb56b43726307d42a4b64f2cee5b2534b5", - "reference": "2721d9eb56b43726307d42a4b64f2cee5b2534b5", + "url": "https://api.github.com/repos/symplify/smart-file-system/zipball/aafc000f17d9f4b2d1274115095e3cbc2c32d63d", + "reference": "aafc000f17d9f4b2d1274115095e3cbc2c32d63d", "shasum": "" }, "require": { @@ -8198,7 +8625,7 @@ ], "description": "Sanitized FileInfo with safe getRealPath() and other handy methods", "support": { - "source": "https://github.com/symplify/smart-file-system/tree/v9.3.1" + "source": "https://github.com/symplify/smart-file-system/tree/v9.3.6" }, "funding": [ { @@ -8210,37 +8637,37 @@ "type": "github" } ], - "time": "2021-04-28T07:48:45+00:00" + "time": "2021-05-11T13:30:32+00:00" }, { "name": "symplify/symfony-php-config", - "version": "v9.3.0", + "version": "v9.3.5", "source": { "type": "git", "url": "https://github.com/symplify/symfony-php-config.git", - "reference": "0a5bf9f1d7d970f2df2b4e4225c297bd774c23c8" + "reference": "9dc9a4010871f822394628487cbc5721c83fe3de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symplify/symfony-php-config/zipball/0a5bf9f1d7d970f2df2b4e4225c297bd774c23c8", - "reference": "0a5bf9f1d7d970f2df2b4e4225c297bd774c23c8", + "url": "https://api.github.com/repos/symplify/symfony-php-config/zipball/9dc9a4010871f822394628487cbc5721c83fe3de", + "reference": "9dc9a4010871f822394628487cbc5721c83fe3de", "shasum": "" }, "require": { "php": ">=7.3", "symfony/dependency-injection": "^5.2", - "symplify/package-builder": "^9.3", - "symplify/symplify-kernel": "^9.3" + "symplify/package-builder": "^9.3.5", + "symplify/symplify-kernel": "^9.3.5" }, "require-dev": { - "phpstan/phpstan": "^0.12.82", + "phpstan/phpstan": "0.12.86", "phpunit/phpunit": "^9.5", "symfony/http-kernel": "^4.4|^5.2" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "9.3-dev" + "dev-main": "9.4-dev" } }, "autoload": { @@ -8254,34 +8681,33 @@ ], "description": "Tools that easy work with Symfony PHP Configs", "support": { - "source": "https://github.com/symplify/symfony-php-config/tree/v9.3.0" + "source": "https://github.com/symplify/symfony-php-config/tree/v9.3.5" }, - "time": "2021-04-26T17:12:31+00:00" + "time": "2021-05-11T14:11:22+00:00" }, { "name": "symplify/symplify-kernel", - "version": "v9.3.1", + "version": "v9.3.6", "source": { "type": "git", "url": "https://github.com/symplify/symplify-kernel.git", - "reference": "4f895a22b50579ad0767f6b18f2e0aaf8b11fcac" + "reference": "ba7f3b8ee3ce80a8543f248495a0999e0ea6af7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symplify/symplify-kernel/zipball/4f895a22b50579ad0767f6b18f2e0aaf8b11fcac", - "reference": "4f895a22b50579ad0767f6b18f2e0aaf8b11fcac", + "url": "https://api.github.com/repos/symplify/symplify-kernel/zipball/ba7f3b8ee3ce80a8543f248495a0999e0ea6af7a", + "reference": "ba7f3b8ee3ce80a8543f248495a0999e0ea6af7a", "shasum": "" }, "require": { - "jean85/pretty-package-versions": "^1.6|^2.0.1", "php": ">=7.3", "symfony/console": "^4.4|^5.2", "symfony/dependency-injection": "^5.2", "symfony/http-kernel": "^4.4|^5.2", - "symplify/autowire-array-parameter": "^9.3.1", - "symplify/composer-json-manipulator": "^9.3.1", - "symplify/package-builder": "^9.3.1", - "symplify/smart-file-system": "^9.3.1" + "symplify/autowire-array-parameter": "^9.3.6", + "symplify/composer-json-manipulator": "^9.3.6", + "symplify/package-builder": "^9.3.6", + "symplify/smart-file-system": "^9.3.6" }, "require-dev": { "phpunit/phpunit": "^9.5" @@ -8303,9 +8729,9 @@ ], "description": "Internal Kernel for Symplify packages", "support": { - "source": "https://github.com/symplify/symplify-kernel/tree/v9.3.1" + "source": "https://github.com/symplify/symplify-kernel/tree/v9.3.6" }, - "time": "2021-05-04T18:52:09+00:00" + "time": "2021-05-11T22:45:48+00:00" }, { "name": "theseer/tokenizer", @@ -8495,7 +8921,8 @@ "stability-flags": { "james-heinrich/getid3": 20, "myth/auth": 20, - "codeigniter4/codeigniter4": 20 + "codeigniter4/codeigniter4": 20, + "michalsn/codeigniter4-uuid": 20 }, "prefer-stable": true, "prefer-lowest": false, diff --git a/package-lock.json b/package-lock.json index 59df7d0f..23c6feb3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1596,9 +1596,9 @@ } }, "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true, "optional": true }, @@ -1747,9 +1747,9 @@ } }, "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true, "optional": true }, @@ -2519,19 +2519,19 @@ } }, "@semantic-release/npm": { - "version": "7.0.10", - "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-7.0.10.tgz", - "integrity": "sha512-DXFEhgSt5u22imTWbw8wfcVGB90nFJNcjUBtJI3zswJojzZ7yXpY4i2Va5RBRQRTtj00BfG0stbilAtKrKp35g==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-7.1.3.tgz", + "integrity": "sha512-x52kQ/jR09WjuWdaTEHgQCvZYMOTx68WnS+TZ4fya5ZAJw4oRtJETtrvUw10FdfM28d/keInQdc66R1Gw5+OEQ==", "dev": true, "requires": { "@semantic-release/error": "^2.2.0", "aggregate-error": "^3.0.0", "execa": "^5.0.0", - "fs-extra": "^9.0.0", + "fs-extra": "^10.0.0", "lodash": "^4.17.15", "nerf-dart": "^1.0.0", - "normalize-url": "^5.0.0", - "npm": "^6.14.9", + "normalize-url": "^6.0.0", + "npm": "^7.0.0", "rc": "^1.2.8", "read-pkg": "^5.0.0", "registry-auth-token": "^4.0.0", @@ -2557,21 +2557,20 @@ } }, "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", "dev": true, "requires": { - "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "get-stream": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", - "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true }, "human-signals": { @@ -2597,11 +2596,2050 @@ "dev": true }, "normalize-url": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-5.3.0.tgz", - "integrity": "sha512-9/nOVLYYe/dO/eJeQUNaGUF4m4Z5E7cb9oNTKabH+bNf19mqj60txTcveQxL0GlcWLXCxkOu2/LwL8oW0idIDA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.0.0.tgz", + "integrity": "sha512-3nv3dKMucKPEXhx/FEtJQR26ksYdyVlLEP9/dYvYwCbLbP6H8ya94IRf+mB93ec+fndv/Ye8SylWfD7jmN6kSA==", "dev": true }, + "npm": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/npm/-/npm-7.12.1.tgz", + "integrity": "sha512-vjIniB3kqujcDTgH+k90J2i5PPqYZyf1gi5Ni5fARK4WQr5FuVnTQlTXloyk15+qWUxwWHcy6U8YCWwh/TLzmA==", + "dev": true, + "requires": { + "@npmcli/arborist": "^2.4.4", + "@npmcli/ci-detect": "^1.2.0", + "@npmcli/config": "^2.2.0", + "@npmcli/run-script": "^1.8.5", + "abbrev": "~1.1.1", + "ansicolors": "~0.3.2", + "ansistyles": "~0.1.3", + "archy": "~1.0.0", + "byte-size": "^7.0.1", + "cacache": "^15.0.6", + "chalk": "^4.1.0", + "chownr": "^2.0.0", + "cli-columns": "^3.1.2", + "cli-table3": "^0.6.0", + "columnify": "~1.5.4", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "hosted-git-info": "^4.0.2", + "ini": "^2.0.0", + "init-package-json": "^2.0.3", + "is-cidr": "^4.0.2", + "json-parse-even-better-errors": "^2.3.1", + "leven": "^3.1.0", + "libnpmaccess": "^4.0.2", + "libnpmdiff": "^2.0.4", + "libnpmexec": "^1.1.1", + "libnpmfund": "^1.0.2", + "libnpmhook": "^6.0.2", + "libnpmorg": "^2.0.2", + "libnpmpack": "^2.0.1", + "libnpmpublish": "^4.0.1", + "libnpmsearch": "^3.1.1", + "libnpmteam": "^2.0.3", + "libnpmversion": "^1.2.0", + "make-fetch-happen": "^8.0.14", + "minipass": "^3.1.3", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "mkdirp-infer-owner": "^2.0.0", + "ms": "^2.1.2", + "node-gyp": "^7.1.2", + "nopt": "^5.0.0", + "npm-audit-report": "^2.1.4", + "npm-package-arg": "^8.1.2", + "npm-pick-manifest": "^6.1.1", + "npm-profile": "^5.0.3", + "npm-registry-fetch": "^10.1.1", + "npm-user-validate": "^1.0.1", + "npmlog": "~4.1.2", + "opener": "^1.5.2", + "pacote": "^11.3.3", + "parse-conflict-json": "^1.1.1", + "qrcode-terminal": "^0.12.0", + "read": "~1.0.7", + "read-package-json": "^3.0.1", + "read-package-json-fast": "^2.0.2", + "readdir-scoped-modules": "^1.1.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "ssri": "^8.0.1", + "tar": "^6.1.0", + "text-table": "~0.2.0", + "tiny-relative-date": "^1.3.0", + "treeverse": "^1.0.4", + "validate-npm-package-name": "~3.0.0", + "which": "^2.0.2", + "write-file-atomic": "^3.0.3" + }, + "dependencies": { + "@npmcli/arborist": { + "version": "2.4.4", + "bundled": true, + "dev": true, + "requires": { + "@npmcli/installed-package-contents": "^1.0.7", + "@npmcli/map-workspaces": "^1.0.2", + "@npmcli/metavuln-calculator": "^1.1.0", + "@npmcli/move-file": "^1.1.0", + "@npmcli/name-from-folder": "^1.0.1", + "@npmcli/node-gyp": "^1.0.1", + "@npmcli/run-script": "^1.8.2", + "bin-links": "^2.2.1", + "cacache": "^15.0.3", + "common-ancestor-path": "^1.0.1", + "json-parse-even-better-errors": "^2.3.1", + "json-stringify-nice": "^1.1.4", + "mkdirp-infer-owner": "^2.0.0", + "npm-install-checks": "^4.0.0", + "npm-package-arg": "^8.1.0", + "npm-pick-manifest": "^6.1.0", + "npm-registry-fetch": "^10.0.0", + "pacote": "^11.2.6", + "parse-conflict-json": "^1.1.1", + "promise-all-reject-late": "^1.0.0", + "promise-call-limit": "^1.0.1", + "read-package-json-fast": "^2.0.2", + "readdir-scoped-modules": "^1.1.0", + "semver": "^7.3.5", + "tar": "^6.1.0", + "treeverse": "^1.0.4", + "walk-up-path": "^1.0.0" + } + }, + "@npmcli/ci-detect": { + "version": "1.3.0", + "bundled": true, + "dev": true + }, + "@npmcli/config": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "requires": { + "ini": "^2.0.0", + "mkdirp-infer-owner": "^2.0.0", + "nopt": "^5.0.0", + "semver": "^7.3.4", + "walk-up-path": "^1.0.0" + } + }, + "@npmcli/disparity-colors": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-styles": "^4.3.0" + } + }, + "@npmcli/git": { + "version": "2.0.9", + "bundled": true, + "dev": true, + "requires": { + "@npmcli/promise-spawn": "^1.3.2", + "lru-cache": "^6.0.0", + "mkdirp": "^1.0.4", + "npm-pick-manifest": "^6.1.1", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^2.0.2" + } + }, + "@npmcli/installed-package-contents": { + "version": "1.0.7", + "bundled": true, + "dev": true, + "requires": { + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "@npmcli/map-workspaces": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "requires": { + "@npmcli/name-from-folder": "^1.0.1", + "glob": "^7.1.6", + "minimatch": "^3.0.4", + "read-package-json-fast": "^2.0.1" + } + }, + "@npmcli/metavuln-calculator": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "requires": { + "cacache": "^15.0.5", + "pacote": "^11.1.11", + "semver": "^7.3.2" + } + }, + "@npmcli/move-file": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "requires": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + } + }, + "@npmcli/name-from-folder": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "@npmcli/node-gyp": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "@npmcli/promise-spawn": { + "version": "1.3.2", + "bundled": true, + "dev": true, + "requires": { + "infer-owner": "^1.0.4" + } + }, + "@npmcli/run-script": { + "version": "1.8.5", + "bundled": true, + "dev": true, + "requires": { + "@npmcli/node-gyp": "^1.0.2", + "@npmcli/promise-spawn": "^1.3.2", + "infer-owner": "^1.0.4", + "node-gyp": "^7.1.0", + "read-package-json-fast": "^2.0.1" + } + }, + "@tootallnate/once": { + "version": "1.1.2", + "bundled": true, + "dev": true + }, + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true + }, + "agent-base": { + "version": "6.0.2", + "bundled": true, + "dev": true, + "requires": { + "debug": "4" + } + }, + "agentkeepalive": { + "version": "4.1.4", + "bundled": true, + "dev": true, + "requires": { + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" + } + }, + "aggregate-error": { + "version": "3.1.0", + "bundled": true, + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ajv": { + "version": "6.12.6", + "bundled": true, + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "bundled": true, + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "ansicolors": { + "version": "0.3.2", + "bundled": true, + "dev": true + }, + "ansistyles": { + "version": "0.1.3", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "archy": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "asap": { + "version": "2.0.6", + "bundled": true, + "dev": true + }, + "asn1": { + "version": "0.2.4", + "bundled": true, + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true, + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "bundled": true, + "dev": true + }, + "aws4": { + "version": "1.11.0", + "bundled": true, + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bin-links": { + "version": "2.2.1", + "bundled": true, + "dev": true, + "requires": { + "cmd-shim": "^4.0.1", + "mkdirp": "^1.0.3", + "npm-normalize-package-bin": "^1.0.0", + "read-cmd-shim": "^2.0.0", + "rimraf": "^3.0.0", + "write-file-atomic": "^3.0.3" + } + }, + "binary-extensions": { + "version": "2.2.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "builtins": { + "version": "1.0.3", + "bundled": true, + "dev": true + }, + "byte-size": { + "version": "7.0.1", + "bundled": true, + "dev": true + }, + "cacache": { + "version": "15.0.6", + "bundled": true, + "dev": true, + "requires": { + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + } + }, + "caseless": { + "version": "0.12.0", + "bundled": true, + "dev": true + }, + "chalk": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chownr": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "cidr-regex": { + "version": "3.1.1", + "bundled": true, + "dev": true, + "requires": { + "ip-regex": "^4.1.0" + } + }, + "clean-stack": { + "version": "2.2.0", + "bundled": true, + "dev": true + }, + "cli-columns": { + "version": "3.1.2", + "bundled": true, + "dev": true, + "requires": { + "string-width": "^2.0.0", + "strip-ansi": "^3.0.1" + } + }, + "cli-table3": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "requires": { + "colors": "^1.1.2", + "object-assign": "^4.1.0", + "string-width": "^4.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "bundled": true, + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "string-width": { + "version": "4.2.2", + "bundled": true, + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "clone": { + "version": "1.0.4", + "bundled": true, + "dev": true + }, + "cmd-shim": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "requires": { + "mkdirp-infer-owner": "^2.0.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "color-convert": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "bundled": true, + "dev": true + }, + "colors": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "columnify": { + "version": "1.5.4", + "bundled": true, + "dev": true, + "requires": { + "strip-ansi": "^3.0.0", + "wcwidth": "^1.0.0" + } + }, + "combined-stream": { + "version": "1.0.8", + "bundled": true, + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "common-ancestor-path": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "debug": { + "version": "4.3.1", + "bundled": true, + "dev": true, + "requires": { + "ms": "2.1.2" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "bundled": true, + "dev": true + } + } + }, + "debuglog": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "defaults": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "requires": { + "clone": "^1.0.2" + } + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "depd": { + "version": "1.1.2", + "bundled": true, + "dev": true + }, + "dezalgo": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "diff": { + "version": "5.0.0", + "bundled": true, + "dev": true + }, + "ecc-jsbn": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "emoji-regex": { + "version": "8.0.0", + "bundled": true, + "dev": true + }, + "encoding": { + "version": "0.1.13", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "iconv-lite": "^0.6.2" + } + }, + "env-paths": { + "version": "2.2.1", + "bundled": true, + "dev": true + }, + "err-code": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "extend": { + "version": "3.0.2", + "bundled": true, + "dev": true + }, + "extsprintf": { + "version": "1.3.0", + "bundled": true, + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "bundled": true, + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "bundled": true, + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true, + "dev": true + }, + "form-data": { + "version": "2.3.3", + "bundled": true, + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fs-minipass": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "bundled": true, + "dev": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.7", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.6", + "bundled": true, + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "har-validator": { + "version": "5.1.5", + "bundled": true, + "dev": true, + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "4.0.0", + "bundled": true, + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true + }, + "hosted-git-info": { + "version": "4.0.2", + "bundled": true, + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "http-cache-semantics": { + "version": "4.1.0", + "bundled": true, + "dev": true + }, + "http-proxy-agent": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "http-signature": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-proxy-agent": { + "version": "5.0.0", + "bundled": true, + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "humanize-ms": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "requires": { + "ms": "^2.0.0" + } + }, + "iconv-lite": { + "version": "0.6.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "ignore-walk": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "imurmurhash": { + "version": "0.1.4", + "bundled": true, + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "bundled": true, + "dev": true + }, + "infer-owner": { + "version": "1.0.4", + "bundled": true, + "dev": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "bundled": true, + "dev": true + }, + "ini": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "init-package-json": { + "version": "2.0.3", + "bundled": true, + "dev": true, + "requires": { + "glob": "^7.1.1", + "npm-package-arg": "^8.1.2", + "promzard": "^0.3.0", + "read": "~1.0.1", + "read-package-json": "^3.0.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4", + "validate-npm-package-name": "^3.0.0" + } + }, + "ip": { + "version": "1.1.5", + "bundled": true, + "dev": true + }, + "ip-regex": { + "version": "4.3.0", + "bundled": true, + "dev": true + }, + "is-cidr": { + "version": "4.0.2", + "bundled": true, + "dev": true, + "requires": { + "cidr-regex": "^3.1.1" + } + }, + "is-core-module": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "is-lambda": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true, + "dev": true + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "bundled": true, + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true, + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "bundled": true, + "dev": true + }, + "json-stringify-nice": { + "version": "1.1.4", + "bundled": true, + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true, + "dev": true + }, + "jsonparse": { + "version": "1.3.1", + "bundled": true, + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "just-diff": { + "version": "3.1.1", + "bundled": true, + "dev": true + }, + "just-diff-apply": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "leven": { + "version": "3.1.0", + "bundled": true, + "dev": true + }, + "libnpmaccess": { + "version": "4.0.2", + "bundled": true, + "dev": true, + "requires": { + "aproba": "^2.0.0", + "minipass": "^3.1.1", + "npm-package-arg": "^8.1.2", + "npm-registry-fetch": "^10.0.0" + } + }, + "libnpmdiff": { + "version": "2.0.4", + "bundled": true, + "dev": true, + "requires": { + "@npmcli/disparity-colors": "^1.0.1", + "@npmcli/installed-package-contents": "^1.0.7", + "binary-extensions": "^2.2.0", + "diff": "^5.0.0", + "minimatch": "^3.0.4", + "npm-package-arg": "^8.1.1", + "pacote": "^11.3.0", + "tar": "^6.1.0" + } + }, + "libnpmexec": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "requires": { + "@npmcli/arborist": "^2.3.0", + "@npmcli/ci-detect": "^1.3.0", + "@npmcli/run-script": "^1.8.4", + "chalk": "^4.1.0", + "mkdirp-infer-owner": "^2.0.0", + "npm-package-arg": "^8.1.2", + "pacote": "^11.3.1", + "proc-log": "^1.0.0", + "read": "^1.0.7", + "read-package-json-fast": "^2.0.2", + "walk-up-path": "^1.0.0" + } + }, + "libnpmfund": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "@npmcli/arborist": "^2.0.0" + } + }, + "libnpmhook": { + "version": "6.0.2", + "bundled": true, + "dev": true, + "requires": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^10.0.0" + } + }, + "libnpmorg": { + "version": "2.0.2", + "bundled": true, + "dev": true, + "requires": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^10.0.0" + } + }, + "libnpmpack": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "@npmcli/run-script": "^1.8.3", + "npm-package-arg": "^8.1.0", + "pacote": "^11.2.6" + } + }, + "libnpmpublish": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "requires": { + "normalize-package-data": "^3.0.2", + "npm-package-arg": "^8.1.2", + "npm-registry-fetch": "^10.0.0", + "semver": "^7.1.3", + "ssri": "^8.0.1" + } + }, + "libnpmsearch": { + "version": "3.1.1", + "bundled": true, + "dev": true, + "requires": { + "npm-registry-fetch": "^10.0.0" + } + }, + "libnpmteam": { + "version": "2.0.3", + "bundled": true, + "dev": true, + "requires": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^10.0.0" + } + }, + "libnpmversion": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "requires": { + "@npmcli/git": "^2.0.7", + "@npmcli/run-script": "^1.8.4", + "json-parse-even-better-errors": "^2.3.1", + "semver": "^7.3.5", + "stringify-package": "^1.0.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "bundled": true, + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "make-fetch-happen": { + "version": "8.0.14", + "bundled": true, + "dev": true, + "requires": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.0.5", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^5.0.0", + "ssri": "^8.0.0" + } + }, + "mime-db": { + "version": "1.47.0", + "bundled": true, + "dev": true + }, + "mime-types": { + "version": "2.1.30", + "bundled": true, + "dev": true, + "requires": { + "mime-db": "1.47.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minipass": { + "version": "3.1.3", + "bundled": true, + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "minipass-collect": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-fetch": { + "version": "1.3.3", + "bundled": true, + "dev": true, + "requires": { + "encoding": "^0.1.12", + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + } + }, + "minipass-flush": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-json-stream": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-sized": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minizlib": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "bundled": true, + "dev": true + }, + "mkdirp-infer-owner": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "chownr": "^2.0.0", + "infer-owner": "^1.0.4", + "mkdirp": "^1.0.3" + } + }, + "ms": { + "version": "2.1.3", + "bundled": true, + "dev": true + }, + "mute-stream": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "node-gyp": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "requires": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.3", + "nopt": "^5.0.0", + "npmlog": "^4.1.2", + "request": "^2.88.2", + "rimraf": "^3.0.2", + "semver": "^7.3.2", + "tar": "^6.0.2", + "which": "^2.0.2" + } + }, + "nopt": { + "version": "5.0.0", + "bundled": true, + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "normalize-package-data": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "requires": { + "hosted-git-info": "^4.0.1", + "resolve": "^1.20.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-audit-report": { + "version": "2.1.4", + "bundled": true, + "dev": true, + "requires": { + "chalk": "^4.0.0" + } + }, + "npm-bundled": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-install-checks": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "semver": "^7.1.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "npm-package-arg": { + "version": "8.1.2", + "bundled": true, + "dev": true, + "requires": { + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" + } + }, + "npm-packlist": { + "version": "2.2.2", + "bundled": true, + "dev": true, + "requires": { + "glob": "^7.1.6", + "ignore-walk": "^3.0.3", + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-pick-manifest": { + "version": "6.1.1", + "bundled": true, + "dev": true, + "requires": { + "npm-install-checks": "^4.0.0", + "npm-normalize-package-bin": "^1.0.1", + "npm-package-arg": "^8.1.2", + "semver": "^7.3.4" + } + }, + "npm-profile": { + "version": "5.0.3", + "bundled": true, + "dev": true, + "requires": { + "npm-registry-fetch": "^10.0.0" + } + }, + "npm-registry-fetch": { + "version": "10.1.1", + "bundled": true, + "dev": true, + "requires": { + "lru-cache": "^6.0.0", + "make-fetch-happen": "^8.0.9", + "minipass": "^3.1.3", + "minipass-fetch": "^1.3.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.0.0", + "npm-package-arg": "^8.0.0" + } + }, + "npm-user-validate": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "opener": { + "version": "1.5.2", + "bundled": true, + "dev": true + }, + "p-map": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "pacote": { + "version": "11.3.3", + "bundled": true, + "dev": true, + "requires": { + "@npmcli/git": "^2.0.1", + "@npmcli/installed-package-contents": "^1.0.6", + "@npmcli/promise-spawn": "^1.2.0", + "@npmcli/run-script": "^1.8.2", + "cacache": "^15.0.5", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "infer-owner": "^1.0.4", + "minipass": "^3.1.3", + "mkdirp": "^1.0.3", + "npm-package-arg": "^8.0.1", + "npm-packlist": "^2.1.4", + "npm-pick-manifest": "^6.0.0", + "npm-registry-fetch": "^10.0.0", + "promise-retry": "^2.0.1", + "read-package-json-fast": "^2.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.1.0" + } + }, + "parse-conflict-json": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "requires": { + "json-parse-even-better-errors": "^2.3.0", + "just-diff": "^3.0.1", + "just-diff-apply": "^3.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "bundled": true, + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "bundled": true, + "dev": true + }, + "proc-log": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "bundled": true, + "dev": true + }, + "promise-all-reject-late": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "promise-call-limit": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "promise-inflight": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "promise-retry": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + } + }, + "promzard": { + "version": "0.3.0", + "bundled": true, + "dev": true, + "requires": { + "read": "1" + } + }, + "psl": { + "version": "1.8.0", + "bundled": true, + "dev": true + }, + "punycode": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "qrcode-terminal": { + "version": "0.12.0", + "bundled": true, + "dev": true + }, + "qs": { + "version": "6.5.2", + "bundled": true, + "dev": true + }, + "read": { + "version": "1.0.7", + "bundled": true, + "dev": true, + "requires": { + "mute-stream": "~0.0.4" + } + }, + "read-cmd-shim": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "read-package-json": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "glob": "^7.1.1", + "json-parse-even-better-errors": "^2.3.0", + "normalize-package-data": "^3.0.0", + "npm-normalize-package-bin": "^1.0.0" + } + }, + "read-package-json-fast": { + "version": "2.0.2", + "bundled": true, + "dev": true, + "requires": { + "json-parse-even-better-errors": "^2.3.0", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "bundled": true, + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdir-scoped-modules": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "graceful-fs": "^4.1.2", + "once": "^1.3.0" + } + }, + "request": { + "version": "2.88.2", + "bundled": true, + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "tough-cookie": { + "version": "2.5.0", + "bundled": true, + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + } + } + }, + "resolve": { + "version": "1.20.0", + "bundled": true, + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "retry": { + "version": "0.12.0", + "bundled": true, + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true + }, + "semver": { + "version": "7.3.5", + "bundled": true, + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "signal-exit": { + "version": "3.0.3", + "bundled": true, + "dev": true + }, + "smart-buffer": { + "version": "4.1.0", + "bundled": true, + "dev": true + }, + "socks": { + "version": "2.6.1", + "bundled": true, + "dev": true, + "requires": { + "ip": "^1.1.5", + "smart-buffer": "^4.1.0" + } + }, + "socks-proxy-agent": { + "version": "5.0.0", + "bundled": true, + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4", + "socks": "^2.3.3" + } + }, + "spdx-correct": { + "version": "3.1.1", + "bundled": true, + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "bundled": true, + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.7", + "bundled": true, + "dev": true + }, + "sshpk": { + "version": "1.16.1", + "bundled": true, + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "8.0.1", + "bundled": true, + "dev": true, + "requires": { + "minipass": "^3.1.1" + } + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "stringify-package": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "bundled": true, + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "tar": { + "version": "6.1.0", + "bundled": true, + "dev": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + } + }, + "text-table": { + "version": "0.2.0", + "bundled": true, + "dev": true + }, + "tiny-relative-date": { + "version": "1.3.0", + "bundled": true, + "dev": true + }, + "treeverse": { + "version": "1.0.4", + "bundled": true, + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "dev": true + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "bundled": true, + "dev": true, + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "unique-filename": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "bundled": true, + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "uri-js": { + "version": "4.4.1", + "bundled": true, + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "uuid": { + "version": "3.4.0", + "bundled": true, + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "validate-npm-package-name": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "builtins": "^1.0.3" + } + }, + "verror": { + "version": "1.10.0", + "bundled": true, + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "walk-up-path": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "wcwidth": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "which": { + "version": "2.0.2", + "bundled": true, + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "write-file-atomic": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "yallist": { + "version": "4.0.0", + "bundled": true, + "dev": true + } + } + }, "onetime": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", @@ -4325,16 +6363,16 @@ "dev": true }, "commitizen": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/commitizen/-/commitizen-4.2.1.tgz", - "integrity": "sha512-nZsp8IThkDu7C+93BFD/mLShb9Gd6Wsaf90tpKE3x/6u5y/Q52kzanIJpGr0qvIsJ5bCMpgKtr3Lbu3miEJfaA==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/commitizen/-/commitizen-4.2.4.tgz", + "integrity": "sha512-LlZChbDzg3Ir3O2S7jSo/cgWp5/QwylQVr59K4xayVq8S4/RdKzSyJkghAiZZHfhh5t4pxunUoyeg0ml1q/7aw==", "dev": true, "requires": { "cachedir": "2.2.0", "cz-conventional-changelog": "3.2.0", "dedent": "0.7.0", "detect-indent": "6.0.0", - "find-node-modules": "2.0.0", + "find-node-modules": "^2.1.2", "find-root": "1.1.0", "fs-extra": "8.1.0", "glob": "7.1.4", @@ -4346,6 +6384,15 @@ "strip-json-comments": "3.0.1" }, "dependencies": { + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -4372,6 +6419,37 @@ "word-wrap": "^1.0.3" } }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-node-modules": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/find-node-modules/-/find-node-modules-2.1.2.tgz", + "integrity": "sha512-x+3P4mbtRPlSiVE1Qco0Z4YLU8WFiFcuWTf3m75OV9Uzcfs2Bg+O9N+r/K0AnmINBW06KpfqKwYJbFlFq4qNug==", + "dev": true, + "requires": { + "findup-sync": "^4.0.0", + "merge": "^2.1.0" + } + }, + "findup-sync": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", + "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^4.0.2", + "resolve-dir": "^1.0.1" + } + }, "glob": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", @@ -4386,11 +6464,42 @@ "path-is-absolute": "^1.0.0" } }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true + }, + "merge": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", + "integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==", + "dev": true + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "picomatch": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", + "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } } } }, @@ -4777,8 +6886,7 @@ "dependencies": { "hosted-git-info": { "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "resolved": "", "dev": true }, "meow": { @@ -6863,16 +8971,6 @@ } } }, - "find-node-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/find-node-modules/-/find-node-modules-2.0.0.tgz", - "integrity": "sha512-8MWIBRgJi/WpjjfVXumjPKCtmQ10B+fjx6zmSA+770GMJirLhWIzg8l763rhjl9xaeaHbnxPNRQKq2mgMhr+aw==", - "dev": true, - "requires": { - "findup-sync": "^3.0.0", - "merge": "^1.2.1" - } - }, "find-root": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", @@ -6898,18 +8996,6 @@ "semver-regex": "^3.1.2" } }, - "findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, "flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", @@ -8722,9 +10808,9 @@ } }, "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, "lodash._reinterpolate": { @@ -9334,12 +11420,6 @@ "yargs-parser": "^20.2.3" } }, - "merge": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz", - "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==", - "dev": true - }, "merge-source-map": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.0.4.tgz", @@ -9515,9 +11595,9 @@ "dev": true }, "nanoid": { - "version": "3.1.22", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.22.tgz", - "integrity": "sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ==", + "version": "3.1.23", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", + "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", "dev": true }, "nanomatch": { @@ -9646,3535 +11726,6 @@ "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", "dev": true }, - "npm": { - "version": "6.14.11", - "resolved": "https://registry.npmjs.org/npm/-/npm-6.14.11.tgz", - "integrity": "sha512-1Zh7LjuIoEhIyjkBflSSGzfjuPQwDlghNloppjruOH5bmj9midT9qcNT0tRUZRR04shU9ekrxNy9+UTBrqeBpQ==", - "dev": true, - "requires": { - "JSONStream": "^1.3.5", - "abbrev": "~1.1.1", - "ansicolors": "~0.3.2", - "ansistyles": "~0.1.3", - "aproba": "^2.0.0", - "archy": "~1.0.0", - "bin-links": "^1.1.8", - "bluebird": "^3.5.5", - "byte-size": "^5.0.1", - "cacache": "^12.0.3", - "call-limit": "^1.1.1", - "chownr": "^1.1.4", - "ci-info": "^2.0.0", - "cli-columns": "^3.1.2", - "cli-table3": "^0.5.1", - "cmd-shim": "^3.0.3", - "columnify": "~1.5.4", - "config-chain": "^1.1.12", - "debuglog": "*", - "detect-indent": "~5.0.0", - "detect-newline": "^2.1.0", - "dezalgo": "~1.0.3", - "editor": "~1.0.0", - "figgy-pudding": "^3.5.1", - "find-npm-prefix": "^1.0.2", - "fs-vacuum": "~1.2.10", - "fs-write-stream-atomic": "~1.0.10", - "gentle-fs": "^2.3.1", - "glob": "^7.1.6", - "graceful-fs": "^4.2.4", - "has-unicode": "~2.0.1", - "hosted-git-info": "^2.8.8", - "iferr": "^1.0.2", - "imurmurhash": "*", - "infer-owner": "^1.0.4", - "inflight": "~1.0.6", - "inherits": "^2.0.4", - "ini": "^1.3.8", - "init-package-json": "^1.10.3", - "is-cidr": "^3.0.0", - "json-parse-better-errors": "^1.0.2", - "lazy-property": "~1.0.0", - "libcipm": "^4.0.8", - "libnpm": "^3.0.1", - "libnpmaccess": "^3.0.2", - "libnpmhook": "^5.0.3", - "libnpmorg": "^1.0.1", - "libnpmsearch": "^2.0.2", - "libnpmteam": "^1.0.2", - "libnpx": "^10.2.4", - "lock-verify": "^2.1.0", - "lockfile": "^1.0.4", - "lodash._baseindexof": "*", - "lodash._baseuniq": "~4.6.0", - "lodash._bindcallback": "*", - "lodash._cacheindexof": "*", - "lodash._createcache": "*", - "lodash._getnative": "*", - "lodash.clonedeep": "~4.5.0", - "lodash.restparam": "*", - "lodash.union": "~4.6.0", - "lodash.uniq": "~4.5.0", - "lodash.without": "~4.4.0", - "lru-cache": "^5.1.1", - "meant": "^1.0.2", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.5", - "move-concurrently": "^1.0.1", - "node-gyp": "^5.1.0", - "nopt": "^4.0.3", - "normalize-package-data": "^2.5.0", - "npm-audit-report": "^1.3.3", - "npm-cache-filename": "~1.0.2", - "npm-install-checks": "^3.0.2", - "npm-lifecycle": "^3.1.5", - "npm-package-arg": "^6.1.1", - "npm-packlist": "^1.4.8", - "npm-pick-manifest": "^3.0.2", - "npm-profile": "^4.0.4", - "npm-registry-fetch": "^4.0.7", - "npm-user-validate": "^1.0.1", - "npmlog": "~4.1.2", - "once": "~1.4.0", - "opener": "^1.5.2", - "osenv": "^0.1.5", - "pacote": "^9.5.12", - "path-is-inside": "~1.0.2", - "promise-inflight": "~1.0.1", - "qrcode-terminal": "^0.12.0", - "query-string": "^6.8.2", - "qw": "~1.0.1", - "read": "~1.0.7", - "read-cmd-shim": "^1.0.5", - "read-installed": "~4.0.3", - "read-package-json": "^2.1.1", - "read-package-tree": "^5.3.1", - "readable-stream": "^3.6.0", - "readdir-scoped-modules": "^1.1.0", - "request": "^2.88.0", - "retry": "^0.12.0", - "rimraf": "^2.7.1", - "safe-buffer": "^5.1.2", - "semver": "^5.7.1", - "sha": "^3.0.0", - "slide": "~1.1.6", - "sorted-object": "~2.0.1", - "sorted-union-stream": "~2.1.3", - "ssri": "^6.0.1", - "stringify-package": "^1.0.1", - "tar": "^4.4.13", - "text-table": "~0.2.0", - "tiny-relative-date": "^1.3.0", - "uid-number": "0.0.6", - "umask": "~1.1.0", - "unique-filename": "^1.1.1", - "unpipe": "~1.0.0", - "update-notifier": "^2.5.0", - "uuid": "^3.3.3", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "~3.0.0", - "which": "^1.3.1", - "worker-farm": "^1.7.0", - "write-file-atomic": "^2.4.3" - }, - "dependencies": { - "JSONStream": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true - }, - "agent-base": { - "version": "4.3.0", - "bundled": true, - "dev": true, - "requires": { - "es6-promisify": "^5.0.0" - } - }, - "agentkeepalive": { - "version": "3.5.2", - "bundled": true, - "dev": true, - "requires": { - "humanize-ms": "^1.2.1" - } - }, - "ansi-align": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "requires": { - "string-width": "^2.0.0" - } - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "bundled": true, - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "ansicolors": { - "version": "0.3.2", - "bundled": true, - "dev": true - }, - "ansistyles": { - "version": "0.1.3", - "bundled": true, - "dev": true - }, - "aproba": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "archy": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "asap": { - "version": "2.0.6", - "bundled": true, - "dev": true - }, - "asn1": { - "version": "0.2.4", - "bundled": true, - "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "bundled": true, - "dev": true - }, - "aws-sign2": { - "version": "0.7.0", - "bundled": true, - "dev": true - }, - "aws4": { - "version": "1.8.0", - "bundled": true, - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "bin-links": { - "version": "1.1.8", - "bundled": true, - "dev": true, - "requires": { - "bluebird": "^3.5.3", - "cmd-shim": "^3.0.0", - "gentle-fs": "^2.3.0", - "graceful-fs": "^4.1.15", - "npm-normalize-package-bin": "^1.0.0", - "write-file-atomic": "^2.3.0" - } - }, - "bluebird": { - "version": "3.5.5", - "bundled": true, - "dev": true - }, - "boxen": { - "version": "1.3.0", - "bundled": true, - "dev": true, - "requires": { - "ansi-align": "^2.0.0", - "camelcase": "^4.0.0", - "chalk": "^2.0.1", - "cli-boxes": "^1.0.0", - "string-width": "^2.0.0", - "term-size": "^1.2.0", - "widest-line": "^2.0.0" - } - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "buffer-from": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "builtins": { - "version": "1.0.3", - "bundled": true, - "dev": true - }, - "byline": { - "version": "5.0.0", - "bundled": true, - "dev": true - }, - "byte-size": { - "version": "5.0.1", - "bundled": true, - "dev": true - }, - "cacache": { - "version": "12.0.3", - "bundled": true, - "dev": true, - "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "infer-owner": "^1.0.3", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" - } - }, - "call-limit": { - "version": "1.1.1", - "bundled": true, - "dev": true - }, - "camelcase": { - "version": "4.1.0", - "bundled": true, - "dev": true - }, - "capture-stack-trace": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "caseless": { - "version": "0.12.0", - "bundled": true, - "dev": true - }, - "chalk": { - "version": "2.4.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chownr": { - "version": "1.1.4", - "bundled": true, - "dev": true - }, - "ci-info": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "cidr-regex": { - "version": "2.0.10", - "bundled": true, - "dev": true, - "requires": { - "ip-regex": "^2.1.0" - } - }, - "cli-boxes": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "cli-columns": { - "version": "3.1.2", - "bundled": true, - "dev": true, - "requires": { - "string-width": "^2.0.0", - "strip-ansi": "^3.0.1" - } - }, - "cli-table3": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "requires": { - "colors": "^1.1.2", - "object-assign": "^4.1.0", - "string-width": "^2.1.1" - } - }, - "cliui": { - "version": "5.0.0", - "bundled": true, - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "bundled": true, - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "string-width": { - "version": "3.1.0", - "bundled": true, - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "clone": { - "version": "1.0.4", - "bundled": true, - "dev": true - }, - "cmd-shim": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "mkdirp": "~0.5.0" - } - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "color-convert": { - "version": "1.9.1", - "bundled": true, - "dev": true, - "requires": { - "color-name": "^1.1.1" - } - }, - "color-name": { - "version": "1.1.3", - "bundled": true, - "dev": true - }, - "colors": { - "version": "1.3.3", - "bundled": true, - "dev": true, - "optional": true - }, - "columnify": { - "version": "1.5.4", - "bundled": true, - "dev": true, - "requires": { - "strip-ansi": "^3.0.0", - "wcwidth": "^1.0.0" - } - }, - "combined-stream": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "bundled": true, - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "config-chain": { - "version": "1.1.12", - "bundled": true, - "dev": true, - "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "configstore": { - "version": "3.1.5", - "bundled": true, - "dev": true, - "requires": { - "dot-prop": "^4.2.1", - "graceful-fs": "^4.1.2", - "make-dir": "^1.0.0", - "unique-string": "^1.0.0", - "write-file-atomic": "^2.0.0", - "xdg-basedir": "^3.0.0" - } - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "copy-concurrently": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - }, - "dependencies": { - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true - }, - "iferr": { - "version": "0.1.5", - "bundled": true, - "dev": true - } - } - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "create-error-class": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "requires": { - "capture-stack-trace": "^1.0.0" - } - }, - "cross-spawn": { - "version": "5.1.0", - "bundled": true, - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "dependencies": { - "lru-cache": { - "version": "4.1.5", - "bundled": true, - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "yallist": { - "version": "2.1.2", - "bundled": true, - "dev": true - } - } - }, - "crypto-random-string": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "cyclist": { - "version": "0.2.2", - "bundled": true, - "dev": true - }, - "dashdash": { - "version": "1.14.1", - "bundled": true, - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "debug": { - "version": "3.1.0", - "bundled": true, - "dev": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "bundled": true, - "dev": true - } - } - }, - "debuglog": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "decamelize": { - "version": "1.2.0", - "bundled": true, - "dev": true - }, - "decode-uri-component": { - "version": "0.2.0", - "bundled": true, - "dev": true - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true - }, - "defaults": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "requires": { - "clone": "^1.0.2" - } - }, - "define-properties": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "delayed-stream": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "detect-indent": { - "version": "5.0.0", - "bundled": true, - "dev": true - }, - "detect-newline": { - "version": "2.1.0", - "bundled": true, - "dev": true - }, - "dezalgo": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "requires": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, - "dot-prop": { - "version": "4.2.1", - "bundled": true, - "dev": true, - "requires": { - "is-obj": "^1.0.0" - } - }, - "dotenv": { - "version": "5.0.1", - "bundled": true, - "dev": true - }, - "duplexer3": { - "version": "0.1.4", - "bundled": true, - "dev": true - }, - "duplexify": { - "version": "3.6.0", - "bundled": true, - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "ecc-jsbn": { - "version": "0.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "editor": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "emoji-regex": { - "version": "7.0.3", - "bundled": true, - "dev": true - }, - "encoding": { - "version": "0.1.12", - "bundled": true, - "dev": true, - "requires": { - "iconv-lite": "~0.4.13" - } - }, - "end-of-stream": { - "version": "1.4.1", - "bundled": true, - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "env-paths": { - "version": "2.2.0", - "bundled": true, - "dev": true - }, - "err-code": { - "version": "1.1.2", - "bundled": true, - "dev": true - }, - "errno": { - "version": "0.1.7", - "bundled": true, - "dev": true, - "requires": { - "prr": "~1.0.1" - } - }, - "es-abstract": { - "version": "1.12.0", - "bundled": true, - "dev": true, - "requires": { - "es-to-primitive": "^1.1.1", - "function-bind": "^1.1.1", - "has": "^1.0.1", - "is-callable": "^1.1.3", - "is-regex": "^1.0.4" - } - }, - "es-to-primitive": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es6-promise": { - "version": "4.2.8", - "bundled": true, - "dev": true - }, - "es6-promisify": { - "version": "5.0.0", - "bundled": true, - "dev": true, - "requires": { - "es6-promise": "^4.0.3" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "bundled": true, - "dev": true - }, - "execa": { - "version": "0.7.0", - "bundled": true, - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "dependencies": { - "get-stream": { - "version": "3.0.0", - "bundled": true, - "dev": true - } - } - }, - "extend": { - "version": "3.0.2", - "bundled": true, - "dev": true - }, - "extsprintf": { - "version": "1.3.0", - "bundled": true, - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "figgy-pudding": { - "version": "3.5.1", - "bundled": true, - "dev": true - }, - "find-npm-prefix": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "flush-write-stream": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.4" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "forever-agent": { - "version": "0.6.1", - "bundled": true, - "dev": true - }, - "form-data": { - "version": "2.3.2", - "bundled": true, - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "1.0.6", - "mime-types": "^2.1.12" - } - }, - "from2": { - "version": "2.3.0", - "bundled": true, - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "fs-minipass": { - "version": "1.2.7", - "bundled": true, - "dev": true, - "requires": { - "minipass": "^2.6.0" - }, - "dependencies": { - "minipass": { - "version": "2.9.0", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - } - } - }, - "fs-vacuum": { - "version": "1.2.10", - "bundled": true, - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "path-is-inside": "^1.0.1", - "rimraf": "^2.5.2" - } - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "bundled": true, - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - }, - "dependencies": { - "iferr": { - "version": "0.1.5", - "bundled": true, - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "function-bind": { - "version": "1.1.1", - "bundled": true, - "dev": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - }, - "dependencies": { - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, - "genfun": { - "version": "5.0.0", - "bundled": true, - "dev": true - }, - "gentle-fs": { - "version": "2.3.1", - "bundled": true, - "dev": true, - "requires": { - "aproba": "^1.1.2", - "chownr": "^1.1.2", - "cmd-shim": "^3.0.3", - "fs-vacuum": "^1.2.10", - "graceful-fs": "^4.1.11", - "iferr": "^0.1.5", - "infer-owner": "^1.0.4", - "mkdirp": "^0.5.1", - "path-is-inside": "^1.0.2", - "read-cmd-shim": "^1.0.1", - "slide": "^1.1.6" - }, - "dependencies": { - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true - }, - "iferr": { - "version": "0.1.5", - "bundled": true, - "dev": true - } - } - }, - "get-caller-file": { - "version": "2.0.5", - "bundled": true, - "dev": true - }, - "get-stream": { - "version": "4.1.0", - "bundled": true, - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "getpass": { - "version": "0.1.7", - "bundled": true, - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "7.1.6", - "bundled": true, - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "global-dirs": { - "version": "0.1.1", - "bundled": true, - "dev": true, - "requires": { - "ini": "^1.3.4" - } - }, - "got": { - "version": "6.7.1", - "bundled": true, - "dev": true, - "requires": { - "create-error-class": "^3.0.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-redirect": "^1.0.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "lowercase-keys": "^1.0.0", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "unzip-response": "^2.0.1", - "url-parse-lax": "^1.0.0" - }, - "dependencies": { - "get-stream": { - "version": "3.0.0", - "bundled": true, - "dev": true - } - } - }, - "graceful-fs": { - "version": "4.2.4", - "bundled": true, - "dev": true - }, - "har-schema": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "har-validator": { - "version": "5.1.5", - "bundled": true, - "dev": true, - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "bundled": true, - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "bundled": true, - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "bundled": true, - "dev": true - } - } - }, - "has": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "has-symbols": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true - }, - "hosted-git-info": { - "version": "2.8.8", - "bundled": true, - "dev": true - }, - "http-cache-semantics": { - "version": "3.8.1", - "bundled": true, - "dev": true - }, - "http-proxy-agent": { - "version": "2.1.0", - "bundled": true, - "dev": true, - "requires": { - "agent-base": "4", - "debug": "3.1.0" - } - }, - "http-signature": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "https-proxy-agent": { - "version": "2.2.4", - "bundled": true, - "dev": true, - "requires": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" - } - }, - "humanize-ms": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "requires": { - "ms": "^2.0.0" - } - }, - "iconv-lite": { - "version": "0.4.23", - "bundled": true, - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "iferr": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "ignore-walk": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "import-lazy": { - "version": "2.1.0", - "bundled": true, - "dev": true - }, - "imurmurhash": { - "version": "0.1.4", - "bundled": true, - "dev": true - }, - "infer-owner": { - "version": "1.0.4", - "bundled": true, - "dev": true - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "bundled": true, - "dev": true - }, - "ini": { - "version": "1.3.8", - "bundled": true, - "dev": true - }, - "init-package-json": { - "version": "1.10.3", - "bundled": true, - "dev": true, - "requires": { - "glob": "^7.1.1", - "npm-package-arg": "^4.0.0 || ^5.0.0 || ^6.0.0", - "promzard": "^0.3.0", - "read": "~1.0.1", - "read-package-json": "1 || 2", - "semver": "2.x || 3.x || 4 || 5", - "validate-npm-package-license": "^3.0.1", - "validate-npm-package-name": "^3.0.0" - } - }, - "ip": { - "version": "1.1.5", - "bundled": true, - "dev": true - }, - "ip-regex": { - "version": "2.1.0", - "bundled": true, - "dev": true - }, - "is-callable": { - "version": "1.1.4", - "bundled": true, - "dev": true - }, - "is-ci": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "requires": { - "ci-info": "^1.5.0" - }, - "dependencies": { - "ci-info": { - "version": "1.6.0", - "bundled": true, - "dev": true - } - } - }, - "is-cidr": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "cidr-regex": "^2.0.10" - } - }, - "is-date-object": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-installed-globally": { - "version": "0.1.0", - "bundled": true, - "dev": true, - "requires": { - "global-dirs": "^0.1.0", - "is-path-inside": "^1.0.0" - } - }, - "is-npm": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "is-obj": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "is-path-inside": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "requires": { - "path-is-inside": "^1.0.1" - } - }, - "is-redirect": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "is-regex": { - "version": "1.0.4", - "bundled": true, - "dev": true, - "requires": { - "has": "^1.0.1" - } - }, - "is-retry-allowed": { - "version": "1.2.0", - "bundled": true, - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "is-symbol": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "has-symbols": "^1.0.0" - } - }, - "is-typedarray": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "isexe": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "isstream": { - "version": "0.1.2", - "bundled": true, - "dev": true - }, - "jsbn": { - "version": "0.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "json-schema": { - "version": "0.2.3", - "bundled": true, - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "bundled": true, - "dev": true - }, - "jsonparse": { - "version": "1.3.1", - "bundled": true, - "dev": true - }, - "jsprim": { - "version": "1.4.1", - "bundled": true, - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "latest-version": { - "version": "3.1.0", - "bundled": true, - "dev": true, - "requires": { - "package-json": "^4.0.0" - } - }, - "lazy-property": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "libcipm": { - "version": "4.0.8", - "bundled": true, - "dev": true, - "requires": { - "bin-links": "^1.1.2", - "bluebird": "^3.5.1", - "figgy-pudding": "^3.5.1", - "find-npm-prefix": "^1.0.2", - "graceful-fs": "^4.1.11", - "ini": "^1.3.5", - "lock-verify": "^2.1.0", - "mkdirp": "^0.5.1", - "npm-lifecycle": "^3.0.0", - "npm-logical-tree": "^1.2.1", - "npm-package-arg": "^6.1.0", - "pacote": "^9.1.0", - "read-package-json": "^2.0.13", - "rimraf": "^2.6.2", - "worker-farm": "^1.6.0" - } - }, - "libnpm": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "bin-links": "^1.1.2", - "bluebird": "^3.5.3", - "find-npm-prefix": "^1.0.2", - "libnpmaccess": "^3.0.2", - "libnpmconfig": "^1.2.1", - "libnpmhook": "^5.0.3", - "libnpmorg": "^1.0.1", - "libnpmpublish": "^1.1.2", - "libnpmsearch": "^2.0.2", - "libnpmteam": "^1.0.2", - "lock-verify": "^2.0.2", - "npm-lifecycle": "^3.0.0", - "npm-logical-tree": "^1.2.1", - "npm-package-arg": "^6.1.0", - "npm-profile": "^4.0.2", - "npm-registry-fetch": "^4.0.0", - "npmlog": "^4.1.2", - "pacote": "^9.5.3", - "read-package-json": "^2.0.13", - "stringify-package": "^1.0.0" - } - }, - "libnpmaccess": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "requires": { - "aproba": "^2.0.0", - "get-stream": "^4.0.0", - "npm-package-arg": "^6.1.0", - "npm-registry-fetch": "^4.0.0" - } - }, - "libnpmconfig": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1", - "find-up": "^3.0.0", - "ini": "^1.3.5" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.2.0", - "bundled": true, - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "bundled": true, - "dev": true - } - } - }, - "libnpmhook": { - "version": "5.0.3", - "bundled": true, - "dev": true, - "requires": { - "aproba": "^2.0.0", - "figgy-pudding": "^3.4.1", - "get-stream": "^4.0.0", - "npm-registry-fetch": "^4.0.0" - } - }, - "libnpmorg": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "requires": { - "aproba": "^2.0.0", - "figgy-pudding": "^3.4.1", - "get-stream": "^4.0.0", - "npm-registry-fetch": "^4.0.0" - } - }, - "libnpmpublish": { - "version": "1.1.2", - "bundled": true, - "dev": true, - "requires": { - "aproba": "^2.0.0", - "figgy-pudding": "^3.5.1", - "get-stream": "^4.0.0", - "lodash.clonedeep": "^4.5.0", - "normalize-package-data": "^2.4.0", - "npm-package-arg": "^6.1.0", - "npm-registry-fetch": "^4.0.0", - "semver": "^5.5.1", - "ssri": "^6.0.1" - } - }, - "libnpmsearch": { - "version": "2.0.2", - "bundled": true, - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1", - "get-stream": "^4.0.0", - "npm-registry-fetch": "^4.0.0" - } - }, - "libnpmteam": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "aproba": "^2.0.0", - "figgy-pudding": "^3.4.1", - "get-stream": "^4.0.0", - "npm-registry-fetch": "^4.0.0" - } - }, - "libnpx": { - "version": "10.2.4", - "bundled": true, - "dev": true, - "requires": { - "dotenv": "^5.0.1", - "npm-package-arg": "^6.0.0", - "rimraf": "^2.6.2", - "safe-buffer": "^5.1.0", - "update-notifier": "^2.3.0", - "which": "^1.3.0", - "y18n": "^4.0.0", - "yargs": "^14.2.3" - } - }, - "lock-verify": { - "version": "2.1.0", - "bundled": true, - "dev": true, - "requires": { - "npm-package-arg": "^6.1.0", - "semver": "^5.4.1" - } - }, - "lockfile": { - "version": "1.0.4", - "bundled": true, - "dev": true, - "requires": { - "signal-exit": "^3.0.2" - } - }, - "lodash._baseindexof": { - "version": "3.1.0", - "bundled": true, - "dev": true - }, - "lodash._baseuniq": { - "version": "4.6.0", - "bundled": true, - "dev": true, - "requires": { - "lodash._createset": "~4.0.0", - "lodash._root": "~3.0.0" - } - }, - "lodash._bindcallback": { - "version": "3.0.1", - "bundled": true, - "dev": true - }, - "lodash._cacheindexof": { - "version": "3.0.2", - "bundled": true, - "dev": true - }, - "lodash._createcache": { - "version": "3.1.2", - "bundled": true, - "dev": true, - "requires": { - "lodash._getnative": "^3.0.0" - } - }, - "lodash._createset": { - "version": "4.0.3", - "bundled": true, - "dev": true - }, - "lodash._getnative": { - "version": "3.9.1", - "bundled": true, - "dev": true - }, - "lodash._root": { - "version": "3.0.1", - "bundled": true, - "dev": true - }, - "lodash.clonedeep": { - "version": "4.5.0", - "bundled": true, - "dev": true - }, - "lodash.restparam": { - "version": "3.6.1", - "bundled": true, - "dev": true - }, - "lodash.union": { - "version": "4.6.0", - "bundled": true, - "dev": true - }, - "lodash.uniq": { - "version": "4.5.0", - "bundled": true, - "dev": true - }, - "lodash.without": { - "version": "4.4.0", - "bundled": true, - "dev": true - }, - "lowercase-keys": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "lru-cache": { - "version": "5.1.1", - "bundled": true, - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "make-dir": { - "version": "1.3.0", - "bundled": true, - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "make-fetch-happen": { - "version": "5.0.2", - "bundled": true, - "dev": true, - "requires": { - "agentkeepalive": "^3.4.1", - "cacache": "^12.0.0", - "http-cache-semantics": "^3.8.1", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.3", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "node-fetch-npm": "^2.0.2", - "promise-retry": "^1.1.1", - "socks-proxy-agent": "^4.0.0", - "ssri": "^6.0.0" - } - }, - "meant": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "mime-db": { - "version": "1.35.0", - "bundled": true, - "dev": true - }, - "mime-types": { - "version": "2.1.19", - "bundled": true, - "dev": true, - "requires": { - "mime-db": "~1.35.0" - } - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "bundled": true, - "dev": true - }, - "minizlib": { - "version": "1.3.3", - "bundled": true, - "dev": true, - "requires": { - "minipass": "^2.9.0" - }, - "dependencies": { - "minipass": { - "version": "2.9.0", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - } - } - }, - "mississippi": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, - "mkdirp": { - "version": "0.5.5", - "bundled": true, - "dev": true, - "requires": { - "minimist": "^1.2.5" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "bundled": true, - "dev": true - } - } - }, - "move-concurrently": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - }, - "dependencies": { - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true - } - } - }, - "ms": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "mute-stream": { - "version": "0.0.7", - "bundled": true, - "dev": true - }, - "node-fetch-npm": { - "version": "2.0.2", - "bundled": true, - "dev": true, - "requires": { - "encoding": "^0.1.11", - "json-parse-better-errors": "^1.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node-gyp": { - "version": "5.1.0", - "bundled": true, - "dev": true, - "requires": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.2", - "mkdirp": "^0.5.1", - "nopt": "^4.0.1", - "npmlog": "^4.1.2", - "request": "^2.88.0", - "rimraf": "^2.6.3", - "semver": "^5.7.1", - "tar": "^4.4.12", - "which": "^1.3.1" - } - }, - "nopt": { - "version": "4.0.3", - "bundled": true, - "dev": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "normalize-package-data": { - "version": "2.5.0", - "bundled": true, - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "resolve": { - "version": "1.10.0", - "bundled": true, - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - } - } - }, - "npm-audit-report": { - "version": "1.3.3", - "bundled": true, - "dev": true, - "requires": { - "cli-table3": "^0.5.0", - "console-control-strings": "^1.1.0" - } - }, - "npm-bundled": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-cache-filename": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "npm-install-checks": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "requires": { - "semver": "^2.3.0 || 3.x || 4 || 5" - } - }, - "npm-lifecycle": { - "version": "3.1.5", - "bundled": true, - "dev": true, - "requires": { - "byline": "^5.0.0", - "graceful-fs": "^4.1.15", - "node-gyp": "^5.0.2", - "resolve-from": "^4.0.0", - "slide": "^1.1.6", - "uid-number": "0.0.6", - "umask": "^1.1.0", - "which": "^1.3.1" - } - }, - "npm-logical-tree": { - "version": "1.2.1", - "bundled": true, - "dev": true - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "npm-package-arg": { - "version": "6.1.1", - "bundled": true, - "dev": true, - "requires": { - "hosted-git-info": "^2.7.1", - "osenv": "^0.1.5", - "semver": "^5.6.0", - "validate-npm-package-name": "^3.0.0" - } - }, - "npm-packlist": { - "version": "1.4.8", - "bundled": true, - "dev": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1", - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-pick-manifest": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1", - "npm-package-arg": "^6.0.0", - "semver": "^5.4.1" - } - }, - "npm-profile": { - "version": "4.0.4", - "bundled": true, - "dev": true, - "requires": { - "aproba": "^1.1.2 || 2", - "figgy-pudding": "^3.4.1", - "npm-registry-fetch": "^4.0.0" - } - }, - "npm-registry-fetch": { - "version": "4.0.7", - "bundled": true, - "dev": true, - "requires": { - "JSONStream": "^1.3.4", - "bluebird": "^3.5.1", - "figgy-pudding": "^3.4.1", - "lru-cache": "^5.1.1", - "make-fetch-happen": "^5.0.0", - "npm-package-arg": "^6.1.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "bundled": true, - "dev": true - } - } - }, - "npm-run-path": { - "version": "2.0.2", - "bundled": true, - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "npm-user-validate": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "oauth-sign": { - "version": "0.9.0", - "bundled": true, - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true - }, - "object-keys": { - "version": "1.0.12", - "bundled": true, - "dev": true - }, - "object.getownpropertydescriptors": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" - } - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "opener": { - "version": "1.5.2", - "bundled": true, - "dev": true - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "p-finally": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "package-json": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "requires": { - "got": "^6.7.1", - "registry-auth-token": "^3.0.1", - "registry-url": "^3.0.3", - "semver": "^5.1.0" - } - }, - "pacote": { - "version": "9.5.12", - "bundled": true, - "dev": true, - "requires": { - "bluebird": "^3.5.3", - "cacache": "^12.0.2", - "chownr": "^1.1.2", - "figgy-pudding": "^3.5.1", - "get-stream": "^4.1.0", - "glob": "^7.1.3", - "infer-owner": "^1.0.4", - "lru-cache": "^5.1.1", - "make-fetch-happen": "^5.0.0", - "minimatch": "^3.0.4", - "minipass": "^2.3.5", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "normalize-package-data": "^2.4.0", - "npm-normalize-package-bin": "^1.0.0", - "npm-package-arg": "^6.1.0", - "npm-packlist": "^1.1.12", - "npm-pick-manifest": "^3.0.0", - "npm-registry-fetch": "^4.0.0", - "osenv": "^0.1.5", - "promise-inflight": "^1.0.1", - "promise-retry": "^1.1.1", - "protoduck": "^5.0.1", - "rimraf": "^2.6.2", - "safe-buffer": "^5.1.2", - "semver": "^5.6.0", - "ssri": "^6.0.1", - "tar": "^4.4.10", - "unique-filename": "^1.1.1", - "which": "^1.3.1" - }, - "dependencies": { - "minipass": { - "version": "2.9.0", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - } - } - }, - "parallel-transform": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "requires": { - "cyclist": "~0.2.2", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "path-exists": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "path-key": { - "version": "2.0.1", - "bundled": true, - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "bundled": true, - "dev": true - }, - "performance-now": { - "version": "2.1.0", - "bundled": true, - "dev": true - }, - "pify": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "prepend-http": { - "version": "1.0.4", - "bundled": true, - "dev": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "promise-inflight": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "promise-retry": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "requires": { - "err-code": "^1.0.0", - "retry": "^0.10.0" - }, - "dependencies": { - "retry": { - "version": "0.10.1", - "bundled": true, - "dev": true - } - } - }, - "promzard": { - "version": "0.3.0", - "bundled": true, - "dev": true, - "requires": { - "read": "1" - } - }, - "proto-list": { - "version": "1.2.4", - "bundled": true, - "dev": true - }, - "protoduck": { - "version": "5.0.1", - "bundled": true, - "dev": true, - "requires": { - "genfun": "^5.0.0" - } - }, - "prr": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "psl": { - "version": "1.1.29", - "bundled": true, - "dev": true - }, - "pump": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "1.5.1", - "bundled": true, - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "punycode": { - "version": "1.4.1", - "bundled": true, - "dev": true - }, - "qrcode-terminal": { - "version": "0.12.0", - "bundled": true, - "dev": true - }, - "qs": { - "version": "6.5.2", - "bundled": true, - "dev": true - }, - "query-string": { - "version": "6.8.2", - "bundled": true, - "dev": true, - "requires": { - "decode-uri-component": "^0.2.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" - } - }, - "qw": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - } - }, - "read": { - "version": "1.0.7", - "bundled": true, - "dev": true, - "requires": { - "mute-stream": "~0.0.4" - } - }, - "read-cmd-shim": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "requires": { - "graceful-fs": "^4.1.2" - } - }, - "read-installed": { - "version": "4.0.3", - "bundled": true, - "dev": true, - "requires": { - "debuglog": "^1.0.1", - "graceful-fs": "^4.1.2", - "read-package-json": "^2.0.0", - "readdir-scoped-modules": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "slide": "~1.1.3", - "util-extend": "^1.0.1" - } - }, - "read-package-json": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "requires": { - "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "json-parse-better-errors": "^1.0.1", - "normalize-package-data": "^2.0.0", - "npm-normalize-package-bin": "^1.0.0" - } - }, - "read-package-tree": { - "version": "5.3.1", - "bundled": true, - "dev": true, - "requires": { - "read-package-json": "^2.0.0", - "readdir-scoped-modules": "^1.0.0", - "util-promisify": "^2.1.0" - } - }, - "readable-stream": { - "version": "3.6.0", - "bundled": true, - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readdir-scoped-modules": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "requires": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "graceful-fs": "^4.1.2", - "once": "^1.3.0" - } - }, - "registry-auth-token": { - "version": "3.4.0", - "bundled": true, - "dev": true, - "requires": { - "rc": "^1.1.6", - "safe-buffer": "^5.0.1" - } - }, - "registry-url": { - "version": "3.1.0", - "bundled": true, - "dev": true, - "requires": { - "rc": "^1.0.1" - } - }, - "request": { - "version": "2.88.0", - "bundled": true, - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, - "require-directory": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "resolve-from": { - "version": "4.0.0", - "bundled": true, - "dev": true - }, - "retry": { - "version": "0.12.0", - "bundled": true, - "dev": true - }, - "rimraf": { - "version": "2.7.1", - "bundled": true, - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-queue": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "requires": { - "aproba": "^1.1.1" - }, - "dependencies": { - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true - } - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true - }, - "semver": { - "version": "5.7.1", - "bundled": true, - "dev": true - }, - "semver-diff": { - "version": "2.1.0", - "bundled": true, - "dev": true, - "requires": { - "semver": "^5.0.3" - } - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "sha": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "graceful-fs": "^4.1.2" - } - }, - "shebang-command": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true - }, - "slide": { - "version": "1.1.6", - "bundled": true, - "dev": true - }, - "smart-buffer": { - "version": "4.1.0", - "bundled": true, - "dev": true - }, - "socks": { - "version": "2.3.3", - "bundled": true, - "dev": true, - "requires": { - "ip": "1.1.5", - "smart-buffer": "^4.1.0" - } - }, - "socks-proxy-agent": { - "version": "4.0.2", - "bundled": true, - "dev": true, - "requires": { - "agent-base": "~4.2.1", - "socks": "~2.3.2" - }, - "dependencies": { - "agent-base": { - "version": "4.2.1", - "bundled": true, - "dev": true, - "requires": { - "es6-promisify": "^5.0.0" - } - } - } - }, - "sorted-object": { - "version": "2.0.1", - "bundled": true, - "dev": true - }, - "sorted-union-stream": { - "version": "2.1.3", - "bundled": true, - "dev": true, - "requires": { - "from2": "^1.3.0", - "stream-iterate": "^1.1.0" - }, - "dependencies": { - "from2": { - "version": "1.3.0", - "bundled": true, - "dev": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "~1.1.10" - } - }, - "isarray": { - "version": "0.0.1", - "bundled": true, - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "bundled": true, - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "bundled": true, - "dev": true - } - } - }, - "spdx-correct": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.1.0", - "bundled": true, - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "bundled": true, - "dev": true - }, - "split-on-first": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "sshpk": { - "version": "1.14.2", - "bundled": true, - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "ssri": { - "version": "6.0.1", - "bundled": true, - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1" - } - }, - "stream-each": { - "version": "1.2.2", - "bundled": true, - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } - }, - "stream-iterate": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "requires": { - "readable-stream": "^2.1.5", - "stream-shift": "^1.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "stream-shift": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "strict-uri-encode": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "string-width": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "string_decoder": { - "version": "1.3.0", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.0", - "bundled": true, - "dev": true - } - } - }, - "stringify-package": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-eof": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true - }, - "supports-color": { - "version": "5.4.0", - "bundled": true, - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "tar": { - "version": "4.4.13", - "bundled": true, - "dev": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - }, - "dependencies": { - "minipass": { - "version": "2.9.0", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - } - } - }, - "term-size": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "requires": { - "execa": "^0.7.0" - } - }, - "text-table": { - "version": "0.2.0", - "bundled": true, - "dev": true - }, - "through": { - "version": "2.3.8", - "bundled": true, - "dev": true - }, - "through2": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "requires": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "timed-out": { - "version": "4.0.1", - "bundled": true, - "dev": true - }, - "tiny-relative-date": { - "version": "1.3.0", - "bundled": true, - "dev": true - }, - "tough-cookie": { - "version": "2.4.3", - "bundled": true, - "dev": true, - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "bundled": true, - "dev": true, - "optional": true - }, - "typedarray": { - "version": "0.0.6", - "bundled": true, - "dev": true - }, - "uid-number": { - "version": "0.0.6", - "bundled": true, - "dev": true - }, - "umask": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "unique-filename": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "unique-string": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "crypto-random-string": "^1.0.0" - } - }, - "unpipe": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "unzip-response": { - "version": "2.0.1", - "bundled": true, - "dev": true - }, - "update-notifier": { - "version": "2.5.0", - "bundled": true, - "dev": true, - "requires": { - "boxen": "^1.2.1", - "chalk": "^2.0.1", - "configstore": "^3.0.0", - "import-lazy": "^2.1.0", - "is-ci": "^1.0.10", - "is-installed-globally": "^0.1.0", - "is-npm": "^1.0.0", - "latest-version": "^3.0.0", - "semver-diff": "^2.0.0", - "xdg-basedir": "^3.0.0" - } - }, - "uri-js": { - "version": "4.4.0", - "bundled": true, - "dev": true, - "requires": { - "punycode": "^2.1.0" - }, - "dependencies": { - "punycode": { - "version": "2.1.1", - "bundled": true, - "dev": true - } - } - }, - "url-parse-lax": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "prepend-http": "^1.0.1" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "util-extend": { - "version": "1.0.3", - "bundled": true, - "dev": true - }, - "util-promisify": { - "version": "2.1.0", - "bundled": true, - "dev": true, - "requires": { - "object.getownpropertydescriptors": "^2.0.3" - } - }, - "uuid": { - "version": "3.3.3", - "bundled": true, - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "validate-npm-package-name": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "builtins": "^1.0.3" - } - }, - "verror": { - "version": "1.10.0", - "bundled": true, - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "wcwidth": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "requires": { - "defaults": "^1.0.3" - } - }, - "which": { - "version": "1.3.1", - "bundled": true, - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "dev": true, - "requires": { - "string-width": "^1.0.2" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, - "widest-line": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "requires": { - "string-width": "^2.1.1" - } - }, - "worker-farm": { - "version": "1.7.0", - "bundled": true, - "dev": true, - "requires": { - "errno": "~0.1.7" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "bundled": true, - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "bundled": true, - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "string-width": { - "version": "3.1.0", - "bundled": true, - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "write-file-atomic": { - "version": "2.4.3", - "bundled": true, - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "xdg-basedir": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "xtend": { - "version": "4.0.1", - "bundled": true, - "dev": true - }, - "y18n": { - "version": "4.0.0", - "bundled": true, - "dev": true - }, - "yallist": { - "version": "3.0.3", - "bundled": true, - "dev": true - }, - "yargs": { - "version": "14.2.3", - "bundled": true, - "dev": true, - "requires": { - "cliui": "^5.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^15.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "bundled": true, - "dev": true - }, - "find-up": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "locate-path": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "bundled": true, - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "bundled": true, - "dev": true - }, - "string-width": { - "version": "3.1.0", - "bundled": true, - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "yargs-parser": { - "version": "15.0.1", - "bundled": true, - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "dependencies": { - "camelcase": { - "version": "5.3.1", - "bundled": true, - "dev": true - } - } - } - } - }, "npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -13815,13 +12366,13 @@ "dev": true }, "postcss": { - "version": "8.2.8", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.8.tgz", - "integrity": "sha512-1F0Xb2T21xET7oQV9eKuctbM9S7BC0fetoHCc4H13z0PT6haiRLP4T0ZY4XWh7iLP0usgqykT6p9B2RtOf4FPw==", + "version": "8.2.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.15.tgz", + "integrity": "sha512-2zO3b26eJD/8rb106Qu2o7Qgg52ND5HPjcyQiK2B98O388h43A448LCslC0dI2P97wCAQRJsFvwTRcXxTKds+Q==", "dev": true, "requires": { "colorette": "^1.2.2", - "nanoid": "^3.1.20", + "nanoid": "^3.1.23", "source-map": "^0.6.1" }, "dependencies": { @@ -18559,9 +17110,9 @@ }, "dependencies": { "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "normalize-package-data": { diff --git a/package.json b/package.json index a2a21d85..a9dec1e0 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "eslint-plugin-prettier": "^3.3.1", "husky": "^5.2.0", "lint-staged": "^10.5.4", - "postcss": "^8.2.8", + "postcss": "^8.2.15", "postcss-cli": "^8.3.1", "postcss-import": "^14.0.0", "postcss-preset-env": "^6.7.0", diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 00000000..d9423057 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,41 @@ +parameters: + tmpDir: build/phpstan + level: 5 + paths: + - app + - tests + bootstrapFiles: + - vendor/codeigniter4/codeigniter4/system/Test/bootstrap.php + scanDirectories: + - app/Helpers + - vendor/codeigniter4/codeigniter4/system/Helpers + - vendor/myth/auth/src/Helpers + excludes_analyse: + - app/Config/Routes.php + - app/Libraries/Router.php + - app/Libraries/ActivityPub/Config/Routes.php + - app/Libraries/Analytics/Config/Routes.php + - app/Views/* + ignoreErrors: + - '#Access to property [\$a-zA-Z]+ on an unknown class Myth\\Auth.*#' # TODO: remove when https://github.com/lonnieezell/myth-auth/pull/347 is merged + - '#Call to method [\a-zA-Z]+\(\) on an unknown class Myth\\Auth.*#' # to remove as well + - '#^Access to an undefined property ActivityPub\\Entities\\Actor#' + - '#^Access to an undefined property ActivityPub\\Entities\\Note#' + - '#.* is forbidden to use#' + - '#^Cognitive complexity for#' + - '#^Class cognitive complexity is#' + - '#Do not use chained method calls. Put each on separated lines.#' + - '#Do not inherit from abstract class, better use composition#' + - '#Cannot access property [\$a-z_]+ on ((array\|)?object)#' + - '#^Call to an undefined method CodeIgniter\\Database\\BaseBuilder#' + - '#^Call to an undefined method CodeIgniter\\Database\\ConnectionInterface#' + - '#Access to an undefined property CodeIgniter\\Database\\BaseBuilder::\$pager#' + - + message: '#Function "function_exists\(\)" cannot be used/left in the code#' + paths: + - app/Helpers + - app/Libraries/ActivityPub/Helpers + - app/Libraries/Analytics/Helpers + - + message: '#Function "property_exists\(\)" cannot be used/left in the code#' + path: app/Libraries/ActivityPub/Helpers diff --git a/rector.php b/rector.php index 20ea8a67..9403850f 100644 --- a/rector.php +++ b/rector.php @@ -25,16 +25,14 @@ return static function (ContainerConfigurator $containerConfigurator): void { ]); // Define what rule sets will be applied - $parameters->set(Option::SETS, [ - SetList::PHP_73, - SetList::TYPE_DECLARATION, - SetList::TYPE_DECLARATION_STRICT, - SetList::CODE_QUALITY, - SetList::CODING_STYLE, - SetList::EARLY_RETURN, - SetList::DEAD_CODE, - SetList::ORDER, - ]); + $containerConfigurator->import(SetList::PHP_73); + $containerConfigurator->import(SetList::TYPE_DECLARATION); + $containerConfigurator->import(SetList::TYPE_DECLARATION_STRICT); + $containerConfigurator->import(SetList::CODE_QUALITY); + $containerConfigurator->import(SetList::CODING_STYLE); + $containerConfigurator->import(SetList::EARLY_RETURN); + $containerConfigurator->import(SetList::DEAD_CODE); + $containerConfigurator->import(SetList::ORDER); // auto import fully qualified class names $parameters->set(Option::AUTO_IMPORT_NAMES, true); diff --git a/tests/_support/DatabaseTestCase.php b/tests/_support/DatabaseTestCase.php index 59c68af3..26c1f2fa 100644 --- a/tests/_support/DatabaseTestCase.php +++ b/tests/_support/DatabaseTestCase.php @@ -5,6 +5,9 @@ namespace Tests\Support; use CodeIgniter\Test\CIUnitTestCase; use CodeIgniter\Test\DatabaseTestTrait; +/** + * @phpstan-ignore-next-line + */ class DatabaseTestCase extends CIUnitTestCase { use DatabaseTestTrait; @@ -20,7 +23,7 @@ class DatabaseTestCase extends CIUnitTestCase * The seed file(s) used for all tests within this test case. * Should be fully-namespaced or relative to $basePath * - * @var string|array + * @var string|string[] */ protected $seed = 'Tests\Support\Database\Seeds\ExampleSeeder'; @@ -38,7 +41,7 @@ class DatabaseTestCase extends CIUnitTestCase * Note that running "all" runs migrations in date order, * but specifying namespaces runs them in namespace order (then date) * - * @var string|array|null + * @var string|string[]|null */ protected $namespace = 'Tests\Support'; diff --git a/tests/_support/SessionTestCase.php b/tests/_support/SessionTestCase.php index acfa12f7..6e781dec 100644 --- a/tests/_support/SessionTestCase.php +++ b/tests/_support/SessionTestCase.php @@ -6,6 +6,9 @@ use CodeIgniter\Test\CIUnitTestCase; use CodeIgniter\Test\Mock\MockSession; use Config\Services; +/** + * @phpstan-ignore-next-line + */ class SessionTestCase extends CIUnitTestCase { /**