mirror of
https://github.com/chenasraf/nextcloud-forum.git
synced 2026-05-17 17:28:02 +00:00
fix: remove/consolidate redundant endpoints
This commit is contained in:
@@ -63,65 +63,7 @@ class PostController extends OCSController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get posts by thread
|
||||
*
|
||||
* @param int $threadId Thread ID
|
||||
* @param int<1, 200> $limit Maximum number of posts to return
|
||||
* @param int $offset Offset for pagination
|
||||
* @return DataResponse<Http::STATUS_OK, list<array<string, mixed>>, array{}>
|
||||
*
|
||||
* 200: Posts returned
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[PublicPage]
|
||||
#[RequirePermission('canView', resourceType: 'category', resourceIdFromThreadId: 'threadId')]
|
||||
#[ApiRoute(verb: 'GET', url: '/api/threads/{threadId}/posts')]
|
||||
public function byThread(int $threadId, int $limit = 50, int $offset = 0): DataResponse {
|
||||
try {
|
||||
$posts = $this->postMapper->findByThreadId($threadId, $limit, $offset);
|
||||
|
||||
// Prefetch BBCodes once for all posts to avoid repeated queries
|
||||
$bbcodes = $this->bbCodeMapper->findAllEnabled();
|
||||
|
||||
// Fetch reactions for all posts at once (performance optimization)
|
||||
$postIds = array_map(fn ($p) => $p->getId(), $posts);
|
||||
$reactions = $this->reactionMapper->findByPostIds($postIds);
|
||||
|
||||
// Group reactions by post ID
|
||||
$reactionsByPostId = [];
|
||||
foreach ($reactions as $reaction) {
|
||||
$postId = $reaction->getPostId();
|
||||
if (!isset($reactionsByPostId[$postId])) {
|
||||
$reactionsByPostId[$postId] = [];
|
||||
}
|
||||
$reactionsByPostId[$postId][] = $reaction;
|
||||
}
|
||||
|
||||
// Get current user ID to mark user's reactions
|
||||
$currentUserId = $this->userSession->getUser()?->getUID();
|
||||
|
||||
// Extract unique author IDs
|
||||
$authorIds = array_unique(array_map(fn ($p) => $p->getAuthorId(), $posts));
|
||||
|
||||
// Batch fetch author data (includes roles)
|
||||
$authors = $this->userService->enrichMultipleUsers($authorIds);
|
||||
|
||||
// Get category ID for permission checks
|
||||
$categoryId = $this->permissionService->getCategoryIdFromThread($threadId);
|
||||
|
||||
// Enrich posts with content, reactions, and pre-fetched author data
|
||||
return new DataResponse(array_map(function ($p) use ($bbcodes, $reactionsByPostId, $currentUserId, $authors, $categoryId) {
|
||||
$postReactions = $reactionsByPostId[$p->getId()] ?? [];
|
||||
return $this->postEnrichmentService->enrichPost($p, $bbcodes, $postReactions, $currentUserId, $authors[$p->getAuthorId()], $categoryId);
|
||||
}, $posts));
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->error('Error fetching posts by thread: ' . $e->getMessage());
|
||||
return new DataResponse(['error' => 'Failed to fetch posts'], Http::STATUS_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get paginated posts by thread with first post separated
|
||||
* Get posts by thread with first post separated
|
||||
*
|
||||
* @param int $threadId Thread ID
|
||||
* @param int $page Page number (1-indexed)
|
||||
@@ -133,8 +75,8 @@ class PostController extends OCSController {
|
||||
#[NoAdminRequired]
|
||||
#[PublicPage]
|
||||
#[RequirePermission('canView', resourceType: 'category', resourceIdFromThreadId: 'threadId')]
|
||||
#[ApiRoute(verb: 'GET', url: '/api/threads/{threadId}/posts/paginated')]
|
||||
public function byThreadPaginated(int $threadId, int $page = 0, int $perPage = 20): DataResponse {
|
||||
#[ApiRoute(verb: 'GET', url: '/api/threads/{threadId}/posts')]
|
||||
public function byThread(int $threadId, int $page = 0, int $perPage = 20): DataResponse {
|
||||
try {
|
||||
// Get current user ID
|
||||
$currentUserId = $this->userSession->getUser()?->getUID();
|
||||
@@ -245,7 +187,7 @@ class PostController extends OCSController {
|
||||
],
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->error('Error fetching paginated posts by thread: ' . $e->getMessage());
|
||||
$this->logger->error('Error fetching posts by thread: ' . $e->getMessage());
|
||||
return new DataResponse(['error' => 'Failed to fetch posts'], Http::STATUS_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,51 +105,6 @@ class ThreadController extends OCSController {
|
||||
* Get threads by category
|
||||
*
|
||||
* @param int $categoryId Category ID
|
||||
* @param int<1, 200> $limit Maximum number of threads to return
|
||||
* @param int $offset Offset for pagination
|
||||
* @return DataResponse<Http::STATUS_OK, list<array<string, mixed>>, array{}>
|
||||
*
|
||||
* 200: Threads returned
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[PublicPage]
|
||||
#[RequirePermission('canView', resourceType: 'category', resourceIdParam: 'categoryId')]
|
||||
#[ApiRoute(verb: 'GET', url: '/api/categories/{categoryId}/threads')]
|
||||
public function byCategory(int $categoryId, int $limit = 50, int $offset = 0): DataResponse {
|
||||
try {
|
||||
$threads = $this->threadMapper->findByCategoryId($categoryId, $limit, $offset);
|
||||
|
||||
// Extract unique author IDs (thread authors + last reply authors)
|
||||
$authorIds = array_map(fn ($t) => $t->getAuthorId(), $threads);
|
||||
$lastReplyAuthorIds = array_filter(array_map(fn ($t) => $t->getLastReplyAuthorId(), $threads));
|
||||
$allAuthorIds = array_unique(array_merge($authorIds, $lastReplyAuthorIds));
|
||||
|
||||
// Batch fetch author data (includes roles)
|
||||
$authors = $this->userService->enrichMultipleUsers($allAuthorIds);
|
||||
|
||||
// Enrich threads with pre-fetched author data and last reply info
|
||||
return new DataResponse(array_map(function ($t) use ($authors) {
|
||||
$lastReply = null;
|
||||
$lastReplyAuthorId = $t->getLastReplyAuthorId();
|
||||
if ($lastReplyAuthorId !== null) {
|
||||
$lastReply = [
|
||||
'postId' => $t->getLastPostId(),
|
||||
'author' => $authors[$lastReplyAuthorId] ?? null,
|
||||
'createdAt' => $t->getLastReplyAt(),
|
||||
];
|
||||
}
|
||||
return $this->threadEnrichmentService->enrichThread($t, $authors[$t->getAuthorId()] ?? null, $lastReply);
|
||||
}, $threads));
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->error('Error fetching threads by category: ' . $e->getMessage());
|
||||
return new DataResponse(['error' => 'Failed to fetch threads'], Http::STATUS_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get paginated threads by category
|
||||
*
|
||||
* @param int $categoryId Category ID
|
||||
* @param int $page Page number (1-indexed)
|
||||
* @param int $perPage Number of threads per page
|
||||
* @return DataResponse<Http::STATUS_OK, array{threads: list<array<string, mixed>>, pagination: array{page: int, perPage: int, total: int, totalPages: int}}, array{}>
|
||||
@@ -159,8 +114,8 @@ class ThreadController extends OCSController {
|
||||
#[NoAdminRequired]
|
||||
#[PublicPage]
|
||||
#[RequirePermission('canView', resourceType: 'category', resourceIdParam: 'categoryId')]
|
||||
#[ApiRoute(verb: 'GET', url: '/api/categories/{categoryId}/threads/paginated')]
|
||||
public function byCategoryPaginated(int $categoryId, int $page = 1, int $perPage = 20): DataResponse {
|
||||
#[ApiRoute(verb: 'GET', url: '/api/categories/{categoryId}/threads')]
|
||||
public function byCategory(int $categoryId, int $page = 1, int $perPage = 20): DataResponse {
|
||||
try {
|
||||
// Count total threads in category
|
||||
$totalThreads = $this->threadMapper->countByCategoryId($categoryId);
|
||||
@@ -205,7 +160,7 @@ class ThreadController extends OCSController {
|
||||
],
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->error('Error fetching paginated threads by category: ' . $e->getMessage());
|
||||
$this->logger->error('Error fetching threads by category: ' . $e->getMessage());
|
||||
return new DataResponse(['error' => 'Failed to fetch threads'], Http::STATUS_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6089,107 +6089,7 @@
|
||||
"/ocs/v2.php/apps/forum/api/threads/{threadId}/posts": {
|
||||
"get": {
|
||||
"operationId": "post-by-thread",
|
||||
"summary": "Get posts by thread",
|
||||
"tags": [
|
||||
"post"
|
||||
],
|
||||
"security": [
|
||||
{},
|
||||
{
|
||||
"bearer_auth": []
|
||||
},
|
||||
{
|
||||
"basic_auth": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "threadId",
|
||||
"in": "path",
|
||||
"description": "Thread ID",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "limit",
|
||||
"in": "query",
|
||||
"description": "Maximum number of posts to return",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"default": 50,
|
||||
"minimum": 1,
|
||||
"maximum": 200
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "offset",
|
||||
"in": "query",
|
||||
"description": "Offset for pagination",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"default": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "OCS-APIRequest",
|
||||
"in": "header",
|
||||
"description": "Required to be true for the API request to pass",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Posts returned",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"ocs"
|
||||
],
|
||||
"properties": {
|
||||
"ocs": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"meta",
|
||||
"data"
|
||||
],
|
||||
"properties": {
|
||||
"meta": {
|
||||
"$ref": "#/components/schemas/OCSMeta"
|
||||
},
|
||||
"data": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/ocs/v2.php/apps/forum/api/threads/{threadId}/posts/paginated": {
|
||||
"get": {
|
||||
"operationId": "post-by-thread-paginated",
|
||||
"summary": "Get paginated posts by thread with first post separated",
|
||||
"summary": "Get posts by thread with first post separated",
|
||||
"tags": [
|
||||
"post"
|
||||
],
|
||||
@@ -10513,106 +10413,6 @@
|
||||
"basic_auth": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "categoryId",
|
||||
"in": "path",
|
||||
"description": "Category ID",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "limit",
|
||||
"in": "query",
|
||||
"description": "Maximum number of threads to return",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"default": 50,
|
||||
"minimum": 1,
|
||||
"maximum": 200
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "offset",
|
||||
"in": "query",
|
||||
"description": "Offset for pagination",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"default": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "OCS-APIRequest",
|
||||
"in": "header",
|
||||
"description": "Required to be true for the API request to pass",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Threads returned",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"ocs"
|
||||
],
|
||||
"properties": {
|
||||
"ocs": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"meta",
|
||||
"data"
|
||||
],
|
||||
"properties": {
|
||||
"meta": {
|
||||
"$ref": "#/components/schemas/OCSMeta"
|
||||
},
|
||||
"data": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/ocs/v2.php/apps/forum/api/categories/{categoryId}/threads/paginated": {
|
||||
"get": {
|
||||
"operationId": "thread-by-category-paginated",
|
||||
"summary": "Get paginated threads by category",
|
||||
"tags": [
|
||||
"thread"
|
||||
],
|
||||
"security": [
|
||||
{},
|
||||
{
|
||||
"bearer_auth": []
|
||||
},
|
||||
{
|
||||
"basic_auth": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "categoryId",
|
||||
|
||||
202
openapi.json
202
openapi.json
@@ -6089,107 +6089,7 @@
|
||||
"/ocs/v2.php/apps/forum/api/threads/{threadId}/posts": {
|
||||
"get": {
|
||||
"operationId": "post-by-thread",
|
||||
"summary": "Get posts by thread",
|
||||
"tags": [
|
||||
"post"
|
||||
],
|
||||
"security": [
|
||||
{},
|
||||
{
|
||||
"bearer_auth": []
|
||||
},
|
||||
{
|
||||
"basic_auth": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "threadId",
|
||||
"in": "path",
|
||||
"description": "Thread ID",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "limit",
|
||||
"in": "query",
|
||||
"description": "Maximum number of posts to return",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"default": 50,
|
||||
"minimum": 1,
|
||||
"maximum": 200
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "offset",
|
||||
"in": "query",
|
||||
"description": "Offset for pagination",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"default": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "OCS-APIRequest",
|
||||
"in": "header",
|
||||
"description": "Required to be true for the API request to pass",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Posts returned",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"ocs"
|
||||
],
|
||||
"properties": {
|
||||
"ocs": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"meta",
|
||||
"data"
|
||||
],
|
||||
"properties": {
|
||||
"meta": {
|
||||
"$ref": "#/components/schemas/OCSMeta"
|
||||
},
|
||||
"data": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/ocs/v2.php/apps/forum/api/threads/{threadId}/posts/paginated": {
|
||||
"get": {
|
||||
"operationId": "post-by-thread-paginated",
|
||||
"summary": "Get paginated posts by thread with first post separated",
|
||||
"summary": "Get posts by thread with first post separated",
|
||||
"tags": [
|
||||
"post"
|
||||
],
|
||||
@@ -10513,106 +10413,6 @@
|
||||
"basic_auth": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "categoryId",
|
||||
"in": "path",
|
||||
"description": "Category ID",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "limit",
|
||||
"in": "query",
|
||||
"description": "Maximum number of threads to return",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"default": 50,
|
||||
"minimum": 1,
|
||||
"maximum": 200
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "offset",
|
||||
"in": "query",
|
||||
"description": "Offset for pagination",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"default": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "OCS-APIRequest",
|
||||
"in": "header",
|
||||
"description": "Required to be true for the API request to pass",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Threads returned",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"ocs"
|
||||
],
|
||||
"properties": {
|
||||
"ocs": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"meta",
|
||||
"data"
|
||||
],
|
||||
"properties": {
|
||||
"meta": {
|
||||
"$ref": "#/components/schemas/OCSMeta"
|
||||
},
|
||||
"data": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/ocs/v2.php/apps/forum/api/categories/{categoryId}/threads/paginated": {
|
||||
"get": {
|
||||
"operationId": "thread-by-category-paginated",
|
||||
"summary": "Get paginated threads by category",
|
||||
"tags": [
|
||||
"thread"
|
||||
],
|
||||
"security": [
|
||||
{},
|
||||
{
|
||||
"bearer_auth": []
|
||||
},
|
||||
{
|
||||
"basic_auth": []
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "categoryId",
|
||||
|
||||
@@ -307,15 +307,12 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
const resp = await ocs.get<PaginatedResponse>(
|
||||
`/categories/${this.category!.id}/threads/paginated`,
|
||||
{
|
||||
params: {
|
||||
page,
|
||||
perPage: this.perPage,
|
||||
},
|
||||
const resp = await ocs.get<PaginatedResponse>(`/categories/${this.category!.id}/threads`, {
|
||||
params: {
|
||||
page,
|
||||
perPage: this.perPage,
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
const data = resp.data
|
||||
if (data) {
|
||||
|
||||
@@ -616,15 +616,12 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
const resp = await ocs.get<PaginatedResponse>(
|
||||
`/threads/${this.thread!.id}/posts/paginated`,
|
||||
{
|
||||
params: {
|
||||
page,
|
||||
perPage: this.perPage,
|
||||
},
|
||||
const resp = await ocs.get<PaginatedResponse>(`/threads/${this.thread!.id}/posts`, {
|
||||
params: {
|
||||
page,
|
||||
perPage: this.perPage,
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
const data = resp.data
|
||||
if (data) {
|
||||
|
||||
@@ -158,7 +158,7 @@ describe('ThreadView', () => {
|
||||
mockFetchThread.mockResolvedValue(mockThread.value)
|
||||
mockCheckCategoryPermission.mockResolvedValue(false)
|
||||
mockOcsGet.mockImplementation((url: string) => {
|
||||
if (url.includes('/posts/paginated')) {
|
||||
if (url.includes('/posts')) {
|
||||
return mockGetResponse({
|
||||
data: {
|
||||
firstPost: mockFirstPost,
|
||||
@@ -360,7 +360,7 @@ describe('ThreadView', () => {
|
||||
})
|
||||
|
||||
mockOcsGet.mockImplementation((url: string) => {
|
||||
if (url.includes('/posts/paginated')) {
|
||||
if (url.includes('/posts')) {
|
||||
return mockGetResponse({
|
||||
data: {
|
||||
firstPost: guestFirstPost,
|
||||
@@ -407,7 +407,7 @@ describe('ThreadView', () => {
|
||||
})
|
||||
|
||||
mockOcsGet.mockImplementation((url: string) => {
|
||||
if (url.includes('/posts/paginated')) {
|
||||
if (url.includes('/posts')) {
|
||||
return mockGetResponse({
|
||||
data: {
|
||||
firstPost: mockFirstPost,
|
||||
@@ -459,7 +459,7 @@ describe('ThreadView', () => {
|
||||
mockFetchThread.mockResolvedValue(mockThread.value)
|
||||
|
||||
mockOcsGet.mockImplementation((url: string) => {
|
||||
if (url.includes('/posts/paginated')) {
|
||||
if (url.includes('/posts')) {
|
||||
return mockGetResponse({
|
||||
data: {
|
||||
firstPost: mockFirstPost,
|
||||
@@ -505,7 +505,7 @@ describe('ThreadView', () => {
|
||||
mockFetchThread.mockResolvedValue(mockThread.value)
|
||||
|
||||
mockOcsGet.mockImplementation((url: string) => {
|
||||
if (url.includes('/posts/paginated')) {
|
||||
if (url.includes('/posts')) {
|
||||
return mockGetResponse({
|
||||
data: {
|
||||
firstPost: mockFirstPost,
|
||||
@@ -542,7 +542,7 @@ describe('ThreadView', () => {
|
||||
const guestReply = createMockPost({ id: 10, authorId: guestAuthorId, author: guestAuthor })
|
||||
|
||||
mockOcsGet.mockImplementation((url: string) => {
|
||||
if (url.includes('/posts/paginated')) {
|
||||
if (url.includes('/posts')) {
|
||||
return mockGetResponse({
|
||||
data: {
|
||||
firstPost: mockFirstPost,
|
||||
|
||||
@@ -133,75 +133,25 @@ class PostControllerTest extends TestCase {
|
||||
);
|
||||
}
|
||||
|
||||
public function testByThreadReturnsPostsSuccessfully(): void {
|
||||
$threadId = 1;
|
||||
$limit = 50;
|
||||
$offset = 0;
|
||||
|
||||
// Create mock posts
|
||||
$post1 = $this->createMockPost(1, $threadId, 'user1', 'Test content 1');
|
||||
$post2 = $this->createMockPost(2, $threadId, 'user2', 'Test content 2');
|
||||
$posts = [$post1, $post2];
|
||||
|
||||
// Create mock BBCode
|
||||
$bbcode = new BBCode();
|
||||
$bbcode->setId(1);
|
||||
$bbcode->setTag('b');
|
||||
$bbcode->setReplacement('<strong>{content}</strong>');
|
||||
$bbcode->setEnabled(true);
|
||||
|
||||
// Create mock reactions
|
||||
$reaction1 = $this->createMockReaction(1, 1, 'user1', '👍');
|
||||
$reaction2 = $this->createMockReaction(2, 1, 'user2', '👍');
|
||||
|
||||
// Mock user session
|
||||
$user = $this->createMock(IUser::class);
|
||||
$user->method('getUID')->willReturn('user1');
|
||||
$this->userSession->method('getUser')->willReturn($user);
|
||||
|
||||
// Set up expectations
|
||||
$this->postMapper->expects($this->once())
|
||||
->method('findByThreadId')
|
||||
->with($threadId, $limit, $offset)
|
||||
->willReturn($posts);
|
||||
|
||||
$this->bbCodeMapper->expects($this->once())
|
||||
->method('findAllEnabled')
|
||||
->willReturn([$bbcode]);
|
||||
|
||||
$this->reactionMapper->expects($this->once())
|
||||
->method('findByPostIds')
|
||||
->with([1, 2])
|
||||
->willReturn([$reaction1, $reaction2]);
|
||||
|
||||
// Mock userService to return enriched user data
|
||||
$this->userService->expects($this->once())
|
||||
->method('enrichMultipleUsers')
|
||||
->with(['user1', 'user2'])
|
||||
->willReturn([
|
||||
'user1' => ['userId' => 'user1', 'displayName' => 'User 1', 'roles' => []],
|
||||
'user2' => ['userId' => 'user2', 'displayName' => 'User 2', 'roles' => []],
|
||||
]);
|
||||
|
||||
// Execute
|
||||
$response = $this->controller->byThread($threadId, $limit, $offset);
|
||||
|
||||
// Assert
|
||||
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
|
||||
$data = $response->getData();
|
||||
$this->assertIsArray($data);
|
||||
$this->assertCount(2, $data);
|
||||
$this->assertEquals(1, $data[0]['id']);
|
||||
$this->assertEquals(2, $data[1]['id']);
|
||||
$this->assertArrayHasKey('reactions', $data[0]);
|
||||
$this->assertArrayHasKey('reactions', $data[1]);
|
||||
}
|
||||
|
||||
public function testByThreadHandlesEmptyPosts(): void {
|
||||
$threadId = 1;
|
||||
|
||||
// Mock user session (no user = guest)
|
||||
$this->userSession->method('getUser')->willReturn(null);
|
||||
|
||||
$this->postMapper->expects($this->once())
|
||||
->method('findByThreadId')
|
||||
->method('countRepliesByThreadId')
|
||||
->with($threadId)
|
||||
->willReturn(0);
|
||||
|
||||
$this->postMapper->expects($this->once())
|
||||
->method('findFirstPostByThreadId')
|
||||
->with($threadId)
|
||||
->willReturn(null);
|
||||
|
||||
$this->postMapper->expects($this->once())
|
||||
->method('findRepliesByThreadId')
|
||||
->with($threadId, 20, 0)
|
||||
->willReturn([]);
|
||||
|
||||
$this->bbCodeMapper->expects($this->once())
|
||||
@@ -213,11 +163,20 @@ class PostControllerTest extends TestCase {
|
||||
->with([])
|
||||
->willReturn([]);
|
||||
|
||||
$this->userService->method('enrichMultipleUsers')->willReturn([]);
|
||||
|
||||
$response = $this->controller->byThread($threadId);
|
||||
|
||||
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
|
||||
$this->assertIsArray($response->getData());
|
||||
$this->assertCount(0, $response->getData());
|
||||
$data = $response->getData();
|
||||
$this->assertArrayHasKey('firstPost', $data);
|
||||
$this->assertArrayHasKey('replies', $data);
|
||||
$this->assertArrayHasKey('pagination', $data);
|
||||
$this->assertNull($data['firstPost']);
|
||||
$this->assertCount(0, $data['replies']);
|
||||
$this->assertEquals(1, $data['pagination']['page']);
|
||||
$this->assertEquals(1, $data['pagination']['totalPages']);
|
||||
$this->assertEquals(0, $data['pagination']['total']);
|
||||
}
|
||||
|
||||
public function testShowReturnsPostSuccessfully(): void {
|
||||
@@ -978,7 +937,7 @@ class PostControllerTest extends TestCase {
|
||||
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
|
||||
}
|
||||
|
||||
public function testByThreadPaginatedReturnsPostsSuccessfully(): void {
|
||||
public function testByThreadReturnsPostsSuccessfully(): void {
|
||||
$threadId = 1;
|
||||
$page = 1;
|
||||
$perPage = 20;
|
||||
@@ -1043,7 +1002,7 @@ class PostControllerTest extends TestCase {
|
||||
]);
|
||||
|
||||
// Execute
|
||||
$response = $this->controller->byThreadPaginated($threadId, $page, $perPage);
|
||||
$response = $this->controller->byThread($threadId, $page, $perPage);
|
||||
|
||||
// Assert
|
||||
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
|
||||
@@ -1059,7 +1018,7 @@ class PostControllerTest extends TestCase {
|
||||
$this->assertEquals(1, $data['pagination']['totalPages']);
|
||||
}
|
||||
|
||||
public function testByThreadPaginatedStartsAtLastPageForUnreadThread(): void {
|
||||
public function testByThreadStartsAtLastPageForUnreadThread(): void {
|
||||
$threadId = 1;
|
||||
$perPage = 20;
|
||||
|
||||
@@ -1109,7 +1068,7 @@ class PostControllerTest extends TestCase {
|
||||
]);
|
||||
|
||||
// Execute with page=0 (auto-calculate start page)
|
||||
$response = $this->controller->byThreadPaginated($threadId, 0, $perPage);
|
||||
$response = $this->controller->byThread($threadId, 0, $perPage);
|
||||
|
||||
// Assert
|
||||
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
|
||||
@@ -1120,7 +1079,7 @@ class PostControllerTest extends TestCase {
|
||||
$this->assertNull($data['pagination']['lastReadPostId']);
|
||||
}
|
||||
|
||||
public function testByThreadPaginatedStartsAtOldestUnreadPage(): void {
|
||||
public function testByThreadStartsAtOldestUnreadPage(): void {
|
||||
$threadId = 1;
|
||||
$perPage = 20;
|
||||
|
||||
@@ -1185,7 +1144,7 @@ class PostControllerTest extends TestCase {
|
||||
]);
|
||||
|
||||
// Execute with page=0 (auto-calculate start page)
|
||||
$response = $this->controller->byThreadPaginated($threadId, 0, $perPage);
|
||||
$response = $this->controller->byThread($threadId, 0, $perPage);
|
||||
|
||||
// Assert
|
||||
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
|
||||
@@ -1196,7 +1155,7 @@ class PostControllerTest extends TestCase {
|
||||
$this->assertEquals(31, $data['pagination']['lastReadPostId']);
|
||||
}
|
||||
|
||||
public function testByThreadPaginatedGoesToLastPageWhenAllRead(): void {
|
||||
public function testByThreadGoesToLastPageWhenAllRead(): void {
|
||||
$threadId = 1;
|
||||
$perPage = 20;
|
||||
|
||||
@@ -1252,7 +1211,7 @@ class PostControllerTest extends TestCase {
|
||||
]);
|
||||
|
||||
// Execute with page=0 (auto-calculate start page)
|
||||
$response = $this->controller->byThreadPaginated($threadId, 0, $perPage);
|
||||
$response = $this->controller->byThread($threadId, 0, $perPage);
|
||||
|
||||
// Assert
|
||||
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
|
||||
@@ -1263,7 +1222,7 @@ class PostControllerTest extends TestCase {
|
||||
$this->assertEquals(50, $data['pagination']['lastReadPostId']);
|
||||
}
|
||||
|
||||
public function testByThreadPaginatedWorksForGuestUser(): void {
|
||||
public function testByThreadWorksForGuestUser(): void {
|
||||
$threadId = 1;
|
||||
$page = 1;
|
||||
$perPage = 20;
|
||||
@@ -1302,7 +1261,7 @@ class PostControllerTest extends TestCase {
|
||||
]);
|
||||
|
||||
// Execute
|
||||
$response = $this->controller->byThreadPaginated($threadId, $page, $perPage);
|
||||
$response = $this->controller->byThread($threadId, $page, $perPage);
|
||||
|
||||
// Assert
|
||||
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
|
||||
@@ -1312,7 +1271,7 @@ class PostControllerTest extends TestCase {
|
||||
$this->assertNull($data['pagination']['lastReadPostId']);
|
||||
}
|
||||
|
||||
public function testByThreadPaginatedRespectsExplicitPageParameter(): void {
|
||||
public function testByThreadRespectsExplicitPageParameter(): void {
|
||||
$threadId = 1;
|
||||
$perPage = 20;
|
||||
|
||||
@@ -1354,7 +1313,7 @@ class PostControllerTest extends TestCase {
|
||||
]);
|
||||
|
||||
// Execute with explicit page=2
|
||||
$response = $this->controller->byThreadPaginated($threadId, 2, $perPage);
|
||||
$response = $this->controller->byThread($threadId, 2, $perPage);
|
||||
|
||||
// Assert
|
||||
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
|
||||
|
||||
@@ -160,15 +160,20 @@ class ThreadControllerTest extends TestCase {
|
||||
|
||||
public function testByCategoryReturnsThreadsSuccessfully(): void {
|
||||
$categoryId = 1;
|
||||
$limit = 50;
|
||||
$offset = 0;
|
||||
$page = 1;
|
||||
$perPage = 20;
|
||||
|
||||
$thread1 = $this->createMockThread(1, $categoryId, 'user1', 'Test Thread 1');
|
||||
$thread2 = $this->createMockThread(2, $categoryId, 'user2', 'Test Thread 2');
|
||||
|
||||
$this->threadMapper->expects($this->once())
|
||||
->method('countByCategoryId')
|
||||
->with($categoryId)
|
||||
->willReturn(2);
|
||||
|
||||
$this->threadMapper->expects($this->once())
|
||||
->method('findByCategoryId')
|
||||
->with($categoryId, $limit, $offset)
|
||||
->with($categoryId, $perPage, 0)
|
||||
->willReturn([$thread1, $thread2]);
|
||||
|
||||
$this->userService->expects($this->once())
|
||||
@@ -178,12 +183,17 @@ class ThreadControllerTest extends TestCase {
|
||||
'user2' => ['userId' => 'user2', 'displayName' => 'User 2'],
|
||||
]);
|
||||
|
||||
$response = $this->controller->byCategory($categoryId, $limit, $offset);
|
||||
$response = $this->controller->byCategory($categoryId, $page, $perPage);
|
||||
|
||||
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
|
||||
$data = $response->getData();
|
||||
$this->assertIsArray($data);
|
||||
$this->assertCount(2, $data);
|
||||
$this->assertArrayHasKey('threads', $data);
|
||||
$this->assertArrayHasKey('pagination', $data);
|
||||
$this->assertCount(2, $data['threads']);
|
||||
$this->assertEquals(1, $data['pagination']['page']);
|
||||
$this->assertEquals(20, $data['pagination']['perPage']);
|
||||
$this->assertEquals(2, $data['pagination']['total']);
|
||||
$this->assertEquals(1, $data['pagination']['totalPages']);
|
||||
}
|
||||
|
||||
public function testShowReturnsThreadAndIncrementsViewCount(): void {
|
||||
@@ -1141,7 +1151,7 @@ class ThreadControllerTest extends TestCase {
|
||||
'user2' => ['userId' => 'user2', 'displayName' => 'User 2'],
|
||||
]);
|
||||
|
||||
$response = $this->controller->byCategoryPaginated($categoryId, $page, $perPage);
|
||||
$response = $this->controller->byCategory($categoryId, $page, $perPage);
|
||||
|
||||
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
|
||||
$data = $response->getData();
|
||||
@@ -1172,7 +1182,7 @@ class ThreadControllerTest extends TestCase {
|
||||
|
||||
$this->userService->method('enrichMultipleUsers')->willReturn([]);
|
||||
|
||||
$response = $this->controller->byCategoryPaginated($categoryId, $page, $perPage);
|
||||
$response = $this->controller->byCategory($categoryId, $page, $perPage);
|
||||
|
||||
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
|
||||
$data = $response->getData();
|
||||
@@ -1198,7 +1208,7 @@ class ThreadControllerTest extends TestCase {
|
||||
|
||||
$this->userService->method('enrichMultipleUsers')->willReturn([]);
|
||||
|
||||
$response = $this->controller->byCategoryPaginated($categoryId, $page, $perPage);
|
||||
$response = $this->controller->byCategory($categoryId, $page, $perPage);
|
||||
|
||||
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
|
||||
$data = $response->getData();
|
||||
@@ -1223,7 +1233,7 @@ class ThreadControllerTest extends TestCase {
|
||||
|
||||
$this->userService->method('enrichMultipleUsers')->willReturn([]);
|
||||
|
||||
$response = $this->controller->byCategoryPaginated($categoryId, 5, $perPage);
|
||||
$response = $this->controller->byCategory($categoryId, 5, $perPage);
|
||||
|
||||
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
|
||||
$data = $response->getData();
|
||||
@@ -1248,7 +1258,7 @@ class ThreadControllerTest extends TestCase {
|
||||
|
||||
$this->userService->method('enrichMultipleUsers')->willReturn([]);
|
||||
|
||||
$response = $this->controller->byCategoryPaginated($categoryId, $page, $perPage);
|
||||
$response = $this->controller->byCategory($categoryId, $page, $perPage);
|
||||
|
||||
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
|
||||
$data = $response->getData();
|
||||
@@ -1285,7 +1295,7 @@ class ThreadControllerTest extends TestCase {
|
||||
'user2' => ['userId' => 'user2', 'displayName' => 'User 2'],
|
||||
]);
|
||||
|
||||
$response = $this->controller->byCategoryPaginated($categoryId, $page, $perPage);
|
||||
$response = $this->controller->byCategory($categoryId, $page, $perPage);
|
||||
|
||||
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
|
||||
$data = $response->getData();
|
||||
@@ -1323,7 +1333,7 @@ class ThreadControllerTest extends TestCase {
|
||||
'user1' => ['userId' => 'user1', 'displayName' => 'User 1'],
|
||||
]);
|
||||
|
||||
$response = $this->controller->byCategoryPaginated($categoryId, $page, $perPage);
|
||||
$response = $this->controller->byCategory($categoryId, $page, $perPage);
|
||||
|
||||
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
|
||||
$data = $response->getData();
|
||||
|
||||
Reference in New Issue
Block a user