Merge pull request #7426 from pixelfed/staging

Staging
pull/7439/head
dansup 1 day ago committed by GitHub
commit d70076505d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -127,6 +127,8 @@ RUN install-php-extensions \
vips \
ffi
RUN printf 'ffi.enable=1\n' > /usr/local/etc/php/conf.d/zz-ffi-enable.ini
COPY --from=ffmpeg /usr/local/ffmpeg/bin/ffmpeg /usr/bin/ffmpeg
COPY --from=ffmpeg /usr/local/ffmpeg/bin/ffprobe /usr/bin/ffprobe
COPY --from=ffmpeg /usr/local/ffmpeg/lib /usr/local/lib

@ -2642,6 +2642,16 @@ class ApiV1Controller extends Controller
$inTypes = $includeReblogs ?
['photo', 'photo:album', 'video', 'video:album', 'photo:video:album', 'share'] :
['photo', 'photo:album', 'video', 'video:album', 'photo:video:album'];
// "Photo reblogs only"
$photosReblogsOnly = $request->filled('photos_reblogs_only')
? $request->boolean('photos_reblogs_only')
: data_get($other, 'photo_reblogs_only', false);
$reblogTargetTypes = array_diff($inTypes, ['share']);
// Filtering happens after the fetch, so fetch deeper to fill a page
$fetchLimit = $photosReblogsOnly ? $limit * 6 : $limit * 2;
AccountService::setLastActive($request->user()->id);
$cachedFilters = CustomFilter::getCachedFiltersForAccount($pid);
@ -2770,7 +2780,7 @@ class ApiV1Controller extends Controller
->whereIn('type', $inTypes)
->whereIn('visibility', ['public', 'unlisted', 'private'])
->orderByDesc('id')
->take(($limit * 2))
->take($fetchLimit)
->get()
->map(function ($s) use ($pid, $napi) {
try {
@ -2786,7 +2796,8 @@ class ApiV1Controller extends Controller
return false;
}
$status['account'] = $account;
// Not $status['account'] = $account: $account is resolved from
// the row, StatusService picks the right one per client
if ($pid) {
$status['favourited'] = (bool) LikeService::liked($pid, $s['id']);
@ -2796,8 +2807,15 @@ class ApiV1Controller extends Controller
return $status;
})
->filter(function ($status) {
return $status && isset($status['account']);
->filter(function ($status) use ($photosReblogsOnly, $reblogTargetTypes) {
if (! $status || ! isset($status['account'])) {
return false;
}
// direct posts pass; a boost must share a photo or video
return ! $photosReblogsOnly
|| empty($status['reblog'])
|| in_array(data_get($status['reblog'], 'pf_type'), $reblogTargetTypes);
})
->map(function ($status) use ($pid) {
if (! empty($status['reblog'])) {
@ -2841,7 +2859,7 @@ class ApiV1Controller extends Controller
->whereIn('type', $inTypes)
->whereIn('visibility', ['public', 'unlisted', 'private'])
->orderByDesc('id')
->take(($limit * 2))
->take($fetchLimit)
->get()
->map(function ($s) use ($pid, $napi) {
try {
@ -2857,7 +2875,8 @@ class ApiV1Controller extends Controller
return false;
}
$status['account'] = $account;
// Not $status['account'] = $account: $account is resolved from
// the row, StatusService picks the right one per client
if ($pid) {
$status['favourited'] = (bool) LikeService::liked($pid, $s['id']);
@ -2867,8 +2886,15 @@ class ApiV1Controller extends Controller
return $status;
})
->filter(function ($status) {
return $status && isset($status['account']);
->filter(function ($status) use ($photosReblogsOnly, $reblogTargetTypes) {
if (! $status || ! isset($status['account'])) {
return false;
}
// direct posts pass; a boost must share a photo or video
return ! $photosReblogsOnly
|| empty($status['reblog'])
|| in_array(data_get($status['reblog'], 'pf_type'), $reblogTargetTypes);
})
->map(function ($status) use ($pid) {
if (! empty($status['reblog'])) {

@ -328,6 +328,7 @@ class InternalApiController extends Controller
'id',
'uri',
'caption',
'rendered',
'profile_id',
'type',
'in_reply_to_id',

@ -179,7 +179,7 @@ class PublicApiController extends Controller
$replies = $status->comments()
->whereNull('reblog_of_id')
->whereIn('scope', $scope)
->select('id', 'caption', 'local', 'visibility', 'scope', 'is_nsfw', 'profile_id', 'in_reply_to_id', 'type', 'reply_count', 'created_at')
->select('id', 'caption', 'rendered', 'local', 'visibility', 'scope', 'is_nsfw', 'profile_id', 'in_reply_to_id', 'type', 'reply_count', 'created_at')
->where('id', '>=', $request->min_id)
->orderBy('id', 'desc')
->paginate($limit);
@ -188,7 +188,7 @@ class PublicApiController extends Controller
$replies = $status->comments()
->whereNull('reblog_of_id')
->whereIn('scope', $scope)
->select('id', 'caption', 'local', 'visibility', 'scope', 'is_nsfw', 'profile_id', 'in_reply_to_id', 'type', 'reply_count', 'created_at')
->select('id', 'caption', 'rendered', 'local', 'visibility', 'scope', 'is_nsfw', 'profile_id', 'in_reply_to_id', 'type', 'reply_count', 'created_at')
->where('id', '<=', $request->max_id)
->orderBy('id', 'desc')
->paginate($limit);
@ -197,7 +197,7 @@ class PublicApiController extends Controller
$replies = Status::whereInReplyToId($status->id)
->whereNull('reblog_of_id')
->whereIn('scope', $scope)
->select('id', 'caption', 'local', 'visibility', 'scope', 'is_nsfw', 'profile_id', 'in_reply_to_id', 'type', 'reply_count', 'created_at')
->select('id', 'caption', 'rendered', 'local', 'visibility', 'scope', 'is_nsfw', 'profile_id', 'in_reply_to_id', 'type', 'reply_count', 'created_at')
->orderBy('id', 'desc')
->paginate($limit);
}

@ -340,7 +340,10 @@ class SearchController extends Controller
if ($media) {
$url = $media->remote_url;
}
$content = $item->caption ? Autolink::create()->autolink($item->caption) : null;
// Remote posts keep the HTML they arrived with, so the link targets survive
$content = $item->local || ! $item->rendered
? ($item->caption ? Autolink::create()->autolink($item->caption) : null)
: $item->rendered;
$this->tokens['posts'] = [[
'count' => 0,
'url' => "/i/web/post/_/$item->profile_id/$item->id",
@ -364,7 +367,10 @@ class SearchController extends Controller
if ($media) {
$url = $media->remote_url;
}
$content = $item->caption ? Autolink::create()->autolink($item->caption) : null;
// Remote posts keep the HTML they arrived with, so the link targets survive
$content = $item->local || ! $item->rendered
? ($item->caption ? Autolink::create()->autolink($item->caption) : null)
: $item->rendered;
$this->tokens['posts'] = [[
'count' => 0,
'url' => "/i/web/post/_/$item->profile_id/$item->id",

@ -90,6 +90,20 @@ class StatusService
unset($res['_pid']);
}
// A client that resolves reblogs declares include_reblogs; one that
// only reads the top level renders a boost as an empty card, so give it
// the shared status there instead.
if (! $mastodonMode
&& request()->has('_pe')
&& ! request()->filled('include_reblogs')
&& ! empty($res['reblog'])) {
foreach (['account', 'content', 'content_text', 'emojis', 'media_attachments'] as $key) {
if (array_key_exists($key, $res['reblog'])) {
$res[$key] = $res['reblog'][$key];
}
}
}
return $res;
}
@ -115,6 +129,14 @@ class StatusService
return $status;
}
// The shared status nests under `reblog` and needs Mastodon field names too
if (! empty($status['reblog'])) {
$status['reblog']['replies_count'] = $status['reblog']['reply_count'] ?? 0;
$status['reblog']['favourited'] = false;
$status['reblog']['muted'] = false;
$status['reblog']['reblogged'] = false;
}
unset(
$status['_v'],
$status['comments_disabled'],
@ -153,6 +175,7 @@ class StatusService
MediaService::getMastodon($status['id'])
);
$status['favourited'] = false;
$status['muted'] = false;
$status['reblogged'] = false;

@ -22,7 +22,10 @@ class StatusStatelessTransformer extends Fractal\TransformerAbstract
{
$taggedPeople = MediaTagService::get($status->id);
$poll = $status->type === 'poll' ? PollService::get($status->id) : null;
$rendered = $status->caption ? nl2br(Autolink::create()->autolink($status->caption)) : '';
// Remote posts keep the HTML they arrived with, so the link targets survive
$rendered = $status->local || ! $status->rendered
? ($status->caption ? nl2br(Autolink::create()->autolink($status->caption)) : '')
: $status->rendered;
return [
'_v' => 1,

@ -24,7 +24,10 @@ class StatusTransformer extends Fractal\TransformerAbstract
$pid = request()->user()->profile_id;
$taggedPeople = MediaTagService::get($status->id);
$poll = $status->type === 'poll' ? PollService::get($status->id, $pid) : null;
$content = $status->caption ? nl2br(Autolink::create()->autolink($status->caption)) : '';
// Remote posts keep the HTML they arrived with, so the link targets survive
$content = $status->local || ! $status->rendered
? ($status->caption ? nl2br(Autolink::create()->autolink($status->caption)) : '')
: $status->rendered;
return [
'_v' => 1,

@ -77,8 +77,23 @@ return [
],
],
'mariadb' => [
'dump' => [
'useSingleTransaction' => true,
'useQuick' => true,
],
],
'pgsql' => [
'dump' => [
'useSingleTransaction' => true,
'useQuick' => true,
],
],
// Hardcoding 'mysql' breaks backup:run on non-MySQL installs
'databases' => [
'mysql',
env('DB_CONNECTION', 'mysql'),
],
],

@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* 2018_08_12_042648_update_status_table_change_caption_to_text calls
* `->change()` without `->nullable()`, making both columns NOT NULL.
* DirectMessageController still writes null into caption, which errors
* on PostgreSQL.
*/
public function up(): void
{
Schema::table('statuses', function ($table) {
if (config('database.default') !== 'postgres') {
return;
}
$table->text('caption')->nullable()->change();
$table->text('rendered')->nullable()->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
//
}
};
Loading…
Cancel
Save