Skip to content

Add ability to block and subscribe Hashtags - #2180

Open
blued-gear wants to merge 18 commits into
mainfrom
new/block_hashtags
Open

Add ability to block and subscribe Hashtags#2180
blued-gear wants to merge 18 commits into
mainfrom
new/block_hashtags

Conversation

@blued-gear

@blued-gear blued-gear commented Jul 26, 2026

Copy link
Copy Markdown
Collaborator

This PR enables users to block and subscribe to Hashtags and list their blocks / subscriptions (in UI and API equally).

Closes #1993 and #1452

Comment thread src/Repository/ContentRepository.php Outdated
# Conflicts:
#	src/Controller/User/Profile/UserBlockController.php
#	src/Repository/ContentRepository.php
#	src/Repository/Criteria.php
#	src/Utils/SqlHelpers.php
</header>
</div>

{{ component('hashtag_sub', {hashtag: hashtag}) }}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we make sure every tag page passes a hashtag here? I can reproduce a 500 at /tag/blockedtag/threads/newest/all because TagEntryFrontController only passes tag. The posts, comments and people controllers have the same issue.


public function block(User $user, Hashtag $hashtag): void
{
$user->blockHashtag($hashtag);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking a hashtag should also remove an existing subscription, like domains and magazines do. I reproduced subscribing and then blocking the same hashtag, and it stays subscribed. Can we unsubscribe here before adding the block? Also, subscribing removes a block directly without dispatching HashtagBlockChangedEvent, so the cached block list can stay stale.

// only include the subcluase if there are (/ might be) blocks
if (null === $criteria->cachedUserBlockedHashtags || !empty($criteria->cachedUserBlockedHashtags)) {
if (null === $criteria->cachedUserBlockedHashtags) {
$blockingClauseEntry = $blockingClauseEntry.' AND NOT EXISTS (SELECT 1 FROM hashtag_link hl INNER JOIN hashtag_block hb ON hl.hashtag_id = hb.hashtag_id WHERE hl.entry_id = c.id AND hb.user_id = :loggedInUser)';

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we apply this blocked hashtag filtering in EntryRepository and PostRepository too? I created an entry and post containing a blocked hashtag, and both standalone repositories still returned the content. Those repositories back tag, user and API listings, so those paths currently bypass this filter.

Comment thread src/Entity/HashtagSubscription.php Outdated
#[ManyToOne(targetEntity: User::class, inversedBy: 'subscribedHashtags')]
#[JoinColumn(nullable: false, onDelete: 'CASCADE')]
public ?User $user;
#[ManyToOne(targetEntity: Hashtag::class)]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This association needs inversedBy: 'subscriptions' to match Hashtag::$subscriptions. doctrine:schema:validate currently reports this relationship as invalid.

'domain:subscribe' => 'oauth2.grant.domain.subscribe',
'domain:block' => 'oauth2.grant.domain.block',
// Grants allowing applications to (un)subscribe or (un)block hashtags on behalf of the user
'hashtag' => 'oauth2.grant.hashtag.all',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add the matching English translations for these consent keys? They are missing from messages.en.yaml, so the OAuth consent screen will show the raw oauth2.grant.hashtag.* keys. The general subscribe and block descriptions should mention hashtags too.

#[OA\Response(
response: 200,
description: 'Hashtag unblocked',
content: new Model(type: DomainDto::class),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This response documents DomainDto, but the endpoint serializes a HashtagResponseDto. The unsubscribe endpoint has the same mismatch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ability to block Hashtags

4 participants