fix: remove fediverse prefix to prevent migration error + load routes during podcast import
refactor migration queries to use forge functions
This commit is contained in:
parent
072b3ff61d
commit
7ff1dbe903
|
@ -27,7 +27,8 @@ class View extends BaseView
|
||||||
*
|
*
|
||||||
* Examples: { title|esc(js) } { created_on|date(Y-m-d)|esc(attr) }
|
* Examples: { title|esc(js) } { created_on|date(Y-m-d)|esc(attr) }
|
||||||
*
|
*
|
||||||
* @var string[]
|
* @var array<string, string>
|
||||||
|
* @phpstan-var array<string, callable-string>
|
||||||
*/
|
*/
|
||||||
public $filters = [];
|
public $filters = [];
|
||||||
|
|
||||||
|
@ -35,7 +36,8 @@ class View extends BaseView
|
||||||
* Parser Plugins provide a way to extend the functionality provided by the core Parser by creating aliases that
|
* Parser Plugins provide a way to extend the functionality provided by the core Parser by creating aliases that
|
||||||
* will be replaced with any callable. Can be single or tag pair.
|
* will be replaced with any callable. Can be single or tag pair.
|
||||||
*
|
*
|
||||||
* @var string[]
|
* @var array<string, string>
|
||||||
|
* @phpstan-var array<string, callable-string>
|
||||||
*/
|
*/
|
||||||
public $plugins = [];
|
public $plugins = [];
|
||||||
|
|
||||||
|
|
|
@ -290,7 +290,7 @@ class EpisodeController extends BaseController
|
||||||
$episodeComments = model(PostModel::class)
|
$episodeComments = model(PostModel::class)
|
||||||
->whereIn('in_reply_to_id', function (BaseBuilder $builder): BaseBuilder {
|
->whereIn('in_reply_to_id', function (BaseBuilder $builder): BaseBuilder {
|
||||||
return $builder->select('id')
|
return $builder->select('id')
|
||||||
->from(config('Fediverse')->tablesPrefix . 'posts')
|
->from('fediverse_posts')
|
||||||
->where('episode_id', $this->episode->id);
|
->where('episode_id', $this->episode->id);
|
||||||
})
|
})
|
||||||
->where('`published_at` <= UTC_TIMESTAMP()', null, false)
|
->where('`published_at` <= UTC_TIMESTAMP()', null, false)
|
||||||
|
|
|
@ -195,7 +195,7 @@ class AddPodcasts extends BaseMigration
|
||||||
$this->forge->addUniqueKey('handle');
|
$this->forge->addUniqueKey('handle');
|
||||||
$this->forge->addUniqueKey('guid');
|
$this->forge->addUniqueKey('guid');
|
||||||
$this->forge->addUniqueKey('actor_id');
|
$this->forge->addUniqueKey('actor_id');
|
||||||
$this->forge->addForeignKey('actor_id', config('Fediverse')->tablesPrefix . 'actors', 'id', '', 'CASCADE');
|
$this->forge->addForeignKey('actor_id', 'fediverse_actors', 'id', '', 'CASCADE');
|
||||||
$this->forge->addForeignKey('cover_id', 'media', 'id');
|
$this->forge->addForeignKey('cover_id', 'media', 'id');
|
||||||
$this->forge->addForeignKey('banner_id', 'media', 'id', '', 'SET NULL');
|
$this->forge->addForeignKey('banner_id', 'media', 'id', '', 'SET NULL');
|
||||||
$this->forge->addForeignKey('category_id', 'categories', 'id');
|
$this->forge->addForeignKey('category_id', 'categories', 'id');
|
||||||
|
|
|
@ -164,10 +164,10 @@ class AddEpisodes extends BaseMigration
|
||||||
|
|
||||||
// Add Full-Text Search index on title and description_markdown
|
// Add Full-Text Search index on title and description_markdown
|
||||||
$prefix = $this->db->getPrefix();
|
$prefix = $this->db->getPrefix();
|
||||||
$createQuery = <<<CODE_SAMPLE
|
$createQuery = <<<SQL
|
||||||
ALTER TABLE {$prefix}episodes
|
ALTER TABLE {$prefix}episodes
|
||||||
ADD FULLTEXT(title, description_markdown);
|
ADD FULLTEXT title (title, description_markdown);
|
||||||
CODE_SAMPLE;
|
SQL;
|
||||||
$this->db->query($createQuery);
|
$this->db->query($createQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,12 +64,9 @@ class AddEpisodeComments extends BaseMigration
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$fediverseTablesPrefix = config('Fediverse')
|
|
||||||
->tablesPrefix;
|
|
||||||
|
|
||||||
$this->forge->addPrimaryKey('id');
|
$this->forge->addPrimaryKey('id');
|
||||||
$this->forge->addForeignKey('episode_id', 'episodes', 'id', '', 'CASCADE');
|
$this->forge->addForeignKey('episode_id', 'episodes', 'id', '', 'CASCADE');
|
||||||
$this->forge->addForeignKey('actor_id', $fediverseTablesPrefix . 'actors', 'id', '', 'CASCADE');
|
$this->forge->addForeignKey('actor_id', 'fediverse_actors', 'id', '', 'CASCADE');
|
||||||
$this->forge->addForeignKey('created_by', 'users', 'id');
|
$this->forge->addForeignKey('created_by', 'users', 'id');
|
||||||
$this->forge->createTable('episode_comments');
|
$this->forge->createTable('episode_comments');
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,12 +27,9 @@ class AddLikes extends BaseMigration
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$fediverseTablesPrefix = config('Fediverse')
|
|
||||||
->tablesPrefix;
|
|
||||||
|
|
||||||
$this->forge->addField('`created_at` timestamp NOT NULL DEFAULT current_timestamp()');
|
$this->forge->addField('`created_at` timestamp NOT NULL DEFAULT current_timestamp()');
|
||||||
$this->forge->addPrimaryKey(['actor_id', 'comment_id']);
|
$this->forge->addPrimaryKey(['actor_id', 'comment_id']);
|
||||||
$this->forge->addForeignKey('actor_id', $fediverseTablesPrefix . 'actors', 'id', '', 'CASCADE');
|
$this->forge->addForeignKey('actor_id', 'fediverse_actors', 'id', '', 'CASCADE');
|
||||||
$this->forge->addForeignKey('comment_id', 'episode_comments', 'id', '', 'CASCADE');
|
$this->forge->addForeignKey('comment_id', 'episode_comments', 'id', '', 'CASCADE');
|
||||||
$this->forge->createTable('likes');
|
$this->forge->createTable('likes');
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ class AddCreditsView extends BaseMigration
|
||||||
$podcastPersonsTable = $this->db->prefixTable('podcasts_persons');
|
$podcastPersonsTable = $this->db->prefixTable('podcasts_persons');
|
||||||
$episodePersonsTable = $this->db->prefixTable('episodes_persons');
|
$episodePersonsTable = $this->db->prefixTable('episodes_persons');
|
||||||
$episodesTable = $this->db->prefixTable('episodes');
|
$episodesTable = $this->db->prefixTable('episodes');
|
||||||
$createQuery = <<<CODE_SAMPLE
|
$createQuery = <<<SQL
|
||||||
CREATE VIEW `{$viewName}` AS
|
CREATE VIEW `{$viewName}` AS
|
||||||
SELECT `person_group`, `person_id`, `full_name`, `person_role`, `podcast_id`, NULL AS `episode_id` FROM `{$podcastPersonsTable}`
|
SELECT `person_group`, `person_id`, `full_name`, `person_role`, `podcast_id`, NULL AS `episode_id` FROM `{$podcastPersonsTable}`
|
||||||
INNER JOIN `{$personsTable}`
|
INNER JOIN `{$personsTable}`
|
||||||
|
@ -33,7 +33,7 @@ class AddCreditsView extends BaseMigration
|
||||||
ON (`episode_id`=`{$episodesTable}`.`id`)
|
ON (`episode_id`=`{$episodesTable}`.`id`)
|
||||||
WHERE `{$episodesTable}`.published_at <= UTC_TIMESTAMP()
|
WHERE `{$episodesTable}`.published_at <= UTC_TIMESTAMP()
|
||||||
ORDER BY `person_group`, `full_name`, `person_role`, `podcast_id`, `episode_id`;
|
ORDER BY `person_group`, `full_name`, `person_role`, `podcast_id`, `episode_id`;
|
||||||
CODE_SAMPLE;
|
SQL;
|
||||||
$this->db->query($createQuery);
|
$this->db->query($createQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,10 +17,8 @@ class AddEpisodeIdToPosts extends BaseMigration
|
||||||
public function up(): void
|
public function up(): void
|
||||||
{
|
{
|
||||||
$prefix = $this->db->getPrefix();
|
$prefix = $this->db->getPrefix();
|
||||||
$fediverseTablesPrefix = config('Fediverse')
|
|
||||||
->tablesPrefix;
|
|
||||||
|
|
||||||
$this->forge->addColumn("{$fediverseTablesPrefix}posts", [
|
$this->forge->addColumn('fediverse_posts', [
|
||||||
'episode_id' => [
|
'episode_id' => [
|
||||||
'type' => 'INT',
|
'type' => 'INT',
|
||||||
'unsigned' => true,
|
'unsigned' => true,
|
||||||
|
@ -29,22 +27,22 @@ class AddEpisodeIdToPosts extends BaseMigration
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$alterQuery = <<<CODE_SAMPLE
|
$this->forge->addForeignKey(
|
||||||
ALTER TABLE {$prefix}{$fediverseTablesPrefix}posts
|
'episode_id',
|
||||||
ADD FOREIGN KEY {$prefix}{$fediverseTablesPrefix}posts_episode_id_foreign(episode_id) REFERENCES {$prefix}episodes(id) ON DELETE CASCADE;
|
'episodes',
|
||||||
CODE_SAMPLE;
|
'id',
|
||||||
$this->db->query($alterQuery);
|
'',
|
||||||
|
'CASCADE',
|
||||||
|
$prefix . 'fediverse_posts_episode_id_foreign'
|
||||||
|
);
|
||||||
|
$this->forge->processIndexes('fediverse_posts');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function down(): void
|
public function down(): void
|
||||||
{
|
{
|
||||||
$fediverseTablesPrefix = config('Fediverse')
|
$prefix = $this->db->getPrefix();
|
||||||
->tablesPrefix;
|
|
||||||
|
|
||||||
$this->forge->dropForeignKey(
|
$this->forge->dropForeignKey('fediverse_posts', $prefix . 'fediverse_posts_episode_id_foreign');
|
||||||
$fediverseTablesPrefix . 'posts',
|
$this->forge->dropColumn('fediverse_posts', 'episode_id');
|
||||||
$fediverseTablesPrefix . 'posts_episode_id_foreign'
|
|
||||||
);
|
|
||||||
$this->forge->dropColumn($fediverseTablesPrefix . 'posts', 'episode_id');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,8 @@ class AddCreatedByToPosts extends BaseMigration
|
||||||
public function up(): void
|
public function up(): void
|
||||||
{
|
{
|
||||||
$prefix = $this->db->getPrefix();
|
$prefix = $this->db->getPrefix();
|
||||||
$fediverseTablesPrefix = config('Fediverse')
|
|
||||||
->tablesPrefix;
|
|
||||||
|
|
||||||
$this->forge->addColumn("{$fediverseTablesPrefix}posts", [
|
$this->forge->addColumn('fediverse_posts', [
|
||||||
'created_by' => [
|
'created_by' => [
|
||||||
'type' => 'INT',
|
'type' => 'INT',
|
||||||
'unsigned' => true,
|
'unsigned' => true,
|
||||||
|
@ -29,22 +27,22 @@ class AddCreatedByToPosts extends BaseMigration
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$alterQuery = <<<CODE_SAMPLE
|
$this->forge->addForeignKey(
|
||||||
ALTER TABLE {$prefix}{$fediverseTablesPrefix}posts
|
'created_by',
|
||||||
ADD FOREIGN KEY {$prefix}{$fediverseTablesPrefix}posts_created_by_foreign(created_by) REFERENCES {$prefix}users(id) ON DELETE CASCADE;
|
'users',
|
||||||
CODE_SAMPLE;
|
'id',
|
||||||
$this->db->query($alterQuery);
|
'',
|
||||||
|
'CASCADE',
|
||||||
|
$prefix . 'fediverse_posts_created_by_foreign'
|
||||||
|
);
|
||||||
|
$this->forge->processIndexes('fediverse_posts');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function down(): void
|
public function down(): void
|
||||||
{
|
{
|
||||||
$fediverseTablesPrefix = config('Fediverse')
|
$prefix = $this->db->getPrefix();
|
||||||
->tablesPrefix;
|
|
||||||
|
|
||||||
$this->forge->dropForeignKey(
|
$this->forge->dropForeignKey('fediverse_posts', $prefix . 'fediverse_posts_created_by_foreign');
|
||||||
$fediverseTablesPrefix . 'posts',
|
$this->forge->dropColumn('fediverse_posts', 'created_by');
|
||||||
$fediverseTablesPrefix . 'posts_created_by_foreign'
|
|
||||||
);
|
|
||||||
$this->forge->dropColumn($fediverseTablesPrefix . 'posts', 'created_by');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,23 +10,23 @@ class AddFullTextSearchIndexes extends BaseMigration
|
||||||
{
|
{
|
||||||
$prefix = $this->db->getPrefix();
|
$prefix = $this->db->getPrefix();
|
||||||
|
|
||||||
$createQuery = <<<CODE_SAMPLE
|
$createQuery = <<<SQL
|
||||||
ALTER TABLE {$prefix}episodes DROP INDEX IF EXISTS title;
|
ALTER TABLE {$prefix}episodes DROP INDEX IF EXISTS title;
|
||||||
CODE_SAMPLE;
|
SQL;
|
||||||
|
|
||||||
$this->db->query($createQuery);
|
$this->db->query($createQuery);
|
||||||
|
|
||||||
$createQuery = <<<CODE_SAMPLE
|
$createQuery = <<<SQL
|
||||||
ALTER TABLE {$prefix}episodes
|
ALTER TABLE {$prefix}episodes
|
||||||
ADD FULLTEXT episodes_search (title, description_markdown, slug, location_name);
|
ADD FULLTEXT episodes_search (title, description_markdown, slug, location_name);
|
||||||
CODE_SAMPLE;
|
SQL;
|
||||||
|
|
||||||
$this->db->query($createQuery);
|
$this->db->query($createQuery);
|
||||||
|
|
||||||
$createQuery = <<<CODE_SAMPLE
|
$createQuery = <<<SQL
|
||||||
ALTER TABLE {$prefix}podcasts
|
ALTER TABLE {$prefix}podcasts
|
||||||
ADD FULLTEXT podcasts_search (title, description_markdown, handle, location_name);
|
ADD FULLTEXT podcasts_search (title, description_markdown, handle, location_name);
|
||||||
CODE_SAMPLE;
|
SQL;
|
||||||
|
|
||||||
$this->db->query($createQuery);
|
$this->db->query($createQuery);
|
||||||
}
|
}
|
||||||
|
@ -35,17 +35,17 @@ class AddFullTextSearchIndexes extends BaseMigration
|
||||||
{
|
{
|
||||||
$prefix = $this->db->getPrefix();
|
$prefix = $this->db->getPrefix();
|
||||||
|
|
||||||
$createQuery = <<<CODE_SAMPLE
|
$createQuery = <<<SQL
|
||||||
ALTER TABLE {$prefix}episodes
|
ALTER TABLE {$prefix}episodes
|
||||||
DROP INDEX IF EXISTS episodes_search;
|
DROP INDEX IF EXISTS episodes_search;
|
||||||
CODE_SAMPLE;
|
SQL;
|
||||||
|
|
||||||
$this->db->query($createQuery);
|
$this->db->query($createQuery);
|
||||||
|
|
||||||
$createQuery = <<<CODE_SAMPLE
|
$createQuery = <<<SQL
|
||||||
ALTER TABLE {$prefix}podcasts
|
ALTER TABLE {$prefix}podcasts
|
||||||
DROP INDEX IF EXISTS podcasts_search;
|
DROP INDEX IF EXISTS podcasts_search;
|
||||||
CODE_SAMPLE;
|
SQL;
|
||||||
|
|
||||||
$this->db->query($createQuery);
|
$this->db->query($createQuery);
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,8 @@ class BaseClip extends Entity
|
||||||
protected ?float $end_time = null;
|
protected ?float $end_time = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string[]
|
* @var array<int, string>
|
||||||
|
* @phpstan-var list<string>
|
||||||
*/
|
*/
|
||||||
protected $dates = ['created_at', 'updated_at', 'job_started_at', 'job_ended_at'];
|
protected $dates = ['created_at', 'updated_at', 'job_started_at', 'job_ended_at'];
|
||||||
|
|
||||||
|
|
|
@ -144,7 +144,8 @@ class Episode extends Entity
|
||||||
protected ?string $publication_status = null;
|
protected ?string $publication_status = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string[]
|
* @var array<int, string>
|
||||||
|
* @phpstan-var list<string>
|
||||||
*/
|
*/
|
||||||
protected $dates = ['published_at', 'created_at', 'updated_at'];
|
protected $dates = ['published_at', 'created_at', 'updated_at'];
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,8 @@ class EpisodeComment extends UuidEntity
|
||||||
protected bool $has_replies = false;
|
protected bool $has_replies = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string[]
|
* @var array<int, string>
|
||||||
|
* @phpstan-var list<string>
|
||||||
*/
|
*/
|
||||||
protected $dates = ['created_at'];
|
protected $dates = ['created_at'];
|
||||||
|
|
||||||
|
|
|
@ -166,7 +166,8 @@ class Podcast extends Entity
|
||||||
protected ?string $publication_status = null;
|
protected ?string $publication_status = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string[]
|
* @var array<int, string>
|
||||||
|
* @phpstan-var list<string>
|
||||||
*/
|
*/
|
||||||
protected $dates = ['published_at', 'created_at', 'updated_at'];
|
protected $dates = ['published_at', 'created_at', 'updated_at'];
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,17 @@ use CodeIgniter\HTTP\ResponseInterface;
|
||||||
|
|
||||||
class AllowCorsFilter implements FilterInterface
|
class AllowCorsFilter implements FilterInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @param string[]|null $arguments
|
||||||
|
*/
|
||||||
public function before(RequestInterface $request, $arguments = null): void
|
public function before(RequestInterface $request, $arguments = null): void
|
||||||
{
|
{
|
||||||
// Do something here
|
// Do something here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string[]|null $arguments
|
||||||
|
*/
|
||||||
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null): void
|
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null): void
|
||||||
{
|
{
|
||||||
if (! $response->hasHeader('Cache-Control')) {
|
if (! $response->hasHeader('Cache-Control')) {
|
||||||
|
|
|
@ -206,7 +206,7 @@ if (! function_exists('publication_status_banner')) {
|
||||||
$bannerDisclaimer = lang('Podcast.publication_status_banner.draft_mode');
|
$bannerDisclaimer = lang('Podcast.publication_status_banner.draft_mode');
|
||||||
$bannerText = lang('Podcast.publication_status_banner.scheduled', [
|
$bannerText = lang('Podcast.publication_status_banner.scheduled', [
|
||||||
'publication_date' => local_datetime($publicationDate),
|
'publication_date' => local_datetime($publicationDate),
|
||||||
], null, false);
|
]);
|
||||||
$linkRoute = route_to('podcast-publish_edit', $podcastId);
|
$linkRoute = route_to('podcast-publish_edit', $podcastId);
|
||||||
$linkLabel = lang('Podcast.publish_edit');
|
$linkLabel = lang('Podcast.publish_edit');
|
||||||
break;
|
break;
|
||||||
|
@ -492,10 +492,10 @@ if (! function_exists('category_label')) {
|
||||||
{
|
{
|
||||||
$categoryLabel = '';
|
$categoryLabel = '';
|
||||||
if ($category->parent_id !== null) {
|
if ($category->parent_id !== null) {
|
||||||
$categoryLabel .= lang('Podcast.category_options.' . $category->parent->code, [], null, false) . ' › ';
|
$categoryLabel .= lang('Podcast.category_options.' . $category->parent->code) . ' › ';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $categoryLabel . lang('Podcast.category_options.' . $category->code, [], null, false);
|
return $categoryLabel . lang('Podcast.category_options.' . $category->code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,18 +14,25 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Libraries;
|
namespace App\Libraries;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
use CodeIgniter\Router\RouteCollection as CodeIgniterRouteCollection;
|
use CodeIgniter\Router\RouteCollection as CodeIgniterRouteCollection;
|
||||||
|
|
||||||
class RouteCollection extends CodeIgniterRouteCollection
|
class RouteCollection extends CodeIgniterRouteCollection
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The current hostname from $_SERVER['HTTP_HOST']
|
||||||
|
*/
|
||||||
|
private ?string $httpHost = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does the heavy lifting of creating an actual route. You must specify
|
* Does the heavy lifting of creating an actual route. You must specify
|
||||||
* the request method(s) that this route will work for. They can be separated
|
* the request method(s) that this route will work for. They can be separated
|
||||||
* by a pipe character "|" if there is more than one.
|
* by a pipe character "|" if there is more than one.
|
||||||
*
|
*
|
||||||
* @param array|Closure|string $to
|
* @param array<int, mixed>|Closure|string $to
|
||||||
|
* @param array<string, mixed> $options
|
||||||
*/
|
*/
|
||||||
protected function create(string $verb, string $from, $to, ?array $options = null)
|
protected function create(string $verb, string $from, $to, ?array $options = null): void
|
||||||
{
|
{
|
||||||
$overwrite = false;
|
$overwrite = false;
|
||||||
$prefix = $this->group === null ? '' : $this->group . '/';
|
$prefix = $this->group === null ? '' : $this->group . '/';
|
||||||
|
@ -81,8 +88,8 @@ class RouteCollection extends CodeIgniterRouteCollection
|
||||||
// Get a constant string to work with.
|
// Get a constant string to work with.
|
||||||
$to = preg_replace('/(\$\d+)/', '$X', $to);
|
$to = preg_replace('/(\$\d+)/', '$X', $to);
|
||||||
|
|
||||||
for ($i = (int) $options['offset'] + 1; $i < (int) $options['offset'] + 7; $i++) {
|
for ($i = (int) $options['offset'] + 1; $i < (int) $options['offset'] + 7; ++$i) {
|
||||||
$to = preg_replace_callback('/\$X/', static fn ($m) => '$' . $i, $to, 1);
|
$to = preg_replace_callback('/\$X/', static fn ($m): string => '$' . $i, $to, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +104,7 @@ class RouteCollection extends CodeIgniterRouteCollection
|
||||||
// If no namespace found, add the default namespace
|
// If no namespace found, add the default namespace
|
||||||
if (strpos($to, '\\') === false || strpos($to, '\\') > 0) {
|
if (strpos($to, '\\') === false || strpos($to, '\\') > 0) {
|
||||||
$namespace = $options['namespace'] ?? $this->defaultNamespace;
|
$namespace = $options['namespace'] ?? $this->defaultNamespace;
|
||||||
$to = trim($namespace, '\\') . '\\' . $to;
|
$to = trim((string) $namespace, '\\') . '\\' . $to;
|
||||||
}
|
}
|
||||||
// Always ensure that we escape our namespace so we're not pointing to
|
// Always ensure that we escape our namespace so we're not pointing to
|
||||||
// \CodeIgniter\Routes\Controller::method.
|
// \CodeIgniter\Routes\Controller::method.
|
||||||
|
@ -134,4 +141,140 @@ class RouteCollection extends CodeIgniterRouteCollection
|
||||||
$this->routes['*'][$name]['redirect'] = $options['redirect'];
|
$this->routes['*'][$name]['redirect'] = $options['redirect'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares the hostname passed in against the current hostname
|
||||||
|
* on this page request.
|
||||||
|
*
|
||||||
|
* @param string $hostname Hostname in route options
|
||||||
|
*/
|
||||||
|
private function checkHostname($hostname): bool
|
||||||
|
{
|
||||||
|
// CLI calls can't be on hostname.
|
||||||
|
if ($this->httpHost === null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return strtolower($this->httpHost) === strtolower($hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<int, mixed> $to
|
||||||
|
*
|
||||||
|
* @return string|array<int, mixed>
|
||||||
|
*/
|
||||||
|
private function processArrayCallableSyntax(string $from, array $to): string | array
|
||||||
|
{
|
||||||
|
// [classname, method]
|
||||||
|
// eg, [Home::class, 'index']
|
||||||
|
if (is_callable($to, true, $callableName)) {
|
||||||
|
// If the route has placeholders, add params automatically.
|
||||||
|
$params = $this->getMethodParams($from);
|
||||||
|
|
||||||
|
return '\\' . $callableName . $params;
|
||||||
|
}
|
||||||
|
|
||||||
|
// [[classname, method], params]
|
||||||
|
// eg, [[Home::class, 'index'], '$1/$2']
|
||||||
|
if (
|
||||||
|
isset($to[0], $to[1])
|
||||||
|
&& is_callable($to[0], true, $callableName)
|
||||||
|
&& is_string($to[1])
|
||||||
|
) {
|
||||||
|
return '\\' . $callableName . '/' . $to[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $to;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares the subdomain(s) passed in against the current subdomain
|
||||||
|
* on this page request.
|
||||||
|
*
|
||||||
|
* @param string|string[] $subdomains
|
||||||
|
*/
|
||||||
|
private function checkSubdomains($subdomains): bool
|
||||||
|
{
|
||||||
|
// CLI calls can't be on subdomain.
|
||||||
|
if ($this->httpHost === null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->currentSubdomain === null) {
|
||||||
|
$this->currentSubdomain = $this->determineCurrentSubdomain();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! is_array($subdomains)) {
|
||||||
|
$subdomains = [$subdomains];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Routes can be limited to any sub-domain. In that case, though,
|
||||||
|
// it does require a sub-domain to be present.
|
||||||
|
if (! empty($this->currentSubdomain) && in_array('*', $subdomains, true)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return in_array($this->currentSubdomain, $subdomains, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the method param string like `/$1/$2` for placeholders
|
||||||
|
*/
|
||||||
|
private function getMethodParams(string $from): string
|
||||||
|
{
|
||||||
|
preg_match_all('/\(.+?\)/', $from, $matches);
|
||||||
|
$count = is_countable($matches[0]) ? count($matches[0]) : 0;
|
||||||
|
|
||||||
|
$params = '';
|
||||||
|
|
||||||
|
for ($i = 1; $i <= $count; ++$i) {
|
||||||
|
$params .= '/$' . $i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $params;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Examines the HTTP_HOST to get the best match for the subdomain. It
|
||||||
|
* won't be perfect, but should work for our needs.
|
||||||
|
*
|
||||||
|
* It's especially not perfect since it's possible to register a domain
|
||||||
|
* with a period (.) as part of the domain name.
|
||||||
|
*
|
||||||
|
* @return false|string the subdomain
|
||||||
|
*/
|
||||||
|
private function determineCurrentSubdomain()
|
||||||
|
{
|
||||||
|
// We have to ensure that a scheme exists
|
||||||
|
// on the URL else parse_url will mis-interpret
|
||||||
|
// 'host' as the 'path'.
|
||||||
|
$url = $this->httpHost;
|
||||||
|
if (strpos($url, 'http') !== 0) {
|
||||||
|
$url = 'http://' . $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
$parsedUrl = parse_url($url);
|
||||||
|
|
||||||
|
$host = explode('.', $parsedUrl['host']);
|
||||||
|
|
||||||
|
if ($host[0] === 'www') {
|
||||||
|
unset($host[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get rid of any domains, which will be the last
|
||||||
|
unset($host[count($host) - 1]);
|
||||||
|
|
||||||
|
// Account for .co.uk, .co.nz, etc. domains
|
||||||
|
if (end($host) === 'co') {
|
||||||
|
$host = array_slice($host, 0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we only have 1 part left, then we don't have a sub-domain.
|
||||||
|
if (count($host) === 1) {
|
||||||
|
// Set it to false so we don't make it back here again.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_shift($host);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ class ComponentRenderer
|
||||||
$matches[name] = tag name
|
$matches[name] = tag name
|
||||||
$matches[attributes] = array of attribute string (class="foo")
|
$matches[attributes] = array of attribute string (class="foo")
|
||||||
*/
|
*/
|
||||||
return preg_replace_callback($pattern, function ($match): string {
|
return preg_replace_callback($pattern, function (array $match): string {
|
||||||
$view = $this->locateView($match['name']);
|
$view = $this->locateView($match['name']);
|
||||||
$attributes = $this->parseAttributes($match['attributes']);
|
$attributes = $this->parseAttributes($match['attributes']);
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ class ComponentRenderer
|
||||||
$matches[attributes] = string of tag attributes (class="foo")
|
$matches[attributes] = string of tag attributes (class="foo")
|
||||||
$matches[slot] = the content inside the tags
|
$matches[slot] = the content inside the tags
|
||||||
*/
|
*/
|
||||||
return preg_replace_callback($pattern, function ($match): string {
|
return preg_replace_callback($pattern, function (array $match): string {
|
||||||
$view = $this->locateView($match['name']);
|
$view = $this->locateView($match['name']);
|
||||||
$attributes = $this->parseAttributes($match['attributes']);
|
$attributes = $this->parseAttributes($match['attributes']);
|
||||||
$attributes['slot'] = $match['slot'];
|
$attributes['slot'] = $match['slot'];
|
||||||
|
|
|
@ -94,13 +94,13 @@ class Vite
|
||||||
private function getHtmlTag(string $assetUrl, string $type): string
|
private function getHtmlTag(string $assetUrl, string $type): string
|
||||||
{
|
{
|
||||||
return match ($type) {
|
return match ($type) {
|
||||||
'css' => <<<CODE_SAMPLE
|
'css' => <<<HTML
|
||||||
<link rel="stylesheet" href="{$assetUrl}"/>
|
<link rel="stylesheet" href="{$assetUrl}"/>
|
||||||
CODE_SAMPLE
|
HTML
|
||||||
,
|
,
|
||||||
'js' => <<<CODE_SAMPLE
|
'js' => <<<HTML
|
||||||
<script type="module" src="{$assetUrl}"></script>
|
<script type="module" src="{$assetUrl}"></script>
|
||||||
CODE_SAMPLE
|
HTML
|
||||||
,
|
,
|
||||||
default => '',
|
default => '',
|
||||||
};
|
};
|
||||||
|
|
|
@ -67,15 +67,10 @@ class CategoryModel extends Model
|
||||||
static function (array $result, Category $category): array {
|
static function (array $result, Category $category): array {
|
||||||
$result[$category->id] = '';
|
$result[$category->id] = '';
|
||||||
if ($category->parent instanceof Category) {
|
if ($category->parent instanceof Category) {
|
||||||
$result[$category->id] = lang(
|
$result[$category->id] = lang('Podcast.category_options.' . $category->parent->code) . ' › ';
|
||||||
'Podcast.category_options.' . $category->parent->code,
|
|
||||||
[],
|
|
||||||
null,
|
|
||||||
false
|
|
||||||
) . ' › ';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$result[$category->id] .= lang('Podcast.category_options.' . $category->code, [], null, false);
|
$result[$category->id] .= lang('Podcast.category_options.' . $category->code);
|
||||||
return $result;
|
return $result;
|
||||||
},
|
},
|
||||||
[],
|
[],
|
||||||
|
|
|
@ -216,7 +216,7 @@ class EpisodeCommentModel extends UuidModel
|
||||||
)
|
)
|
||||||
->whereIn('in_reply_to_id', static function (BaseBuilder $builder) use (&$episodeId): BaseBuilder {
|
->whereIn('in_reply_to_id', static function (BaseBuilder $builder) use (&$episodeId): BaseBuilder {
|
||||||
return $builder->select('id')
|
return $builder->select('id')
|
||||||
->from(config('Fediverse')->tablesPrefix . 'posts')
|
->from('fediverse_posts')
|
||||||
->where([
|
->where([
|
||||||
'episode_id' => $episodeId,
|
'episode_id' => $episodeId,
|
||||||
'in_reply_to_id' => null,
|
'in_reply_to_id' => null,
|
||||||
|
|
|
@ -382,13 +382,11 @@ class EpisodeModel extends UuidModel
|
||||||
->groupBy('episode_id')
|
->groupBy('episode_id')
|
||||||
->getCompiledSelect();
|
->getCompiledSelect();
|
||||||
|
|
||||||
$postsTable = config('Fediverse')
|
|
||||||
->tablesPrefix . 'posts';
|
|
||||||
$episodePostsRepliesCount = (new PostModel())->builder()
|
$episodePostsRepliesCount = (new PostModel())->builder()
|
||||||
->select($postsTable . '.episode_id as episode_id, COUNT(*) as `comments_count`')
|
->select('fediverse_posts.episode_id as episode_id, COUNT(*) as `comments_count`')
|
||||||
->join($postsTable . ' as fp', $postsTable . '.id = fp.in_reply_to_id')
|
->join('fediverse_posts as fp', 'fediverse_posts.id = fp.in_reply_to_id')
|
||||||
->where($postsTable . '.in_reply_to_id', null)
|
->where('fediverse_posts.in_reply_to_id', null)
|
||||||
->groupBy($postsTable . '.episode_id')
|
->groupBy('fediverse_posts.episode_id')
|
||||||
->getCompiledSelect();
|
->getCompiledSelect();
|
||||||
|
|
||||||
/** @var BaseResult $query */
|
/** @var BaseResult $query */
|
||||||
|
@ -409,11 +407,7 @@ class EpisodeModel extends UuidModel
|
||||||
{
|
{
|
||||||
$episodePostsCount = $this->builder()
|
$episodePostsCount = $this->builder()
|
||||||
->select('episodes.id, COUNT(*) as `posts_count`')
|
->select('episodes.id, COUNT(*) as `posts_count`')
|
||||||
->join(
|
->join('fediverse_posts', 'episodes.id = fediverse_posts.episode_id')
|
||||||
config('Fediverse')
|
|
||||||
->tablesPrefix . 'posts',
|
|
||||||
'episodes.id = ' . config('Fediverse')->tablesPrefix . 'posts.episode_id'
|
|
||||||
)
|
|
||||||
->where('in_reply_to_id', null)
|
->where('in_reply_to_id', null)
|
||||||
->groupBy('episodes.id')
|
->groupBy('episodes.id')
|
||||||
->get()
|
->get()
|
||||||
|
|
|
@ -145,7 +145,7 @@ class PersonModel extends Model
|
||||||
$this->select('`id`, `full_name`')
|
$this->select('`id`, `full_name`')
|
||||||
->orderBy('`full_name`', 'ASC')
|
->orderBy('`full_name`', 'ASC')
|
||||||
->findAll(),
|
->findAll(),
|
||||||
static function ($result, $person) {
|
static function (array $result, $person): array {
|
||||||
$result[$person->id] = $person->full_name;
|
$result[$person->id] = $person->full_name;
|
||||||
return $result;
|
return $result;
|
||||||
},
|
},
|
||||||
|
|
|
@ -158,12 +158,12 @@ class PlatformModel extends Model
|
||||||
$podcastsPlatformsTable = $this->db->prefixTable('podcasts_platforms');
|
$podcastsPlatformsTable = $this->db->prefixTable('podcasts_platforms');
|
||||||
$platformsTable = $this->db->prefixTable('platforms');
|
$platformsTable = $this->db->prefixTable('platforms');
|
||||||
|
|
||||||
$deleteJoinQuery = <<<CODE_SAMPLE
|
$deleteJoinQuery = <<<SQL
|
||||||
DELETE {$podcastsPlatformsTable}
|
DELETE {$podcastsPlatformsTable}
|
||||||
FROM {$podcastsPlatformsTable}
|
FROM {$podcastsPlatformsTable}
|
||||||
INNER JOIN {$platformsTable} ON {$platformsTable}.slug = {$podcastsPlatformsTable}.platform_slug
|
INNER JOIN {$platformsTable} ON {$platformsTable}.slug = {$podcastsPlatformsTable}.platform_slug
|
||||||
WHERE `podcast_id` = ? AND `type` = ?
|
WHERE `podcast_id` = ? AND `type` = ?
|
||||||
CODE_SAMPLE;
|
SQL;
|
||||||
|
|
||||||
$this->db->query($deleteJoinQuery, [$podcastId, $platformType]);
|
$this->db->query($deleteJoinQuery, [$podcastId, $platformType]);
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,7 @@ class PodcastModel extends Model
|
||||||
* @var array<string, string>
|
* @var array<string, string>
|
||||||
*/
|
*/
|
||||||
protected $validationRules = [
|
protected $validationRules = [
|
||||||
|
'id' => 'permit_empty|is_natural_no_zero',
|
||||||
'title' => 'required',
|
'title' => 'required',
|
||||||
'handle' => 'required|regex_match[/^[a-zA-Z0-9\_]{1,32}$/]|is_unique[podcasts.handle,id,{id}]',
|
'handle' => 'required|regex_match[/^[a-zA-Z0-9\_]{1,32}$/]|is_unique[podcasts.handle,id,{id}]',
|
||||||
'description_markdown' => 'required',
|
'description_markdown' => 'required',
|
||||||
|
@ -174,23 +175,15 @@ class PodcastModel extends Model
|
||||||
$prefix = $this->db->getPrefix();
|
$prefix = $this->db->getPrefix();
|
||||||
|
|
||||||
if ($orderBy === 'activity') {
|
if ($orderBy === 'activity') {
|
||||||
$fediverseTablePrefix = $prefix . config('Fediverse')
|
|
||||||
->tablesPrefix;
|
|
||||||
$this->builder()
|
$this->builder()
|
||||||
->select(
|
->select('podcasts.*, MAX(`' . $prefix . 'fediverse_posts`.`published_at`) as max_published_at')
|
||||||
'podcasts.*, MAX(' . $fediverseTablePrefix . 'posts.published_at' . ') as max_published_at'
|
->join('fediverse_posts', 'fediverse_posts.actor_id = podcasts.actor_id', 'left')
|
||||||
)
|
|
||||||
->join(
|
|
||||||
$fediverseTablePrefix . 'posts',
|
|
||||||
$fediverseTablePrefix . 'posts.actor_id = podcasts.actor_id',
|
|
||||||
'left'
|
|
||||||
)
|
|
||||||
->groupStart()
|
->groupStart()
|
||||||
->where(
|
->where(
|
||||||
'`' . $fediverseTablePrefix . 'posts`.`published_at` <= UTC_TIMESTAMP()',
|
'`' . $prefix . 'fediverse_posts`.`published_at` <= UTC_TIMESTAMP()',
|
||||||
null,
|
null,
|
||||||
false
|
false
|
||||||
)->orWhere($fediverseTablePrefix . 'posts.published_at', null)
|
)->orWhere('fediverse_posts.published_at', null)
|
||||||
->groupEnd()
|
->groupEnd()
|
||||||
->groupBy('podcasts.actor_id')
|
->groupBy('podcasts.actor_id')
|
||||||
->orderBy('max_published_at', 'DESC');
|
->orderBy('max_published_at', 'DESC');
|
||||||
|
|
|
@ -58,8 +58,8 @@ class PostModel extends FediversePostModel
|
||||||
public function setEpisodeIdForRepliesOfEpisodePosts(): int | false
|
public function setEpisodeIdForRepliesOfEpisodePosts(): int | false
|
||||||
{
|
{
|
||||||
// make sure that posts in reply to episode activities have an episode id
|
// make sure that posts in reply to episode activities have an episode id
|
||||||
$postsToUpdate = $this->db->table(config('Fediverse')->tablesPrefix . 'posts as p1')
|
$postsToUpdate = $this->db->table('fediverse_posts as p1')
|
||||||
->join(config('Fediverse')->tablesPrefix . 'posts as p2', 'p1.id = p2.in_reply_to_id')
|
->join('fediverse_posts as p2', 'p1.id = p2.in_reply_to_id')
|
||||||
->select('p2.id, p1.episode_id')
|
->select('p2.id, p1.episode_id')
|
||||||
->where([
|
->where([
|
||||||
'p2.in_reply_to_id IS NOT' => null,
|
'p2.in_reply_to_id IS NOT' => null,
|
||||||
|
|
|
@ -82,7 +82,7 @@ class RolesDoc extends BaseCommand
|
||||||
$pattern,
|
$pattern,
|
||||||
['role', 'description', 'permissions'],
|
['role', 'description', 'permissions'],
|
||||||
$authGroups->instanceGroups,
|
$authGroups->instanceGroups,
|
||||||
static function ($table, $key, $value) use ($instanceMatrix): void {
|
static function ($table, $key, array $value) use ($instanceMatrix): void {
|
||||||
$table->addRow($value['title'], $value['description'], implode(', ', $instanceMatrix[$key]));
|
$table->addRow($value['title'], $value['description'], implode(', ', $instanceMatrix[$key]));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -109,7 +109,7 @@ class RolesDoc extends BaseCommand
|
||||||
$pattern,
|
$pattern,
|
||||||
['role', 'description', 'permissions'],
|
['role', 'description', 'permissions'],
|
||||||
$authGroups->podcastGroups,
|
$authGroups->podcastGroups,
|
||||||
static function ($table, $key, $value) use ($podcastMatrix): void {
|
static function ($table, $key, array $value) use ($podcastMatrix): void {
|
||||||
$table->addRow($value['title'], $value['description'], implode(', ', $podcastMatrix[$key]));
|
$table->addRow($value['title'], $value['description'], implode(', ', $podcastMatrix[$key]));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -83,7 +83,7 @@ class ContributorController extends BaseController
|
||||||
$users = (new UserModel())->findAll();
|
$users = (new UserModel())->findAll();
|
||||||
$contributorOptions = array_reduce(
|
$contributorOptions = array_reduce(
|
||||||
$users,
|
$users,
|
||||||
static function ($result, $user) {
|
static function (array $result, $user): array {
|
||||||
$result[$user->id] = $user->username;
|
$result[$user->id] = $user->username;
|
||||||
return $result;
|
return $result;
|
||||||
},
|
},
|
||||||
|
@ -94,7 +94,7 @@ class ContributorController extends BaseController
|
||||||
$roleOptions = [];
|
$roleOptions = [];
|
||||||
array_walk(
|
array_walk(
|
||||||
$roles,
|
$roles,
|
||||||
static function ($role, $key) use (&$roleOptions): array {
|
static function (string $role, $key) use (&$roleOptions): array {
|
||||||
$roleOptions[$role] = lang('Auth.podcast_groups.' . $role . '.title');
|
$roleOptions[$role] = lang('Auth.podcast_groups.' . $role . '.title');
|
||||||
return $roleOptions;
|
return $roleOptions;
|
||||||
},
|
},
|
||||||
|
@ -137,7 +137,7 @@ class ContributorController extends BaseController
|
||||||
$roleOptions = [];
|
$roleOptions = [];
|
||||||
array_walk(
|
array_walk(
|
||||||
$roles,
|
$roles,
|
||||||
static function ($role) use (&$roleOptions): array {
|
static function (string $role) use (&$roleOptions): array {
|
||||||
$roleOptions[$role] = lang('Auth.podcast_groups.' . $role . '.title');
|
$roleOptions[$role] = lang('Auth.podcast_groups.' . $role . '.title');
|
||||||
return $roleOptions;
|
return $roleOptions;
|
||||||
},
|
},
|
||||||
|
|
|
@ -66,7 +66,7 @@ class UserController extends BaseController
|
||||||
$roleOptions = [];
|
$roleOptions = [];
|
||||||
array_walk(
|
array_walk(
|
||||||
$roles,
|
$roles,
|
||||||
static function ($role, $key) use (&$roleOptions): array {
|
static function (array $role, $key) use (&$roleOptions): array {
|
||||||
$roleOptions[$key] = $role['title'];
|
$roleOptions[$key] = $role['title'];
|
||||||
return $roleOptions;
|
return $roleOptions;
|
||||||
},
|
},
|
||||||
|
@ -172,7 +172,7 @@ class UserController extends BaseController
|
||||||
$roleOptions = [];
|
$roleOptions = [];
|
||||||
array_walk(
|
array_walk(
|
||||||
$roles,
|
$roles,
|
||||||
static function ($role, $key) use (&$roleOptions): array {
|
static function (array $role, $key) use (&$roleOptions): array {
|
||||||
$roleOptions[$key] = $role['title'];
|
$roleOptions[$key] = $role['title'];
|
||||||
return $roleOptions;
|
return $roleOptions;
|
||||||
},
|
},
|
||||||
|
|
|
@ -38,8 +38,6 @@ class Fediverse extends BaseConfig
|
||||||
|
|
||||||
public string $defaultCoverImageMimetype = 'image/jpeg';
|
public string $defaultCoverImageMimetype = 'image/jpeg';
|
||||||
|
|
||||||
public string $tablesPrefix = 'fediverse_';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* --------------------------------------------------------------------
|
* --------------------------------------------------------------------
|
||||||
* Cache options
|
* Cache options
|
||||||
|
|
|
@ -291,14 +291,11 @@ class ActorController extends Controller
|
||||||
|
|
||||||
public function followers(): ResponseInterface
|
public function followers(): ResponseInterface
|
||||||
{
|
{
|
||||||
$tablesPrefix = config('Fediverse')
|
|
||||||
->tablesPrefix;
|
|
||||||
|
|
||||||
// get followers for a specific actor
|
// get followers for a specific actor
|
||||||
$followers = model('ActorModel', false)
|
$followers = model('ActorModel', false)
|
||||||
->join($tablesPrefix . 'follows', $tablesPrefix . 'follows.actor_id = id', 'inner')
|
->join('fediverse_follows', 'fediverse_follows.actor_id = id', 'inner')
|
||||||
->where($tablesPrefix . 'follows.target_actor_id', $this->actor->id)
|
->where('fediverse_follows.target_actor_id', $this->actor->id)
|
||||||
->orderBy($tablesPrefix . 'follows.created_at', 'DESC');
|
->orderBy('fediverse_follows.created_at', 'DESC');
|
||||||
|
|
||||||
$pageNumber = (int) $this->request->getGet('page');
|
$pageNumber = (int) $this->request->getGet('page');
|
||||||
|
|
||||||
|
|
|
@ -113,11 +113,11 @@ class AddActors extends BaseMigration
|
||||||
$this->forge->addPrimaryKey('id');
|
$this->forge->addPrimaryKey('id');
|
||||||
$this->forge->addUniqueKey('uri');
|
$this->forge->addUniqueKey('uri');
|
||||||
$this->forge->addUniqueKey(['username', 'domain']);
|
$this->forge->addUniqueKey(['username', 'domain']);
|
||||||
$this->forge->createTable(config('Fediverse')->tablesPrefix . 'actors');
|
$this->forge->createTable('fediverse_actors');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function down(): void
|
public function down(): void
|
||||||
{
|
{
|
||||||
$this->forge->dropTable(config('Fediverse')->tablesPrefix . 'actors');
|
$this->forge->dropTable('fediverse_actors');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,21 +75,18 @@ class AddPosts extends BaseMigration
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$tablesPrefix = config('Fediverse')
|
|
||||||
->tablesPrefix;
|
|
||||||
|
|
||||||
$this->forge->addPrimaryKey('id');
|
$this->forge->addPrimaryKey('id');
|
||||||
$this->forge->addUniqueKey('uri');
|
$this->forge->addUniqueKey('uri');
|
||||||
// FIXME: an actor must reblog a post only once
|
// FIXME: an actor must reblog a post only once
|
||||||
// $this->forge->addUniqueKey(['actor_id', 'reblog_of_id']);
|
// $this->forge->addUniqueKey(['actor_id', 'reblog_of_id']);
|
||||||
$this->forge->addForeignKey('actor_id', $tablesPrefix . 'actors', 'id', '', 'CASCADE');
|
$this->forge->addForeignKey('actor_id', 'fediverse_actors', 'id', '', 'CASCADE');
|
||||||
$this->forge->addForeignKey('in_reply_to_id', $tablesPrefix . 'posts', 'id', '', 'CASCADE');
|
$this->forge->addForeignKey('in_reply_to_id', 'fediverse_posts', 'id', '', 'CASCADE');
|
||||||
$this->forge->addForeignKey('reblog_of_id', $tablesPrefix . 'posts', 'id', '', 'CASCADE');
|
$this->forge->addForeignKey('reblog_of_id', 'fediverse_posts', 'id', '', 'CASCADE');
|
||||||
$this->forge->createTable($tablesPrefix . 'posts');
|
$this->forge->createTable('fediverse_posts');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function down(): void
|
public function down(): void
|
||||||
{
|
{
|
||||||
$this->forge->dropTable(config('Fediverse')->tablesPrefix . 'posts');
|
$this->forge->dropTable('fediverse_posts');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,18 +58,15 @@ class AddActivities extends BaseMigration
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$tablesPrefix = config('Fediverse')
|
|
||||||
->tablesPrefix;
|
|
||||||
|
|
||||||
$this->forge->addPrimaryKey('id');
|
$this->forge->addPrimaryKey('id');
|
||||||
$this->forge->addForeignKey('actor_id', $tablesPrefix . 'actors', 'id', '', 'CASCADE');
|
$this->forge->addForeignKey('actor_id', 'fediverse_actors', 'id', '', 'CASCADE');
|
||||||
$this->forge->addForeignKey('target_actor_id', $tablesPrefix . 'actors', 'id', '', 'CASCADE');
|
$this->forge->addForeignKey('target_actor_id', 'fediverse_actors', 'id', '', 'CASCADE');
|
||||||
$this->forge->addForeignKey('post_id', $tablesPrefix . 'posts', 'id', '', 'CASCADE');
|
$this->forge->addForeignKey('post_id', 'fediverse_posts', 'id', '', 'CASCADE');
|
||||||
$this->forge->createTable($tablesPrefix . 'activities');
|
$this->forge->createTable('fediverse_activities');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function down(): void
|
public function down(): void
|
||||||
{
|
{
|
||||||
$this->forge->dropTable(config('Fediverse')->tablesPrefix . 'activities');
|
$this->forge->dropTable('fediverse_activities');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,18 +29,15 @@ class AddFavourites extends BaseMigration
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$tablesPrefix = config('Fediverse')
|
|
||||||
->tablesPrefix;
|
|
||||||
|
|
||||||
$this->forge->addField('`created_at` timestamp NOT NULL DEFAULT current_timestamp()');
|
$this->forge->addField('`created_at` timestamp NOT NULL DEFAULT current_timestamp()');
|
||||||
$this->forge->addPrimaryKey(['actor_id', 'post_id']);
|
$this->forge->addPrimaryKey(['actor_id', 'post_id']);
|
||||||
$this->forge->addForeignKey('actor_id', $tablesPrefix . 'actors', 'id', '', 'CASCADE');
|
$this->forge->addForeignKey('actor_id', 'fediverse_actors', 'id', '', 'CASCADE');
|
||||||
$this->forge->addForeignKey('post_id', $tablesPrefix . 'posts', 'id', '', 'CASCADE');
|
$this->forge->addForeignKey('post_id', 'fediverse_posts', 'id', '', 'CASCADE');
|
||||||
$this->forge->createTable($tablesPrefix . 'favourites');
|
$this->forge->createTable('fediverse_favourites');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function down(): void
|
public function down(): void
|
||||||
{
|
{
|
||||||
$this->forge->dropTable(config('Fediverse')->tablesPrefix . 'favourites');
|
$this->forge->dropTable('fediverse_favourites');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,18 +31,15 @@ class AddFollowers extends BaseMigration
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$tablesPrefix = config('Fediverse')
|
|
||||||
->tablesPrefix;
|
|
||||||
|
|
||||||
$this->forge->addField('`created_at` timestamp NOT NULL DEFAULT current_timestamp()');
|
$this->forge->addField('`created_at` timestamp NOT NULL DEFAULT current_timestamp()');
|
||||||
$this->forge->addPrimaryKey(['actor_id', 'target_actor_id']);
|
$this->forge->addPrimaryKey(['actor_id', 'target_actor_id']);
|
||||||
$this->forge->addForeignKey('actor_id', $tablesPrefix . 'actors', 'id', '', 'CASCADE');
|
$this->forge->addForeignKey('actor_id', 'fediverse_actors', 'id', '', 'CASCADE');
|
||||||
$this->forge->addForeignKey('target_actor_id', $tablesPrefix . 'actors', 'id', '', 'CASCADE');
|
$this->forge->addForeignKey('target_actor_id', 'fediverse_actors', 'id', '', 'CASCADE');
|
||||||
$this->forge->createTable($tablesPrefix . 'follows');
|
$this->forge->createTable('fediverse_follows');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function down(): void
|
public function down(): void
|
||||||
{
|
{
|
||||||
$this->forge->dropTable(config('Fediverse')->tablesPrefix . 'follows');
|
$this->forge->dropTable('fediverse_follows');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,11 +75,11 @@ class AddPreviewCards extends BaseMigration
|
||||||
|
|
||||||
$this->forge->addPrimaryKey('id');
|
$this->forge->addPrimaryKey('id');
|
||||||
$this->forge->addUniqueKey('url');
|
$this->forge->addUniqueKey('url');
|
||||||
$this->forge->createTable(config('Fediverse')->tablesPrefix . 'preview_cards');
|
$this->forge->createTable('fediverse_preview_cards');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function down(): void
|
public function down(): void
|
||||||
{
|
{
|
||||||
$this->forge->dropTable(config('Fediverse')->tablesPrefix . 'preview_cards');
|
$this->forge->dropTable('fediverse_preview_cards');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,17 +29,14 @@ class AddPostsPreviewCards extends BaseMigration
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$tablesPrefix = config('Fediverse')
|
|
||||||
->tablesPrefix;
|
|
||||||
|
|
||||||
$this->forge->addPrimaryKey(['post_id', 'preview_card_id']);
|
$this->forge->addPrimaryKey(['post_id', 'preview_card_id']);
|
||||||
$this->forge->addForeignKey('post_id', $tablesPrefix . 'posts', 'id', '', 'CASCADE');
|
$this->forge->addForeignKey('post_id', 'fediverse_posts', 'id', '', 'CASCADE');
|
||||||
$this->forge->addForeignKey('preview_card_id', $tablesPrefix . 'preview_cards', 'id', '', 'CASCADE');
|
$this->forge->addForeignKey('preview_card_id', 'fediverse_preview_cards', 'id', '', 'CASCADE');
|
||||||
$this->forge->createTable($tablesPrefix . 'posts_preview_cards');
|
$this->forge->createTable('fediverse_posts_preview_cards');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function down(): void
|
public function down(): void
|
||||||
{
|
{
|
||||||
$this->forge->dropTable(config('Fediverse')->tablesPrefix . 'posts_preview_cards');
|
$this->forge->dropTable('fediverse_posts_preview_cards');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,11 +28,11 @@ class AddBlockedDomains extends BaseMigration
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
$this->forge->addPrimaryKey('name');
|
$this->forge->addPrimaryKey('name');
|
||||||
$this->forge->createTable(config('Fediverse')->tablesPrefix . 'blocked_domains');
|
$this->forge->createTable('fediverse_blocked_domains');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function down(): void
|
public function down(): void
|
||||||
{
|
{
|
||||||
$this->forge->dropTable(config('Fediverse')->tablesPrefix . 'blocked_domains');
|
$this->forge->dropTable('fediverse_blocked_domains');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,19 +55,16 @@ class AddNotifications extends BaseMigration
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$tablesPrefix = config('Fediverse')
|
|
||||||
->tablesPrefix;
|
|
||||||
|
|
||||||
$this->forge->addPrimaryKey('id');
|
$this->forge->addPrimaryKey('id');
|
||||||
$this->forge->addForeignKey('actor_id', $tablesPrefix . 'actors', 'id', '', 'CASCADE');
|
$this->forge->addForeignKey('actor_id', 'fediverse_actors', 'id', '', 'CASCADE');
|
||||||
$this->forge->addForeignKey('target_actor_id', $tablesPrefix . 'actors', 'id', '', 'CASCADE');
|
$this->forge->addForeignKey('target_actor_id', 'fediverse_actors', 'id', '', 'CASCADE');
|
||||||
$this->forge->addForeignKey('post_id', $tablesPrefix . 'posts', 'id', '', 'CASCADE');
|
$this->forge->addForeignKey('post_id', 'fediverse_posts', 'id', '', 'CASCADE');
|
||||||
$this->forge->addForeignKey('activity_id', $tablesPrefix . 'activities', 'id', '', 'CASCADE');
|
$this->forge->addForeignKey('activity_id', 'fediverse_activities', 'id', '', 'CASCADE');
|
||||||
$this->forge->createTable($tablesPrefix . 'notifications');
|
$this->forge->createTable('fediverse_notifications');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function down(): void
|
public function down(): void
|
||||||
{
|
{
|
||||||
$this->forge->dropTable(config('Fediverse')->tablesPrefix . 'notifications');
|
$this->forge->dropTable('fediverse_notifications');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -408,7 +408,7 @@ if (! function_exists('linkify')) {
|
||||||
),
|
),
|
||||||
'handle' => preg_replace_callback(
|
'handle' => preg_replace_callback(
|
||||||
'~(?<!\w)@(?<username>\w++)(?:@(?<domain>(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]))?~',
|
'~(?<!\w)@(?<username>\w++)(?:@(?<domain>(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]))?~',
|
||||||
static function ($match) use (&$links) {
|
static function (array $match) use (&$links) {
|
||||||
// check if host is set and look for actor in database
|
// check if host is set and look for actor in database
|
||||||
if (isset($match['host'])) {
|
if (isset($match['host'])) {
|
||||||
if (
|
if (
|
||||||
|
@ -489,7 +489,7 @@ if (! function_exists('linkify')) {
|
||||||
// Insert all links
|
// Insert all links
|
||||||
return preg_replace_callback(
|
return preg_replace_callback(
|
||||||
'~<(\d+)>~',
|
'~<(\d+)>~',
|
||||||
static function ($match) use (&$links) {
|
static function (array $match) use (&$links): string {
|
||||||
return $links[$match[1] - 1];
|
return $links[$match[1] - 1];
|
||||||
},
|
},
|
||||||
$text,
|
$text,
|
||||||
|
|
|
@ -13,14 +13,15 @@ namespace Modules\Fediverse\Models;
|
||||||
use CodeIgniter\Database\BaseResult;
|
use CodeIgniter\Database\BaseResult;
|
||||||
use CodeIgniter\I18n\Time;
|
use CodeIgniter\I18n\Time;
|
||||||
use DateTimeInterface;
|
use DateTimeInterface;
|
||||||
|
use Michalsn\Uuid\UuidModel;
|
||||||
use Modules\Fediverse\Entities\Activity;
|
use Modules\Fediverse\Entities\Activity;
|
||||||
|
|
||||||
class ActivityModel extends BaseUuidModel
|
class ActivityModel extends UuidModel
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $table = 'activities';
|
protected $table = 'fediverse_activities';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
|
|
|
@ -11,14 +11,15 @@ declare(strict_types=1);
|
||||||
namespace Modules\Fediverse\Models;
|
namespace Modules\Fediverse\Models;
|
||||||
|
|
||||||
use CodeIgniter\Events\Events;
|
use CodeIgniter\Events\Events;
|
||||||
|
use CodeIgniter\Model;
|
||||||
use Modules\Fediverse\Entities\Actor;
|
use Modules\Fediverse\Entities\Actor;
|
||||||
|
|
||||||
class ActorModel extends BaseModel
|
class ActorModel extends Model
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $table = 'actors';
|
protected $table = 'fediverse_actors';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string[]
|
* @var string[]
|
||||||
|
@ -119,10 +120,8 @@ class ActorModel extends BaseModel
|
||||||
config('Fediverse')
|
config('Fediverse')
|
||||||
->cachePrefix . "actor#{$actorId}_followers";
|
->cachePrefix . "actor#{$actorId}_followers";
|
||||||
if (! ($found = cache($cacheName))) {
|
if (! ($found = cache($cacheName))) {
|
||||||
$tablesPrefix = config('Fediverse')
|
$found = $this->join('fediverse_follows', 'fediverse_follows.actor_id = id', 'inner')
|
||||||
->tablesPrefix;
|
->where('fediverse_follows.target_actor_id', $actorId)
|
||||||
$found = $this->join($tablesPrefix . 'follows', $tablesPrefix . 'follows.actor_id = id', 'inner')
|
|
||||||
->where($tablesPrefix . 'follows.target_actor_id', $actorId)
|
|
||||||
->findAll();
|
->findAll();
|
||||||
|
|
||||||
cache()
|
cache()
|
||||||
|
@ -225,28 +224,27 @@ class ActorModel extends BaseModel
|
||||||
->cachePrefix . 'blocked_actors';
|
->cachePrefix . 'blocked_actors';
|
||||||
if (! ($found = cache($cacheName))) {
|
if (! ($found = cache($cacheName))) {
|
||||||
$tablePrefix = config('Database')
|
$tablePrefix = config('Database')
|
||||||
->default['DBPrefix'] . config('Fediverse')
|
->default['DBPrefix'];
|
||||||
->tablesPrefix;
|
|
||||||
$result = $this->select('COUNT(DISTINCT `cp_fediverse_actors`.`id`) as `total_active_actors`', false)
|
$result = $this->select('COUNT(DISTINCT `cp_fediverse_actors`.`id`) as `total_active_actors`', false)
|
||||||
->join(
|
->join(
|
||||||
$tablePrefix . 'posts',
|
$tablePrefix . 'fediverse_posts',
|
||||||
$tablePrefix . 'actors.id = ' . $tablePrefix . 'posts.actor_id',
|
$tablePrefix . 'fediverse_actors.id = ' . $tablePrefix . 'fediverse_posts.actor_id',
|
||||||
'left outer'
|
'left outer'
|
||||||
)
|
)
|
||||||
->join(
|
->join(
|
||||||
$tablePrefix . 'favourites',
|
$tablePrefix . 'fediverse_favourites',
|
||||||
$tablePrefix . 'actors.id = ' . $tablePrefix . 'favourites.actor_id',
|
$tablePrefix . 'fediverse_actors.id = ' . $tablePrefix . 'fediverse_favourites.actor_id',
|
||||||
'left outer'
|
'left outer'
|
||||||
)
|
)
|
||||||
->where($tablePrefix . 'actors.domain', get_current_domain())
|
->where($tablePrefix . 'actors.domain', get_current_domain())
|
||||||
->groupStart()
|
->groupStart()
|
||||||
->where(
|
->where(
|
||||||
"`{$tablePrefix}posts`.`created_at` >= UTC_TIMESTAMP() - INTERVAL {$lastNumberOfMonths} month",
|
"`{$tablePrefix}fediverse_posts`.`created_at` >= UTC_TIMESTAMP() - INTERVAL {$lastNumberOfMonths} month",
|
||||||
null,
|
null,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
->orWhere(
|
->orWhere(
|
||||||
"`{$tablePrefix}favourites`.`created_at` >= UTC_TIMESTAMP() - INTERVAL {$lastNumberOfMonths} month",
|
"`{$tablePrefix}fediverse_favourites`.`created_at` >= UTC_TIMESTAMP() - INTERVAL {$lastNumberOfMonths} month",
|
||||||
null,
|
null,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
|
@ -265,12 +263,8 @@ class ActorModel extends BaseModel
|
||||||
|
|
||||||
public function resetFollowersCount(): int | false
|
public function resetFollowersCount(): int | false
|
||||||
{
|
{
|
||||||
$tablePrefix = config('Fediverse')
|
$actorsFollowersCount = $this->db->table('fediverse_follows')
|
||||||
->tablesPrefix;
|
->select('target_actor_id as id, COUNT(*) as `followers_count`')
|
||||||
|
|
||||||
$actorsFollowersCount = $this->db->table($tablePrefix . 'follows')->select(
|
|
||||||
'target_actor_id as id, COUNT(*) as `followers_count`'
|
|
||||||
)
|
|
||||||
->groupBy('id')
|
->groupBy('id')
|
||||||
->get()
|
->get()
|
||||||
->getResultArray();
|
->getResultArray();
|
||||||
|
@ -284,10 +278,7 @@ class ActorModel extends BaseModel
|
||||||
|
|
||||||
public function resetPostsCount(): int | false
|
public function resetPostsCount(): int | false
|
||||||
{
|
{
|
||||||
$tablePrefix = config('Fediverse')
|
$actorsFollowersCount = $this->db->table($tablePrefix . 'fediverse_posts')->select(
|
||||||
->tablesPrefix;
|
|
||||||
|
|
||||||
$actorsFollowersCount = $this->db->table($tablePrefix . 'posts')->select(
|
|
||||||
'actor_id as id, COUNT(*) as `posts_count`'
|
'actor_id as id, COUNT(*) as `posts_count`'
|
||||||
)
|
)
|
||||||
->where([
|
->where([
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Modules\Fediverse\Models;
|
|
||||||
|
|
||||||
use CodeIgniter\Database\ConnectionInterface;
|
|
||||||
use CodeIgniter\Model;
|
|
||||||
use CodeIgniter\Validation\ValidationInterface;
|
|
||||||
|
|
||||||
class BaseModel extends Model
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Model constructor.
|
|
||||||
*
|
|
||||||
* @param ConnectionInterface|null $db DB Connection
|
|
||||||
* @param ValidationInterface|null $validation Validation
|
|
||||||
*/
|
|
||||||
public function __construct(ConnectionInterface &$db = null, ValidationInterface $validation = null)
|
|
||||||
{
|
|
||||||
parent::__construct($db, $validation);
|
|
||||||
|
|
||||||
$this->table = config('Fediverse')
|
|
||||||
->tablesPrefix . $this->table;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Modules\Fediverse\Models;
|
|
||||||
|
|
||||||
use CodeIgniter\Database\ConnectionInterface;
|
|
||||||
use CodeIgniter\Validation\ValidationInterface;
|
|
||||||
use Michalsn\Uuid\UuidModel;
|
|
||||||
|
|
||||||
class BaseUuidModel extends UuidModel
|
|
||||||
{
|
|
||||||
public function __construct(ConnectionInterface &$db = null, ValidationInterface $validation = null)
|
|
||||||
{
|
|
||||||
parent::__construct($db, $validation);
|
|
||||||
|
|
||||||
$this->table = config('Fediverse')
|
|
||||||
->tablesPrefix . $this->table;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -12,14 +12,15 @@ namespace Modules\Fediverse\Models;
|
||||||
|
|
||||||
use CodeIgniter\Database\BaseResult;
|
use CodeIgniter\Database\BaseResult;
|
||||||
use CodeIgniter\Events\Events;
|
use CodeIgniter\Events\Events;
|
||||||
|
use CodeIgniter\Model;
|
||||||
use Modules\Fediverse\Entities\BlockedDomain;
|
use Modules\Fediverse\Entities\BlockedDomain;
|
||||||
|
|
||||||
class BlockedDomainModel extends BaseModel
|
class BlockedDomainModel extends Model
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $table = 'blocked_domains';
|
protected $table = 'fediverse_blocked_domains';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
|
|
|
@ -11,18 +11,19 @@ declare(strict_types=1);
|
||||||
namespace Modules\Fediverse\Models;
|
namespace Modules\Fediverse\Models;
|
||||||
|
|
||||||
use CodeIgniter\Events\Events;
|
use CodeIgniter\Events\Events;
|
||||||
|
use Michalsn\Uuid\UuidModel;
|
||||||
use Modules\Fediverse\Activities\LikeActivity;
|
use Modules\Fediverse\Activities\LikeActivity;
|
||||||
use Modules\Fediverse\Activities\UndoActivity;
|
use Modules\Fediverse\Activities\UndoActivity;
|
||||||
use Modules\Fediverse\Entities\Actor;
|
use Modules\Fediverse\Entities\Actor;
|
||||||
use Modules\Fediverse\Entities\Favourite;
|
use Modules\Fediverse\Entities\Favourite;
|
||||||
use Modules\Fediverse\Entities\Post;
|
use Modules\Fediverse\Entities\Post;
|
||||||
|
|
||||||
class FavouriteModel extends BaseUuidModel
|
class FavouriteModel extends UuidModel
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $table = 'favourites';
|
protected $table = 'fediverse_favourites';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string[]
|
* @var string[]
|
||||||
|
|
|
@ -12,18 +12,19 @@ namespace Modules\Fediverse\Models;
|
||||||
|
|
||||||
use CodeIgniter\Events\Events;
|
use CodeIgniter\Events\Events;
|
||||||
use CodeIgniter\I18n\Time;
|
use CodeIgniter\I18n\Time;
|
||||||
|
use CodeIgniter\Model;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Modules\Fediverse\Activities\FollowActivity;
|
use Modules\Fediverse\Activities\FollowActivity;
|
||||||
use Modules\Fediverse\Activities\UndoActivity;
|
use Modules\Fediverse\Activities\UndoActivity;
|
||||||
use Modules\Fediverse\Entities\Actor;
|
use Modules\Fediverse\Entities\Actor;
|
||||||
use Modules\Fediverse\Entities\Follow;
|
use Modules\Fediverse\Entities\Follow;
|
||||||
|
|
||||||
class FollowModel extends BaseModel
|
class FollowModel extends Model
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $table = 'follows';
|
protected $table = 'fediverse_follows';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string[]
|
* @var string[]
|
||||||
|
|
|
@ -10,14 +10,15 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Modules\Fediverse\Models;
|
namespace Modules\Fediverse\Models;
|
||||||
|
|
||||||
|
use Michalsn\Uuid\UuidModel;
|
||||||
use Modules\Fediverse\Entities\Notification;
|
use Modules\Fediverse\Entities\Notification;
|
||||||
|
|
||||||
class NotificationModel extends BaseUuidModel
|
class NotificationModel extends UuidModel
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $table = 'notifications';
|
protected $table = 'fediverse_notifications';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
|
|
|
@ -15,6 +15,7 @@ use CodeIgniter\Events\Events;
|
||||||
use CodeIgniter\HTTP\URI;
|
use CodeIgniter\HTTP\URI;
|
||||||
use CodeIgniter\I18n\Time;
|
use CodeIgniter\I18n\Time;
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use Michalsn\Uuid\UuidModel;
|
||||||
use Modules\Fediverse\Activities\AnnounceActivity;
|
use Modules\Fediverse\Activities\AnnounceActivity;
|
||||||
use Modules\Fediverse\Activities\CreateActivity;
|
use Modules\Fediverse\Activities\CreateActivity;
|
||||||
use Modules\Fediverse\Activities\DeleteActivity;
|
use Modules\Fediverse\Activities\DeleteActivity;
|
||||||
|
@ -23,12 +24,12 @@ use Modules\Fediverse\Entities\Actor;
|
||||||
use Modules\Fediverse\Entities\Post;
|
use Modules\Fediverse\Entities\Post;
|
||||||
use Modules\Fediverse\Objects\TombstoneObject;
|
use Modules\Fediverse\Objects\TombstoneObject;
|
||||||
|
|
||||||
class PostModel extends BaseUuidModel
|
class PostModel extends UuidModel
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $table = 'posts';
|
protected $table = 'fediverse_posts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
|
@ -172,16 +173,10 @@ class PostModel extends BaseUuidModel
|
||||||
($withBlocked ? '_withBlocked' : '');
|
($withBlocked ? '_withBlocked' : '');
|
||||||
|
|
||||||
if (! ($found = cache($cacheName))) {
|
if (! ($found = cache($cacheName))) {
|
||||||
$tablesPrefix = config('Fediverse')
|
|
||||||
->tablesPrefix;
|
|
||||||
if (! $withBlocked) {
|
if (! $withBlocked) {
|
||||||
$this->select($tablesPrefix . 'posts.*')
|
$this->select('fediverse_posts.*')
|
||||||
->join(
|
->join('fediverse_actors', 'fediverse_actors.id = fediverse_posts.actor_id', 'inner')
|
||||||
$tablesPrefix . 'actors',
|
->where('fediverse_actors.is_blocked', 0);
|
||||||
$tablesPrefix . 'actors.id = ' . $tablesPrefix . 'posts.actor_id',
|
|
||||||
'inner'
|
|
||||||
)
|
|
||||||
->where($tablesPrefix . 'actors.is_blocked', 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->where('in_reply_to_id', $this->uuid->fromString($postId) ->getBytes())
|
$this->where('in_reply_to_id', $this->uuid->fromString($postId) ->getBytes())
|
||||||
|
@ -222,7 +217,7 @@ class PostModel extends BaseUuidModel
|
||||||
|
|
||||||
public function addPreviewCard(string $postId, int $previewCardId): bool
|
public function addPreviewCard(string $postId, int $previewCardId): bool
|
||||||
{
|
{
|
||||||
return $this->db->table(config('Fediverse')->tablesPrefix . 'posts_preview_cards')
|
return $this->db->table('fediverse_posts_preview_cards')
|
||||||
->insert([
|
->insert([
|
||||||
'post_id' => $this->uuid->fromString($postId)
|
'post_id' => $this->uuid->fromString($postId)
|
||||||
->getBytes(),
|
->getBytes(),
|
||||||
|
@ -370,7 +365,7 @@ class PostModel extends BaseUuidModel
|
||||||
if (
|
if (
|
||||||
$post->preview_card &&
|
$post->preview_card &&
|
||||||
$this->db
|
$this->db
|
||||||
->table(config('Fediverse')->tablesPrefix . 'posts_preview_cards')
|
->table('fediverse_posts_preview_cards')
|
||||||
->where('preview_card_id', $post->preview_card->id)
|
->where('preview_card_id', $post->preview_card->id)
|
||||||
->countAll() <= 1
|
->countAll() <= 1
|
||||||
) {
|
) {
|
||||||
|
@ -599,11 +594,9 @@ class PostModel extends BaseUuidModel
|
||||||
$cacheName = config('Fediverse')
|
$cacheName = config('Fediverse')
|
||||||
->cachePrefix . 'blocked_actors';
|
->cachePrefix . 'blocked_actors';
|
||||||
if (! ($found = cache($cacheName))) {
|
if (! ($found = cache($cacheName))) {
|
||||||
$tablePrefix = config('Fediverse')
|
|
||||||
->tablesPrefix;
|
|
||||||
$result = $this->select('COUNT(*) as total_local_posts')
|
$result = $this->select('COUNT(*) as total_local_posts')
|
||||||
->join($tablePrefix . 'actors', $tablePrefix . 'actors.id = ' . $tablePrefix . 'posts.actor_id')
|
->join('fediverse_actors', 'fediverse_actors.id = fediverse_posts.actor_id')
|
||||||
->where($tablePrefix . 'actors.domain', get_current_domain())
|
->where('fediverse_actors.domain', get_current_domain())
|
||||||
->where('`published_at` <= UTC_TIMESTAMP()', null, false)
|
->where('`published_at` <= UTC_TIMESTAMP()', null, false)
|
||||||
->get()
|
->get()
|
||||||
->getResultArray();
|
->getResultArray();
|
||||||
|
@ -619,12 +612,8 @@ class PostModel extends BaseUuidModel
|
||||||
|
|
||||||
public function resetFavouritesCount(): int | false
|
public function resetFavouritesCount(): int | false
|
||||||
{
|
{
|
||||||
$tablePrefix = config('Fediverse')
|
$postsFavouritesCount = $this->db->table('fediverse_favourites')
|
||||||
->tablesPrefix;
|
->select('post_id as id, COUNT(*) as `favourites_count`')
|
||||||
|
|
||||||
$postsFavouritesCount = $this->db->table($tablePrefix . 'favourites')->select(
|
|
||||||
'post_id as id, COUNT(*) as `favourites_count`'
|
|
||||||
)
|
|
||||||
->groupBy('id')
|
->groupBy('id')
|
||||||
->get()
|
->get()
|
||||||
->getResultArray();
|
->getResultArray();
|
||||||
|
@ -639,12 +628,9 @@ class PostModel extends BaseUuidModel
|
||||||
|
|
||||||
public function resetReblogsCount(): int | false
|
public function resetReblogsCount(): int | false
|
||||||
{
|
{
|
||||||
$tablePrefix = config('Fediverse')
|
$postsReblogsCount = $this->select('fediverse_posts.id, COUNT(*) as `replies_count`')
|
||||||
->tablesPrefix;
|
->join('fediverse_posts as p2', 'fediverse_posts.id = p2.reblog_of_id')
|
||||||
|
->groupBy('fediverse_posts.id')
|
||||||
$postsReblogsCount = $this->select($tablePrefix . 'posts.id, COUNT(*) as `replies_count`')
|
|
||||||
->join($tablePrefix . 'posts as p2', $tablePrefix . 'posts.id = p2.reblog_of_id')
|
|
||||||
->groupBy($tablePrefix . 'posts.id')
|
|
||||||
->get()
|
->get()
|
||||||
->getResultArray();
|
->getResultArray();
|
||||||
|
|
||||||
|
@ -658,12 +644,9 @@ class PostModel extends BaseUuidModel
|
||||||
|
|
||||||
public function resetRepliesCount(): int | false
|
public function resetRepliesCount(): int | false
|
||||||
{
|
{
|
||||||
$tablePrefix = config('Fediverse')
|
$postsRepliesCount = $this->select('fediverse_posts.id, COUNT(*) as `replies_count`')
|
||||||
->tablesPrefix;
|
->join('fediverse_posts as p2', 'fediverse_posts.id = p2.in_reply_to_id')
|
||||||
|
->groupBy('fediverse_posts.id')
|
||||||
$postsRepliesCount = $this->select($tablePrefix . 'posts.id, COUNT(*) as `replies_count`')
|
|
||||||
->join($tablePrefix . 'posts as p2', $tablePrefix . 'posts.id = p2.in_reply_to_id')
|
|
||||||
->groupBy($tablePrefix . 'posts.id')
|
|
||||||
->get()
|
->get()
|
||||||
->getResultArray();
|
->getResultArray();
|
||||||
|
|
||||||
|
|
|
@ -11,14 +11,15 @@ declare(strict_types=1);
|
||||||
namespace Modules\Fediverse\Models;
|
namespace Modules\Fediverse\Models;
|
||||||
|
|
||||||
use CodeIgniter\Database\BaseResult;
|
use CodeIgniter\Database\BaseResult;
|
||||||
|
use CodeIgniter\Model;
|
||||||
use Modules\Fediverse\Entities\PreviewCard;
|
use Modules\Fediverse\Entities\PreviewCard;
|
||||||
|
|
||||||
class PreviewCardModel extends BaseModel
|
class PreviewCardModel extends Model
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $table = 'preview_cards';
|
protected $table = 'fediverse_preview_cards';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string[]
|
* @var string[]
|
||||||
|
@ -75,11 +76,9 @@ class PreviewCardModel extends BaseModel
|
||||||
config('Fediverse')
|
config('Fediverse')
|
||||||
->cachePrefix . "post#{$postId}_preview_card";
|
->cachePrefix . "post#{$postId}_preview_card";
|
||||||
if (! ($found = cache($cacheName))) {
|
if (! ($found = cache($cacheName))) {
|
||||||
$tablesPrefix = config('Fediverse')
|
|
||||||
->tablesPrefix;
|
|
||||||
$found = $this->join(
|
$found = $this->join(
|
||||||
$tablesPrefix . 'posts_preview_cards',
|
'fediverse_posts_preview_cards',
|
||||||
$tablesPrefix . 'posts_preview_cards.preview_card_id = id',
|
'fediverse_posts_preview_cards.preview_card_id = id',
|
||||||
'inner',
|
'inner',
|
||||||
)
|
)
|
||||||
->where('post_id', service('uuid') ->fromString($postId) ->getBytes())
|
->where('post_id', service('uuid') ->fromString($postId) ->getBytes())
|
||||||
|
|
|
@ -243,8 +243,6 @@ class InstallController extends Controller
|
||||||
{
|
{
|
||||||
$migrate = Services::migrations();
|
$migrate = Services::migrations();
|
||||||
|
|
||||||
$migrate->setNamespace('CodeIgniter\Settings')
|
|
||||||
->latest();
|
|
||||||
$migrate->setNamespace(null)
|
$migrate->setNamespace(null)
|
||||||
->latest();
|
->latest();
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ if (! function_exists('media_url')) {
|
||||||
$relativePath = implode('/', $relativePath);
|
$relativePath = implode('/', $relativePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
$uri = new URI(rtrim((string) config(Media::class)->baseURL, '/') . '/' . ltrim($relativePath));
|
$uri = new URI(rtrim(config(Media::class)->baseURL, '/') . '/' . ltrim($relativePath));
|
||||||
|
|
||||||
return URI::createURIString(
|
return URI::createURIString(
|
||||||
$scheme ?? $uri->getScheme(),
|
$scheme ?? $uri->getScheme(),
|
||||||
|
|
|
@ -18,6 +18,7 @@ use CodeIgniter\CLI\BaseCommand;
|
||||||
use CodeIgniter\CLI\CLI;
|
use CodeIgniter\CLI\CLI;
|
||||||
use CodeIgniter\I18n\Time;
|
use CodeIgniter\I18n\Time;
|
||||||
use CodeIgniter\Shield\Entities\User;
|
use CodeIgniter\Shield\Entities\User;
|
||||||
|
use Config\Services;
|
||||||
use Exception;
|
use Exception;
|
||||||
use League\HTMLToMarkdown\HtmlConverter;
|
use League\HTMLToMarkdown\HtmlConverter;
|
||||||
use Modules\Auth\Models\UserModel;
|
use Modules\Auth\Models\UserModel;
|
||||||
|
@ -95,6 +96,9 @@ class PodcastImport extends BaseCommand
|
||||||
|
|
||||||
public function run(array $params): void
|
public function run(array $params): void
|
||||||
{
|
{
|
||||||
|
// FIXME: getting named routes doesn't work from v4.3 anymore, so loading all routes before importing
|
||||||
|
Services::routes()->loadRoutes();
|
||||||
|
|
||||||
$this->init();
|
$this->init();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -503,7 +507,7 @@ class PodcastImport extends BaseCommand
|
||||||
->get()
|
->get()
|
||||||
->getResultArray();
|
->getResultArray();
|
||||||
|
|
||||||
return array_map(static function ($element) {
|
return array_map(static function (array $element) {
|
||||||
return $element['guid'];
|
return $element['guid'];
|
||||||
}, $result);
|
}, $result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,6 @@ class DatabaseUpdate extends BaseCommand
|
||||||
{
|
{
|
||||||
$migrate = Services::migrations();
|
$migrate = Services::migrations();
|
||||||
|
|
||||||
$migrate->setNamespace('CodeIgniter\Settings')
|
|
||||||
->latest();
|
|
||||||
$migrate->setNamespace(null)
|
$migrate->setNamespace(null)
|
||||||
->latest();
|
->latest();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,14 +16,14 @@ class AddIsPublishedOnHubsToPodcasts extends BaseMigration
|
||||||
{
|
{
|
||||||
public function up(): void
|
public function up(): void
|
||||||
{
|
{
|
||||||
$prefix = $this->db->getPrefix();
|
$this->forge->addColumn('podcasts', [
|
||||||
|
'is_published_on_hubs' => [
|
||||||
$createQuery = <<<CODE_SAMPLE
|
'type' => 'BOOLEAN',
|
||||||
ALTER TABLE {$prefix}podcasts
|
'null' => false,
|
||||||
ADD COLUMN `is_published_on_hubs` BOOLEAN NOT NULL DEFAULT 0 AFTER `custom_rss`;
|
'default' => 0,
|
||||||
CODE_SAMPLE;
|
'after' => 'custom_rss',
|
||||||
|
],
|
||||||
$this->db->query($createQuery);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function down(): void
|
public function down(): void
|
||||||
|
|
|
@ -16,14 +16,14 @@ class AddIsPublishedOnHubsToEpisodes extends BaseMigration
|
||||||
{
|
{
|
||||||
public function up(): void
|
public function up(): void
|
||||||
{
|
{
|
||||||
$prefix = $this->db->getPrefix();
|
$this->forge->addColumn('episodes', [
|
||||||
|
'is_published_on_hubs' => [
|
||||||
$createQuery = <<<CODE_SAMPLE
|
'type' => 'BOOLEAN',
|
||||||
ALTER TABLE {$prefix}episodes
|
'null' => false,
|
||||||
ADD COLUMN `is_published_on_hubs` BOOLEAN NOT NULL DEFAULT 0 AFTER `custom_rss`;
|
'default' => 0,
|
||||||
CODE_SAMPLE;
|
'after' => 'custom_rss',
|
||||||
|
],
|
||||||
$this->db->query($createQuery);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function down(): void
|
public function down(): void
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
use Rector\CodeQuality\Rector\PropertyFetch\ExplicitMethodCallOverMagicGetSetRector;
|
|
||||||
use Rector\CodingStyle\Rector\ClassMethod\UnSpreadOperatorRector;
|
use Rector\CodingStyle\Rector\ClassMethod\UnSpreadOperatorRector;
|
||||||
use Rector\CodingStyle\Rector\Encapsed\EncapsedStringsToSprintfRector;
|
use Rector\CodingStyle\Rector\Encapsed\EncapsedStringsToSprintfRector;
|
||||||
use Rector\CodingStyle\Rector\Stmt\NewlineAfterStatementRector;
|
use Rector\CodingStyle\Rector\Stmt\NewlineAfterStatementRector;
|
||||||
|
@ -13,7 +12,6 @@ use Rector\DeadCode\Rector\If_\UnwrapFutureCompatibleIfPhpVersionRector;
|
||||||
use Rector\DeadCode\Rector\Stmt\RemoveUnreachableStatementRector;
|
use Rector\DeadCode\Rector\Stmt\RemoveUnreachableStatementRector;
|
||||||
use Rector\EarlyReturn\Rector\If_\ChangeAndIfToEarlyReturnRector;
|
use Rector\EarlyReturn\Rector\If_\ChangeAndIfToEarlyReturnRector;
|
||||||
use Rector\EarlyReturn\Rector\If_\ChangeOrIfContinueToMultiContinueRector;
|
use Rector\EarlyReturn\Rector\If_\ChangeOrIfContinueToMultiContinueRector;
|
||||||
use Rector\EarlyReturn\Rector\If_\ChangeOrIfReturnToEarlyReturnRector;
|
|
||||||
use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector;
|
use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector;
|
||||||
use Rector\Php71\Rector\FuncCall\RemoveExtraParametersRector;
|
use Rector\Php71\Rector\FuncCall\RemoveExtraParametersRector;
|
||||||
use Rector\Set\ValueObject\SetList;
|
use Rector\Set\ValueObject\SetList;
|
||||||
|
@ -49,11 +47,9 @@ return static function (RectorConfig $rectorConfig): void {
|
||||||
__DIR__ . '/modules/Admin/Language/*/PersonsTaxonomy.php',
|
__DIR__ . '/modules/Admin/Language/*/PersonsTaxonomy.php',
|
||||||
|
|
||||||
// skip rules from used sets
|
// skip rules from used sets
|
||||||
ChangeOrIfReturnToEarlyReturnRector::class,
|
|
||||||
ChangeOrIfContinueToMultiContinueRector::class,
|
ChangeOrIfContinueToMultiContinueRector::class,
|
||||||
EncapsedStringsToSprintfRector::class,
|
EncapsedStringsToSprintfRector::class,
|
||||||
UnSpreadOperatorRector::class,
|
UnSpreadOperatorRector::class,
|
||||||
ExplicitMethodCallOverMagicGetSetRector::class,
|
|
||||||
RemoveExtraParametersRector::class,
|
RemoveExtraParametersRector::class,
|
||||||
UnwrapFutureCompatibleIfPhpVersionRector::class,
|
UnwrapFutureCompatibleIfPhpVersionRector::class,
|
||||||
|
|
||||||
|
|
|
@ -31,9 +31,9 @@ $userPodcasts = get_podcasts_user_can_interact_with(auth()->user()); ?>
|
||||||
$items = [
|
$items = [
|
||||||
[
|
[
|
||||||
'type' => 'html',
|
'type' => 'html',
|
||||||
'content' => esc(<<<CODE_SAMPLE
|
'content' => esc(<<<HTML
|
||||||
<span class="px-4 my-2 text-xs font-semibold tracking-wider uppercase text-skin-muted">{$notificationsTitle}</span>
|
<span class="px-4 my-2 text-xs font-semibold tracking-wider uppercase text-skin-muted">{$notificationsTitle}</span>
|
||||||
CODE_SAMPLE),
|
HTML),
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ if ($userPodcasts !== []) {
|
||||||
|
|
||||||
$items[] = [
|
$items[] = [
|
||||||
'type' => 'link',
|
'type' => 'link',
|
||||||
'title' => <<<CODE_SAMPLE
|
'title' => <<<HTML
|
||||||
<div class="inline-flex items-center flex-1 text-sm align-middle">
|
<div class="inline-flex items-center flex-1 text-sm align-middle">
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<img src="{$userPodcast->cover->tiny_url}" class="w-6 h-6 mr-2 rounded-full" loading="lazy" />
|
<img src="{$userPodcast->cover->tiny_url}" class="w-6 h-6 mr-2 rounded-full" loading="lazy" />
|
||||||
|
@ -53,7 +53,7 @@ if ($userPodcasts !== []) {
|
||||||
</div>
|
</div>
|
||||||
<span class="max-w-xs truncate">{$userPodcastTitle}</span>
|
<span class="max-w-xs truncate">{$userPodcastTitle}</span>
|
||||||
</div>
|
</div>
|
||||||
CODE_SAMPLE
|
HTML
|
||||||
,
|
,
|
||||||
'uri' => route_to('notification-list', $userPodcast->id),
|
'uri' => route_to('notification-list', $userPodcast->id),
|
||||||
];
|
];
|
||||||
|
@ -62,9 +62,9 @@ if ($userPodcasts !== []) {
|
||||||
$noNotificationsText = lang('Notifications.no_notifications');
|
$noNotificationsText = lang('Notifications.no_notifications');
|
||||||
$items[] = [
|
$items[] = [
|
||||||
'type' => 'html',
|
'type' => 'html',
|
||||||
'content' => esc(<<<CODE_SAMPLE
|
'content' => esc(<<<HTML
|
||||||
<span class="mx-4 my-2 text-sm italic text-center text-skin-muted">{$noNotificationsText}</span>
|
<span class="mx-4 my-2 text-sm italic text-center text-skin-muted">{$noNotificationsText}</span>
|
||||||
CODE_SAMPLE),
|
HTML),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
@ -90,11 +90,11 @@ foreach ($userPodcasts as $userPodcast) {
|
||||||
$checkMark = interact_as_actor_id() === $userPodcast->actor_id ? icon('check', 'ml-2 bg-accent-base text-accent-contrast rounded-full') : '';
|
$checkMark = interact_as_actor_id() === $userPodcast->actor_id ? icon('check', 'ml-2 bg-accent-base text-accent-contrast rounded-full') : '';
|
||||||
$userPodcastTitle = esc($userPodcast->title);
|
$userPodcastTitle = esc($userPodcast->title);
|
||||||
|
|
||||||
$interactButtons .= <<<CODE_SAMPLE
|
$interactButtons .= <<<HTML
|
||||||
<button class="inline-flex items-center w-full px-4 py-1 hover:bg-highlight" id="interact-as-actor-{$userPodcast->id}" name="actor_id" value="{$userPodcast->actor_id}">
|
<button class="inline-flex items-center w-full px-4 py-1 hover:bg-highlight" id="interact-as-actor-{$userPodcast->id}" name="actor_id" value="{$userPodcast->actor_id}">
|
||||||
<div class="inline-flex items-center flex-1 text-sm"><img src="{$userPodcast->cover->tiny_url}" class="w-6 h-6 mr-2 rounded-full" loading="lazy" /><span class="max-w-xs truncate">{$userPodcastTitle}</span>{$checkMark}</div>
|
<div class="inline-flex items-center flex-1 text-sm"><img src="{$userPodcast->cover->tiny_url}" class="w-6 h-6 mr-2 rounded-full" loading="lazy" /><span class="max-w-xs truncate">{$userPodcastTitle}</span>{$checkMark}</div>
|
||||||
</button>
|
</button>
|
||||||
CODE_SAMPLE;
|
HTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
$interactAsText = lang('Common.choose_interact');
|
$interactAsText = lang('Common.choose_interact');
|
||||||
|
@ -126,7 +126,7 @@ if ($userPodcasts !== []) {
|
||||||
$menuItems = array_merge([
|
$menuItems = array_merge([
|
||||||
[
|
[
|
||||||
'type' => 'html',
|
'type' => 'html',
|
||||||
'content' => esc(<<<CODE_SAMPLE
|
'content' => esc(<<<HTML
|
||||||
<nav class="flex flex-col py-2 whitespace-nowrap">
|
<nav class="flex flex-col py-2 whitespace-nowrap">
|
||||||
<span class="px-4 mb-2 text-xs font-semibold tracking-wider uppercase text-skin-muted">{$interactAsText}</span>
|
<span class="px-4 mb-2 text-xs font-semibold tracking-wider uppercase text-skin-muted">{$interactAsText}</span>
|
||||||
<form action="{$interactAsRoute}" method="POST" class="flex flex-col">
|
<form action="{$interactAsRoute}" method="POST" class="flex flex-col">
|
||||||
|
@ -134,7 +134,7 @@ if ($userPodcasts !== []) {
|
||||||
{$interactButtons}
|
{$interactButtons}
|
||||||
</form>
|
</form>
|
||||||
</nav>
|
</nav>
|
||||||
CODE_SAMPLE),
|
HTML),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'type' => 'separator',
|
'type' => 'separator',
|
||||||
|
|
|
@ -66,9 +66,9 @@ if ($episode->published_at === null) {
|
||||||
$title = lang('Episode.messages.unpublishBeforeDeleteTip');
|
$title = lang('Episode.messages.unpublishBeforeDeleteTip');
|
||||||
$items[] = [
|
$items[] = [
|
||||||
'type' => 'html',
|
'type' => 'html',
|
||||||
'content' => esc(<<<CODE_SAMPLE
|
'content' => esc(<<<HTML
|
||||||
<span class="inline-flex items-center px-4 py-1 font-semibold text-gray-400 cursor-not-allowed" data-tooltip="bottom" title="{$title}">{$icon}{$label}</span>
|
<span class="inline-flex items-center px-4 py-1 font-semibold text-gray-400 cursor-not-allowed" data-tooltip="bottom" title="{$title}">{$icon}{$label}</span>
|
||||||
CODE_SAMPLE),
|
HTML),
|
||||||
];
|
];
|
||||||
} ?>
|
} ?>
|
||||||
<DropdownMenu id="more-dropdown-<?= $episode->id ?>-menu" labelledby="more-dropdown-<?= $episode->id ?>" offsetY="-32" items="<?= esc(json_encode($items)) ?>" />
|
<DropdownMenu id="more-dropdown-<?= $episode->id ?>-menu" labelledby="more-dropdown-<?= $episode->id ?>" offsetY="-32" items="<?= esc(json_encode($items)) ?>" />
|
||||||
|
|
|
@ -149,9 +149,9 @@ data_table(
|
||||||
$title = lang('Episode.messages.unpublishBeforeDeleteTip');
|
$title = lang('Episode.messages.unpublishBeforeDeleteTip');
|
||||||
$items[] = [
|
$items[] = [
|
||||||
'type' => 'html',
|
'type' => 'html',
|
||||||
'content' => esc(<<<CODE_SAMPLE
|
'content' => esc(<<<HTML
|
||||||
<span class="inline-flex items-center px-4 py-1 font-semibold text-gray-400 cursor-not-allowed" data-tooltip="bottom" title="{$title}">{$icon}<span class="ml-2">{$label}</span></span>
|
<span class="inline-flex items-center px-4 py-1 font-semibold text-gray-400 cursor-not-allowed" data-tooltip="bottom" title="{$title}">{$icon}<span class="ml-2">{$label}</span></span>
|
||||||
CODE_SAMPLE),
|
HTML),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
return '<button id="more-dropdown-' . $episode->id . '" type="button" class="inline-flex items-center p-1 rounded-full focus:ring-accent" data-dropdown="button" data-dropdown-target="more-dropdown-' . $episode->id . '-menu" aria-haspopup="true" aria-expanded="false">' .
|
return '<button id="more-dropdown-' . $episode->id . '" type="button" class="inline-flex items-center p-1 rounded-full focus:ring-accent" data-dropdown="button" data-dropdown-target="more-dropdown-' . $episode->id . '-menu" aria-haspopup="true" aria-expanded="false">' .
|
||||||
|
|
|
@ -31,15 +31,15 @@
|
||||||
? ''
|
? ''
|
||||||
: '@' . esc($notification->actor->domain));
|
: '@' . esc($notification->actor->domain));
|
||||||
|
|
||||||
$actorUsernameHtml = <<<CODE_SAMPLE
|
$actorUsernameHtml = <<<HTML
|
||||||
<strong class="break-all">{$actorUsername}</strong>
|
<strong class="break-all">{$actorUsername}</strong>
|
||||||
CODE_SAMPLE;
|
HTML;
|
||||||
|
|
||||||
$targetActorUsername = '@' . esc($notification->target_actor->username);
|
$targetActorUsername = '@' . esc($notification->target_actor->username);
|
||||||
|
|
||||||
$targetActorUsernameHtml = <<<CODE_SAMPLE
|
$targetActorUsernameHtml = <<<HTML
|
||||||
<strong class="break-all">{$targetActorUsername}</strong>
|
<strong class="break-all">{$targetActorUsername}</strong>
|
||||||
CODE_SAMPLE;
|
HTML;
|
||||||
|
|
||||||
$notificationTitle = match ($notification->type) {
|
$notificationTitle = match ($notification->type) {
|
||||||
'reply' => lang('Notifications.reply', [
|
'reply' => lang('Notifications.reply', [
|
||||||
|
|
|
@ -26,9 +26,9 @@ $userPodcasts = get_podcasts_user_can_interact_with(auth()->user()); ?>
|
||||||
$items = [
|
$items = [
|
||||||
[
|
[
|
||||||
'type' => 'html',
|
'type' => 'html',
|
||||||
'content' => esc(<<<CODE_SAMPLE
|
'content' => esc(<<<HTML
|
||||||
<span class="px-4 my-2 text-xs font-semibold tracking-wider uppercase text-skin-muted">{$notificationsTitle}</span>
|
<span class="px-4 my-2 text-xs font-semibold tracking-wider uppercase text-skin-muted">{$notificationsTitle}</span>
|
||||||
CODE_SAMPLE),
|
HTML),
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ if ($userPodcasts !== []) {
|
||||||
|
|
||||||
$items[] = [
|
$items[] = [
|
||||||
'type' => 'link',
|
'type' => 'link',
|
||||||
'title' => <<<CODE_SAMPLE
|
'title' => <<<HTML
|
||||||
<div class="inline-flex items-center flex-1 text-sm align-middle">
|
<div class="inline-flex items-center flex-1 text-sm align-middle">
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<img src="{$userPodcast->cover->tiny_url}" class="w-6 h-6 mr-2 rounded-full" loading="lazy" />
|
<img src="{$userPodcast->cover->tiny_url}" class="w-6 h-6 mr-2 rounded-full" loading="lazy" />
|
||||||
|
@ -48,7 +48,7 @@ if ($userPodcasts !== []) {
|
||||||
</div>
|
</div>
|
||||||
<span class="max-w-xs truncate">{$userPodcastTitle}</span>
|
<span class="max-w-xs truncate">{$userPodcastTitle}</span>
|
||||||
</div>
|
</div>
|
||||||
CODE_SAMPLE
|
HTML
|
||||||
,
|
,
|
||||||
'uri' => route_to('notification-list', $userPodcast->id),
|
'uri' => route_to('notification-list', $userPodcast->id),
|
||||||
];
|
];
|
||||||
|
@ -57,9 +57,9 @@ if ($userPodcasts !== []) {
|
||||||
$noNotificationsText = lang('Notifications.no_notifications');
|
$noNotificationsText = lang('Notifications.no_notifications');
|
||||||
$items[] = [
|
$items[] = [
|
||||||
'type' => 'html',
|
'type' => 'html',
|
||||||
'content' => esc(<<<CODE_SAMPLE
|
'content' => esc(<<<HTML
|
||||||
<span class="mx-4 my-2 text-sm italic text-center text-skin-muted">{$noNotificationsText}</span>
|
<span class="mx-4 my-2 text-sm italic text-center text-skin-muted">{$noNotificationsText}</span>
|
||||||
CODE_SAMPLE),
|
HTML),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
@ -90,11 +90,11 @@ foreach ($userPodcasts as $userPodcast) {
|
||||||
$checkMark = interact_as_actor_id() === $userPodcast->actor_id ? icon('check', 'ml-2 bg-accent-base text-accent-contrast rounded-full') : '';
|
$checkMark = interact_as_actor_id() === $userPodcast->actor_id ? icon('check', 'ml-2 bg-accent-base text-accent-contrast rounded-full') : '';
|
||||||
$userPodcastTitle = esc($userPodcast->title);
|
$userPodcastTitle = esc($userPodcast->title);
|
||||||
|
|
||||||
$interactButtons .= <<<CODE_SAMPLE
|
$interactButtons .= <<<HTML
|
||||||
<button class="inline-flex items-center w-full px-4 py-1 hover:bg-highlight" id="interact-as-actor-{$userPodcast->id}" name="actor_id" value="{$userPodcast->actor_id}">
|
<button class="inline-flex items-center w-full px-4 py-1 hover:bg-highlight" id="interact-as-actor-{$userPodcast->id}" name="actor_id" value="{$userPodcast->actor_id}">
|
||||||
<div class="inline-flex items-center flex-1 text-sm"><img src="{$userPodcast->cover->tiny_url}" class="w-6 h-6 mr-2 rounded-full" loading="lazy" /><span class="max-w-xs truncate">{$userPodcastTitle}</span>{$checkMark}</div>
|
<div class="inline-flex items-center flex-1 text-sm"><img src="{$userPodcast->cover->tiny_url}" class="w-6 h-6 mr-2 rounded-full" loading="lazy" /><span class="max-w-xs truncate">{$userPodcastTitle}</span>{$checkMark}</div>
|
||||||
</button>
|
</button>
|
||||||
CODE_SAMPLE;
|
HTML;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ if ($userPodcasts !== []) {
|
||||||
$menuItems = array_merge([
|
$menuItems = array_merge([
|
||||||
[
|
[
|
||||||
'type' => 'html',
|
'type' => 'html',
|
||||||
'content' => esc(<<<CODE_SAMPLE
|
'content' => esc(<<<HTML
|
||||||
<nav class="flex flex-col py-2 whitespace-nowrap">
|
<nav class="flex flex-col py-2 whitespace-nowrap">
|
||||||
<span class="px-4 mb-2 text-xs font-semibold tracking-wider uppercase text-skin-muted">{$interactAsText}</span>
|
<span class="px-4 mb-2 text-xs font-semibold tracking-wider uppercase text-skin-muted">{$interactAsText}</span>
|
||||||
<form action="{$interactAsRoute}" method="POST" class="flex flex-col">
|
<form action="{$interactAsRoute}" method="POST" class="flex flex-col">
|
||||||
|
@ -135,7 +135,7 @@ if ($userPodcasts !== []) {
|
||||||
{$interactButtons}
|
{$interactButtons}
|
||||||
</form>
|
</form>
|
||||||
</nav>
|
</nav>
|
||||||
CODE_SAMPLE),
|
HTML),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'type' => 'separator',
|
'type' => 'separator',
|
||||||
|
|
Loading…
Reference in New Issue