refactor: update code base to php 8 and set phpstan lvl to 6
This commit is contained in:
parent
4a33c50fb6
commit
6b74a9e98a
|
@ -1,4 +1,4 @@
|
|||
image: php:7.3-fpm
|
||||
image: php:8.0-fpm
|
||||
|
||||
stages:
|
||||
- quality
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
{
|
||||
"files": "*.php",
|
||||
"options": {
|
||||
"phpVersion": "7.3",
|
||||
"phpVersion": "7.4",
|
||||
"singleQuote": true
|
||||
}
|
||||
},
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
# should be used only for development purposes
|
||||
####################################################
|
||||
|
||||
FROM php:7.3-fpm
|
||||
FROM php:8.0-fpm
|
||||
|
||||
LABEL maintainer="Yassine Doghri<yassine@podlibre.org>"
|
||||
|
||||
|
@ -37,8 +37,8 @@ RUN apt-get update && apt-get install -y \
|
|||
zlib1g-dev \
|
||||
&& docker-php-ext-install intl
|
||||
|
||||
RUN docker-php-ext-configure gd --with-jpeg-dir=/usr/include/ \
|
||||
&& docker-php-ext-install gd
|
||||
RUN docker-php-ext-configure gd --with-jpeg \
|
||||
&& docker-php-ext-install gd
|
||||
|
||||
RUN pecl install -o -f redis \
|
||||
&& rm -rf /tmp/pear \
|
||||
|
|
|
@ -10,7 +10,7 @@ or shared hosting, you can install it on most PHP-MySQL compatible web servers.
|
|||
- [1. Install Wizard](#1-install-wizard)
|
||||
- [1-alt Manual configuration](#1-alt-manual-configuration)
|
||||
- [Web Server Requirements](#web-server-requirements)
|
||||
- [PHP v7.3 or higher](#php-v73-or-higher)
|
||||
- [PHP v8.0 or higher](#php-v73-or-higher)
|
||||
- [MySQL compatible database](#mysql-compatible-database)
|
||||
- [Privileges](#privileges)
|
||||
- [(Optional) Other recommendations](#optional-other-recommendations)
|
||||
|
@ -59,9 +59,9 @@ through the install wizard, you can create and update the `.env` file yourself:
|
|||
|
||||
## Web Server Requirements
|
||||
|
||||
### PHP v7.3 or higher
|
||||
### PHP v8.0 or higher
|
||||
|
||||
PHP version 7.3 or higher is required, with the following extensions installed:
|
||||
PHP version 8.0 or higher is required, with the following extensions installed:
|
||||
|
||||
- [intl](https://php.net/manual/en/intl.requirements.php)
|
||||
- [libcurl](https://php.net/manual/en/curl.requirements.php)
|
||||
|
|
|
@ -17,10 +17,8 @@ class FlatAuthorization extends MythAuthFlatAuthorization
|
|||
|
||||
/**
|
||||
* Checks a group to see if they have the specified permission.
|
||||
*
|
||||
* @param int|string $permission
|
||||
*/
|
||||
public function groupHasPermission($permission, int $groupId): bool
|
||||
public function groupHasPermission(int|string $permission, int $groupId): bool
|
||||
{
|
||||
// Get the Permission ID
|
||||
$permissionId = $this->getPermissionID($permission);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?php namespace Config;
|
||||
|
||||
use App\Libraries\PodcastActor;
|
||||
use App\Libraries\NoteObject;
|
||||
use ActivityPub\Config\ActivityPub as ActivityPubBase;
|
||||
|
||||
class ActivityPub extends ActivityPubBase
|
||||
|
@ -8,18 +10,32 @@ class ActivityPub extends ActivityPubBase
|
|||
* --------------------------------------------------------------------
|
||||
* ActivityPub Objects
|
||||
* --------------------------------------------------------------------
|
||||
* @var string
|
||||
*/
|
||||
public $actorObject = 'App\Libraries\PodcastActor';
|
||||
public $noteObject = 'App\Libraries\NoteObject';
|
||||
public $actorObject = PodcastActor::class;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $noteObject = NoteObject::class;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
* Default avatar and cover images
|
||||
* --------------------------------------------------------------------
|
||||
* @var string
|
||||
*/
|
||||
public $defaultAvatarImagePath = 'assets/images/castopod-avatar-default.jpg';
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $defaultAvatarImageMimetype = 'image/jpeg';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $defaultCoverImagePath = 'assets/images/castopod-cover-default.jpg';
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $defaultCoverImageMimetype = 'image/jpeg';
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ class Analytics extends AnalyticsBase
|
|||
* --------------------------------------------------------------------
|
||||
* Route filters options
|
||||
* --------------------------------------------------------------------
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public $routeFilters = [
|
||||
'analytics-full-data' => 'permission:podcasts-view,podcast-view',
|
||||
|
|
|
@ -12,25 +12,21 @@ class Database extends Config
|
|||
/**
|
||||
* The directory that holds the Migrations
|
||||
* and Seeds directories.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $filesPath = APPPATH . 'Database' . DIRECTORY_SEPARATOR;
|
||||
public string $filesPath = APPPATH . 'Database' . DIRECTORY_SEPARATOR;
|
||||
|
||||
/**
|
||||
* Lets you choose which connection group to
|
||||
* use if no other is specified.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $defaultGroup = 'default';
|
||||
public string $defaultGroup = 'default';
|
||||
|
||||
/**
|
||||
* The default database connection.
|
||||
*
|
||||
* @var array
|
||||
* @var array<string, string|bool|int|array>
|
||||
*/
|
||||
public $default = [
|
||||
public array $default = [
|
||||
'DSN' => '',
|
||||
'hostname' => 'localhost',
|
||||
'username' => '',
|
||||
|
@ -54,9 +50,9 @@ class Database extends Config
|
|||
* This database connection is used when
|
||||
* running PHPUnit database tests.
|
||||
*
|
||||
* @var array
|
||||
* @var array<string, string|bool|int|array>
|
||||
*/
|
||||
public $tests = [
|
||||
public array $tests = [
|
||||
'DSN' => '',
|
||||
'hostname' => '127.0.0.1',
|
||||
'username' => '',
|
||||
|
|
|
@ -29,7 +29,7 @@ class Exceptions extends BaseConfig
|
|||
* Any status codes here will NOT be logged if logging is turned on.
|
||||
* By default, only 404 (Page Not Found) exceptions are ignored.
|
||||
*
|
||||
* @var array
|
||||
* @var int[]
|
||||
*/
|
||||
public $ignoreCodes = [404];
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ class Filters extends BaseConfig
|
|||
* Configures aliases for Filter classes to
|
||||
* make reading things nicer and simpler.
|
||||
*
|
||||
* @var array
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public $aliases = [
|
||||
'csrf' => CSRF::class,
|
||||
|
@ -33,7 +33,7 @@ class Filters extends BaseConfig
|
|||
* List of filter aliases that are always
|
||||
* applied before and after every request.
|
||||
*
|
||||
* @var array
|
||||
* @var array<string, string[]>
|
||||
*/
|
||||
public $globals = [
|
||||
'before' => [
|
||||
|
@ -53,7 +53,7 @@ class Filters extends BaseConfig
|
|||
* Example:
|
||||
* 'post' => ['csrf', 'throttle']
|
||||
*
|
||||
* @var array
|
||||
* @var array<string, string[]>
|
||||
*/
|
||||
public $methods = [];
|
||||
|
||||
|
@ -64,7 +64,7 @@ class Filters extends BaseConfig
|
|||
* Example:
|
||||
* 'isLoggedIn' => ['before' => ['account/*', 'profiles/*']]
|
||||
*
|
||||
* @var array
|
||||
* @var array<string, array<string, string[]>>
|
||||
*/
|
||||
public $filters = [];
|
||||
|
||||
|
|
|
@ -23,7 +23,10 @@ class Kint extends BaseConfig
|
|||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public $plugins;
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
public $plugins = [];
|
||||
|
||||
/**
|
||||
* @var int
|
||||
|
@ -60,9 +63,15 @@ class Kint extends BaseConfig
|
|||
*/
|
||||
public $richSort = Renderer::SORT_FULL;
|
||||
|
||||
public $richObjectPlugins;
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
public $richObjectPlugins = [];
|
||||
|
||||
public $richTabPlugins;
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
public $richTabPlugins = [];
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
|
@ -36,9 +36,9 @@ class Logger extends BaseConfig
|
|||
* For a live site you'll usually enable Critical or higher (3) to be logged otherwise
|
||||
* your log files will fill up very fast.
|
||||
*
|
||||
* @var integer|array
|
||||
* @var integer|int[]
|
||||
*/
|
||||
public $threshold = 4;
|
||||
public int|array $threshold = 4;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
|
@ -50,7 +50,7 @@ class Logger extends BaseConfig
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
public $dateFormat = 'Y-m-d H:i:s';
|
||||
public string $dateFormat = 'Y-m-d H:i:s';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
|
@ -75,9 +75,9 @@ class Logger extends BaseConfig
|
|||
* Handlers are executed in the order defined in this array, starting with
|
||||
* the handler on top and continuing down.
|
||||
*
|
||||
* @var array
|
||||
* @var array<string, string|int|array<string, string>>
|
||||
*/
|
||||
public $handlers = [
|
||||
public array $handlers = [
|
||||
/*
|
||||
* --------------------------------------------------------------------
|
||||
* File Handler
|
||||
|
@ -125,9 +125,9 @@ class Logger extends BaseConfig
|
|||
],
|
||||
|
||||
/**
|
||||
* The ChromeLoggerHandler requires the use of the Chrome web browser
|
||||
* and the ChromeLogger extension. Uncomment this block to use it.
|
||||
*/
|
||||
* The ChromeLoggerHandler requires the use of the Chrome web browser
|
||||
* and the ChromeLogger extension. Uncomment this block to use it.
|
||||
*/
|
||||
// 'CodeIgniter\Log\Handlers\ChromeLoggerHandler' => [
|
||||
// /*
|
||||
// * The log levels that this handler will handle.
|
||||
|
|
|
@ -164,13 +164,13 @@ $routes->group(
|
|||
]);
|
||||
|
||||
$routes->group('persons', function ($routes): void {
|
||||
$routes->get('/', 'PodcastPersonController/$1', [
|
||||
$routes->get('/', 'PodcastPodcastController/$1', [
|
||||
'as' => 'podcast-person-manage',
|
||||
'filter' => 'permission:podcast-edit',
|
||||
]);
|
||||
$routes->post(
|
||||
'/',
|
||||
'PodcastPersonController::attemptAdd/$1',
|
||||
'PodcastPodcastController::attemptAdd/$1',
|
||||
[
|
||||
'filter' => 'permission:podcast-edit',
|
||||
],
|
||||
|
@ -178,7 +178,7 @@ $routes->group(
|
|||
|
||||
$routes->get(
|
||||
'(:num)/remove',
|
||||
'PodcastPersonController::remove/$1/$2',
|
||||
'PodcastPodcastController::remove/$1/$2',
|
||||
[
|
||||
'as' => 'podcast-person-remove',
|
||||
'filter' => 'permission:podcast-edit',
|
||||
|
|
|
@ -34,18 +34,12 @@ class Services extends BaseService
|
|||
/**
|
||||
* The Router class uses a RouteCollection's array of routes, and determines
|
||||
* the correct Controller and Method to execute.
|
||||
*
|
||||
* @param RouteCollectionInterface|null $routes
|
||||
* @param Request|null $request
|
||||
* @param boolean $getShared
|
||||
*
|
||||
* @return Router
|
||||
*/
|
||||
public static function router(
|
||||
RouteCollectionInterface $routes = null,
|
||||
Request $request = null,
|
||||
?RouteCollectionInterface $routes = null,
|
||||
?Request $request = null,
|
||||
bool $getShared = true
|
||||
) {
|
||||
): Router {
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('router', $routes, $request);
|
||||
}
|
||||
|
@ -60,16 +54,11 @@ class Services extends BaseService
|
|||
* The Negotiate class provides the content negotiation features for
|
||||
* working the request to determine correct language, encoding, charset,
|
||||
* and more.
|
||||
*
|
||||
* @param RequestInterface|null $request
|
||||
* @param boolean $getShared
|
||||
*
|
||||
* @return Negotiate
|
||||
*/
|
||||
public static function negotiator(
|
||||
RequestInterface $request = null,
|
||||
?RequestInterface $request = null,
|
||||
bool $getShared = true
|
||||
) {
|
||||
): Negotiate {
|
||||
if ($getShared) {
|
||||
return static::getSharedInstance('negotiator', $request);
|
||||
}
|
||||
|
@ -79,6 +68,9 @@ class Services extends BaseService
|
|||
return new Negotiate($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public static function authentication(
|
||||
string $lib = 'local',
|
||||
Model $userModel = null,
|
||||
|
@ -112,6 +104,9 @@ class Services extends BaseService
|
|||
return $instance->setUserModel($userModel)->setLoginModel($loginModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public static function authorization(
|
||||
Model $groupModel = null,
|
||||
Model $permissionModel = null,
|
||||
|
@ -144,7 +139,7 @@ class Services extends BaseService
|
|||
return $instance->setUserModel($userModel);
|
||||
}
|
||||
|
||||
public static function breadcrumb(bool $getShared = true)
|
||||
public static function breadcrumb(bool $getShared = true): Breadcrumb
|
||||
{
|
||||
if ($getShared) {
|
||||
return self::getSharedInstance('breadcrumb');
|
||||
|
|
|
@ -29,7 +29,7 @@ class View extends BaseView
|
|||
* { title|esc(js) }
|
||||
* { created_on|date(Y-m-d)|esc(attr) }
|
||||
*
|
||||
* @var array
|
||||
* @var string[]
|
||||
*/
|
||||
public $filters = [];
|
||||
|
||||
|
@ -38,7 +38,7 @@ class View extends BaseView
|
|||
* by the core Parser by creating aliases that will be replaced with
|
||||
* any callable. Can be single or tag pair.
|
||||
*
|
||||
* @var array
|
||||
* @var string[]
|
||||
*/
|
||||
public $plugins = [];
|
||||
}
|
||||
|
|
|
@ -15,9 +15,12 @@ class ActorController extends ActivityPubActorController
|
|||
{
|
||||
use AnalyticsTrait;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
protected $helpers = ['auth', 'svg', 'components', 'misc'];
|
||||
|
||||
public function follow()
|
||||
public function follow(): string
|
||||
{
|
||||
// Prevent analytics hit when authenticated
|
||||
if (!can_user_interact()) {
|
||||
|
|
|
@ -25,7 +25,7 @@ class BaseController extends Controller
|
|||
* class instantiation. These helpers will be available
|
||||
* to all other controllers that extend BaseController.
|
||||
*
|
||||
* @var array
|
||||
* @var string[]
|
||||
*/
|
||||
protected $helpers = ['auth', 'breadcrumb', 'svg', 'components', 'misc'];
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ use Exception;
|
|||
use App\Authorization\GroupModel;
|
||||
use App\Models\PodcastModel;
|
||||
use App\Models\UserModel;
|
||||
use CodeIgniter\HTTP\RedirectResponse;
|
||||
|
||||
class ContributorController extends BaseController
|
||||
{
|
||||
|
@ -28,9 +29,9 @@ class ContributorController extends BaseController
|
|||
*/
|
||||
protected $user;
|
||||
|
||||
public function _remap($method, ...$params)
|
||||
public function _remap(string $method, string ...$params): mixed
|
||||
{
|
||||
$this->podcast = (new PodcastModel())->getPodcastById($params[0]);
|
||||
$this->podcast = (new PodcastModel())->getPodcastById((int) $params[0]);
|
||||
|
||||
if (count($params) <= 1) {
|
||||
return $this->$method();
|
||||
|
@ -38,8 +39,8 @@ class ContributorController extends BaseController
|
|||
|
||||
if (
|
||||
$this->user = (new UserModel())->getPodcastContributor(
|
||||
$params[1],
|
||||
$params[0],
|
||||
(int) $params[1],
|
||||
(int) $params[0],
|
||||
)
|
||||
) {
|
||||
return $this->$method();
|
||||
|
@ -48,7 +49,7 @@ class ContributorController extends BaseController
|
|||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
public function list()
|
||||
public function list(): string
|
||||
{
|
||||
$data = [
|
||||
'podcast' => $this->podcast,
|
||||
|
@ -58,7 +59,7 @@ class ContributorController extends BaseController
|
|||
return view('admin/contributor/list', $data);
|
||||
}
|
||||
|
||||
public function view()
|
||||
public function view(): string
|
||||
{
|
||||
$data = [
|
||||
'contributor' => (new UserModel())->getPodcastContributor(
|
||||
|
@ -74,7 +75,7 @@ class ContributorController extends BaseController
|
|||
return view('admin/contributor/view', $data);
|
||||
}
|
||||
|
||||
public function add()
|
||||
public function add(): string
|
||||
{
|
||||
helper('form');
|
||||
|
||||
|
@ -108,7 +109,7 @@ class ContributorController extends BaseController
|
|||
return view('admin/contributor/add', $data);
|
||||
}
|
||||
|
||||
public function attemptAdd()
|
||||
public function attemptAdd(): RedirectResponse
|
||||
{
|
||||
try {
|
||||
(new PodcastModel())->addPodcastContributor(
|
||||
|
@ -116,7 +117,7 @@ class ContributorController extends BaseController
|
|||
$this->podcast->id,
|
||||
$this->request->getPost('role'),
|
||||
);
|
||||
} catch (Exception $exception) {
|
||||
} catch (Exception) {
|
||||
return redirect()
|
||||
->back()
|
||||
->withInput()
|
||||
|
@ -128,7 +129,7 @@ class ContributorController extends BaseController
|
|||
return redirect()->route('contributor-list', [$this->podcast->id]);
|
||||
}
|
||||
|
||||
public function edit()
|
||||
public function edit(): string
|
||||
{
|
||||
helper('form');
|
||||
|
||||
|
@ -159,7 +160,7 @@ class ContributorController extends BaseController
|
|||
return view('admin/contributor/edit', $data);
|
||||
}
|
||||
|
||||
public function attemptEdit()
|
||||
public function attemptEdit(): RedirectResponse
|
||||
{
|
||||
(new PodcastModel())->updatePodcastContributor(
|
||||
$this->user->id,
|
||||
|
@ -170,7 +171,7 @@ class ContributorController extends BaseController
|
|||
return redirect()->route('contributor-list', [$this->podcast->id]);
|
||||
}
|
||||
|
||||
public function remove()
|
||||
public function remove(): RedirectResponse
|
||||
{
|
||||
if ($this->podcast->created_by === $this->user->id) {
|
||||
return redirect()
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
|
||||
namespace App\Controllers\Admin;
|
||||
|
||||
use CodeIgniter\Exceptions\PageNotFoundException;
|
||||
use CodeIgniter\HTTP\RedirectResponse;
|
||||
use Config\Database;
|
||||
use App\Entities\Episode;
|
||||
use App\Entities\Note;
|
||||
use App\Entities\Podcast;
|
||||
|
@ -29,12 +32,14 @@ class EpisodeController extends BaseController
|
|||
*/
|
||||
protected $episode;
|
||||
|
||||
public function _remap(string $method, ...$params)
|
||||
public function _remap(string $method, string ...$params): mixed
|
||||
{
|
||||
if (
|
||||
!($this->podcast = (new PodcastModel())->getPodcastById($params[0]))
|
||||
($this->podcast = (new PodcastModel())->getPodcastById(
|
||||
(int) $params[0],
|
||||
)) === null
|
||||
) {
|
||||
throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
if (count($params) > 1) {
|
||||
|
@ -46,7 +51,7 @@ class EpisodeController extends BaseController
|
|||
])
|
||||
->first())
|
||||
) {
|
||||
throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
unset($params[1]);
|
||||
|
@ -56,7 +61,7 @@ class EpisodeController extends BaseController
|
|||
return $this->$method(...$params);
|
||||
}
|
||||
|
||||
public function list()
|
||||
public function list(): string
|
||||
{
|
||||
$episodes = (new EpisodeModel())
|
||||
->where('podcast_id', $this->podcast->id)
|
||||
|
@ -74,7 +79,7 @@ class EpisodeController extends BaseController
|
|||
return view('admin/episode/list', $data);
|
||||
}
|
||||
|
||||
public function view()
|
||||
public function view(): string
|
||||
{
|
||||
$data = [
|
||||
'podcast' => $this->podcast,
|
||||
|
@ -88,7 +93,7 @@ class EpisodeController extends BaseController
|
|||
return view('admin/episode/view', $data);
|
||||
}
|
||||
|
||||
public function create()
|
||||
public function create(): string
|
||||
{
|
||||
helper(['form']);
|
||||
|
||||
|
@ -102,7 +107,7 @@ class EpisodeController extends BaseController
|
|||
return view('admin/episode/create', $data);
|
||||
}
|
||||
|
||||
public function attemptCreate()
|
||||
public function attemptCreate(): RedirectResponse
|
||||
{
|
||||
$rules = [
|
||||
'audio_file' => 'uploaded[audio_file]|ext_in[audio_file,mp3,m4a]',
|
||||
|
@ -204,7 +209,7 @@ class EpisodeController extends BaseController
|
|||
]);
|
||||
}
|
||||
|
||||
public function edit()
|
||||
public function edit(): string
|
||||
{
|
||||
helper(['form']);
|
||||
|
||||
|
@ -220,7 +225,7 @@ class EpisodeController extends BaseController
|
|||
return view('admin/episode/edit', $data);
|
||||
}
|
||||
|
||||
public function attemptEdit()
|
||||
public function attemptEdit(): RedirectResponse
|
||||
{
|
||||
$rules = [
|
||||
'audio_file' =>
|
||||
|
@ -282,17 +287,14 @@ class EpisodeController extends BaseController
|
|||
}
|
||||
} elseif ($transcriptChoice === 'remote-url') {
|
||||
if (
|
||||
$transcriptFileRemoteUrl = $this->request->getPost(
|
||||
($transcriptFileRemoteUrl = $this->request->getPost(
|
||||
'transcript_file_remote_url',
|
||||
)
|
||||
)) &&
|
||||
(($transcriptFile = $this->episode->transcript_file) &&
|
||||
$transcriptFile !== null)
|
||||
) {
|
||||
if (
|
||||
($transcriptFile = $this->episode->transcript_file) &&
|
||||
$transcriptFile !== null
|
||||
) {
|
||||
unlink($transcriptFile);
|
||||
$this->episode->transcript_file_path = null;
|
||||
}
|
||||
unlink($transcriptFile);
|
||||
$this->episode->transcript_file_path = null;
|
||||
}
|
||||
$this->episode->transcript_file_remote_url = $transcriptFileRemoteUrl;
|
||||
}
|
||||
|
@ -306,17 +308,14 @@ class EpisodeController extends BaseController
|
|||
}
|
||||
} elseif ($chaptersChoice === 'remote-url') {
|
||||
if (
|
||||
$chaptersFileRemoteUrl = $this->request->getPost(
|
||||
($chaptersFileRemoteUrl = $this->request->getPost(
|
||||
'chapters_file_remote_url',
|
||||
)
|
||||
)) &&
|
||||
(($chaptersFile = $this->episode->chapters_file) &&
|
||||
$chaptersFile !== null)
|
||||
) {
|
||||
if (
|
||||
($chaptersFile = $this->episode->chapters_file) &&
|
||||
$chaptersFile !== null
|
||||
) {
|
||||
unlink($chaptersFile);
|
||||
$this->episode->chapters_file_path = null;
|
||||
}
|
||||
unlink($chaptersFile);
|
||||
$this->episode->chapters_file_path = null;
|
||||
}
|
||||
$this->episode->chapters_file_remote_url = $chaptersFileRemoteUrl;
|
||||
}
|
||||
|
@ -351,7 +350,7 @@ class EpisodeController extends BaseController
|
|||
]);
|
||||
}
|
||||
|
||||
public function transcriptDelete()
|
||||
public function transcriptDelete(): RedirectResponse
|
||||
{
|
||||
unlink($this->episode->transcript_file);
|
||||
$this->episode->transcript_file_path = null;
|
||||
|
@ -368,7 +367,7 @@ class EpisodeController extends BaseController
|
|||
return redirect()->back();
|
||||
}
|
||||
|
||||
public function chaptersDelete()
|
||||
public function chaptersDelete(): RedirectResponse
|
||||
{
|
||||
unlink($this->episode->chapters_file);
|
||||
$this->episode->chapters_file_path = null;
|
||||
|
@ -385,7 +384,7 @@ class EpisodeController extends BaseController
|
|||
return redirect()->back();
|
||||
}
|
||||
|
||||
public function publish()
|
||||
public function publish(): string
|
||||
{
|
||||
if ($this->episode->publication_status === 'not_published') {
|
||||
helper(['form']);
|
||||
|
@ -400,12 +399,12 @@ class EpisodeController extends BaseController
|
|||
1 => $this->episode->title,
|
||||
]);
|
||||
return view('admin/episode/publish', $data);
|
||||
} else {
|
||||
throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
public function attemptPublish()
|
||||
public function attemptPublish(): RedirectResponse
|
||||
{
|
||||
$rules = [
|
||||
'publication_method' => 'required',
|
||||
|
@ -420,7 +419,7 @@ class EpisodeController extends BaseController
|
|||
->with('errors', $this->validator->getErrors());
|
||||
}
|
||||
|
||||
$db = \Config\Database::connect();
|
||||
$db = Database::connect();
|
||||
$db->transStart();
|
||||
|
||||
$newNote = new Note([
|
||||
|
@ -482,7 +481,7 @@ class EpisodeController extends BaseController
|
|||
]);
|
||||
}
|
||||
|
||||
public function publishEdit()
|
||||
public function publishEdit(): string
|
||||
{
|
||||
if ($this->episode->publication_status === 'scheduled') {
|
||||
helper(['form']);
|
||||
|
@ -503,12 +502,11 @@ class EpisodeController extends BaseController
|
|||
1 => $this->episode->title,
|
||||
]);
|
||||
return view('admin/episode/publish_edit', $data);
|
||||
} else {
|
||||
throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
public function attemptPublishEdit()
|
||||
public function attemptPublishEdit(): RedirectResponse
|
||||
{
|
||||
$rules = [
|
||||
'note_id' => 'required',
|
||||
|
@ -524,7 +522,7 @@ class EpisodeController extends BaseController
|
|||
->with('errors', $this->validator->getErrors());
|
||||
}
|
||||
|
||||
$db = \Config\Database::connect();
|
||||
$db = Database::connect();
|
||||
$db->transStart();
|
||||
|
||||
$note = (new NoteModel())->getNoteById(
|
||||
|
@ -584,7 +582,7 @@ class EpisodeController extends BaseController
|
|||
]);
|
||||
}
|
||||
|
||||
public function unpublish()
|
||||
public function unpublish(): string
|
||||
{
|
||||
if ($this->episode->publication_status === 'published') {
|
||||
helper(['form']);
|
||||
|
@ -599,12 +597,12 @@ class EpisodeController extends BaseController
|
|||
1 => $this->episode->title,
|
||||
]);
|
||||
return view('admin/episode/unpublish', $data);
|
||||
} else {
|
||||
throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
public function attemptUnpublish()
|
||||
public function attemptUnpublish(): RedirectResponse
|
||||
{
|
||||
$rules = [
|
||||
'understand' => 'required',
|
||||
|
@ -617,7 +615,7 @@ class EpisodeController extends BaseController
|
|||
->with('errors', $this->validator->getErrors());
|
||||
}
|
||||
|
||||
$db = \Config\Database::connect();
|
||||
$db = Database::connect();
|
||||
|
||||
$db->transStart();
|
||||
|
||||
|
@ -650,14 +648,14 @@ class EpisodeController extends BaseController
|
|||
]);
|
||||
}
|
||||
|
||||
public function delete()
|
||||
public function delete(): RedirectResponse
|
||||
{
|
||||
(new EpisodeModel())->delete($this->episode->id);
|
||||
|
||||
return redirect()->route('episode-list', [$this->podcast->id]);
|
||||
}
|
||||
|
||||
public function soundbitesEdit()
|
||||
public function soundbitesEdit(): string
|
||||
{
|
||||
helper(['form']);
|
||||
|
||||
|
@ -673,7 +671,7 @@ class EpisodeController extends BaseController
|
|||
return view('admin/episode/soundbites', $data);
|
||||
}
|
||||
|
||||
public function soundbitesAttemptEdit()
|
||||
public function soundbitesAttemptEdit(): RedirectResponse
|
||||
{
|
||||
$soundbites_array = $this->request->getPost('soundbites_array');
|
||||
$rules = [
|
||||
|
@ -682,7 +680,7 @@ class EpisodeController extends BaseController
|
|||
'soundbites_array.0.duration' =>
|
||||
'permit_empty|required_with[soundbites_array.0.start_time]|decimal|greater_than_equal_to[0]',
|
||||
];
|
||||
foreach ($soundbites_array as $soundbite_id => $soundbite) {
|
||||
foreach (array_keys($soundbites_array) as $soundbite_id) {
|
||||
$rules += [
|
||||
"soundbites_array.{$soundbite_id}.start_time" => 'required|decimal|greater_than_equal_to[0]',
|
||||
"soundbites_array.{$soundbite_id}.duration" => 'required|decimal|greater_than_equal_to[0]',
|
||||
|
@ -728,7 +726,7 @@ class EpisodeController extends BaseController
|
|||
]);
|
||||
}
|
||||
|
||||
public function soundbiteDelete($soundbiteId)
|
||||
public function soundbiteDelete(int $soundbiteId): RedirectResponse
|
||||
{
|
||||
(new SoundbiteModel())->deleteSoundbite(
|
||||
$this->podcast->id,
|
||||
|
@ -742,7 +740,7 @@ class EpisodeController extends BaseController
|
|||
]);
|
||||
}
|
||||
|
||||
public function embeddablePlayer()
|
||||
public function embeddablePlayer(): string
|
||||
{
|
||||
helper(['form']);
|
||||
|
||||
|
|
|
@ -8,27 +8,20 @@
|
|||
|
||||
namespace App\Controllers\Admin;
|
||||
|
||||
use CodeIgniter\HTTP\RedirectResponse;
|
||||
use App\Entities\Podcast;
|
||||
use App\Entities\Episode;
|
||||
use CodeIgniter\Exceptions\PageNotFoundException;
|
||||
use App\Models\EpisodePersonModel;
|
||||
use App\Models\PodcastModel;
|
||||
use App\Models\EpisodeModel;
|
||||
use App\Models\PersonModel;
|
||||
|
||||
class EpisodePersonController extends BaseController
|
||||
{
|
||||
/**
|
||||
* @var Podcast
|
||||
*/
|
||||
protected $podcast;
|
||||
protected Podcast $podcast;
|
||||
protected Episode $episode;
|
||||
|
||||
/**
|
||||
* @var Episode
|
||||
*/
|
||||
protected $episode;
|
||||
|
||||
public function _remap($method, ...$params)
|
||||
public function _remap(string $method, string ...$params): mixed
|
||||
{
|
||||
if (count($params) <= 2) {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
|
@ -36,7 +29,7 @@ class EpisodePersonController extends BaseController
|
|||
|
||||
if (
|
||||
($this->podcast = (new PodcastModel())->getPodcastById(
|
||||
$params[0],
|
||||
(int) $params[0],
|
||||
)) &&
|
||||
($this->episode = (new EpisodeModel())
|
||||
->where([
|
||||
|
@ -54,14 +47,14 @@ class EpisodePersonController extends BaseController
|
|||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
public function index()
|
||||
public function index(): string
|
||||
{
|
||||
helper('form');
|
||||
|
||||
$data = [
|
||||
'episode' => $this->episode,
|
||||
'podcast' => $this->podcast,
|
||||
'episodePersons' => (new EpisodePersonModel())->getEpisodePersons(
|
||||
'episodePersons' => (new PersonModel())->getEpisodePersons(
|
||||
$this->podcast->id,
|
||||
$this->episode->id,
|
||||
),
|
||||
|
@ -75,7 +68,7 @@ class EpisodePersonController extends BaseController
|
|||
return view('admin/episode/person', $data);
|
||||
}
|
||||
|
||||
public function attemptAdd()
|
||||
public function attemptAdd(): RedirectResponse
|
||||
{
|
||||
$rules = [
|
||||
'person' => 'required',
|
||||
|
@ -88,7 +81,7 @@ class EpisodePersonController extends BaseController
|
|||
->with('errors', $this->validator->getErrors());
|
||||
}
|
||||
|
||||
(new EpisodePersonModel())->addEpisodePersons(
|
||||
(new PersonModel())->addEpisodePersons(
|
||||
$this->podcast->id,
|
||||
$this->episode->id,
|
||||
$this->request->getPost('person'),
|
||||
|
@ -98,9 +91,9 @@ class EpisodePersonController extends BaseController
|
|||
return redirect()->back();
|
||||
}
|
||||
|
||||
public function remove($episodePersonId)
|
||||
public function remove(int $episodePersonId): RedirectResponse
|
||||
{
|
||||
(new EpisodePersonModel())->removeEpisodePersons(
|
||||
(new PersonModel())->removeEpisodePersons(
|
||||
$this->podcast->id,
|
||||
$this->episode->id,
|
||||
$episodePersonId,
|
||||
|
|
|
@ -10,12 +10,12 @@ namespace App\Controllers\Admin;
|
|||
|
||||
class FediverseController extends BaseController
|
||||
{
|
||||
public function dashboard()
|
||||
public function dashboard(): string
|
||||
{
|
||||
return view('admin/fediverse/dashboard');
|
||||
}
|
||||
|
||||
public function blockedActors()
|
||||
public function blockedActors(): string
|
||||
{
|
||||
helper(['form']);
|
||||
|
||||
|
@ -26,7 +26,7 @@ class FediverseController extends BaseController
|
|||
]);
|
||||
}
|
||||
|
||||
public function blockedDomains()
|
||||
public function blockedDomains(): string
|
||||
{
|
||||
helper(['form']);
|
||||
|
||||
|
|
|
@ -8,9 +8,10 @@
|
|||
|
||||
namespace App\Controllers\Admin;
|
||||
|
||||
use CodeIgniter\HTTP\RedirectResponse;
|
||||
class HomeController extends BaseController
|
||||
{
|
||||
public function index()
|
||||
public function index(): RedirectResponse
|
||||
{
|
||||
session()->keepFlashdata('message');
|
||||
return redirect()->route('podcast-list');
|
||||
|
|
|
@ -8,24 +8,25 @@
|
|||
|
||||
namespace App\Controllers\Admin;
|
||||
|
||||
use CodeIgniter\HTTP\RedirectResponse;
|
||||
use Config\Services;
|
||||
use App\Models\UserModel;
|
||||
|
||||
class MyAccountController extends BaseController
|
||||
{
|
||||
public function index()
|
||||
public function index(): string
|
||||
{
|
||||
return view('admin/my_account/view');
|
||||
}
|
||||
|
||||
public function changePassword()
|
||||
public function changePassword(): string
|
||||
{
|
||||
helper('form');
|
||||
|
||||
return view('admin/my_account/change_password');
|
||||
}
|
||||
|
||||
public function attemptChange()
|
||||
public function attemptChange(): RedirectResponse
|
||||
{
|
||||
$auth = Services::authentication();
|
||||
$userModel = new UserModel();
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
namespace App\Controllers\Admin;
|
||||
|
||||
use CodeIgniter\HTTP\RedirectResponse;
|
||||
use App\Entities\Page;
|
||||
use CodeIgniter\Exceptions\PageNotFoundException;
|
||||
use App\Models\PageModel;
|
||||
|
@ -19,7 +20,7 @@ class PageController extends BaseController
|
|||
*/
|
||||
protected $page;
|
||||
|
||||
public function _remap($method, ...$params)
|
||||
public function _remap(string $method, string ...$params): mixed
|
||||
{
|
||||
if (count($params) === 0) {
|
||||
return $this->$method();
|
||||
|
@ -32,7 +33,7 @@ class PageController extends BaseController
|
|||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
function list()
|
||||
function list(): string
|
||||
{
|
||||
$data = [
|
||||
'pages' => (new PageModel())->findAll(),
|
||||
|
@ -41,19 +42,19 @@ class PageController extends BaseController
|
|||
return view('admin/page/list', $data);
|
||||
}
|
||||
|
||||
function view()
|
||||
function view(): string
|
||||
{
|
||||
return view('admin/page/view', ['page' => $this->page]);
|
||||
}
|
||||
|
||||
function create()
|
||||
function create(): string
|
||||
{
|
||||
helper('form');
|
||||
|
||||
return view('admin/page/create');
|
||||
}
|
||||
|
||||
function attemptCreate()
|
||||
function attemptCreate(): RedirectResponse
|
||||
{
|
||||
$page = new Page([
|
||||
'title' => $this->request->getPost('title'),
|
||||
|
@ -80,7 +81,7 @@ class PageController extends BaseController
|
|||
);
|
||||
}
|
||||
|
||||
function edit()
|
||||
function edit(): string
|
||||
{
|
||||
helper('form');
|
||||
|
||||
|
@ -88,7 +89,7 @@ class PageController extends BaseController
|
|||
return view('admin/page/edit', ['page' => $this->page]);
|
||||
}
|
||||
|
||||
function attemptEdit()
|
||||
function attemptEdit(): RedirectResponse
|
||||
{
|
||||
$this->page->title = $this->request->getPost('title');
|
||||
$this->page->slug = $this->request->getPost('slug');
|
||||
|
@ -106,7 +107,7 @@ class PageController extends BaseController
|
|||
return redirect()->route('page-list');
|
||||
}
|
||||
|
||||
public function delete()
|
||||
public function delete(): RedirectResponse
|
||||
{
|
||||
(new PageModel())->delete($this->page->id);
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
namespace App\Controllers\Admin;
|
||||
|
||||
use CodeIgniter\HTTP\RedirectResponse;
|
||||
use App\Entities\Person;
|
||||
use CodeIgniter\Exceptions\PageNotFoundException;
|
||||
use App\Models\PersonModel;
|
||||
|
@ -19,27 +20,31 @@ class PersonController extends BaseController
|
|||
*/
|
||||
protected $person;
|
||||
|
||||
public function _remap($method, ...$params)
|
||||
public function _remap(string $method, string ...$params): mixed
|
||||
{
|
||||
if (count($params) === 0) {
|
||||
return $this->$method();
|
||||
}
|
||||
|
||||
if ($this->person = (new PersonModel())->getPersonById($params[0])) {
|
||||
if (
|
||||
($this->person = (new PersonModel())->getPersonById(
|
||||
(int) $params[0],
|
||||
)) !== null
|
||||
) {
|
||||
return $this->$method();
|
||||
}
|
||||
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
public function index()
|
||||
public function index(): string
|
||||
{
|
||||
$data = ['persons' => (new PersonModel())->findAll()];
|
||||
|
||||
return view('admin/person/list', $data);
|
||||
}
|
||||
|
||||
public function view()
|
||||
public function view(): string
|
||||
{
|
||||
$data = ['person' => $this->person];
|
||||
|
||||
|
@ -47,14 +52,14 @@ class PersonController extends BaseController
|
|||
return view('admin/person/view', $data);
|
||||
}
|
||||
|
||||
public function create()
|
||||
public function create(): string
|
||||
{
|
||||
helper(['form']);
|
||||
|
||||
return view('admin/person/create');
|
||||
}
|
||||
|
||||
public function attemptCreate()
|
||||
public function attemptCreate(): RedirectResponse
|
||||
{
|
||||
$rules = [
|
||||
'image' =>
|
||||
|
@ -89,7 +94,7 @@ class PersonController extends BaseController
|
|||
return redirect()->route('person-list');
|
||||
}
|
||||
|
||||
public function edit()
|
||||
public function edit(): string
|
||||
{
|
||||
helper('form');
|
||||
|
||||
|
@ -101,7 +106,7 @@ class PersonController extends BaseController
|
|||
return view('admin/person/edit', $data);
|
||||
}
|
||||
|
||||
public function attemptEdit()
|
||||
public function attemptEdit(): RedirectResponse
|
||||
{
|
||||
$rules = [
|
||||
'image' =>
|
||||
|
@ -138,7 +143,7 @@ class PersonController extends BaseController
|
|||
return redirect()->route('person-view', [$this->person->id]);
|
||||
}
|
||||
|
||||
public function delete()
|
||||
public function delete(): RedirectResponse
|
||||
{
|
||||
(new PersonModel())->delete($this->person->id);
|
||||
|
||||
|
|
|
@ -26,18 +26,17 @@ class PodcastController extends BaseController
|
|||
*/
|
||||
protected $podcast;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param array<string> $params
|
||||
* @return static|string
|
||||
*/
|
||||
public function _remap(string $method, ...$params)
|
||||
public function _remap(string $method, string ...$params): mixed
|
||||
{
|
||||
if (count($params) === 0) {
|
||||
return $this->$method();
|
||||
}
|
||||
|
||||
if ($this->podcast = (new PodcastModel())->getPodcastById($params[0])) {
|
||||
if (
|
||||
($this->podcast = (new PodcastModel())->getPodcastById(
|
||||
(int) $params[0],
|
||||
)) !== null
|
||||
) {
|
||||
return $this->$method();
|
||||
}
|
||||
|
||||
|
|
|
@ -8,22 +8,21 @@
|
|||
|
||||
namespace App\Controllers\Admin;
|
||||
|
||||
use CodeIgniter\HTTP\RedirectResponse;
|
||||
use App\Entities\Podcast;
|
||||
use CodeIgniter\Exceptions\PageNotFoundException;
|
||||
use ErrorException;
|
||||
use Config\Database;
|
||||
use Podlibre\PodcastNamespace\ReversedTaxonomy;
|
||||
use App\Entities\PodcastPerson;
|
||||
use App\Entities\Episode;
|
||||
use App\Entities\Image;
|
||||
use App\Entities\Person;
|
||||
use App\Models\CategoryModel;
|
||||
use App\Models\LanguageModel;
|
||||
use App\Models\PodcastModel;
|
||||
use App\Models\EpisodeModel;
|
||||
use App\Models\PlatformModel;
|
||||
use App\Models\PersonModel;
|
||||
use App\Models\PodcastPersonModel;
|
||||
use App\Models\EpisodePersonModel;
|
||||
use Config\Services;
|
||||
use League\HTMLToMarkdown\HtmlConverter;
|
||||
|
||||
|
@ -34,20 +33,20 @@ class PodcastImportController extends BaseController
|
|||
*/
|
||||
protected $podcast;
|
||||
|
||||
public function _remap(string $method, string ...$params)
|
||||
public function _remap(string $method, string ...$params): mixed
|
||||
{
|
||||
if (count($params) === 0) {
|
||||
return $this->$method();
|
||||
}
|
||||
|
||||
if ($this->podcast = (new PodcastModel())->getPodcastById($params[0])) {
|
||||
if (($this->podcast = (new PodcastModel())->getPodcastById((int) $params[0])) !== null) {
|
||||
return $this->$method();
|
||||
}
|
||||
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
public function index()
|
||||
public function index(): string
|
||||
{
|
||||
helper(['form', 'misc']);
|
||||
|
||||
|
@ -65,7 +64,7 @@ class PodcastImportController extends BaseController
|
|||
return view('admin/podcast/import', $data);
|
||||
}
|
||||
|
||||
public function attemptImport()
|
||||
public function attemptImport(): RedirectResponse
|
||||
{
|
||||
helper(['media', 'misc']);
|
||||
|
||||
|
@ -92,11 +91,11 @@ class PodcastImportController extends BaseController
|
|||
->withInput()
|
||||
->with('errors', [
|
||||
$errorException->getMessage() .
|
||||
': <a href="' .
|
||||
$this->request->getPost('imported_feed_url') .
|
||||
'" rel="noreferrer noopener" target="_blank">' .
|
||||
$this->request->getPost('imported_feed_url') .
|
||||
' ⎋</a>',
|
||||
': <a href="' .
|
||||
$this->request->getPost('imported_feed_url') .
|
||||
'" rel="noreferrer noopener" target="_blank">' .
|
||||
$this->request->getPost('imported_feed_url') .
|
||||
' ⎋</a>',
|
||||
]);
|
||||
}
|
||||
$nsItunes = $feed->channel[0]->children(
|
||||
|
@ -151,40 +150,40 @@ class PodcastImportController extends BaseController
|
|||
'language_code' => $this->request->getPost('language'),
|
||||
'category_id' => $this->request->getPost('category'),
|
||||
'parental_advisory' =>
|
||||
$nsItunes->explicit === null
|
||||
? null
|
||||
: (in_array($nsItunes->explicit, ['yes', 'true'])
|
||||
? 'explicit'
|
||||
: (in_array($nsItunes->explicit, ['no', 'false'])
|
||||
? 'clean'
|
||||
: null)),
|
||||
$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' =>
|
||||
$nsItunes->type === null ? 'episodic' : $nsItunes->type,
|
||||
$nsItunes->type === null ? 'episodic' : $nsItunes->type,
|
||||
'copyright' => (string) $feed->channel[0]->copyright,
|
||||
'is_blocked' =>
|
||||
$nsItunes->block === null
|
||||
? false
|
||||
: $nsItunes->block === 'yes',
|
||||
$nsItunes->block === null
|
||||
? false
|
||||
: $nsItunes->block === 'yes',
|
||||
'is_completed' =>
|
||||
$nsItunes->complete === null
|
||||
? false
|
||||
: $nsItunes->complete === 'yes',
|
||||
$nsItunes->complete === null
|
||||
? false
|
||||
: $nsItunes->complete === 'yes',
|
||||
'location_name' => $nsPodcast->location
|
||||
? (string) $nsPodcast->location
|
||||
: null,
|
||||
'location_geo' =>
|
||||
!$nsPodcast->location ||
|
||||
!$nsPodcast->location ||
|
||||
$nsPodcast->location->attributes()['geo'] === null
|
||||
? null
|
||||
: (string) $nsPodcast->location->attributes()['geo'],
|
||||
? null
|
||||
: (string) $nsPodcast->location->attributes()['geo'],
|
||||
'location_osm_id' =>
|
||||
!$nsPodcast->location ||
|
||||
!$nsPodcast->location ||
|
||||
$nsPodcast->location->attributes()['osm'] === null
|
||||
? null
|
||||
: (string) $nsPodcast->location->attributes()['osm'],
|
||||
? null
|
||||
: (string) $nsPodcast->location->attributes()['osm'],
|
||||
'created_by' => user_id(),
|
||||
'updated_by' => user_id(),
|
||||
]);
|
||||
|
@ -194,11 +193,11 @@ class PodcastImportController extends BaseController
|
|||
->withInput()
|
||||
->with('errors', [
|
||||
$ex->getMessage() .
|
||||
': <a href="' .
|
||||
$this->request->getPost('imported_feed_url') .
|
||||
'" rel="noreferrer noopener" target="_blank">' .
|
||||
$this->request->getPost('imported_feed_url') .
|
||||
' ⎋</a>',
|
||||
': <a href="' .
|
||||
$this->request->getPost('imported_feed_url') .
|
||||
'" rel="noreferrer noopener" target="_blank">' .
|
||||
$this->request->getPost('imported_feed_url') .
|
||||
' ⎋</a>',
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -235,7 +234,7 @@ class PodcastImportController extends BaseController
|
|||
foreach ($platformType['elements'] as $platform) {
|
||||
$platformLabel = $platform->attributes()['platform'];
|
||||
$platformSlug = slugify($platformLabel);
|
||||
if ($platformModel->getPlatform($platformSlug)) {
|
||||
if ($platformModel->getPlatform($platformSlug) !== null) {
|
||||
$podcastsPlatformsData[] = [
|
||||
'platform_slug' => $platformSlug,
|
||||
'podcast_id' => $newPodcastId,
|
||||
|
@ -255,45 +254,41 @@ class PodcastImportController extends BaseController
|
|||
}
|
||||
|
||||
foreach ($nsPodcast->person as $podcastPerson) {
|
||||
$fullName = (string) $podcastPerson;
|
||||
$personModel = new PersonModel();
|
||||
$newPersonId = null;
|
||||
if ($newPerson = $personModel->getPerson($podcastPerson)) {
|
||||
if (($newPerson = $personModel->getPerson($fullName)) !== null) {
|
||||
$newPersonId = $newPerson->id;
|
||||
} elseif (
|
||||
!($newPersonId = $personModel->createPerson(
|
||||
$podcastPerson,
|
||||
$podcastPerson->attributes()['href'],
|
||||
$podcastPerson->attributes()['img'],
|
||||
))
|
||||
) {
|
||||
return redirect()
|
||||
->back()
|
||||
->withInput()
|
||||
->with('errors', $personModel->errors());
|
||||
} else {
|
||||
$newPodcastPerson = new Person([
|
||||
'full_name' => $fullName,
|
||||
'unique_name' => slugify($fullName),
|
||||
'information_url' => $podcastPerson->attributes()['href'],
|
||||
'image' => new Image(download_file($podcastPerson->attributes()['img'])),
|
||||
'created_by' => user_id(),
|
||||
'updated_by' => user_id(),
|
||||
]);
|
||||
|
||||
if (!$newPersonId = $personModel->insert($newPodcastPerson)) {
|
||||
return redirect()
|
||||
->back()
|
||||
->withInput()
|
||||
->with('errors', $personModel->errors());
|
||||
}
|
||||
}
|
||||
|
||||
$personGroup =
|
||||
$podcastPerson->attributes()['group'] === null
|
||||
? ['slug' => '']
|
||||
: ReversedTaxonomy::$taxonomy[
|
||||
(string) $podcastPerson->attributes()['group']
|
||||
];
|
||||
isset($podcastPerson->attributes()['group'])
|
||||
? ['slug' => '']
|
||||
: ReversedTaxonomy::$taxonomy[(string) $podcastPerson->attributes()['group']];
|
||||
$personRole =
|
||||
$podcastPerson->attributes()['role'] === null ||
|
||||
isset($podcastPerson->attributes()['role']) ||
|
||||
$personGroup === null
|
||||
? ['slug' => '']
|
||||
: $personGroup['roles'][
|
||||
strval($podcastPerson->attributes()['role'])
|
||||
];
|
||||
$newPodcastPerson = new PodcastPerson([
|
||||
'podcast_id' => $newPodcastId,
|
||||
'person_id' => $newPersonId,
|
||||
'person_group' => $personGroup['slug'],
|
||||
'person_role' => $personRole['slug'],
|
||||
]);
|
||||
$podcastPersonModel = new PodcastPersonModel();
|
||||
? ['slug' => '']
|
||||
: $personGroup['roles'][strval($podcastPerson->attributes()['role'])];
|
||||
|
||||
if (!$podcastPersonModel->insert($newPodcastPerson)) {
|
||||
$podcastPersonModel = new PersonModel();
|
||||
if (!$podcastPersonModel->addPodcastPerson($newPodcastId, $newPersonId, $personGroup['slug'], $personRole['slug'])) {
|
||||
return redirect()
|
||||
->back()
|
||||
->withInput()
|
||||
|
@ -305,8 +300,8 @@ class PodcastImportController extends BaseController
|
|||
$lastItem =
|
||||
$this->request->getPost('max_episodes') !== null &&
|
||||
$this->request->getPost('max_episodes') < $numberItems
|
||||
? $this->request->getPost('max_episodes')
|
||||
: $numberItems;
|
||||
? $this->request->getPost('max_episodes')
|
||||
: $numberItems;
|
||||
|
||||
$slugs = [];
|
||||
|
||||
|
@ -338,22 +333,12 @@ class PodcastImportController extends BaseController
|
|||
$slug = $slug . '-' . $slugNumber;
|
||||
}
|
||||
$slugs[] = $slug;
|
||||
|
||||
$itemDescriptionHtml = null;
|
||||
switch ($this->request->getPost('description_field')) {
|
||||
case 'content':
|
||||
$itemDescriptionHtml = $nsContent->encoded;
|
||||
break;
|
||||
case 'summary':
|
||||
$itemDescriptionHtml = $nsItunes->summary;
|
||||
break;
|
||||
case 'subtitle_summary':
|
||||
$itemDescriptionHtml =
|
||||
$nsItunes->subtitle . '<br/>' . $nsItunes->summary;
|
||||
break;
|
||||
default:
|
||||
$itemDescriptionHtml = $item->description;
|
||||
}
|
||||
$itemDescriptionHtml = match ($this->request->getPost('description_field')) {
|
||||
'content' => $nsContent->encoded,
|
||||
'summary' => $nsItunes->summary,
|
||||
'subtitle_summary' => $nsItunes->subtitle . '<br/>' . $nsItunes->summary,
|
||||
default => $item->description,
|
||||
};
|
||||
|
||||
if (
|
||||
$nsItunes->image !== null &&
|
||||
|
@ -382,42 +367,42 @@ class PodcastImportController extends BaseController
|
|||
'description_html' => $itemDescriptionHtml,
|
||||
'image' => $episodeImage,
|
||||
'parental_advisory' =>
|
||||
$nsItunes->explicit === null
|
||||
? null
|
||||
: (in_array($nsItunes->explicit, ['yes', 'true'])
|
||||
? 'explicit'
|
||||
: (in_array($nsItunes->explicit, ['no', 'false'])
|
||||
? 'clean'
|
||||
: null)),
|
||||
$nsItunes->explicit === null
|
||||
? null
|
||||
: (in_array($nsItunes->explicit, ['yes', 'true'])
|
||||
? 'explicit'
|
||||
: (in_array($nsItunes->explicit, ['no', 'false'])
|
||||
? 'clean'
|
||||
: null)),
|
||||
'number' =>
|
||||
$this->request->getPost('force_renumber') === 'yes'
|
||||
? $itemNumber
|
||||
: $nsItunes->episode,
|
||||
$this->request->getPost('force_renumber') === 'yes'
|
||||
? $itemNumber
|
||||
: $nsItunes->episode,
|
||||
'season_number' =>
|
||||
$this->request->getPost('season_number') === null
|
||||
? $nsItunes->season
|
||||
: $this->request->getPost('season_number'),
|
||||
$this->request->getPost('season_number') === null
|
||||
? $nsItunes->season
|
||||
: $this->request->getPost('season_number'),
|
||||
'type' =>
|
||||
$nsItunes->episodeType === null
|
||||
? 'full'
|
||||
: $nsItunes->episodeType,
|
||||
$nsItunes->episodeType === null
|
||||
? 'full'
|
||||
: $nsItunes->episodeType,
|
||||
'is_blocked' =>
|
||||
$nsItunes->block === null
|
||||
? false
|
||||
: $nsItunes->block === 'yes',
|
||||
$nsItunes->block === null
|
||||
? false
|
||||
: $nsItunes->block === 'yes',
|
||||
'location_name' => $nsPodcast->location
|
||||
? $nsPodcast->location
|
||||
: null,
|
||||
'location_geo' =>
|
||||
!$nsPodcast->location ||
|
||||
!$nsPodcast->location ||
|
||||
$nsPodcast->location->attributes()['geo'] === null
|
||||
? null
|
||||
: $nsPodcast->location->attributes()['geo'],
|
||||
? null
|
||||
: $nsPodcast->location->attributes()['geo'],
|
||||
'location_osm_id' =>
|
||||
!$nsPodcast->location ||
|
||||
!$nsPodcast->location ||
|
||||
$nsPodcast->location->attributes()['osm'] === null
|
||||
? null
|
||||
: $nsPodcast->location->attributes()['osm'],
|
||||
? null
|
||||
: $nsPodcast->location->attributes()['osm'],
|
||||
'created_by' => user_id(),
|
||||
'updated_by' => user_id(),
|
||||
'published_at' => strtotime($item->pubDate),
|
||||
|
@ -434,46 +419,40 @@ class PodcastImportController extends BaseController
|
|||
}
|
||||
|
||||
foreach ($nsPodcast->person as $episodePerson) {
|
||||
$fullName = (string) $episodePerson;
|
||||
$personModel = new PersonModel();
|
||||
$newPersonId = null;
|
||||
if ($newPerson = $personModel->getPerson($episodePerson)) {
|
||||
if (($newPerson = $personModel->getPerson($fullName)) !== null) {
|
||||
$newPersonId = $newPerson->id;
|
||||
} elseif (
|
||||
!($newPersonId = $personModel->createPerson(
|
||||
$episodePerson,
|
||||
$episodePerson->attributes()['href'],
|
||||
$episodePerson->attributes()['img'],
|
||||
))
|
||||
) {
|
||||
return redirect()
|
||||
->back()
|
||||
->withInput()
|
||||
->with('errors', $personModel->errors());
|
||||
} else {
|
||||
$newEpisodePerson = new Person([
|
||||
'full_name' => $fullName,
|
||||
'slug' => slugify($fullName),
|
||||
'information_url' => $episodePerson->attributes()['href'],
|
||||
'image' => new Image(download_file($episodePerson->attributes()['img']))
|
||||
]);
|
||||
|
||||
if (!($newPersonId = $personModel->insert($newEpisodePerson))) {
|
||||
return redirect()
|
||||
->back()
|
||||
->withInput()
|
||||
->with('errors', $personModel->errors());
|
||||
}
|
||||
}
|
||||
|
||||
$personGroup =
|
||||
$episodePerson->attributes()['group'] === null
|
||||
? ['slug' => '']
|
||||
: ReversedTaxonomy::$taxonomy[
|
||||
strval($episodePerson->attributes()['group'])
|
||||
];
|
||||
? ['slug' => '']
|
||||
: ReversedTaxonomy::$taxonomy[strval($episodePerson->attributes()['group'])];
|
||||
$personRole =
|
||||
$episodePerson->attributes()['role'] === null ||
|
||||
$personGroup === null
|
||||
? ['slug' => '']
|
||||
: $personGroup['roles'][
|
||||
strval($episodePerson->attributes()['role'])
|
||||
];
|
||||
$newEpisodePerson = new PodcastPerson([
|
||||
'podcast_id' => $newPodcastId,
|
||||
'episode_id' => $newEpisodeId,
|
||||
'person_id' => $newPersonId,
|
||||
'person_group' => $personGroup['slug'],
|
||||
'person_role' => $personRole['slug'],
|
||||
]);
|
||||
? ['slug' => '']
|
||||
: $personGroup['roles'][strval($episodePerson->attributes()['role'])];
|
||||
|
||||
$episodePersonModel = new EpisodePersonModel();
|
||||
if (!$episodePersonModel->insert($newEpisodePerson)) {
|
||||
|
||||
$episodePersonModel = new PersonModel();
|
||||
if (!$episodePersonModel->addEpisodePerson($newPodcastId, $newEpisodeId, $newPersonId, $personGroup['slug'], $personRole['slug'])) {
|
||||
return redirect()
|
||||
->back()
|
||||
->withInput()
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
|
||||
namespace App\Controllers\Admin;
|
||||
|
||||
use CodeIgniter\HTTP\RedirectResponse;
|
||||
use App\Entities\Podcast;
|
||||
use CodeIgniter\Exceptions\PageNotFoundException;
|
||||
use App\Models\PodcastPersonModel;
|
||||
use App\Models\PodcastModel;
|
||||
use App\Models\PersonModel;
|
||||
|
||||
|
@ -21,13 +21,17 @@ class PodcastPersonController extends BaseController
|
|||
*/
|
||||
protected $podcast;
|
||||
|
||||
public function _remap($method, ...$params)
|
||||
public function _remap(string $method, string ...$params): mixed
|
||||
{
|
||||
if (count($params) === 0) {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
if ($this->podcast = (new PodcastModel())->getPodcastById($params[0])) {
|
||||
if (
|
||||
($this->podcast = (new PodcastModel())->getPodcastById(
|
||||
(int) $params[0],
|
||||
)) !== null
|
||||
) {
|
||||
unset($params[0]);
|
||||
return $this->$method(...$params);
|
||||
}
|
||||
|
@ -35,13 +39,13 @@ class PodcastPersonController extends BaseController
|
|||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
public function index()
|
||||
public function index(): string
|
||||
{
|
||||
helper('form');
|
||||
|
||||
$data = [
|
||||
'podcast' => $this->podcast,
|
||||
'podcastPersons' => (new PodcastPersonModel())->getPodcastPersons(
|
||||
'podcastPersons' => (new PersonModel())->getPodcastPersons(
|
||||
$this->podcast->id,
|
||||
),
|
||||
'personOptions' => (new PersonModel())->getPersonOptions(),
|
||||
|
@ -53,7 +57,7 @@ class PodcastPersonController extends BaseController
|
|||
return view('admin/podcast/person', $data);
|
||||
}
|
||||
|
||||
public function attemptAdd()
|
||||
public function attemptAdd(): RedirectResponse
|
||||
{
|
||||
$rules = [
|
||||
'person' => 'required',
|
||||
|
@ -66,7 +70,7 @@ class PodcastPersonController extends BaseController
|
|||
->with('errors', $this->validator->getErrors());
|
||||
}
|
||||
|
||||
(new PodcastPersonModel())->addPodcastPersons(
|
||||
(new PersonModel())->addPodcastPersons(
|
||||
$this->podcast->id,
|
||||
$this->request->getPost('person'),
|
||||
$this->request->getPost('person_group_role'),
|
||||
|
@ -75,9 +79,9 @@ class PodcastPersonController extends BaseController
|
|||
return redirect()->back();
|
||||
}
|
||||
|
||||
public function remove($podcastPersonId)
|
||||
public function remove(int $podcastPersonId): RedirectResponse
|
||||
{
|
||||
(new PodcastPersonModel())->removePodcastPersons(
|
||||
(new PersonModel())->removePodcastPersons(
|
||||
$this->podcast->id,
|
||||
$podcastPersonId,
|
||||
);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
namespace App\Controllers\Admin;
|
||||
|
||||
use CodeIgniter\HTTP\RedirectResponse;
|
||||
use App\Entities\Podcast;
|
||||
use CodeIgniter\Exceptions\PageNotFoundException;
|
||||
use App\Models\PlatformModel;
|
||||
|
@ -21,13 +22,17 @@ class PodcastPlatformController extends BaseController
|
|||
*/
|
||||
protected $podcast;
|
||||
|
||||
public function _remap($method, ...$params)
|
||||
public function _remap(string $method, string ...$params): mixed
|
||||
{
|
||||
if (count($params) === 0) {
|
||||
return $this->$method();
|
||||
}
|
||||
|
||||
if ($this->podcast = (new PodcastModel())->getPodcastById($params[0])) {
|
||||
if (
|
||||
($this->podcast = (new PodcastModel())->getPodcastById(
|
||||
(int) $params[0],
|
||||
)) !== null
|
||||
) {
|
||||
unset($params[0]);
|
||||
return $this->$method(...$params);
|
||||
}
|
||||
|
@ -35,12 +40,12 @@ class PodcastPlatformController extends BaseController
|
|||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
public function index()
|
||||
public function index(): string
|
||||
{
|
||||
return view('admin/podcast/platforms/dashboard');
|
||||
}
|
||||
|
||||
public function platforms($platformType)
|
||||
public function platforms(string $platformType): string
|
||||
{
|
||||
helper('form');
|
||||
|
||||
|
@ -57,8 +62,9 @@ class PodcastPlatformController extends BaseController
|
|||
return view('admin/podcast/platforms', $data);
|
||||
}
|
||||
|
||||
public function attemptPlatformsUpdate($platformType)
|
||||
{
|
||||
public function attemptPlatformsUpdate(
|
||||
string $platformType
|
||||
): RedirectResponse {
|
||||
$platformModel = new PlatformModel();
|
||||
$validation = Services::validation();
|
||||
|
||||
|
@ -105,8 +111,9 @@ class PodcastPlatformController extends BaseController
|
|||
->with('message', lang('Platforms.messages.updateSuccess'));
|
||||
}
|
||||
|
||||
public function removePodcastPlatform($platformSlug)
|
||||
{
|
||||
public function removePodcastPlatform(
|
||||
string $platformSlug
|
||||
): RedirectResponse {
|
||||
(new PlatformModel())->removePodcastPlatform(
|
||||
$this->podcast->id,
|
||||
$platformSlug,
|
||||
|
|
|
@ -12,6 +12,7 @@ use CodeIgniter\Exceptions\PageNotFoundException;
|
|||
use App\Authorization\GroupModel;
|
||||
use App\Entities\User;
|
||||
use App\Models\UserModel;
|
||||
use CodeIgniter\HTTP\RedirectResponse;
|
||||
use Config\Services;
|
||||
|
||||
class UserController extends BaseController
|
||||
|
@ -21,7 +22,7 @@ class UserController extends BaseController
|
|||
*/
|
||||
protected $user;
|
||||
|
||||
public function _remap($method, ...$params)
|
||||
public function _remap(string $method, string ...$params): mixed
|
||||
{
|
||||
if (count($params) === 0) {
|
||||
return $this->$method();
|
||||
|
@ -34,14 +35,14 @@ class UserController extends BaseController
|
|||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
public function list()
|
||||
public function list(): string
|
||||
{
|
||||
$data = ['users' => (new UserModel())->findAll()];
|
||||
|
||||
return view('admin/user/list', $data);
|
||||
}
|
||||
|
||||
public function view()
|
||||
public function view(): string
|
||||
{
|
||||
$data = ['user' => $this->user];
|
||||
|
||||
|
@ -49,7 +50,7 @@ class UserController extends BaseController
|
|||
return view('admin/user/view', $data);
|
||||
}
|
||||
|
||||
public function create()
|
||||
public function create(): string
|
||||
{
|
||||
helper('form');
|
||||
|
||||
|
@ -60,7 +61,7 @@ class UserController extends BaseController
|
|||
return view('admin/user/create', $data);
|
||||
}
|
||||
|
||||
public function attemptCreate()
|
||||
public function attemptCreate(): RedirectResponse
|
||||
{
|
||||
$userModel = new UserModel();
|
||||
|
||||
|
@ -108,7 +109,7 @@ class UserController extends BaseController
|
|||
);
|
||||
}
|
||||
|
||||
public function edit()
|
||||
public function edit(): string
|
||||
{
|
||||
helper('form');
|
||||
|
||||
|
@ -131,7 +132,7 @@ class UserController extends BaseController
|
|||
return view('admin/user/edit', $data);
|
||||
}
|
||||
|
||||
public function attemptEdit()
|
||||
public function attemptEdit(): RedirectResponse
|
||||
{
|
||||
$authorize = Services::authorization();
|
||||
|
||||
|
@ -149,7 +150,7 @@ class UserController extends BaseController
|
|||
);
|
||||
}
|
||||
|
||||
public function forcePassReset()
|
||||
public function forcePassReset(): RedirectResponse
|
||||
{
|
||||
$userModel = new UserModel();
|
||||
$this->user->forcePasswordReset();
|
||||
|
@ -171,7 +172,7 @@ class UserController extends BaseController
|
|||
);
|
||||
}
|
||||
|
||||
public function ban()
|
||||
public function ban(): RedirectResponse
|
||||
{
|
||||
$authorize = Services::authorization();
|
||||
if ($authorize->inGroup('superadmin', $this->user->id)) {
|
||||
|
@ -204,7 +205,7 @@ class UserController extends BaseController
|
|||
);
|
||||
}
|
||||
|
||||
public function unBan()
|
||||
public function unBan(): RedirectResponse
|
||||
{
|
||||
$userModel = new UserModel();
|
||||
$this->user->unBan();
|
||||
|
@ -225,7 +226,7 @@ class UserController extends BaseController
|
|||
);
|
||||
}
|
||||
|
||||
public function delete()
|
||||
public function delete(): RedirectResponse
|
||||
{
|
||||
$authorize = Services::authorization();
|
||||
if ($authorize->inGroup('superadmin', $this->user->id)) {
|
||||
|
|
|
@ -18,14 +18,14 @@ class AuthController extends MythAuthController
|
|||
* An array of helpers to be automatically loaded
|
||||
* upon class instantiation.
|
||||
*
|
||||
* @var array
|
||||
* @var string[]
|
||||
*/
|
||||
protected $helpers = ['components'];
|
||||
|
||||
/**
|
||||
* Attempt to register a new user.
|
||||
*/
|
||||
public function attemptRegister()
|
||||
public function attemptRegister(): RedirectResponse
|
||||
{
|
||||
// Check if registration is allowed
|
||||
if (!$this->config->allowRegistration) {
|
||||
|
@ -61,9 +61,9 @@ class AuthController extends MythAuthController
|
|||
);
|
||||
$user = new User($this->request->getPost($allowedPostFields));
|
||||
|
||||
$this->config->requireActivation !== false
|
||||
? $user->generateActivateHash()
|
||||
: $user->activate();
|
||||
$this->config->requireActivation === null
|
||||
? $user->activate()
|
||||
: $user->generateActivateHash();
|
||||
|
||||
// Ensure default group gets assigned if set
|
||||
if ($this->config->defaultUserGroup !== null) {
|
||||
|
@ -77,7 +77,7 @@ class AuthController extends MythAuthController
|
|||
->with('errors', $users->errors());
|
||||
}
|
||||
|
||||
if ($this->config->requireActivation !== false) {
|
||||
if ($this->config->requireActivation !== null) {
|
||||
$activator = service('activator');
|
||||
$sent = $activator->send($user);
|
||||
|
||||
|
@ -109,7 +109,7 @@ class AuthController extends MythAuthController
|
|||
*/
|
||||
public function attemptReset(): RedirectResponse
|
||||
{
|
||||
if ($this->config->activeResetter === false) {
|
||||
if ($this->config->activeResetter === null) {
|
||||
return redirect()
|
||||
->route('login')
|
||||
->with('error', lang('Auth.forgotDisabled'));
|
||||
|
@ -173,7 +173,7 @@ class AuthController extends MythAuthController
|
|||
->with('message', lang('Auth.resetSuccess'));
|
||||
}
|
||||
|
||||
public function attemptInteractAsActor()
|
||||
public function attemptInteractAsActor(): RedirectResponse
|
||||
{
|
||||
$rules = [
|
||||
'actor_id' => 'required|numeric',
|
||||
|
|
|
@ -24,7 +24,7 @@ class BaseController extends Controller
|
|||
* class instantiation. These helpers will be available
|
||||
* to all other controllers that extend BaseController.
|
||||
*
|
||||
* @var array
|
||||
* @var string[]
|
||||
*/
|
||||
protected $helpers = ['auth', 'svg', 'components', 'misc'];
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
namespace App\Controllers;
|
||||
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
use Config\Services;
|
||||
use Analytics\AnalyticsTrait;
|
||||
use App\Entities\Episode;
|
||||
use App\Entities\Podcast;
|
||||
|
@ -30,25 +32,25 @@ class EpisodeController extends BaseController
|
|||
*/
|
||||
protected $episode;
|
||||
|
||||
public function _remap($method, ...$params)
|
||||
public function _remap(string $method, string ...$params): mixed
|
||||
{
|
||||
if (count($params) < 2) {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
if (
|
||||
!($this->podcast = (new PodcastModel())->getPodcastByName(
|
||||
($this->podcast = (new PodcastModel())->getPodcastByName(
|
||||
$params[0],
|
||||
))
|
||||
)) === null
|
||||
) {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
if (
|
||||
$this->episode = (new EpisodeModel())->getEpisodeBySlug(
|
||||
($this->episode = (new EpisodeModel())->getEpisodeBySlug(
|
||||
$this->podcast->id,
|
||||
$params[1],
|
||||
)
|
||||
)) !== null
|
||||
) {
|
||||
unset($params[1]);
|
||||
unset($params[0]);
|
||||
|
@ -58,7 +60,7 @@ class EpisodeController extends BaseController
|
|||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
public function index()
|
||||
public function index(): string
|
||||
{
|
||||
// Prevent analytics hit when authenticated
|
||||
if (!can_user_interact()) {
|
||||
|
@ -71,17 +73,9 @@ class EpisodeController extends BaseController
|
|||
(can_user_interact() ? '_authenticated' : '');
|
||||
|
||||
if (!($cachedView = cache($cacheName))) {
|
||||
helper('persons');
|
||||
$episodePersons = [];
|
||||
construct_person_array($this->episode->persons, $episodePersons);
|
||||
$podcastPersons = [];
|
||||
construct_person_array($this->podcast->persons, $podcastPersons);
|
||||
|
||||
$data = [
|
||||
'podcast' => $this->podcast,
|
||||
'episode' => $this->episode,
|
||||
'episodePersons' => $episodePersons,
|
||||
'persons' => $podcastPersons,
|
||||
];
|
||||
|
||||
$secondsToNextUnpublishedEpisode = (new EpisodeModel())->getSecondsToNextUnpublishedEpisode(
|
||||
|
@ -91,22 +85,22 @@ class EpisodeController extends BaseController
|
|||
if (can_user_interact()) {
|
||||
helper('form');
|
||||
return view('podcast/episode_authenticated', $data);
|
||||
} else {
|
||||
// The page cache is set to a decade so it is deleted manually upon podcast update
|
||||
return view('podcast/episode', $data, [
|
||||
'cache' => $secondsToNextUnpublishedEpisode
|
||||
? $secondsToNextUnpublishedEpisode
|
||||
: DECADE,
|
||||
'cache_name' => $cacheName,
|
||||
]);
|
||||
}
|
||||
// The page cache is set to a decade so it is deleted manually upon podcast update
|
||||
return view('podcast/episode', $data, [
|
||||
'cache' => $secondsToNextUnpublishedEpisode
|
||||
? $secondsToNextUnpublishedEpisode
|
||||
: DECADE,
|
||||
'cache_name' => $cacheName,
|
||||
]);
|
||||
}
|
||||
|
||||
return $cachedView;
|
||||
}
|
||||
|
||||
public function embeddablePlayer($theme = 'light-transparent')
|
||||
{
|
||||
public function embeddablePlayer(
|
||||
string $theme = 'light-transparent'
|
||||
): string {
|
||||
header('Content-Security-Policy: frame-ancestors https://* http://*');
|
||||
|
||||
// Prevent analytics hit when authenticated
|
||||
|
@ -114,7 +108,7 @@ class EpisodeController extends BaseController
|
|||
$this->registerPodcastWebpageHit($this->episode->podcast_id);
|
||||
}
|
||||
|
||||
$session = \Config\Services::session();
|
||||
$session = Services::session();
|
||||
$session->start();
|
||||
if (isset($_SERVER['HTTP_REFERER'])) {
|
||||
$session->set(
|
||||
|
@ -152,7 +146,7 @@ class EpisodeController extends BaseController
|
|||
return $cachedView;
|
||||
}
|
||||
|
||||
public function oembedJSON()
|
||||
public function oembedJSON(): ResponseInterface
|
||||
{
|
||||
return $this->response->setJSON([
|
||||
'type' => 'rich',
|
||||
|
@ -174,7 +168,7 @@ class EpisodeController extends BaseController
|
|||
]);
|
||||
}
|
||||
|
||||
public function oembedXML()
|
||||
public function oembedXML(): ResponseInterface
|
||||
{
|
||||
$oembed = new SimpleXMLElement(
|
||||
"<?xml version='1.0' encoding='utf-8' standalone='yes'?><oembed></oembed>",
|
||||
|
|
|
@ -9,20 +9,18 @@
|
|||
namespace App\Controllers;
|
||||
|
||||
use App\Models\PodcastModel;
|
||||
use CodeIgniter\HTTP\RedirectResponse;
|
||||
|
||||
class HomeController extends BaseController
|
||||
{
|
||||
/**
|
||||
* @return RedirectResponse|string
|
||||
*/
|
||||
public function index()
|
||||
public function index(): RedirectResponse|string
|
||||
{
|
||||
$model = new PodcastModel();
|
||||
|
||||
$allPodcasts = $model->findAll();
|
||||
|
||||
// check if there's only one podcast to redirect user to it
|
||||
if (count($allPodcasts) == 1) {
|
||||
if (count($allPodcasts) === 1) {
|
||||
return redirect()->route('podcast-activity', [
|
||||
$allPodcasts[0]->name,
|
||||
]);
|
||||
|
|
|
@ -19,6 +19,7 @@ use Config\Database;
|
|||
use App\Entities\User;
|
||||
use App\Models\UserModel;
|
||||
use CodeIgniter\Controller;
|
||||
use CodeIgniter\HTTP\RedirectResponse;
|
||||
use Config\Services;
|
||||
use Dotenv\Dotenv;
|
||||
|
||||
|
@ -51,7 +52,14 @@ class InstallController extends Controller
|
|||
public function index(): string
|
||||
{
|
||||
if (!file_exists(ROOTPATH . '.env')) {
|
||||
$this->createEnv();
|
||||
// create empty .env file
|
||||
try {
|
||||
$envFile = fopen(ROOTPATH . '.env', 'w');
|
||||
fclose($envFile);
|
||||
} catch (Throwable) {
|
||||
// Could not create the .env file, redirect to a view with instructions on how to add it manually
|
||||
return view('install/manual_config');
|
||||
}
|
||||
}
|
||||
|
||||
// Check if .env has all required fields
|
||||
|
@ -85,7 +93,7 @@ class InstallController extends Controller
|
|||
|
||||
try {
|
||||
$dotenv->required('cache.handler');
|
||||
} catch (ValidationException $validationException) {
|
||||
} catch (ValidationException) {
|
||||
return $this->cacheConfig();
|
||||
}
|
||||
} else {
|
||||
|
@ -101,7 +109,7 @@ class InstallController extends Controller
|
|||
'database.default.DBPrefix',
|
||||
'cache.handler',
|
||||
]);
|
||||
} catch (ValidationException $e) {
|
||||
} catch (ValidationException) {
|
||||
return view('install/manual_config');
|
||||
}
|
||||
}
|
||||
|
@ -117,7 +125,7 @@ class InstallController extends Controller
|
|||
// if so, show a 404 page
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
} catch (DatabaseException $databaseException) {
|
||||
} catch (DatabaseException) {
|
||||
// Could not connect to the database
|
||||
// show database config view to fix value
|
||||
session()->setFlashdata(
|
||||
|
@ -137,28 +145,12 @@ class InstallController extends Controller
|
|||
return $this->createSuperAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the form to generate the .env config file for the instance.
|
||||
* @return mixed|void
|
||||
*/
|
||||
public function createEnv()
|
||||
{
|
||||
// create empty .env file
|
||||
try {
|
||||
$envFile = fopen(ROOTPATH . '.env', 'w');
|
||||
fclose($envFile);
|
||||
} catch (Throwable $throwable) {
|
||||
// Could not create the .env file, redirect to a view with manual instructions on how to add it
|
||||
return view('install/manual_config');
|
||||
}
|
||||
}
|
||||
|
||||
public function instanceConfig()
|
||||
public function instanceConfig(): string
|
||||
{
|
||||
return view('install/instance_config');
|
||||
}
|
||||
|
||||
public function attemptInstanceConfig()
|
||||
public function attemptInstanceConfig(): RedirectResponse
|
||||
{
|
||||
$rules = [
|
||||
'hostname' => 'required|validate_url',
|
||||
|
@ -198,12 +190,12 @@ class InstallController extends Controller
|
|||
);
|
||||
}
|
||||
|
||||
public function databaseConfig()
|
||||
public function databaseConfig(): string
|
||||
{
|
||||
return view('install/database_config');
|
||||
}
|
||||
|
||||
public function attemptDatabaseConfig()
|
||||
public function attemptDatabaseConfig(): RedirectResponse
|
||||
{
|
||||
$rules = [
|
||||
'db_hostname' => 'required',
|
||||
|
@ -236,12 +228,12 @@ class InstallController extends Controller
|
|||
return redirect()->back();
|
||||
}
|
||||
|
||||
public function cacheConfig()
|
||||
public function cacheConfig(): string
|
||||
{
|
||||
return view('install/cache_config');
|
||||
}
|
||||
|
||||
public function attemptCacheConfig()
|
||||
public function attemptCacheConfig(): RedirectResponse
|
||||
{
|
||||
$rules = [
|
||||
'cache_handler' => 'required',
|
||||
|
@ -288,7 +280,7 @@ class InstallController extends Controller
|
|||
/**
|
||||
* Returns the form to create a the first superadmin user for the instance.
|
||||
*/
|
||||
public function createSuperAdmin()
|
||||
public function createSuperAdmin(): string
|
||||
{
|
||||
return view('install/create_superadmin');
|
||||
}
|
||||
|
@ -298,7 +290,7 @@ class InstallController extends Controller
|
|||
*
|
||||
* After creation, user is redirected to login page to input its credentials.
|
||||
*/
|
||||
public function attemptCreateSuperAdmin()
|
||||
public function attemptCreateSuperAdmin(): RedirectResponse
|
||||
{
|
||||
$userModel = new UserModel();
|
||||
|
||||
|
@ -356,7 +348,7 @@ class InstallController extends Controller
|
|||
* writes config values in .env file
|
||||
* overwrites any existing key and appends new ones
|
||||
*
|
||||
* @param array $configData key/value config pairs
|
||||
* @param array<string, string> $configData key/value config pairs
|
||||
*/
|
||||
public static function writeEnv(array $configData): void
|
||||
{
|
||||
|
@ -370,7 +362,7 @@ class InstallController extends Controller
|
|||
$keyVal,
|
||||
&$replaced
|
||||
) {
|
||||
if (strpos($line, (string) $key) === 0) {
|
||||
if (str_starts_with($line, (string) $key)) {
|
||||
$replaced = true;
|
||||
return $keyVal;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
namespace App\Controllers;
|
||||
|
||||
use CodeIgniter\Exceptions\PageNotFoundException;
|
||||
use ActivityPub\Controllers\NoteController as ActivityPubNoteController;
|
||||
use ActivityPub\Entities\Note as ActivityPubNote;
|
||||
use Analytics\AnalyticsTrait;
|
||||
|
@ -34,24 +35,28 @@ class NoteController extends ActivityPubNoteController
|
|||
*/
|
||||
protected $actor;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
protected $helpers = ['auth', 'activitypub', 'svg', 'components', 'misc'];
|
||||
|
||||
public function _remap($method, ...$params)
|
||||
public function _remap(string $method, string ...$params): mixed
|
||||
{
|
||||
if (
|
||||
!($this->podcast = (new PodcastModel())->getPodcastByName(
|
||||
($this->podcast = (new PodcastModel())->getPodcastByName(
|
||||
$params[0],
|
||||
))
|
||||
)) === null
|
||||
) {
|
||||
throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
$this->actor = $this->podcast->actor;
|
||||
|
||||
if (count($params) > 1) {
|
||||
if (!($this->note = model('NoteModel')->getNoteById($params[1]))) {
|
||||
throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
if (
|
||||
count($params) > 1 &&
|
||||
!($this->note = model('NoteModel')->getNoteById($params[1]))
|
||||
) {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
unset($params[0]);
|
||||
unset($params[1]);
|
||||
|
@ -77,27 +82,21 @@ class NoteController extends ActivityPubNoteController
|
|||
);
|
||||
|
||||
if (!($cachedView = cache($cacheName))) {
|
||||
helper('persons');
|
||||
$persons = [];
|
||||
construct_person_array($this->podcast->persons, $persons);
|
||||
|
||||
$data = [
|
||||
'podcast' => $this->podcast,
|
||||
'actor' => $this->actor,
|
||||
'note' => $this->note,
|
||||
'persons' => $persons,
|
||||
];
|
||||
|
||||
// if user is logged in then send to the authenticated activity view
|
||||
if (can_user_interact()) {
|
||||
helper('form');
|
||||
return view('podcast/note_authenticated', $data);
|
||||
} else {
|
||||
return view('podcast/note', $data, [
|
||||
'cache' => DECADE,
|
||||
'cache_name' => $cacheName,
|
||||
]);
|
||||
}
|
||||
return view('podcast/note', $data, [
|
||||
'cache' => DECADE,
|
||||
'cache_name' => $cacheName,
|
||||
]);
|
||||
}
|
||||
|
||||
return $cachedView;
|
||||
|
@ -129,16 +128,13 @@ class NoteController extends ActivityPubNoteController
|
|||
$episodeUri = $this->request->getPost('episode_url');
|
||||
if (
|
||||
$episodeUri &&
|
||||
($params = extract_params_from_episode_uri(new URI($episodeUri)))
|
||||
($params = extract_params_from_episode_uri(new URI($episodeUri))) &&
|
||||
($episode = (new EpisodeModel())->getEpisodeBySlug(
|
||||
$params['podcastName'],
|
||||
$params['episodeSlug'],
|
||||
))
|
||||
) {
|
||||
if (
|
||||
$episode = (new EpisodeModel())->getEpisodeBySlug(
|
||||
$params['podcastName'],
|
||||
$params['episodeSlug'],
|
||||
)
|
||||
) {
|
||||
$newNote->episode_id = $episode->id;
|
||||
}
|
||||
$newNote->episode_id = $episode->id;
|
||||
}
|
||||
|
||||
$newNote->message = $message;
|
||||
|
@ -146,7 +142,7 @@ class NoteController extends ActivityPubNoteController
|
|||
if (
|
||||
!model('NoteModel')->addNote(
|
||||
$newNote,
|
||||
$newNote->episode_id ? false : true,
|
||||
!(bool) $newNote->episode_id,
|
||||
true,
|
||||
)
|
||||
) {
|
||||
|
|
|
@ -21,7 +21,7 @@ class PageController extends BaseController
|
|||
*/
|
||||
protected $page;
|
||||
|
||||
public function _remap($method, ...$params)
|
||||
public function _remap(string $method, string ...$params): mixed
|
||||
{
|
||||
if (count($params) === 0) {
|
||||
return $this->$method();
|
||||
|
@ -36,7 +36,7 @@ class PageController extends BaseController
|
|||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
public function index()
|
||||
public function index(): string
|
||||
{
|
||||
$cacheName = "page-{$this->page->slug}";
|
||||
if (!($found = cache($cacheName))) {
|
||||
|
@ -53,7 +53,7 @@ class PageController extends BaseController
|
|||
return $found;
|
||||
}
|
||||
|
||||
public function credits()
|
||||
public function credits(): string
|
||||
{
|
||||
$locale = service('request')->getLocale();
|
||||
$allPodcasts = (new PodcastModel())->findAll();
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
namespace App\Controllers;
|
||||
|
||||
use CodeIgniter\Exceptions\PageNotFoundException;
|
||||
use Analytics\AnalyticsTrait;
|
||||
use App\Entities\Podcast;
|
||||
use App\Models\EpisodeModel;
|
||||
|
@ -23,23 +24,25 @@ class PodcastController extends BaseController
|
|||
*/
|
||||
protected $podcast;
|
||||
|
||||
public function _remap($method, ...$params)
|
||||
public function _remap(string $method, string ...$params): mixed
|
||||
{
|
||||
if (count($params) === 0) {
|
||||
throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
if (
|
||||
$this->podcast = (new PodcastModel())->getPodcastByName($params[0])
|
||||
($this->podcast = (new PodcastModel())->getPodcastByName(
|
||||
$params[0],
|
||||
)) !== null
|
||||
) {
|
||||
unset($params[0]);
|
||||
return $this->$method(...$params);
|
||||
}
|
||||
|
||||
throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
public function activity()
|
||||
public function activity(): string
|
||||
{
|
||||
// Prevent analytics hit when authenticated
|
||||
if (!can_user_interact()) {
|
||||
|
@ -58,34 +61,28 @@ class PodcastController extends BaseController
|
|||
);
|
||||
|
||||
if (!($cachedView = cache($cacheName))) {
|
||||
helper('persons');
|
||||
$persons = [];
|
||||
construct_person_array($this->podcast->persons, $persons);
|
||||
|
||||
$data = [
|
||||
'podcast' => $this->podcast,
|
||||
'notes' => (new NoteModel())->getActorPublishedNotes(
|
||||
$this->podcast->actor_id,
|
||||
),
|
||||
'persons' => $persons,
|
||||
];
|
||||
|
||||
// if user is logged in then send to the authenticated activity view
|
||||
if (can_user_interact()) {
|
||||
helper('form');
|
||||
return view('podcast/activity_authenticated', $data);
|
||||
} else {
|
||||
return view('podcast/activity', $data, [
|
||||
'cache' => DECADE,
|
||||
'cache_name' => $cacheName,
|
||||
]);
|
||||
}
|
||||
return view('podcast/activity', $data, [
|
||||
'cache' => DECADE,
|
||||
'cache_name' => $cacheName,
|
||||
]);
|
||||
}
|
||||
|
||||
return $cachedView;
|
||||
}
|
||||
|
||||
public function episodes()
|
||||
public function episodes(): string
|
||||
{
|
||||
// Prevent analytics hit when authenticated
|
||||
if (!can_user_interact()) {
|
||||
|
@ -95,7 +92,7 @@ class PodcastController extends BaseController
|
|||
$yearQuery = $this->request->getGet('year');
|
||||
$seasonQuery = $this->request->getGet('season');
|
||||
|
||||
if (!$yearQuery and !$seasonQuery) {
|
||||
if (!$yearQuery && !$seasonQuery) {
|
||||
$defaultQuery = (new PodcastModel())->getDefaultQuery(
|
||||
$this->podcast->id,
|
||||
);
|
||||
|
@ -130,7 +127,7 @@ class PodcastController extends BaseController
|
|||
$episodesNavigation = [];
|
||||
$activeQuery = null;
|
||||
foreach ($years as $year) {
|
||||
$isActive = $yearQuery == $year['year'];
|
||||
$isActive = $yearQuery === $year['year'];
|
||||
if ($isActive) {
|
||||
$activeQuery = [
|
||||
'type' => 'year',
|
||||
|
@ -140,7 +137,7 @@ class PodcastController extends BaseController
|
|||
];
|
||||
}
|
||||
|
||||
array_push($episodesNavigation, [
|
||||
$episodesNavigation[] = [
|
||||
'label' => $year['year'],
|
||||
'number_of_episodes' => $year['number_of_episodes'],
|
||||
'route' =>
|
||||
|
@ -148,11 +145,11 @@ class PodcastController extends BaseController
|
|||
'?year=' .
|
||||
$year['year'],
|
||||
'is_active' => $isActive,
|
||||
]);
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($seasons as $season) {
|
||||
$isActive = $seasonQuery == $season['season_number'];
|
||||
$isActive = $seasonQuery === $season['season_number'];
|
||||
if ($isActive) {
|
||||
$activeQuery = [
|
||||
'type' => 'season',
|
||||
|
@ -164,7 +161,7 @@ class PodcastController extends BaseController
|
|||
];
|
||||
}
|
||||
|
||||
array_push($episodesNavigation, [
|
||||
$episodesNavigation[] = [
|
||||
'label' => lang('Podcast.season', [
|
||||
'seasonNumber' => $season['season_number'],
|
||||
]),
|
||||
|
@ -174,13 +171,9 @@ class PodcastController extends BaseController
|
|||
'?season=' .
|
||||
$season['season_number'],
|
||||
'is_active' => $isActive,
|
||||
]);
|
||||
];
|
||||
}
|
||||
|
||||
helper('persons');
|
||||
$persons = [];
|
||||
construct_person_array($this->podcast->persons, $persons);
|
||||
|
||||
$data = [
|
||||
'podcast' => $this->podcast,
|
||||
'episodesNav' => $episodesNavigation,
|
||||
|
@ -191,7 +184,6 @@ class PodcastController extends BaseController
|
|||
$yearQuery,
|
||||
$seasonQuery,
|
||||
),
|
||||
'persons' => $persons,
|
||||
];
|
||||
|
||||
$secondsToNextUnpublishedEpisode = (new EpisodeModel())->getSecondsToNextUnpublishedEpisode(
|
||||
|
@ -201,14 +193,13 @@ class PodcastController extends BaseController
|
|||
// if user is logged in then send to the authenticated episodes view
|
||||
if (can_user_interact()) {
|
||||
return view('podcast/episodes_authenticated', $data);
|
||||
} else {
|
||||
return view('podcast/episodes', $data, [
|
||||
'cache' => $secondsToNextUnpublishedEpisode
|
||||
? $secondsToNextUnpublishedEpisode
|
||||
: DECADE,
|
||||
'cache_name' => $cacheName,
|
||||
]);
|
||||
}
|
||||
return view('podcast/episodes', $data, [
|
||||
'cache' => $secondsToNextUnpublishedEpisode
|
||||
? $secondsToNextUnpublishedEpisode
|
||||
: DECADE,
|
||||
'cache_name' => $cacheName,
|
||||
]);
|
||||
}
|
||||
|
||||
return $cachedView;
|
||||
|
|
|
@ -123,7 +123,7 @@ class FakePodcastsAnalyticsSeeder extends Seeder
|
|||
: $city->subdivisions[0]->isoCode;
|
||||
$latitude = round($city->location->latitude, 3);
|
||||
$longitude = round($city->location->longitude, 3);
|
||||
} catch (AddressNotFoundException $addressNotFoundException) {
|
||||
} catch (AddressNotFoundException) {
|
||||
//Bad luck, bad IP, nothing to do.
|
||||
}
|
||||
|
||||
|
|
|
@ -18,15 +18,8 @@ use RuntimeException;
|
|||
*/
|
||||
class Actor extends ActivityPubActor
|
||||
{
|
||||
/**
|
||||
* @var Podcast|null
|
||||
*/
|
||||
protected $podcast;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
protected $is_podcast;
|
||||
protected ?Podcast $podcast;
|
||||
protected bool $is_podcast;
|
||||
|
||||
public function getIsPodcast(): bool
|
||||
{
|
||||
|
|
|
@ -21,10 +21,7 @@ use CodeIgniter\Entity\Entity;
|
|||
*/
|
||||
class Category extends Entity
|
||||
{
|
||||
/**
|
||||
* @var Category|null
|
||||
*/
|
||||
protected $parent;
|
||||
protected ?Category $parent;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
|
|
|
@ -16,7 +16,7 @@ use CodeIgniter\Entity\Entity;
|
|||
|
||||
/**
|
||||
* @property int $podcast_id
|
||||
* @property Podcast $podcast
|
||||
* @property Podcast|null $podcast
|
||||
* @property int|null $episode_id
|
||||
* @property Episode|null $episode
|
||||
* @property string $full_name
|
||||
|
@ -25,34 +25,15 @@ use CodeIgniter\Entity\Entity;
|
|||
* @property string $person_role
|
||||
* @property string $role_label
|
||||
* @property int $person_id
|
||||
* @property Person $person
|
||||
* @property Person|null $person
|
||||
*/
|
||||
class Credit extends Entity
|
||||
{
|
||||
/**
|
||||
* @var Person
|
||||
*/
|
||||
protected $person;
|
||||
|
||||
/**
|
||||
* @var Podcast
|
||||
*/
|
||||
protected $podcast;
|
||||
|
||||
/**
|
||||
* @var Episode|null
|
||||
*/
|
||||
protected $episode;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $group_label;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $role_label;
|
||||
protected ?Person $person;
|
||||
protected ?Podcast $podcast;
|
||||
protected ?Episode $episode;
|
||||
protected string $group_label;
|
||||
protected string $role_label;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
|
@ -66,7 +47,7 @@ class Credit extends Entity
|
|||
'person_role' => 'string',
|
||||
];
|
||||
|
||||
public function getPerson(): Person
|
||||
public function getPerson(): ?Person
|
||||
{
|
||||
if ($this->person_id === null) {
|
||||
throw new RuntimeException(
|
||||
|
@ -83,7 +64,7 @@ class Credit extends Entity
|
|||
return $this->person;
|
||||
}
|
||||
|
||||
public function getPodcast(): Podcast
|
||||
public function getPodcast(): ?Podcast
|
||||
{
|
||||
if ($this->podcast_id === null) {
|
||||
throw new RuntimeException(
|
||||
|
|
|
@ -12,8 +12,8 @@ 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 App\Models\PersonModel;
|
||||
use CodeIgniter\Entity\Entity;
|
||||
use CodeIgniter\Files\File;
|
||||
use CodeIgniter\HTTP\Files\UploadedFile;
|
||||
|
@ -39,7 +39,7 @@ use RuntimeException;
|
|||
* @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|null $description Holds text only description, striped of any markdown or html special characters
|
||||
* @property string $description_markdown
|
||||
* @property string $description_html
|
||||
* @property Image $image
|
||||
|
@ -75,101 +75,43 @@ use RuntimeException;
|
|||
* @property Time $updated_at;
|
||||
* @property Time|null $deleted_at;
|
||||
*
|
||||
* @property EpisodePerson[] $persons;
|
||||
* @property Person[] $persons;
|
||||
* @property Soundbite[] $soundbites;
|
||||
* @property string $embeddable_player_url;
|
||||
*/
|
||||
class Episode extends Entity
|
||||
{
|
||||
/**
|
||||
* @var Podcast
|
||||
*/
|
||||
protected $podcast;
|
||||
protected Podcast $podcast;
|
||||
protected string $link;
|
||||
protected File $audio_file;
|
||||
protected string $audio_file_url;
|
||||
protected string $audio_file_analytics_url;
|
||||
protected string $audio_file_web_url;
|
||||
protected string $audio_file_opengraph_url;
|
||||
protected string $embeddable_player_url;
|
||||
protected Image $image;
|
||||
protected ?string $description;
|
||||
protected File $transcript_file;
|
||||
protected File $chapters_file;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @var Person[]
|
||||
*/
|
||||
protected $link;
|
||||
|
||||
/**
|
||||
* @var File
|
||||
*/
|
||||
protected $audio_file;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $audio_file_url;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $audio_file_analytics_url;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $audio_file_web_url;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
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[]
|
||||
*/
|
||||
protected $persons;
|
||||
protected $persons = [];
|
||||
|
||||
/**
|
||||
* @var Soundbite[]
|
||||
*/
|
||||
protected $soundbites;
|
||||
protected $soundbites = [];
|
||||
|
||||
/**
|
||||
* @var Note[]
|
||||
*/
|
||||
protected $notes;
|
||||
protected $notes = [];
|
||||
|
||||
/**
|
||||
* @var Location|null
|
||||
*/
|
||||
protected $location;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $custom_rss_string;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $publication_status;
|
||||
protected ?Location $location;
|
||||
protected string $custom_rss_string;
|
||||
protected string $publication_status;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
|
@ -221,10 +163,8 @@ class Episode extends Entity
|
|||
|
||||
/**
|
||||
* Saves an episode image
|
||||
*
|
||||
* @param Image|null $image
|
||||
*/
|
||||
public function setImage($image = null): self
|
||||
public function setImage(?Image $image = null): static
|
||||
{
|
||||
if ($image === null) {
|
||||
return $this;
|
||||
|
@ -257,10 +197,8 @@ class Episode extends Entity
|
|||
|
||||
/**
|
||||
* Saves an audio file
|
||||
*
|
||||
* @param UploadedFile|File $audioFile
|
||||
*/
|
||||
public function setAudioFile($audioFile)
|
||||
public function setAudioFile(UploadedFile|File $audioFile): static
|
||||
{
|
||||
helper(['media', 'id3']);
|
||||
|
||||
|
@ -283,10 +221,8 @@ class Episode extends Entity
|
|||
|
||||
/**
|
||||
* Saves an episode transcript file
|
||||
*
|
||||
* @param UploadedFile|File $transcriptFile
|
||||
*/
|
||||
public function setTranscriptFile($transcriptFile)
|
||||
public function setTranscriptFile(UploadedFile|File $transcriptFile): static
|
||||
{
|
||||
helper('media');
|
||||
|
||||
|
@ -301,10 +237,8 @@ class Episode extends Entity
|
|||
|
||||
/**
|
||||
* Saves an episode chapters file
|
||||
*
|
||||
* @param UploadedFile|File $chaptersFile
|
||||
*/
|
||||
public function setChaptersFile($chaptersFile)
|
||||
public function setChaptersFile(UploadedFile|File $chaptersFile): static
|
||||
{
|
||||
helper('media');
|
||||
|
||||
|
@ -390,9 +324,8 @@ class Episode extends Entity
|
|||
{
|
||||
if ($this->attributes['transcript_file_path']) {
|
||||
return media_base_url($this->attributes['transcript_file_path']);
|
||||
} else {
|
||||
return $this->attributes['transcript_file_remote_url'];
|
||||
}
|
||||
return $this->attributes['transcript_file_remote_url'];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -411,7 +344,7 @@ class Episode extends Entity
|
|||
/**
|
||||
* Returns the episode's persons
|
||||
*
|
||||
* @return EpisodePerson[]
|
||||
* @return Person[]
|
||||
*/
|
||||
public function getPersons(): array
|
||||
{
|
||||
|
@ -422,7 +355,7 @@ class Episode extends Entity
|
|||
}
|
||||
|
||||
if (empty($this->persons)) {
|
||||
$this->persons = (new EpisodePersonModel())->getEpisodePersons(
|
||||
$this->persons = (new PersonModel())->getEpisodePersons(
|
||||
$this->podcast_id,
|
||||
$this->id,
|
||||
);
|
||||
|
@ -483,7 +416,7 @@ class Episode extends Entity
|
|||
);
|
||||
}
|
||||
|
||||
public function getEmbeddablePlayerUrl($theme = null): string
|
||||
public function getEmbeddablePlayerUrl(string $theme = null): string
|
||||
{
|
||||
return base_url(
|
||||
$theme
|
||||
|
@ -501,25 +434,21 @@ class Episode extends Entity
|
|||
);
|
||||
}
|
||||
|
||||
public function setGuid(?string $guid = null)
|
||||
public function setGuid(?string $guid = null): static
|
||||
{
|
||||
if ($guid === null) {
|
||||
$this->attributes['guid'] = $this->getLink();
|
||||
} else {
|
||||
$this->attributes['guid'] = $guid;
|
||||
}
|
||||
$this->attributes['guid'] = $guid === null ? $this->getLink() : $guid;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPodcast(): Podcast
|
||||
public function getPodcast(): ?Podcast
|
||||
{
|
||||
return (new PodcastModel())->getPodcastById(
|
||||
$this->attributes['podcast_id'],
|
||||
);
|
||||
}
|
||||
|
||||
public function setDescriptionMarkdown(string $descriptionMarkdown)
|
||||
public function setDescriptionMarkdown(string $descriptionMarkdown): static
|
||||
{
|
||||
$converter = new CommonMarkConverter([
|
||||
'html_input' => 'strip',
|
||||
|
@ -563,7 +492,7 @@ class Episode extends Entity
|
|||
if ($this->description === null) {
|
||||
$this->description = trim(
|
||||
preg_replace(
|
||||
'/\s+/',
|
||||
'~\s+~',
|
||||
' ',
|
||||
strip_tags($this->attributes['description_html']),
|
||||
),
|
||||
|
@ -575,11 +504,11 @@ class Episode extends Entity
|
|||
|
||||
public function getPublicationStatus(): string
|
||||
{
|
||||
if ($this->publication_status) {
|
||||
if ($this->publication_status !== '') {
|
||||
return $this->publication_status;
|
||||
}
|
||||
|
||||
if (!$this->published_at) {
|
||||
if ($this->published_at === null) {
|
||||
return 'not_published';
|
||||
}
|
||||
|
||||
|
@ -594,7 +523,7 @@ class Episode extends Entity
|
|||
/**
|
||||
* Saves the location name and fetches OpenStreetMap info
|
||||
*/
|
||||
public function setLocation(?string $newLocationName = null)
|
||||
public function setLocation(?string $newLocationName = null): static
|
||||
{
|
||||
if ($newLocationName === null) {
|
||||
$this->attributes['location_name'] = null;
|
||||
|
@ -667,7 +596,7 @@ class Episode extends Entity
|
|||
/**
|
||||
* Saves custom rss tag into json
|
||||
*/
|
||||
function setCustomRssString(?string $customRssString = null)
|
||||
function setCustomRssString(?string $customRssString = null): static
|
||||
{
|
||||
if ($customRssString === null) {
|
||||
return $this;
|
||||
|
@ -709,19 +638,16 @@ class Episode extends Entity
|
|||
return $partnerLink;
|
||||
}
|
||||
|
||||
function getPartnerImageUrl($serviceSlug = null): string
|
||||
function getPartnerImageUrl(string $serviceSlug = null): string
|
||||
{
|
||||
$partnerImageUrl =
|
||||
rtrim($this->getPodcast()->partner_image_url, '/') .
|
||||
'?pid=' .
|
||||
$this->getPodcast()->partner_id .
|
||||
'&guid=' .
|
||||
urlencode($this->attributes['guid']);
|
||||
|
||||
if ($serviceSlug !== null) {
|
||||
$partnerImageUrl = '&_from=' . $serviceSlug;
|
||||
return '&_from=' . $serviceSlug;
|
||||
}
|
||||
|
||||
return $partnerImageUrl;
|
||||
return rtrim($this->getPodcast()->partner_image_url, '/') .
|
||||
'?pid=' .
|
||||
$this->getPodcast()->partner_id .
|
||||
'&guid=' .
|
||||
urlencode($this->attributes['guid']);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
*/
|
||||
|
||||
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
|
||||
{
|
||||
/**
|
||||
* @var Person
|
||||
*/
|
||||
protected $person;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'id' => 'integer',
|
||||
'podcast_id' => 'integer',
|
||||
'episode_id' => 'integer',
|
||||
'person_id' => 'integer',
|
||||
'person_group' => '?string',
|
||||
'person_role' => '?string',
|
||||
];
|
||||
|
||||
public function getPerson(): Person
|
||||
{
|
||||
return (new PersonModel())->getPersonById(
|
||||
$this->attributes['person_id'],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@ namespace App\Entities;
|
|||
|
||||
use CodeIgniter\Entity\Entity;
|
||||
use CodeIgniter\Files\File;
|
||||
use Config\Images as ImagesConfig;
|
||||
use Config\Images;
|
||||
use Config\Services;
|
||||
use RuntimeException;
|
||||
|
||||
|
@ -35,30 +35,11 @@ use RuntimeException;
|
|||
*/
|
||||
class Image extends Entity
|
||||
{
|
||||
/**
|
||||
* @var ImagesConfig
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var null|File
|
||||
*/
|
||||
protected $file;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $dirname;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $filename;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $extension;
|
||||
protected Images $config;
|
||||
protected ?File $file;
|
||||
protected string $dirname;
|
||||
protected string $filename;
|
||||
protected string $extension;
|
||||
|
||||
public function __construct(
|
||||
?File $file,
|
||||
|
|
|
@ -9,21 +9,23 @@
|
|||
namespace App\Entities;
|
||||
|
||||
use ActivityPub\Entities\Note as ActivityPubNote;
|
||||
use App\Models\ActorModel;
|
||||
use App\Models\EpisodeModel;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* @property int|null $episode_id
|
||||
* @property Episode|null $episode
|
||||
* @property Actor $actor
|
||||
* @property Note $reblog_of_note
|
||||
* @property Note $reply_to_note
|
||||
*/
|
||||
class Note extends ActivityPubNote
|
||||
{
|
||||
/**
|
||||
* @var Episode|null
|
||||
*/
|
||||
protected $episode;
|
||||
protected ?Episode $episode;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'id' => 'string',
|
||||
'uri' => 'string',
|
||||
|
@ -41,10 +43,8 @@ class Note extends ActivityPubNote
|
|||
|
||||
/**
|
||||
* Returns the note's attached episode
|
||||
*
|
||||
* @return \App\Entities\Episode
|
||||
*/
|
||||
public function getEpisode()
|
||||
public function getEpisode(): ?Episode
|
||||
{
|
||||
if ($this->episode_id === null) {
|
||||
throw new RuntimeException(
|
||||
|
|
|
@ -25,15 +25,8 @@ use League\CommonMark\CommonMarkConverter;
|
|||
*/
|
||||
class Page extends Entity
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $link;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $content_html;
|
||||
protected string $link;
|
||||
protected string $content_html;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
|
@ -51,7 +44,7 @@ class Page extends Entity
|
|||
return url_to('page', $this->attributes['slug']);
|
||||
}
|
||||
|
||||
public function setContentMarkdown(string $contentMarkdown): self
|
||||
public function setContentMarkdown(string $contentMarkdown): static
|
||||
{
|
||||
$converter = new CommonMarkConverter([
|
||||
'html_input' => 'strip',
|
||||
|
|
|
@ -20,13 +20,16 @@ use CodeIgniter\Entity\Entity;
|
|||
* @property string $image_mimetype
|
||||
* @property int $created_by
|
||||
* @property int $updated_by
|
||||
* @property string|null $group
|
||||
* @property string|null $role
|
||||
* @property Podcast|null $podcast
|
||||
* @property Episode|null $episode
|
||||
*/
|
||||
class Person extends Entity
|
||||
{
|
||||
/**
|
||||
* @var Image
|
||||
*/
|
||||
protected $image;
|
||||
protected Image $image;
|
||||
protected ?Podcast $podcast;
|
||||
protected ?Episode $episode;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
|
@ -38,6 +41,10 @@ class Person extends Entity
|
|||
'information_url' => '?string',
|
||||
'image_path' => 'string',
|
||||
'image_mimetype' => 'string',
|
||||
'podcast_id' => '?integer',
|
||||
'episode_id' => '?integer',
|
||||
'group' => '?string',
|
||||
'role' => '?string',
|
||||
'created_by' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
];
|
||||
|
@ -45,7 +52,7 @@ class Person extends Entity
|
|||
/**
|
||||
* Saves a picture in `public/media/persons/`
|
||||
*/
|
||||
public function setImage(Image $image): self
|
||||
public function setImage(Image $image): static
|
||||
{
|
||||
helper('media');
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@ namespace App\Entities;
|
|||
use App\Libraries\SimpleRSSElement;
|
||||
use App\Models\CategoryModel;
|
||||
use App\Models\EpisodeModel;
|
||||
use App\Models\PersonModel;
|
||||
use App\Models\PlatformModel;
|
||||
use App\Models\PodcastPersonModel;
|
||||
use CodeIgniter\Entity\Entity;
|
||||
use App\Models\UserModel;
|
||||
use CodeIgniter\I18n\Time;
|
||||
|
@ -22,7 +22,7 @@ use RuntimeException;
|
|||
/**
|
||||
* @property int $id
|
||||
* @property int $actor_id
|
||||
* @property Actor $actor
|
||||
* @property Actor|null $actor
|
||||
* @property string $name
|
||||
* @property string $link
|
||||
* @property string $feed_url
|
||||
|
@ -35,7 +35,7 @@ use RuntimeException;
|
|||
* @property string $image_mimetype
|
||||
* @property string $language_code
|
||||
* @property int $category_id
|
||||
* @property Category $category
|
||||
* @property Category|null $category
|
||||
* @property int[] $other_categories_ids
|
||||
* @property Category[] $other_categories
|
||||
* @property string|null $parental_advisory
|
||||
|
@ -68,7 +68,7 @@ use RuntimeException;
|
|||
* @property Time|null $deleted_at;
|
||||
*
|
||||
* @property Episode[] $episodes
|
||||
* @property PodcastPerson[] $persons
|
||||
* @property Person[] $persons
|
||||
* @property User[] $contributors
|
||||
* @property Platform[] $podcasting_platforms
|
||||
* @property Platform[] $social_platforms
|
||||
|
@ -77,80 +77,54 @@ use RuntimeException;
|
|||
*/
|
||||
class Podcast extends Entity
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $link;
|
||||
|
||||
/**
|
||||
* @var Actor
|
||||
*/
|
||||
protected $actor;
|
||||
|
||||
/**
|
||||
* @var Image
|
||||
*/
|
||||
protected $image;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $description;
|
||||
|
||||
/**
|
||||
* @var Category
|
||||
*/
|
||||
protected $category;
|
||||
protected string $link;
|
||||
protected ?Actor $actor;
|
||||
protected Image $image;
|
||||
protected string $description;
|
||||
protected ?Category $category;
|
||||
|
||||
/**
|
||||
* @var Category[]
|
||||
*/
|
||||
protected $other_categories;
|
||||
protected $other_categories = [];
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
protected $other_categories_ids;
|
||||
protected $other_categories_ids = [];
|
||||
|
||||
/**
|
||||
* @var Episode[]
|
||||
*/
|
||||
protected $episodes;
|
||||
protected $episodes = [];
|
||||
|
||||
/**
|
||||
* @var PodcastPerson[]
|
||||
* @var Person[]
|
||||
*/
|
||||
protected $persons;
|
||||
protected $persons = [];
|
||||
|
||||
/**
|
||||
* @var User[]
|
||||
*/
|
||||
protected $contributors;
|
||||
protected $contributors = [];
|
||||
|
||||
/**
|
||||
* @var Platform[]
|
||||
*/
|
||||
protected $podcasting_platforms;
|
||||
protected $podcasting_platforms = [];
|
||||
|
||||
/**
|
||||
* @var Platform[]
|
||||
*/
|
||||
protected $social_platforms;
|
||||
protected $social_platforms = [];
|
||||
|
||||
/**
|
||||
* @var Platform[]
|
||||
*/
|
||||
protected $funding_platforms;
|
||||
protected $funding_platforms = [];
|
||||
|
||||
/**
|
||||
* @var Location|null
|
||||
*/
|
||||
protected $location;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $custom_rss_string;
|
||||
protected ?Location $location;
|
||||
protected string $custom_rss_string;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
|
@ -193,7 +167,7 @@ class Podcast extends Entity
|
|||
|
||||
public function getActor(): Actor
|
||||
{
|
||||
if (!$this->actor_id) {
|
||||
if ($this->actor_id === 0) {
|
||||
throw new RuntimeException(
|
||||
'Podcast must have an actor_id before getting actor.',
|
||||
);
|
||||
|
@ -208,10 +182,8 @@ class Podcast extends Entity
|
|||
|
||||
/**
|
||||
* Saves a cover image to the corresponding podcast folder in `public/media/podcast_name/`
|
||||
*
|
||||
* @param Image $image
|
||||
*/
|
||||
public function setImage($image): self
|
||||
public function setImage(Image $image): static
|
||||
{
|
||||
// Save image
|
||||
$image->saveImage('podcasts/' . $this->attributes['name'], 'cover');
|
||||
|
@ -263,7 +235,7 @@ class Podcast extends Entity
|
|||
/**
|
||||
* Returns the podcast's persons
|
||||
*
|
||||
* @return PodcastPerson[]
|
||||
* @return Person[]
|
||||
*/
|
||||
public function getPersons(): array
|
||||
{
|
||||
|
@ -274,9 +246,7 @@ class Podcast extends Entity
|
|||
}
|
||||
|
||||
if (empty($this->persons)) {
|
||||
$this->persons = (new PodcastPersonModel())->getPodcastPersons(
|
||||
$this->id,
|
||||
);
|
||||
$this->persons = (new PersonModel())->getPodcastPersons($this->id);
|
||||
}
|
||||
|
||||
return $this->persons;
|
||||
|
@ -284,18 +254,16 @@ class Podcast extends Entity
|
|||
|
||||
/**
|
||||
* Returns the podcast category entity
|
||||
*
|
||||
* @return Category
|
||||
*/
|
||||
public function getCategory(): Category
|
||||
public function getCategory(): ?Category
|
||||
{
|
||||
if (empty($this->id)) {
|
||||
if ($this->id === null) {
|
||||
throw new RuntimeException(
|
||||
'Podcast must be created before getting category.',
|
||||
);
|
||||
}
|
||||
|
||||
if (empty($this->category)) {
|
||||
if ($this->category === null) {
|
||||
$this->category = (new CategoryModel())->getCategoryById(
|
||||
$this->category_id,
|
||||
);
|
||||
|
@ -326,7 +294,7 @@ class Podcast extends Entity
|
|||
return $this->contributors;
|
||||
}
|
||||
|
||||
public function setDescriptionMarkdown(string $descriptionMarkdown): self
|
||||
public function setDescriptionMarkdown(string $descriptionMarkdown): static
|
||||
{
|
||||
$converter = new CommonMarkConverter([
|
||||
'html_input' => 'strip',
|
||||
|
@ -343,7 +311,7 @@ class Podcast extends Entity
|
|||
|
||||
public function setEpisodeDescriptionFooterMarkdown(
|
||||
?string $episodeDescriptionFooterMarkdown = null
|
||||
): self {
|
||||
): static {
|
||||
if ($episodeDescriptionFooterMarkdown) {
|
||||
$converter = new CommonMarkConverter([
|
||||
'html_input' => 'strip',
|
||||
|
@ -363,13 +331,13 @@ class Podcast extends Entity
|
|||
|
||||
public function getDescription(): string
|
||||
{
|
||||
if ($this->description) {
|
||||
if ($this->description !== '') {
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
return trim(
|
||||
preg_replace(
|
||||
'/\s+/',
|
||||
'~\s+~',
|
||||
' ',
|
||||
strip_tags($this->attributes['description_html']),
|
||||
),
|
||||
|
@ -483,7 +451,7 @@ class Podcast extends Entity
|
|||
/**
|
||||
* Saves the location name and fetches OpenStreetMap info
|
||||
*/
|
||||
public function setLocation(?string $newLocationName = null)
|
||||
public function setLocation(?string $newLocationName = null): static
|
||||
{
|
||||
if ($newLocationName === null) {
|
||||
$this->attributes['location_name'] = null;
|
||||
|
@ -529,8 +497,6 @@ class Podcast extends Entity
|
|||
|
||||
/**
|
||||
* Get custom rss tag as XML String
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getCustomRssString(): string
|
||||
{
|
||||
|
@ -555,10 +521,8 @@ class Podcast extends Entity
|
|||
|
||||
/**
|
||||
* Saves custom rss tag into json
|
||||
*
|
||||
* @param string $customRssString
|
||||
*/
|
||||
function setCustomRssString($customRssString): self
|
||||
function setCustomRssString(string $customRssString): static
|
||||
{
|
||||
if (empty($customRssString)) {
|
||||
return $this;
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
*/
|
||||
|
||||
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
|
||||
{
|
||||
/**
|
||||
* @var Person
|
||||
*/
|
||||
protected $person;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'id' => 'integer',
|
||||
'podcast_id' => 'integer',
|
||||
'person_id' => 'integer',
|
||||
'person_group' => '?string',
|
||||
'person_role' => '?string',
|
||||
];
|
||||
|
||||
public function getPerson(): ?Person
|
||||
{
|
||||
return (new PersonModel())->getPersonById(
|
||||
$this->attributes['person_id'],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@ class PermissionFilter implements FilterInterface
|
|||
* sent back to the client, allowing for error pages,
|
||||
* redirects, etc.
|
||||
*
|
||||
* @param array|null $params
|
||||
* @param string[]|null $params
|
||||
* @return void|mixed
|
||||
*/
|
||||
public function before(RequestInterface $request, $params = null)
|
||||
|
@ -50,8 +50,8 @@ class PermissionFilter implements FilterInterface
|
|||
foreach ($params as $permission) {
|
||||
// check if permission is for a specific podcast
|
||||
if (
|
||||
(startsWith($permission, 'podcast-') ||
|
||||
startsWith($permission, 'podcast_episodes-')) &&
|
||||
(str_starts_with($permission, 'podcast-') ||
|
||||
str_starts_with($permission, 'podcast_episodes-')) &&
|
||||
count($routerParams) > 0
|
||||
) {
|
||||
if (
|
||||
|
@ -91,7 +91,7 @@ class PermissionFilter implements FilterInterface
|
|||
* to stop execution of other after filters, short of
|
||||
* throwing an Exception or Error.
|
||||
*
|
||||
* @param array|null $arguments
|
||||
* @param string[]|null $arguments
|
||||
*/
|
||||
public function after(
|
||||
RequestInterface $request,
|
||||
|
|
|
@ -27,7 +27,7 @@ if (!function_exists('set_interact_as_actor')) {
|
|||
/**
|
||||
* Sets the actor id of which the user is acting as
|
||||
*/
|
||||
function set_interact_as_actor($actorId): void
|
||||
function set_interact_as_actor(int $actorId): void
|
||||
{
|
||||
$authenticate = Services::authentication();
|
||||
$authenticate->check();
|
||||
|
@ -65,10 +65,8 @@ if (!function_exists('interact_as_actor_id')) {
|
|||
if (!function_exists('interact_as_actor')) {
|
||||
/**
|
||||
* Get the actor the user is currently interacting as
|
||||
*
|
||||
* @return Actor|false
|
||||
*/
|
||||
function interact_as_actor()
|
||||
function interact_as_actor(): Actor|false
|
||||
{
|
||||
$authenticate = Services::authentication();
|
||||
$authenticate->check();
|
||||
|
|
|
@ -23,7 +23,10 @@ if (!function_exists('render_breadcrumb')) {
|
|||
}
|
||||
|
||||
if (!function_exists('replace_breadcrumb_params')) {
|
||||
function replace_breadcrumb_params($newParams): void
|
||||
/**
|
||||
* @param string[] $newParams
|
||||
*/
|
||||
function replace_breadcrumb_params(array $newParams): void
|
||||
{
|
||||
$breadcrumb = Services::breadcrumb();
|
||||
$breadcrumb->replaceParams($newParams);
|
||||
|
|
|
@ -16,10 +16,8 @@ if (!function_exists('button')) {
|
|||
*
|
||||
* Creates a stylized button or button like anchor tag if the URL is defined.
|
||||
*
|
||||
* @param array $customOptions button options: variant, size, iconLeft, iconRight
|
||||
* @param array $customAttributes Additional attributes
|
||||
*
|
||||
* @return string
|
||||
* @param array<string, string|null|bool> $customOptions button options: variant, size, iconLeft, iconRight
|
||||
* @param array<string, string> $customAttributes Additional attributes
|
||||
*/
|
||||
function button(
|
||||
string $label = '',
|
||||
|
@ -130,10 +128,8 @@ if (!function_exists('icon_button')) {
|
|||
*
|
||||
* @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
|
||||
*
|
||||
* @return string
|
||||
* @param array<string, string|null|bool> $customOptions button options: variant, size, iconLeft, iconRight
|
||||
* @param array<string, string> $customAttributes Additional attributes
|
||||
*/
|
||||
function icon_button(
|
||||
string $icon,
|
||||
|
@ -167,8 +163,6 @@ if (!function_exists('hint_tooltip')) {
|
|||
* Used to produce tooltip with a question mark icon for hint texts
|
||||
*
|
||||
* @param string $hintText The hint text
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function hint_tooltip(string $hintText = '', string $class = ''): string
|
||||
{
|
||||
|
@ -193,11 +187,9 @@ if (!function_exists('data_table')) {
|
|||
*
|
||||
* Creates a stylized table.
|
||||
*
|
||||
* @param array $columns array of associate arrays with `header` and `cell` keys where `cell` is a function with a row of $data as parameter
|
||||
* @param array $data data to loop through and display in rows
|
||||
* @param array ...$rest Any other argument to pass to the `cell` function
|
||||
*
|
||||
* @return string
|
||||
* @param array<array<string, mixed>> $columns array of associate arrays with `header` and `cell` keys where `cell` is a function with a row of $data as parameter
|
||||
* @param mixed[] $data data to loop through and display in rows
|
||||
* @param mixed ...$rest Any other argument to pass to the `cell` function
|
||||
*/
|
||||
function data_table(array $columns, array $data = [], ...$rest): string
|
||||
{
|
||||
|
@ -252,8 +244,6 @@ if (!function_exists('publication_pill')) {
|
|||
* Publication pill component
|
||||
*
|
||||
* Shows the stylized publication datetime in regards to current datetime.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function publication_pill(
|
||||
?Time $publicationDate,
|
||||
|
@ -303,7 +293,6 @@ if (!function_exists('publication_button')) {
|
|||
* Displays the appropriate publication button depending on the publication status.
|
||||
*
|
||||
* @param boolean $publicationStatus the episode's publication status *
|
||||
* @return string
|
||||
*/
|
||||
function publication_button(
|
||||
int $podcastId,
|
||||
|
|
|
@ -15,9 +15,7 @@ if (!function_exists('form_section')) {
|
|||
*
|
||||
* @param string $title The section title
|
||||
* @param string $subtitle The section subtitle
|
||||
* @param array $attributes Additional attributes
|
||||
*
|
||||
* @return string
|
||||
* @param array<string, string> $attributes Additional attributes
|
||||
*/
|
||||
function form_section(
|
||||
string $title = '',
|
||||
|
@ -54,9 +52,7 @@ if (!function_exists('form_section_close')) {
|
|||
/**
|
||||
* Form Section close Tag
|
||||
*
|
||||
* @param string $extra
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function form_section_close(string $extra = ''): string
|
||||
{
|
||||
|
@ -72,10 +68,11 @@ if (!function_exists('form_switch')) {
|
|||
*
|
||||
* Abstracts form_label to stylize it as a switch toggle
|
||||
*
|
||||
* @return string
|
||||
* @param mixed[] $data
|
||||
* @param mixed[] $extra
|
||||
*/
|
||||
function form_switch(
|
||||
$label = '',
|
||||
string $label = '',
|
||||
array $data = [],
|
||||
string $value = '',
|
||||
bool $checked = false,
|
||||
|
@ -104,11 +101,9 @@ if (!function_exists('form_label')) {
|
|||
*
|
||||
* @param string $label_text The text to appear onscreen
|
||||
* @param string $id The id the label applies to
|
||||
* @param array $attributes Additional attributes
|
||||
* @param array<string, string> $attributes Additional attributes
|
||||
* @param string $hintText Hint text to add next to the label
|
||||
* @param boolean $isOptional adds an optional text if true
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function form_label(
|
||||
string $label_text = '',
|
||||
|
@ -151,7 +146,9 @@ if (!function_exists('form_multiselect')) {
|
|||
/**
|
||||
* Multi-select menu
|
||||
*
|
||||
* @return string
|
||||
* @param array<string, string> $options
|
||||
* @param string[] $selected
|
||||
* @param array<string, string> $customExtra
|
||||
*/
|
||||
function form_multiselect(
|
||||
string $name = '',
|
||||
|
|
|
@ -68,7 +68,7 @@ if (!function_exists('write_audio_file_tags')) {
|
|||
],
|
||||
'album' => [$episode->podcast->title],
|
||||
'year' => [
|
||||
$episode->published_at
|
||||
$episode->published_at !== null
|
||||
? $episode->published_at->format('Y')
|
||||
: '',
|
||||
],
|
||||
|
|
|
@ -11,6 +11,10 @@ use Config\Services;
|
|||
if (!function_exists('fetch_osm_location')) {
|
||||
/**
|
||||
* Fetches places from Nominatim OpenStreetMap
|
||||
*
|
||||
* TODO: move this to Location object?
|
||||
*
|
||||
* @return array<string, string>|null
|
||||
*/
|
||||
function fetch_osm_location(string $locationName): ?array
|
||||
{
|
||||
|
|
|
@ -20,7 +20,7 @@ if (!function_exists('save_media')) {
|
|||
function save_media(
|
||||
File $file,
|
||||
string $folder = '',
|
||||
string $filename
|
||||
string $filename = ''
|
||||
): string {
|
||||
if (($extension = $file->getExtension()) !== '') {
|
||||
$filename = $filename . '.' . $extension;
|
||||
|
@ -91,9 +91,9 @@ if (!function_exists('media_path')) {
|
|||
/**
|
||||
* Prefixes the root media path to a given uri
|
||||
*
|
||||
* @param string|array $uri URI string or array of URI segments
|
||||
* @param string|string[] $uri URI string or array of URI segments
|
||||
*/
|
||||
function media_path($uri = ''): string
|
||||
function media_path(string|array $uri = ''): string
|
||||
{
|
||||
// convert segment array to string
|
||||
if (is_array($uri)) {
|
||||
|
@ -109,9 +109,9 @@ if (!function_exists('media_base_url')) {
|
|||
/**
|
||||
* Return the media base URL to use in views
|
||||
*
|
||||
* @param string|string[] $uri URI string or array of URI segments
|
||||
* @param string|string[] $uri URI string or array of URI segments
|
||||
*/
|
||||
function media_base_url($uri = ''): string
|
||||
function media_base_url(string|array $uri = ''): string
|
||||
{
|
||||
// convert segment array to string
|
||||
if (is_array($uri)) {
|
||||
|
|
|
@ -23,23 +23,9 @@ if (!function_exists('get_browser_language')) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!function_exists('startsWith')) {
|
||||
/**
|
||||
* Check if a string starts with some characters
|
||||
*/
|
||||
function startsWith(string $string, string $query): bool
|
||||
{
|
||||
return substr($string, 0, strlen($query)) === $query;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('slugify')) {
|
||||
function slugify($text)
|
||||
function slugify(string $text): string
|
||||
{
|
||||
if (empty($text)) {
|
||||
return 'n-a';
|
||||
}
|
||||
|
||||
// replace non letter or digits by -
|
||||
$text = preg_replace('~[^\pL\d]+~u', '-', $text);
|
||||
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @copyright 2021 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @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 Person[]|PodcastPerson[]|EpisodePerson[] $persons
|
||||
*/
|
||||
function construct_person_array(array $persons, array &$personsArray): void
|
||||
{
|
||||
foreach ($persons as $person) {
|
||||
if (array_key_exists($person->id, $personsArray)) {
|
||||
$personsArray[$person->id]['roles'] .=
|
||||
empty($person->person_group) || empty($person->person_role)
|
||||
? ''
|
||||
: (empty($personsArray[$person->id]['roles'])
|
||||
? ''
|
||||
: ', ') .
|
||||
lang(
|
||||
'PersonsTaxonomy.persons.' .
|
||||
$person->person_group .
|
||||
'.roles.' .
|
||||
$person->person_role .
|
||||
'.label',
|
||||
);
|
||||
} else {
|
||||
$personsArray[$person->person->id] = [
|
||||
'full_name' => $person->person->full_name,
|
||||
'information_url' => $person->person->information_url,
|
||||
'thumbnail_url' => $person->person->image->thumbnail_url,
|
||||
'roles' =>
|
||||
empty($person->person_group) ||
|
||||
empty($person->person_role)
|
||||
? ''
|
||||
: lang(
|
||||
'PersonsTaxonomy.persons.' .
|
||||
$person->person_group .
|
||||
'.roles.' .
|
||||
$person->person_role .
|
||||
'.label',
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -187,19 +187,19 @@ if (!function_exists('get_rss_feed')) {
|
|||
foreach ($podcast->persons as $podcastPerson) {
|
||||
$podcastPersonElement = $channel->addChild(
|
||||
'person',
|
||||
htmlspecialchars($podcastPerson->person->full_name),
|
||||
htmlspecialchars($podcastPerson->full_name),
|
||||
$podcast_namespace,
|
||||
);
|
||||
|
||||
if (
|
||||
$podcastPerson->person_role !== null &&
|
||||
$podcastPerson->person_group !== null
|
||||
$podcastPerson->role !== null &&
|
||||
$podcastPerson->role !== null
|
||||
) {
|
||||
$podcastPersonElement->addAttribute(
|
||||
'role',
|
||||
htmlspecialchars(
|
||||
lang(
|
||||
"PersonsTaxonomy.persons.{$podcastPerson->person_group}.roles.{$podcastPerson->person_role}.label",
|
||||
"PersonsTaxonomy.persons.{$podcastPerson->group}.roles.{$podcastPerson->role}.label",
|
||||
[],
|
||||
'en',
|
||||
),
|
||||
|
@ -207,27 +207,28 @@ if (!function_exists('get_rss_feed')) {
|
|||
);
|
||||
}
|
||||
|
||||
if ($podcastPerson->person_group !== null) {
|
||||
if ($podcastPerson->group !== null) {
|
||||
$podcastPersonElement->addAttribute(
|
||||
'group',
|
||||
htmlspecialchars(
|
||||
lang(
|
||||
"PersonsTaxonomy.persons.{$podcastPerson->person_group}.label",
|
||||
"PersonsTaxonomy.persons.{$podcastPerson->group}.label",
|
||||
[],
|
||||
'en',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
$podcastPersonElement->addAttribute(
|
||||
'img',
|
||||
$podcastPerson->person->image->large_url,
|
||||
$podcastPerson->image->large_url,
|
||||
);
|
||||
|
||||
if ($podcastPerson->person->information_url !== null) {
|
||||
if ($podcastPerson->information_url !== null) {
|
||||
$podcastPersonElement->addAttribute(
|
||||
'href',
|
||||
$podcastPerson->person->information_url,
|
||||
$podcastPerson->information_url,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -417,18 +418,18 @@ if (!function_exists('get_rss_feed')) {
|
|||
foreach ($episode->persons as $episodePerson) {
|
||||
$episodePersonElement = $item->addChild(
|
||||
'person',
|
||||
htmlspecialchars($episodePerson->person->full_name),
|
||||
htmlspecialchars($episodePerson->full_name),
|
||||
$podcast_namespace,
|
||||
);
|
||||
if (
|
||||
!empty($episodePerson->person_role) &&
|
||||
!empty($episodePerson->person_group)
|
||||
!empty($episodePerson->role) &&
|
||||
!empty($episodePerson->group)
|
||||
) {
|
||||
$episodePersonElement->addAttribute(
|
||||
'role',
|
||||
htmlspecialchars(
|
||||
lang(
|
||||
"PersonsTaxonomy.persons.{$episodePerson->person_group}.roles.{$episodePerson->person_role}.label",
|
||||
"PersonsTaxonomy.persons.{$episodePerson->group}.roles.{$episodePerson->role}.label",
|
||||
[],
|
||||
'en',
|
||||
),
|
||||
|
@ -440,7 +441,7 @@ if (!function_exists('get_rss_feed')) {
|
|||
'group',
|
||||
htmlspecialchars(
|
||||
lang(
|
||||
"PersonsTaxonomy.persons.{$episodePerson->person_group}.label",
|
||||
"PersonsTaxonomy.persons.{$episodePerson->group}.label",
|
||||
[],
|
||||
'en',
|
||||
),
|
||||
|
@ -449,12 +450,12 @@ if (!function_exists('get_rss_feed')) {
|
|||
}
|
||||
$episodePersonElement->addAttribute(
|
||||
'img',
|
||||
$episodePerson->person->image->large_url,
|
||||
$episodePerson->image->large_url,
|
||||
);
|
||||
if (!empty($episodePerson->person->information_url)) {
|
||||
if (!empty($episodePerson->information_url)) {
|
||||
$episodePersonElement->addAttribute(
|
||||
'href',
|
||||
$episodePerson->person->information_url,
|
||||
$episodePerson->information_url,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -512,10 +513,11 @@ if (!function_exists('rss_to_array')) {
|
|||
/**
|
||||
* Converts XML to array
|
||||
*
|
||||
* FIXME: should be SimpleRSSElement
|
||||
* @param SimpleXMLElement $xmlNode
|
||||
* FIXME: param should be SimpleRSSElement
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
function rss_to_array(SimpleXMLElement $xmlNode): array
|
||||
function rss_to_array(SimpleXMLElement $rssNode): array
|
||||
{
|
||||
$nameSpaces = [
|
||||
'',
|
||||
|
@ -523,17 +525,17 @@ if (!function_exists('rss_to_array')) {
|
|||
'https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md',
|
||||
];
|
||||
$arrayNode = [];
|
||||
$arrayNode['name'] = $xmlNode->getName();
|
||||
$arrayNode['namespace'] = $xmlNode->getNamespaces(false);
|
||||
foreach ($xmlNode->attributes() as $key => $value) {
|
||||
$arrayNode['name'] = $rssNode->getName();
|
||||
$arrayNode['namespace'] = $rssNode->getNamespaces(false);
|
||||
foreach ($rssNode->attributes() as $key => $value) {
|
||||
$arrayNode['attributes'][$key] = (string) $value;
|
||||
}
|
||||
$textcontent = trim((string) $xmlNode);
|
||||
$textcontent = trim((string) $rssNode);
|
||||
if (strlen($textcontent) > 0) {
|
||||
$arrayNode['content'] = $textcontent;
|
||||
}
|
||||
foreach ($nameSpaces as $currentNameSpace) {
|
||||
foreach ($xmlNode->children($currentNameSpace) as $childXmlNode) {
|
||||
foreach ($rssNode->children($currentNameSpace) as $childXmlNode) {
|
||||
$arrayNode['elements'][] = rss_to_array($childXmlNode);
|
||||
}
|
||||
}
|
||||
|
@ -546,10 +548,13 @@ if (!function_exists('array_to_rss')) {
|
|||
/**
|
||||
* Inserts array (converted to XML node) in XML node
|
||||
*
|
||||
* @param array<string, mixed> $arrayNode
|
||||
* @param SimpleRSSElement $xmlNode The XML parent node where this arrayNode should be attached
|
||||
*/
|
||||
function array_to_rss(array $arrayNode, SimpleRSSElement &$xmlNode)
|
||||
{
|
||||
function array_to_rss(
|
||||
array $arrayNode,
|
||||
SimpleRSSElement &$xmlNode
|
||||
): SimpleRSSElement {
|
||||
if (array_key_exists('elements', $arrayNode)) {
|
||||
foreach ($arrayNode['elements'] as $childArrayNode) {
|
||||
$childXmlNode = $xmlNode->addChild(
|
||||
|
|
|
@ -47,7 +47,9 @@ if (!function_exists('current_season_url')) {
|
|||
|
||||
if (!function_exists('extract_params_from_episode_uri')) {
|
||||
/**
|
||||
* Returns podcast name and episode slug from episode string uri
|
||||
* Returns podcast name and episode slug from episode string
|
||||
*
|
||||
* @return array<string, string>|null
|
||||
*/
|
||||
function extract_params_from_episode_uri(URI $episodeUri): ?array
|
||||
{
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
namespace ActivityPub\Activities;
|
||||
|
||||
use ActivityPub\Core\Activity;
|
||||
use ActivityPub\Entities\Note;
|
||||
|
||||
class AnnounceActivity extends Activity
|
||||
{
|
||||
|
@ -22,7 +23,7 @@ class AnnounceActivity extends Activity
|
|||
*/
|
||||
protected $type = 'Announce';
|
||||
|
||||
public function __construct($reblogNote)
|
||||
public function __construct(Note $reblogNote)
|
||||
{
|
||||
$this->actor = $reblogNote->actor->uri;
|
||||
$this->object = $reblogNote->reblog_of_note->uri;
|
||||
|
|
|
@ -34,7 +34,7 @@ class ActivityRequest
|
|||
protected $activity;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* @var array<string, string[]>
|
||||
*/
|
||||
protected $options = [
|
||||
'headers' => [
|
||||
|
@ -71,7 +71,7 @@ class ActivityRequest
|
|||
($this->uri->getPort() ? ':' . $this->uri->getPort() : '');
|
||||
}
|
||||
|
||||
public function sign($keyId, $privateKey): void
|
||||
public function sign(string $keyId, string $privateKey): void
|
||||
{
|
||||
$rsa = new RSA();
|
||||
$rsa->loadKey($privateKey); // private key
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
namespace ActivityPub\Config;
|
||||
|
||||
use ActivityPub\Objects\ActorObject;
|
||||
use ActivityPub\Objects\NoteObject;
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
|
||||
class ActivityPub extends BaseConfig
|
||||
|
@ -18,12 +20,12 @@ class ActivityPub extends BaseConfig
|
|||
* --------------------------------------------------------------------
|
||||
* @var string
|
||||
*/
|
||||
public $actorObject = 'ActivityPub\Objects\ActorObject';
|
||||
public $actorObject = ActorObject::class;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $noteObject = 'ActivityPub\Objects\NoteObject';
|
||||
public $noteObject = NoteObject::class;
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------
|
||||
|
|
|
@ -41,7 +41,7 @@ class ActorController extends Controller
|
|||
$this->config = config('ActivityPub');
|
||||
}
|
||||
|
||||
public function _remap($method, ...$params)
|
||||
public function _remap(string $method, string ...$params): mixed
|
||||
{
|
||||
if (
|
||||
count($params) > 0 &&
|
||||
|
@ -301,10 +301,7 @@ class ActorController extends Controller
|
|||
->setBody($followersCollection->toJSON());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed|ResponseInterface
|
||||
*/
|
||||
public function attemptFollow()
|
||||
public function attemptFollow(): RedirectResponse|ResponseInterface
|
||||
{
|
||||
$rules = [
|
||||
'handle' =>
|
||||
|
@ -354,7 +351,7 @@ class ActorController extends Controller
|
|||
);
|
||||
}
|
||||
|
||||
public function activity($activityId): RedirectResponse
|
||||
public function activity(string $activityId): RedirectResponse
|
||||
{
|
||||
if (
|
||||
!($activity = model('ActivityModel')->getActivityById($activityId))
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
namespace ActivityPub\Controllers;
|
||||
|
||||
use CodeIgniter\HTTP\RedirectResponse;
|
||||
use CodeIgniter\Controller;
|
||||
|
||||
class BlockController extends Controller
|
||||
|
@ -17,7 +18,7 @@ class BlockController extends Controller
|
|||
*/
|
||||
protected $helpers = ['activitypub'];
|
||||
|
||||
public function attemptBlockActor()
|
||||
public function attemptBlockActor(): RedirectResponse
|
||||
{
|
||||
$rules = [
|
||||
'handle' => 'required',
|
||||
|
@ -51,7 +52,7 @@ class BlockController extends Controller
|
|||
return redirect()->back();
|
||||
}
|
||||
|
||||
function attemptBlockDomain()
|
||||
function attemptBlockDomain(): RedirectResponse
|
||||
{
|
||||
$rules = [
|
||||
'domain' => 'required',
|
||||
|
@ -71,7 +72,7 @@ class BlockController extends Controller
|
|||
return redirect()->back();
|
||||
}
|
||||
|
||||
function attemptUnblockActor()
|
||||
function attemptUnblockActor(): RedirectResponse
|
||||
{
|
||||
$rules = [
|
||||
'actor_id' => 'required',
|
||||
|
@ -89,7 +90,7 @@ class BlockController extends Controller
|
|||
return redirect()->back();
|
||||
}
|
||||
|
||||
function attemptUnblockDomain()
|
||||
function attemptUnblockDomain(): RedirectResponse
|
||||
{
|
||||
$rules = [
|
||||
'domain' => 'required',
|
||||
|
|
|
@ -41,7 +41,7 @@ class NoteController extends Controller
|
|||
$this->config = config('ActivityPub');
|
||||
}
|
||||
|
||||
public function _remap(string $method, string ...$params)
|
||||
public function _remap(string $method, string ...$params): mixed
|
||||
{
|
||||
if (!($this->note = model('NoteModel')->getNoteById($params[0]))) {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
|
@ -63,8 +63,7 @@ class NoteController extends Controller
|
|||
|
||||
public function replies(): RedirectResponse
|
||||
{
|
||||
/** get note replies
|
||||
* @var NoteModel */
|
||||
/** get note replies */
|
||||
$noteReplies = model('NoteModel')
|
||||
->where(
|
||||
'in_reply_to_id',
|
||||
|
@ -216,10 +215,7 @@ class NoteController extends Controller
|
|||
return redirect()->back();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed|ResponseInterface
|
||||
*/
|
||||
public function attemptRemoteAction(string $action)
|
||||
public function attemptRemoteAction(string $action): RedirectResponse|ResponseInterface
|
||||
{
|
||||
$rules = [
|
||||
'handle' =>
|
||||
|
|
|
@ -20,7 +20,7 @@ class WebFingerController extends Controller
|
|||
{
|
||||
try {
|
||||
$webfinger = new WebFinger($this->request->getGet('resource'));
|
||||
} catch (Exception $exception) {
|
||||
} catch (Exception) {
|
||||
// return 404, actor not found
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ abstract class AbstractObject
|
|||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function set(string $property, $value): self
|
||||
public function set(string $property, $value): static
|
||||
{
|
||||
$this->$property = $value;
|
||||
|
||||
|
@ -49,10 +49,7 @@ abstract class AbstractObject
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|bool
|
||||
*/
|
||||
public function toJSON()
|
||||
public function toJSON(): string|bool
|
||||
{
|
||||
return json_encode($this->toArray(), JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace ActivityPub\Core;
|
|||
class ObjectType extends AbstractObject
|
||||
{
|
||||
/**
|
||||
* @var array|string
|
||||
* @var string|string[]
|
||||
*/
|
||||
protected $context = 'https://www.w3.org/ns/activitystreams';
|
||||
|
||||
|
@ -41,12 +41,12 @@ class ObjectType extends AbstractObject
|
|||
protected $published;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* @var string[]
|
||||
*/
|
||||
protected $to = ['https://www.w3.org/ns/activitystreams#Public'];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* @var string[]
|
||||
*/
|
||||
protected $cc = [];
|
||||
}
|
||||
|
|
|
@ -243,7 +243,7 @@ class Note extends UuidEntity
|
|||
return $this->reblog_of_note;
|
||||
}
|
||||
|
||||
public function setMessage(string $message): self
|
||||
public function setMessage(string $message): static
|
||||
{
|
||||
helper('activitypub');
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ class ActivityPubFilter implements FilterInterface
|
|||
* sent back to the client, allowing for error pages,
|
||||
* redirects, etc.
|
||||
*
|
||||
* @param array|null $params
|
||||
* @param string[]|null $params
|
||||
* @return void|mixed
|
||||
*/
|
||||
public function before(RequestInterface $request, $params = null)
|
||||
|
@ -67,7 +67,7 @@ class ActivityPubFilter implements FilterInterface
|
|||
try {
|
||||
// securityCheck: check activity signature before handling it
|
||||
(new HttpSignature())->verify();
|
||||
} catch (Exception $exception) {
|
||||
} catch (Exception) {
|
||||
// Invalid HttpSignature (401 = unauthorized)
|
||||
// TODO: show error message?
|
||||
return service('response')->setStatusCode(401);
|
||||
|
@ -82,7 +82,7 @@ class ActivityPubFilter implements FilterInterface
|
|||
* to stop execution of other after filters, short of
|
||||
* throwing an Exception or Error.
|
||||
*
|
||||
* @param array|null $arguments
|
||||
* @param string[]|null $arguments
|
||||
*/
|
||||
public function after(
|
||||
RequestInterface $request,
|
||||
|
|
|
@ -18,8 +18,6 @@ use CodeIgniter\HTTP\Exceptions\HTTPException;
|
|||
if (!function_exists('get_webfinger_data')) {
|
||||
/**
|
||||
* Retrieve actor webfinger data from username and domain
|
||||
*
|
||||
* @return object|null
|
||||
*/
|
||||
function get_webfinger_data(string $username, string $domain): ?object
|
||||
{
|
||||
|
@ -45,8 +43,7 @@ if (!function_exists('split_handle')) {
|
|||
/**
|
||||
* Splits handle into its parts (username, host and port)
|
||||
*
|
||||
* @param string $handle
|
||||
* @return bool|array
|
||||
* @return array<string, string>|false
|
||||
*/
|
||||
function split_handle(string $handle)
|
||||
{
|
||||
|
@ -107,7 +104,7 @@ if (!function_exists('accept_follow')) {
|
|||
);
|
||||
$acceptRequest->sign($actor->public_key_id, $actor->private_key);
|
||||
$acceptRequest->post();
|
||||
} catch (Exception $exception) {
|
||||
} catch (Exception) {
|
||||
$db->transRollback();
|
||||
}
|
||||
|
||||
|
@ -163,8 +160,6 @@ if (!function_exists('extract_urls_from_message')) {
|
|||
if (!function_exists('create_preview_card_from_url')) {
|
||||
/**
|
||||
* Extract open graph metadata from given url and create preview card
|
||||
*
|
||||
* @return PreviewCard|null
|
||||
*/
|
||||
function create_preview_card_from_url(URI $url): ?PreviewCard
|
||||
{
|
||||
|
@ -223,8 +218,6 @@ if (!function_exists('create_preview_card_from_url')) {
|
|||
if (!function_exists('get_or_create_preview_card_from_url')) {
|
||||
/**
|
||||
* Extract open graph metadata from given url and create preview card
|
||||
*
|
||||
* @return PreviewCard|null
|
||||
*/
|
||||
function get_or_create_preview_card_from_url(URI $url): ?PreviewCard
|
||||
{
|
||||
|
@ -246,8 +239,6 @@ if (!function_exists('get_or_create_actor_from_uri')) {
|
|||
/**
|
||||
* Retrieves actor from database using the actor uri
|
||||
* If Actor is not present, it creates the record in the database and returns it.
|
||||
*
|
||||
* @return Actor|null
|
||||
*/
|
||||
function get_or_create_actor_from_uri(string $actorUri): ?Actor
|
||||
{
|
||||
|
@ -265,8 +256,6 @@ if (!function_exists('get_or_create_actor')) {
|
|||
/**
|
||||
* Retrieves actor from database using the actor username and domain
|
||||
* If actor is not present, it creates the record in the database and returns it.
|
||||
*
|
||||
* @return Actor|null
|
||||
*/
|
||||
function get_or_create_actor(string $username, string $domain): ?Actor
|
||||
{
|
||||
|
@ -292,8 +281,6 @@ if (!function_exists('create_actor_from_uri')) {
|
|||
/**
|
||||
* Creates actor record in database using
|
||||
* the info gathered from the actorUri parameter
|
||||
*
|
||||
* @return Actor|null
|
||||
*/
|
||||
function create_actor_from_uri(string $actorUri): ?Actor
|
||||
{
|
||||
|
@ -352,8 +339,6 @@ if (!function_exists('get_current_domain')) {
|
|||
if (!function_exists('extract_text_from_html')) {
|
||||
/**
|
||||
* Extracts the text from html content
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function extract_text_from_html(string $content): ?string
|
||||
{
|
||||
|
@ -381,7 +366,7 @@ if (!function_exists('linkify')) {
|
|||
case 'https':
|
||||
$text = preg_replace_callback(
|
||||
'~(?:(https?)://([^\s<]+)|(www\.[^\s<]+?\.[^\s<]+))(?<![\.,:])~i',
|
||||
function ($match) use ($protocol, &$links) {
|
||||
function (array $match) use ($protocol, &$links) {
|
||||
if ($match[1]) {
|
||||
$protocol = $match[1];
|
||||
}
|
||||
|
@ -452,7 +437,7 @@ if (!function_exists('linkify')) {
|
|||
]),
|
||||
) .
|
||||
'>';
|
||||
} catch (\CodeIgniter\HTTP\Exceptions\HTTPException $httpException) {
|
||||
} catch (\CodeIgniter\HTTP\Exceptions\HTTPException) {
|
||||
// Couldn't retrieve actor, do not wrap the text in link
|
||||
return '<' .
|
||||
array_push($links, $match[0]) .
|
||||
|
@ -485,7 +470,7 @@ if (!function_exists('linkify')) {
|
|||
'~' .
|
||||
preg_quote($protocol, '~') .
|
||||
'://([^\s<]+?)(?<![\.,:])~i',
|
||||
function ($match) use ($protocol, &$links) {
|
||||
function (array $match) use ($protocol, &$links) {
|
||||
return '<' .
|
||||
array_push(
|
||||
$links,
|
||||
|
|
|
@ -41,7 +41,7 @@ class HttpSignature
|
|||
/**
|
||||
* @var IncomingRequest
|
||||
*/
|
||||
protected $request;
|
||||
protected ?IncomingRequest $request;
|
||||
|
||||
public function __construct(IncomingRequest $request = null)
|
||||
{
|
||||
|
@ -130,9 +130,9 @@ class HttpSignature
|
|||
/**
|
||||
* Split HTTP signature into its parts (keyId, headers and signature)
|
||||
*
|
||||
* @return bool|mixed
|
||||
* @return array<string, string>|false
|
||||
*/
|
||||
private function splitSignature(string $signature)
|
||||
private function splitSignature(string $signature): array|false
|
||||
{
|
||||
if (!preg_match(self::SIGNATURE_PATTERN, $signature, $matches)) {
|
||||
// Signature pattern failed
|
||||
|
@ -150,7 +150,7 @@ class HttpSignature
|
|||
/**
|
||||
* Get plain text that has been originally signed
|
||||
*
|
||||
* @param array $headers HTTP header keys
|
||||
* @param string[] $headers HTTP header keys
|
||||
*/
|
||||
private function getPlainText(array $headers): string
|
||||
{
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace ActivityPub\Models;
|
|||
|
||||
use ActivityPub\Entities\Activity;
|
||||
use CodeIgniter\Database\BaseResult;
|
||||
use CodeIgniter\Database\Exceptions\DataException;
|
||||
use CodeIgniter\I18n\Time;
|
||||
use DateTimeInterface;
|
||||
use Michalsn\Uuid\UuidModel;
|
||||
|
@ -59,7 +60,7 @@ class ActivityModel extends UuidModel
|
|||
protected $useTimestamps = true;
|
||||
protected $updatedField;
|
||||
|
||||
public function getActivityById($activityId)
|
||||
public function getActivityById(string $activityId): ?Activity
|
||||
{
|
||||
$cacheName =
|
||||
config('ActivityPub')->cachePrefix . "activity#{$activityId}";
|
||||
|
@ -76,8 +77,6 @@ class ActivityModel extends UuidModel
|
|||
* Inserts a new activity record in the database
|
||||
*
|
||||
* @param Time $scheduledAt
|
||||
*
|
||||
* @return BaseResult|int|string|false
|
||||
*/
|
||||
public function newActivity(
|
||||
string $type,
|
||||
|
@ -87,7 +86,7 @@ class ActivityModel extends UuidModel
|
|||
string $payload,
|
||||
DateTimeInterface $scheduledAt = null,
|
||||
?string $status = null
|
||||
) {
|
||||
): BaseResult|int|string|false {
|
||||
return $this->insert(
|
||||
[
|
||||
'actor_id' => $actorId,
|
||||
|
@ -102,7 +101,10 @@ class ActivityModel extends UuidModel
|
|||
);
|
||||
}
|
||||
|
||||
public function getScheduledActivities()
|
||||
/**
|
||||
* @return Activity[]
|
||||
*/
|
||||
public function getScheduledActivities(): array
|
||||
{
|
||||
return $this->where('`scheduled_at` <= NOW()', null, false)
|
||||
->where('status', 'queued')
|
||||
|
|
|
@ -58,7 +58,7 @@ class ActorModel extends Model
|
|||
*/
|
||||
protected $useTimestamps = true;
|
||||
|
||||
public function getActorById($id): Actor
|
||||
public function getActorById(int $id): Actor
|
||||
{
|
||||
$cacheName = config('ActivityPub')->cachePrefix . "actor#{$id}";
|
||||
if (!($found = cache($cacheName))) {
|
||||
|
@ -98,7 +98,7 @@ class ActorModel extends Model
|
|||
return $found;
|
||||
}
|
||||
|
||||
public function getActorByUri($actorUri)
|
||||
public function getActorByUri(string $actorUri): ?Actor
|
||||
{
|
||||
$hashedActorUri = md5($actorUri);
|
||||
$cacheName =
|
||||
|
@ -112,7 +112,10 @@ class ActorModel extends Model
|
|||
return $found;
|
||||
}
|
||||
|
||||
public function getFollowers($actorId)
|
||||
/**
|
||||
* @return Actor[]
|
||||
*/
|
||||
public function getFollowers(int $actorId): array
|
||||
{
|
||||
$cacheName =
|
||||
config('ActivityPub')->cachePrefix . "actor#{$actorId}_followers";
|
||||
|
@ -137,7 +140,7 @@ class ActorModel extends Model
|
|||
*/
|
||||
public function isActorBlocked(string $actorUri): bool
|
||||
{
|
||||
if ($actor = $this->getActorByUri($actorUri)) {
|
||||
if (($actor = $this->getActorByUri($actorUri)) !== null) {
|
||||
return $actor->is_blocked;
|
||||
}
|
||||
|
||||
|
@ -161,7 +164,7 @@ class ActorModel extends Model
|
|||
return $found;
|
||||
}
|
||||
|
||||
public function blockActor($actorId): void
|
||||
public function blockActor(int $actorId): void
|
||||
{
|
||||
$prefix = config('ActivityPub')->cachePrefix;
|
||||
cache()->delete($prefix . 'blocked_actors');
|
||||
|
@ -172,7 +175,7 @@ class ActorModel extends Model
|
|||
$this->update($actorId, ['is_blocked' => 1]);
|
||||
}
|
||||
|
||||
public function unblockActor($actorId): void
|
||||
public function unblockActor(int $actorId): void
|
||||
{
|
||||
$prefix = config('ActivityPub')->cachePrefix;
|
||||
cache()->delete($prefix . 'blocked_actors');
|
||||
|
|
|
@ -49,8 +49,10 @@ class BlockedDomainModel extends Model
|
|||
|
||||
/**
|
||||
* Retrieves instance or podcast domain blocks depending on whether or not $podcastId param is set.
|
||||
*
|
||||
* @return BlockedDomain[]
|
||||
*/
|
||||
public function getBlockedDomains()
|
||||
public function getBlockedDomains(): array
|
||||
{
|
||||
$cacheName = config('ActivityPub')->cachePrefix . 'blocked_domains';
|
||||
if (!($found = cache($cacheName))) {
|
||||
|
@ -61,14 +63,14 @@ class BlockedDomainModel extends Model
|
|||
return $found;
|
||||
}
|
||||
|
||||
public function isDomainBlocked($domain)
|
||||
public function isDomainBlocked(string $name): bool
|
||||
{
|
||||
$hashedDomain = md5($domain);
|
||||
$hashedDomainName = md5($name);
|
||||
$cacheName =
|
||||
config('ActivityPub')->cachePrefix .
|
||||
"domain#{$hashedDomain}_isBlocked";
|
||||
"domain#{$hashedDomainName}_isBlocked";
|
||||
if (!($found = cache($cacheName))) {
|
||||
$found = (bool) $this->find($domain);
|
||||
$found = (bool) $this->find($name);
|
||||
|
||||
cache()->save($cacheName, $found, DECADE);
|
||||
}
|
||||
|
@ -76,7 +78,7 @@ class BlockedDomainModel extends Model
|
|||
return $found;
|
||||
}
|
||||
|
||||
public function blockDomain($name)
|
||||
public function blockDomain(string $name): int|bool
|
||||
{
|
||||
$hashedDomain = md5($name);
|
||||
$prefix = config('ActivityPub')->cachePrefix;
|
||||
|
@ -104,10 +106,7 @@ class BlockedDomainModel extends Model
|
|||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|BaseResult
|
||||
*/
|
||||
public function unblockDomain($name)
|
||||
public function unblockDomain(string $name): BaseResult|bool
|
||||
{
|
||||
$hashedDomain = md5($name);
|
||||
$prefix = config('ActivityPub')->cachePrefix;
|
||||
|
|
|
@ -109,9 +109,9 @@ class FavouriteModel extends UuidModel
|
|||
}
|
||||
|
||||
public function removeFavourite(
|
||||
$actor,
|
||||
$note,
|
||||
$registerActivity = true
|
||||
Actor $actor,
|
||||
Note $note,
|
||||
bool $registerActivity = true
|
||||
): void {
|
||||
$this->db->transStart();
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ class FollowModel extends Model
|
|||
}
|
||||
|
||||
$this->db->transComplete();
|
||||
} catch (Exception $exception) {
|
||||
} catch (Exception) {
|
||||
// follow already exists, do nothing
|
||||
}
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ class FollowModel extends Model
|
|||
public function removeFollower(
|
||||
Actor $actor,
|
||||
Actor $targetActor,
|
||||
$registerActivity = true
|
||||
bool $registerActivity = true
|
||||
): void {
|
||||
$this->db->transStart();
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@ use CodeIgniter\Database\BaseResult;
|
|||
use CodeIgniter\Events\Events;
|
||||
use CodeIgniter\HTTP\URI;
|
||||
use CodeIgniter\I18n\Time;
|
||||
use CodeIgniter\Router\Exceptions\RouterException;
|
||||
use InvalidArgumentException;
|
||||
use Michalsn\Uuid\UuidModel;
|
||||
|
||||
class NoteModel extends UuidModel
|
||||
|
@ -86,7 +88,7 @@ class NoteModel extends UuidModel
|
|||
*/
|
||||
protected $beforeInsert = ['setNoteId'];
|
||||
|
||||
public function getNoteById($noteId)
|
||||
public function getNoteById(string $noteId): ?Note
|
||||
{
|
||||
$cacheName = config('ActivityPub')->cachePrefix . "note#{$noteId}";
|
||||
if (!($found = cache($cacheName))) {
|
||||
|
@ -98,7 +100,7 @@ class NoteModel extends UuidModel
|
|||
return $found;
|
||||
}
|
||||
|
||||
public function getNoteByUri($noteUri)
|
||||
public function getNoteByUri(string $noteUri): ?Note
|
||||
{
|
||||
$hashedNoteUri = md5($noteUri);
|
||||
$cacheName =
|
||||
|
@ -117,7 +119,7 @@ class NoteModel extends UuidModel
|
|||
*
|
||||
* @return Note[]
|
||||
*/
|
||||
public function getActorPublishedNotes($actorId): array
|
||||
public function getActorPublishedNotes(int $actorId): array
|
||||
{
|
||||
$cacheName =
|
||||
config('ActivityPub')->cachePrefix .
|
||||
|
@ -179,8 +181,10 @@ class NoteModel extends UuidModel
|
|||
|
||||
/**
|
||||
* Retrieves all published reblogs for a given note
|
||||
*
|
||||
* @return Note[]
|
||||
*/
|
||||
public function getNoteReblogs($noteId)
|
||||
public function getNoteReblogs(string $noteId): array
|
||||
{
|
||||
$cacheName =
|
||||
config('ActivityPub')->cachePrefix . "note#{$noteId}_reblogs";
|
||||
|
@ -200,10 +204,7 @@ class NoteModel extends UuidModel
|
|||
return $found;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|Query
|
||||
*/
|
||||
public function addPreviewCard($noteId, $previewCardId)
|
||||
public function addPreviewCard(string $noteId, int $previewCardId): Query|bool
|
||||
{
|
||||
return $this->db->table('activitypub_notes_preview_cards')->insert([
|
||||
'note_id' => $this->uuid->fromString($noteId)->getBytes(),
|
||||
|
@ -220,7 +221,7 @@ class NoteModel extends UuidModel
|
|||
Note $note,
|
||||
bool $createPreviewCard = true,
|
||||
bool $registerActivity = true
|
||||
) {
|
||||
): string|false {
|
||||
helper('activitypub');
|
||||
|
||||
$this->db->transStart();
|
||||
|
@ -301,7 +302,7 @@ class NoteModel extends UuidModel
|
|||
return $newNoteId;
|
||||
}
|
||||
|
||||
public function editNote($updatedNote): bool
|
||||
public function editNote(Note $updatedNote): bool
|
||||
{
|
||||
$this->db->transStart();
|
||||
|
||||
|
@ -341,10 +342,8 @@ class NoteModel extends UuidModel
|
|||
|
||||
/**
|
||||
* Removes a note from the database and decrements meta data
|
||||
*
|
||||
* @return BaseResult|bool
|
||||
*/
|
||||
public function removeNote(Note $note, bool $registerActivity = true)
|
||||
public function removeNote(Note $note, bool $registerActivity = true): BaseResult|bool
|
||||
{
|
||||
$this->db->transStart();
|
||||
|
||||
|
@ -450,14 +449,11 @@ class NoteModel extends UuidModel
|
|||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|bool
|
||||
*/
|
||||
public function addReply(
|
||||
$reply,
|
||||
$createPreviewCard = true,
|
||||
$registerActivity = true
|
||||
) {
|
||||
Note $reply,
|
||||
bool $createPreviewCard = true,
|
||||
bool $registerActivity = true
|
||||
): string|false {
|
||||
if (!$reply->in_reply_to_id) {
|
||||
throw new Exception('Passed note is not a reply!');
|
||||
}
|
||||
|
@ -489,10 +485,7 @@ class NoteModel extends UuidModel
|
|||
return $noteId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BaseResult|int|string|false
|
||||
*/
|
||||
public function reblog(Actor $actor, Note $note, $registerActivity = true)
|
||||
public function reblog(Actor $actor, Note $note, bool $registerActivity = true): string|false
|
||||
{
|
||||
$this->db->transStart();
|
||||
|
||||
|
@ -503,7 +496,7 @@ class NoteModel extends UuidModel
|
|||
]);
|
||||
|
||||
// add reblog
|
||||
$reblogId = $this->insert($reblog, true);
|
||||
$reblogId = $this->insert($reblog);
|
||||
|
||||
model('ActorModel')
|
||||
->where('id', $actor->id)
|
||||
|
@ -554,10 +547,7 @@ class NoteModel extends UuidModel
|
|||
return $reblogId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BaseResult|bool
|
||||
*/
|
||||
public function undoReblog(Note $reblogNote, bool $registerActivity = true)
|
||||
public function undoReblog(Note $reblogNote, bool $registerActivity = true): BaseResult|bool
|
||||
{
|
||||
$this->db->transStart();
|
||||
|
||||
|
@ -649,7 +639,7 @@ class NoteModel extends UuidModel
|
|||
return $result;
|
||||
}
|
||||
|
||||
public function toggleReblog($actor, $note): void
|
||||
public function toggleReblog(Actor $actor, Note $note): void
|
||||
{
|
||||
if (
|
||||
!($reblogNote = $this->where([
|
||||
|
@ -665,7 +655,11 @@ class NoteModel extends UuidModel
|
|||
}
|
||||
}
|
||||
|
||||
protected function setNoteId($data)
|
||||
/**
|
||||
* @param array<string, array<string|int, mixed>> $data
|
||||
* @return array<string, array<string|int, mixed>>
|
||||
*/
|
||||
protected function setNoteId(array $data): array
|
||||
{
|
||||
$uuid4 = $this->uuid->{$this->uuidVersion}();
|
||||
$data['data']['id'] = $uuid4->toString();
|
||||
|
|
|
@ -51,7 +51,7 @@ class PreviewCardModel extends Model
|
|||
*/
|
||||
protected $useTimestamps = true;
|
||||
|
||||
public function getPreviewCardFromUrl($url)
|
||||
public function getPreviewCardFromUrl(string $url): ?PreviewCard
|
||||
{
|
||||
$hashedPreviewCardUrl = md5($url);
|
||||
$cacheName =
|
||||
|
@ -65,7 +65,7 @@ class PreviewCardModel extends Model
|
|||
return $found;
|
||||
}
|
||||
|
||||
public function getNotePreviewCard($noteId)
|
||||
public function getNotePreviewCard(string $noteId): ?PreviewCard
|
||||
{
|
||||
$cacheName =
|
||||
config('ActivityPub')->cachePrefix . "note#{$noteId}_preview_card";
|
||||
|
@ -89,10 +89,7 @@ class PreviewCardModel extends Model
|
|||
return $found;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|BaseResult
|
||||
*/
|
||||
public function deletePreviewCard($id, $url)
|
||||
public function deletePreviewCard(int $id, string $url): BaseResult|bool
|
||||
{
|
||||
$hashedPreviewCardUrl = md5($url);
|
||||
cache()->delete(
|
||||
|
|
|
@ -14,7 +14,7 @@ use ActivityPub\Core\ObjectType;
|
|||
class ActorObject extends ObjectType
|
||||
{
|
||||
/**
|
||||
* @var array|string
|
||||
* @var string|string[]
|
||||
*/
|
||||
protected $context = [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
|
@ -62,12 +62,12 @@ class ActorObject extends ObjectType
|
|||
protected $url;
|
||||
|
||||
/**
|
||||
* @var array|null
|
||||
* @var array<string, string>|null
|
||||
*/
|
||||
protected $image;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $icon = [];
|
||||
|
||||
|
|
|
@ -38,10 +38,7 @@ class NoteObject extends ObjectType
|
|||
*/
|
||||
protected $replies;
|
||||
|
||||
/**
|
||||
* @param Note $note
|
||||
*/
|
||||
public function __construct($note)
|
||||
public function __construct(Note $note)
|
||||
{
|
||||
$this->id = $note->uri;
|
||||
|
||||
|
|
|
@ -42,15 +42,10 @@ class OrderedCollectionObject extends ObjectType
|
|||
protected $last;
|
||||
|
||||
/**
|
||||
* @var array|null
|
||||
*/
|
||||
protected $orderedItems;
|
||||
|
||||
/**
|
||||
* @param array $orderedItems
|
||||
* @param ObjectType[] $orderedItems
|
||||
*/
|
||||
public function __construct(
|
||||
?array $orderedItems = null,
|
||||
protected ?array $orderedItems = null,
|
||||
?Pager $pager = null
|
||||
) {
|
||||
$this->id = current_url();
|
||||
|
@ -65,7 +60,5 @@ class OrderedCollectionObject extends ObjectType
|
|||
$this->last = $pager->getPageURI($pager->getLastPage());
|
||||
}
|
||||
}
|
||||
|
||||
$this->orderedItems = $orderedItems;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,29 +38,19 @@ class WebFinger
|
|||
protected $port;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $subject;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* @var string[]
|
||||
*/
|
||||
protected $aliases = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* @var array<array<string, string>>
|
||||
*/
|
||||
protected $links = [];
|
||||
|
||||
/**
|
||||
* @param string $resource
|
||||
*/
|
||||
public function __construct($resource)
|
||||
public function __construct(protected string $subject)
|
||||
{
|
||||
$this->subject = $resource;
|
||||
|
||||
// Split resource into its parts (username, domain)
|
||||
$parts = $this->splitResource($resource);
|
||||
$parts = $this->splitResource($subject);
|
||||
if (!$parts) {
|
||||
throw new Exception('Wrong WebFinger resource pattern.');
|
||||
}
|
||||
|
@ -120,9 +110,9 @@ class WebFinger
|
|||
/**
|
||||
* Split resource into its parts (username, domain)
|
||||
*
|
||||
* @return bool|mixed
|
||||
* @return array<string, string>|false
|
||||
*/
|
||||
private function splitResource(string $resource)
|
||||
private function splitResource(string $resource): array|false
|
||||
{
|
||||
if (!preg_match(self::RESOURCE_PATTERN, $resource, $matches)) {
|
||||
// Resource pattern failed
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace Analytics;
|
|||
|
||||
use Config\Services;
|
||||
use Config\Database;
|
||||
|
||||
trait AnalyticsTrait
|
||||
{
|
||||
protected function registerPodcastWebpageHit(int $podcastId): void
|
||||
|
|
|
@ -31,7 +31,7 @@ class Analytics extends BaseConfig
|
|||
*
|
||||
* @param string|string[] $audioFilePath
|
||||
*/
|
||||
public function getAudioFileUrl($audioFilePath): string
|
||||
public function getAudioFileUrl(string|array $audioFilePath): string
|
||||
{
|
||||
return base_url($audioFilePath);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ class AnalyticsController extends Controller
|
|||
*/
|
||||
protected $methodName;
|
||||
|
||||
public function _remap($method, ...$params)
|
||||
public function _remap(string $method, string ...$params): mixed
|
||||
{
|
||||
if (!isset($params[1])) {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
|
@ -39,11 +39,11 @@ class AnalyticsController extends Controller
|
|||
);
|
||||
}
|
||||
|
||||
public function getData($podcastId, $episodeId): ResponseInterface
|
||||
public function getData(int $podcastId, int $episodeId): ResponseInterface
|
||||
{
|
||||
$analytics_model = new $this->className();
|
||||
$methodName = $this->methodName;
|
||||
if ($episodeId) {
|
||||
if ($episodeId !== 0) {
|
||||
return $this->response->setJSON(
|
||||
$analytics_model->$methodName($podcastId, $episodeId),
|
||||
);
|
||||
|
|
|
@ -23,7 +23,7 @@ class EpisodeAnalyticsController extends Controller
|
|||
* class instantiation. These helpers will be available
|
||||
* to all other controllers that extend Analytics.
|
||||
*
|
||||
* @var array
|
||||
* @var string[]
|
||||
*/
|
||||
protected $helpers = ['analytics'];
|
||||
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
*/
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
use Config\Services;
|
||||
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 EpisodeController extends BaseController
|
||||
{
|
||||
use AnalyticsTrait;
|
||||
|
||||
/**
|
||||
* @var Podcast
|
||||
*/
|
||||
protected $podcast;
|
||||
|
||||
/**
|
||||
* @var Episode
|
||||
*/
|
||||
protected $episode;
|
||||
|
||||
public function _remap(string $method, string ...$params): mixed
|
||||
{
|
||||
if (count($params) < 2) {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
if (
|
||||
($this->podcast = (new PodcastModel())->getPodcastByName(
|
||||
$params[0],
|
||||
)) === null
|
||||
) {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
if (
|
||||
($this->episode = (new EpisodeModel())->getEpisodeBySlug(
|
||||
$this->podcast->id,
|
||||
$params[1],
|
||||
)) !== null
|
||||
) {
|
||||
unset($params[1]);
|
||||
unset($params[0]);
|
||||
return $this->$method(...$params);
|
||||
}
|
||||
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
public function index(): string
|
||||
{
|
||||
// Prevent analytics hit when authenticated
|
||||
if (!can_user_interact()) {
|
||||
$this->registerPodcastWebpageHit($this->episode->podcast_id);
|
||||
}
|
||||
|
||||
$locale = service('request')->getLocale();
|
||||
$cacheName =
|
||||
"page_podcast#{$this->podcast->id}_episode#{$this->episode->id}_{$locale}" .
|
||||
(can_user_interact() ? '_authenticated' : '');
|
||||
|
||||
if (!($cachedView = cache($cacheName))) {
|
||||
$data = [
|
||||
'podcast' => $this->podcast,
|
||||
'episode' => $this->episode,
|
||||
];
|
||||
|
||||
$secondsToNextUnpublishedEpisode = (new EpisodeModel())->getSecondsToNextUnpublishedEpisode(
|
||||
$this->podcast->id,
|
||||
);
|
||||
|
||||
if (can_user_interact()) {
|
||||
helper('form');
|
||||
return view('podcast/episode_authenticated', $data);
|
||||
}
|
||||
// The page cache is set to a decade so it is deleted manually upon podcast update
|
||||
return view('podcast/episode', $data, [
|
||||
'cache' => $secondsToNextUnpublishedEpisode
|
||||
? $secondsToNextUnpublishedEpisode
|
||||
: DECADE,
|
||||
'cache_name' => $cacheName,
|
||||
]);
|
||||
}
|
||||
|
||||
return $cachedView;
|
||||
}
|
||||
|
||||
public function embeddablePlayer(
|
||||
string $theme = 'light-transparent'
|
||||
): string {
|
||||
header('Content-Security-Policy: frame-ancestors https://* http://*');
|
||||
|
||||
// Prevent analytics hit when authenticated
|
||||
if (!can_user_interact()) {
|
||||
$this->registerPodcastWebpageHit($this->episode->podcast_id);
|
||||
}
|
||||
|
||||
$session = Services::session();
|
||||
$session->start();
|
||||
if (isset($_SERVER['HTTP_REFERER'])) {
|
||||
$session->set(
|
||||
'embeddable_player_domain',
|
||||
parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST),
|
||||
);
|
||||
}
|
||||
|
||||
$locale = service('request')->getLocale();
|
||||
|
||||
$cacheName = "page_podcast#{$this->podcast->id}_episode#{$this->episode->id}_embeddable_player_{$theme}_{$locale}";
|
||||
|
||||
if (!($cachedView = cache($cacheName))) {
|
||||
$theme = EpisodeModel::$themes[$theme];
|
||||
|
||||
$data = [
|
||||
'podcast' => $this->podcast,
|
||||
'episode' => $this->episode,
|
||||
'theme' => $theme,
|
||||
];
|
||||
|
||||
$secondsToNextUnpublishedEpisode = (new EpisodeModel())->getSecondsToNextUnpublishedEpisode(
|
||||
$this->podcast->id,
|
||||
);
|
||||
|
||||
// The page cache is set to a decade so it is deleted manually upon podcast update
|
||||
return view('embeddable_player', $data, [
|
||||
'cache' => $secondsToNextUnpublishedEpisode
|
||||
? $secondsToNextUnpublishedEpisode
|
||||
: DECADE,
|
||||
'cache_name' => $cacheName,
|
||||
]);
|
||||
}
|
||||
|
||||
return $cachedView;
|
||||
}
|
||||
|
||||
public function oembedJSON(): ResponseInterface
|
||||
{
|
||||
return $this->response->setJSON([
|
||||
'type' => 'rich',
|
||||
'version' => '1.0',
|
||||
'title' => $this->episode->title,
|
||||
'provider_name' => $this->podcast->title,
|
||||
'provider_url' => $this->podcast->link,
|
||||
'author_name' => $this->podcast->title,
|
||||
'author_url' => $this->podcast->link,
|
||||
'html' =>
|
||||
'<iframe src="' .
|
||||
$this->episode->embeddable_player_url .
|
||||
'" width="100%" height="200" frameborder="0" scrolling="no"></iframe>',
|
||||
'width' => 600,
|
||||
'height' => 200,
|
||||
'thumbnail_url' => $this->episode->image->large_url,
|
||||
'thumbnail_width' => config('Images')->largeSize,
|
||||
'thumbnail_height' => config('Images')->largeSize,
|
||||
]);
|
||||
}
|
||||
|
||||
public function oembedXML(): ResponseInterface
|
||||
{
|
||||
$oembed = new SimpleXMLElement(
|
||||
"<?xml version='1.0' encoding='utf-8' standalone='yes'?><oembed></oembed>",
|
||||
);
|
||||
|
||||
$oembed->addChild('type', 'rich');
|
||||
$oembed->addChild('version', '1.0');
|
||||
$oembed->addChild('title', $this->episode->title);
|
||||
$oembed->addChild('provider_name', $this->podcast->title);
|
||||
$oembed->addChild('provider_url', $this->podcast->link);
|
||||
$oembed->addChild('author_name', $this->podcast->title);
|
||||
$oembed->addChild('author_url', $this->podcast->link);
|
||||
$oembed->addChild('thumbnail', $this->episode->image->large_url);
|
||||
$oembed->addChild('thumbnail_width', config('Images')->largeSize);
|
||||
$oembed->addChild('thumbnail_height', config('Images')->largeSize);
|
||||
$oembed->addChild(
|
||||
'html',
|
||||
htmlentities(
|
||||
'<iframe src="' .
|
||||
$this->episode->embeddable_player_url .
|
||||
'" width="100%" height="200" frameborder="0" scrolling="no"></iframe>',
|
||||
),
|
||||
);
|
||||
$oembed->addChild('width', '600');
|
||||
$oembed->addChild('height', '200');
|
||||
|
||||
return $this->response->setXML($oembed);
|
||||
}
|
||||
}
|
|
@ -13,9 +13,9 @@ use CodeIgniter\Controller;
|
|||
|
||||
class UnknownUserAgentsController extends Controller
|
||||
{
|
||||
public function index($lastKnownId = 0): ResponseInterface
|
||||
public function index(int $lastKnownId = 0): ResponseInterface
|
||||
{
|
||||
$model = model('UnknownUserAgentsModel');
|
||||
$model = model('AnalyticsUnknownUserAgentsModel');
|
||||
|
||||
return $this->response->setJSON($model->getUserAgents($lastKnownId));
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ class AnalyticsPodcastsByCountry extends Entity
|
|||
'hits' => 'integer',
|
||||
];
|
||||
|
||||
public function getLabels()
|
||||
public function getLabels(): string
|
||||
{
|
||||
return lang('Countries.' . $this->attributes['labels']);
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ class AnalyticsPodcastsByRegion extends Entity
|
|||
'hits' => 'integer',
|
||||
];
|
||||
|
||||
public function getCountryCode()
|
||||
public function getCountryCode(): string
|
||||
{
|
||||
return lang('Countries.' . $this->attributes['country_code']);
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ class AnalyticsPodcastsByService extends Entity
|
|||
'hits' => 'integer',
|
||||
];
|
||||
|
||||
public function getLabels()
|
||||
public function getLabels(): string
|
||||
{
|
||||
return UserAgentsRSS::getName($this->attributes['labels']) ??
|
||||
$this->attributes['labels'];
|
||||
|
|
|
@ -13,17 +13,24 @@ namespace Analytics\Entities;
|
|||
use CodeIgniter\Entity\Entity;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property int $useragent
|
||||
* @property int $hits
|
||||
* @property Time $created_at
|
||||
* @property Time $updated_at
|
||||
*/
|
||||
class AnalyticsUnknownUseragents extends Entity
|
||||
class AnalyticsUnknownUserAgent extends Entity
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
protected $dates = ['created_at', 'updated_at'];
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'id' => 'integer',
|
||||
'useragent' => 'integer',
|
||||
'hits' => 'integer',
|
||||
];
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
|
||||
use CodeIgniter\I18n\Time;
|
||||
use Config\Services;
|
||||
use Podlibre\Ipcat\IpDb;
|
||||
use GeoIp2\Database\Reader;
|
||||
|
@ -18,7 +19,7 @@ if (!function_exists('base64_url_encode')) {
|
|||
/**
|
||||
* Encode Base64 for URLs
|
||||
*/
|
||||
function base64_url_encode($input)
|
||||
function base64_url_encode(string $input): string
|
||||
{
|
||||
return strtr(base64_encode($input), '+/=', '._-');
|
||||
}
|
||||
|
@ -28,7 +29,7 @@ if (!function_exists('base64_url_decode')) {
|
|||
/**
|
||||
* Decode Base64 from URL
|
||||
*/
|
||||
function base64_url_decode($input)
|
||||
function base64_url_decode(string $input): string
|
||||
{
|
||||
return base64_decode(strtr($input, '._-', '+/='));
|
||||
}
|
||||
|
@ -131,7 +132,7 @@ if (!function_exists('set_user_session_location')) {
|
|||
'longitude' => round($city->location->longitude, 3),
|
||||
];
|
||||
// If things go wrong the show must go on and the user must be able to download the file
|
||||
} catch (Exception $exception) {
|
||||
} catch (Exception) {
|
||||
}
|
||||
$session->set('location', $location);
|
||||
}
|
||||
|
@ -154,7 +155,7 @@ if (!function_exists('set_user_session_player')) {
|
|||
try {
|
||||
$playerFound = UserAgents::find($userAgent);
|
||||
// If things go wrong the show must go on and the user must be able to download the file
|
||||
} catch (Exception $exception) {
|
||||
} catch (Exception) {
|
||||
}
|
||||
if ($playerFound) {
|
||||
$session->set('player', $playerFound);
|
||||
|
@ -176,7 +177,7 @@ if (!function_exists('set_user_session_player')) {
|
|||
[$userAgent],
|
||||
);
|
||||
// If things go wrong the show must go on and the user must be able to download the file
|
||||
} catch (Exception $exception) {
|
||||
} catch (Exception) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -197,7 +198,7 @@ if (!function_exists('set_user_session_browser')) {
|
|||
try {
|
||||
$whichbrowser = new Parser(getallheaders());
|
||||
$browserName = $whichbrowser->browser->name;
|
||||
} catch (Exception $exception) {
|
||||
} catch (Exception) {
|
||||
$browserName = '- Could not get browser name -';
|
||||
}
|
||||
if ($browserName == null) {
|
||||
|
@ -267,6 +268,8 @@ if (!function_exists('podcast_hit')) {
|
|||
* @param integer $episodeId The Episode ID
|
||||
* @param integer $bytesThreshold The minimum total number of bytes that must be downloaded so that an episode is counted (>1mn)
|
||||
* @param integer $fileSize The podcast complete file size
|
||||
* @param integer $duration The episode duration in seconds
|
||||
* @param int $publicationTime The episode's publication time as a UNIX timestamp
|
||||
* @param string $serviceName The name of the service that had fetched the RSS feed
|
||||
*/
|
||||
function podcast_hit(
|
||||
|
@ -274,8 +277,8 @@ if (!function_exists('podcast_hit')) {
|
|||
int $episodeId,
|
||||
int $bytesThreshold,
|
||||
int $fileSize,
|
||||
$duration,
|
||||
$publicationDate,
|
||||
int $duration,
|
||||
int $publicationTime,
|
||||
string $serviceName
|
||||
): void {
|
||||
$session = Services::session();
|
||||
|
@ -341,7 +344,7 @@ if (!function_exists('podcast_hit')) {
|
|||
$db = Database::connect();
|
||||
$procedureName = $db->prefixTable('analytics_podcasts');
|
||||
|
||||
$age = intdiv(time() - $publicationDate, 86400);
|
||||
$age = intdiv(time() - $publicationTime, 86400);
|
||||
|
||||
// We create a sha1 hash for this IP_Address+User_Agent+Podcast_ID (used to count unique listeners):
|
||||
$listenerHashId =
|
||||
|
|
|
@ -10,24 +10,20 @@
|
|||
|
||||
namespace Analytics\Models;
|
||||
|
||||
use Analytics\Entities\AnalyticsUnknownUseragents;
|
||||
use Analytics\Entities\AnalyticsUnknownUserAgent;
|
||||
use CodeIgniter\Model;
|
||||
|
||||
class AnalyticsUnknownUseragentsModel extends Model
|
||||
class AnalyticsUnknownUserAgentModel extends Model
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'analytics_unknown_useragents';
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $returnType = AnalyticsUnknownUseragents::class;
|
||||
protected $returnType = AnalyticsUnknownUserAgent::class;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
|
@ -37,4 +33,12 @@ class AnalyticsUnknownUseragentsModel extends Model
|
|||
* @var bool
|
||||
*/
|
||||
protected $useTimestamps = false;
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getUserAgents(int $lastKnownId = 0): array
|
||||
{
|
||||
return $this->where('id >', $lastKnownId)->findAll();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class UnknownUserAgentsModel
|
||||
* Model for analytics_unknown_useragents table in database
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
*/
|
||||
|
||||
namespace Analytics\Models;
|
||||
|
||||
use CodeIgniter\Model;
|
||||
|
||||
class UnknownUserAgentsModel extends Model
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'analytics_unknown_useragents';
|
||||
|
||||
public function getUserAgents($last_known_id = 0)
|
||||
{
|
||||
return $this->where('id >', $last_known_id)->findAll();
|
||||
}
|
||||
}
|
|
@ -15,11 +15,12 @@ class Breadcrumb
|
|||
/**
|
||||
* List of breadcrumb links.
|
||||
*
|
||||
* @var array
|
||||
* $links = [
|
||||
* 'text' => (string) the anchor text,
|
||||
* 'href' => (string) the anchor href,
|
||||
* 'text' => 'Example Link',
|
||||
* 'href' => 'https://example.com/',
|
||||
* ]
|
||||
*
|
||||
* @var array<array<string, string>>
|
||||
*/
|
||||
protected $links = [];
|
||||
|
||||
|
@ -57,6 +58,8 @@ class Breadcrumb
|
|||
* replaceParams($newParams);
|
||||
*
|
||||
* The breadcrumb is now `Home / podcasts / foo / episodes / bar`
|
||||
*
|
||||
* @param string[] $newParams
|
||||
*/
|
||||
public function replaceParams(array $newParams): void
|
||||
{
|
||||
|
@ -71,7 +74,7 @@ class Breadcrumb
|
|||
/**
|
||||
* Renders the breadcrumb object as an accessible html breadcrumb nav
|
||||
*/
|
||||
public function render($class = null): string
|
||||
public function render(string $class = null): string
|
||||
{
|
||||
$listItems = '';
|
||||
$keys = array_keys($this->links);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue