Files
Leantime/app/Domain/Tickets/Repositories/TicketResource.php

112 lines
3.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace Leantime\Domain\Tickets\Repositories;
use Illuminate\Database\ConnectionInterface;
use Leantime\Core\Db\Db as DbCore;
use Leantime\Core\Support\EntityRelationshipEnum;
/**
* 待办事项(ticket/milestone) ↔ 资源关联层。
*
* 复用多态表 zp_entity_relationship零建表
* entityA = ticket idtask 或 milestone共用 zp_tickets.id 序列)
* entityAType = 'Ticket'
* entityB = 资源 id
* entityBType = 资源类型bom | process | tooling | file | wiki
* relationship = EntityRelationshipEnum::LinkedResource->value
*
* 幂等在服务层事务 + lockForUpdate 实现(仿 Goalcanvas::addGoalMilestoneLink
*/
class TicketResource
{
private ConnectionInterface $db;
public function __construct(DbCore $db)
{
$this->db = $db->getConnection();
}
/**
* 关联一个资源(幂等:已存在则返回 true
*/
public function addLink(int $ticketId, string $resourceType, int $resourceId, int $userId): bool
{
if ($ticketId <= 0 || $resourceId <= 0 || $resourceType === '') {
return false;
}
return $this->db->transaction(function () use ($ticketId, $resourceType, $resourceId, $userId): bool {
$exists = $this->db->table('zp_entity_relationship')
->where('entityA', $ticketId)
->where('entityAType', 'Ticket')
->where('entityB', $resourceId)
->where('entityBType', $resourceType)
->where('relationship', EntityRelationshipEnum::LinkedResource->value)
->lockForUpdate()
->exists();
if ($exists) {
return true;
}
$this->db->table('zp_entity_relationship')->insert([
'entityA' => $ticketId,
'entityAType' => 'Ticket',
'entityB' => $resourceId,
'entityBType' => $resourceType,
'relationship' => EntityRelationshipEnum::LinkedResource->value,
'createdOn' => now(),
'createdBy' => $userId > 0 ? $userId : null,
]);
return true;
});
}
/**
* 解除单个资源关联。
*/
public function removeLink(int $ticketId, string $resourceType, int $resourceId): bool
{
return $this->db->table('zp_entity_relationship')
->where('entityA', $ticketId)
->where('entityAType', 'Ticket')
->where('entityB', $resourceId)
->where('entityBType', $resourceType)
->where('relationship', EntityRelationshipEnum::LinkedResource->value)
->delete() > 0;
}
/**
* 解除 ticket 的全部资源关联(删除 ticket 时级联清理)。
*/
public function removeAllLinks(int $ticketId): bool
{
return $this->db->table('zp_entity_relationship')
->where('entityA', $ticketId)
->where('entityAType', 'Ticket')
->where('relationship', EntityRelationshipEnum::LinkedResource->value)
->delete() > 0;
}
/**
* 某 ticket 已关联的资源(去重后的 [resourceType, resourceId] 列表)。
*
* @return array<int, array{type:string,id:int}>
*/
public function getLinks(int $ticketId): array
{
return $this->db->table('zp_entity_relationship')
->where('entityA', $ticketId)
->where('entityAType', 'Ticket')
->where('relationship', EntityRelationshipEnum::LinkedResource->value)
->orderBy('id')
->get(['entityBType', 'entityB'])
->map(fn ($row) => ['type' => (string) $row->entityBType, 'id' => (int) $row->entityB])
->unique(fn ($item) => $item['type'].':'.$item['id'])
->values()
->all();
}
}