| @@ -3,8 +3,9 @@ | ||
| 3 | 3 | namespace FluentBoards\App\Hooks\Handlers; |
| 4 | 4 | |
| 5 | 5 | use DateTimeImmutable; |
| 6 | 6 | use Exception; |
| 7 | +use FluentBoards\App\App; | |
| 7 | 8 | use FluentBoards\App\Models\Activity; |
| 8 | 9 | use FluentBoards\App\Models\Meta; |
| 9 | 10 | use FluentBoards\App\Models\TaskMeta; |
| 10 | 11 | use FluentBoards\App\Models\Task; |
| @@ -84,8 +85,13 @@ | ||
| 84 | 85 | } |
| 85 | 86 | |
| 86 | 87 | public function searchNonBoardWordpressUsers() |
| 87 | 88 | { |
| 89 | + // This enumerates every WordPress user with their email; only user managers may see it. | |
| 90 | + if (!current_user_can('list_users')) { | |
| 91 | + return []; | |
| 92 | + } | |
| 93 | + | |
| 88 | 94 | $superAdmin = Relation::select('user_id')->distinct()->pluck('user_id'); |
| 89 | 95 | $users = User::whereDoesntHave('boards')->whereNotIn('ID', $superAdmin)->get(); |
| 90 | 96 | |
| 91 | 97 | $formattedUsers = []; |
| @@ -165,18 +171,45 @@ | ||
| 165 | 171 | |
| 166 | 172 | |
| 167 | 173 | |
| 168 | 174 | /** |
| 169 | - * Summary of taskAttachmentDeleted | |
| 170 | - * @param mixed $task | |
| 171 | - * @param mixed $deleteUrl | |
| 175 | + * Delete an attachment file only after the owning database transaction commits. | |
| 176 | + * | |
| 177 | + * @param mixed $deletedAttachment | |
| 178 | + * @param int|null $boardId | |
| 172 | 179 | * @return void |
| 173 | 180 | */ |
| 174 | - public function taskAttachmentDeleted($deletedAttachment) | |
| 181 | + public function taskAttachmentDeleted($deletedAttachment, $boardId = null) | |
| 175 | 182 | { |
| 183 | + if ($deletedAttachment->attachment_type === 'url') { | |
| 184 | + return; | |
| 185 | + } | |
| 186 | + | |
| 187 | + if ($boardId === null) { | |
| 188 | + $task = Task::find(absint($deletedAttachment->object_id)); | |
| 189 | + $boardId = $task ? $task->board_id : null; | |
| 190 | + } | |
| 191 | + | |
| 192 | + $dbInstance = App::getInstance('db'); | |
| 193 | + | |
| 194 | + if ($dbInstance->inTransaction()) { | |
| 195 | + $attachmentSnapshot = clone $deletedAttachment; | |
| 196 | + $dbInstance->afterCommit(function () use ($attachmentSnapshot, $boardId) { | |
| 197 | + try { | |
| 198 | + $this->fileHandler->deleteAttachmentFile($attachmentSnapshot, $boardId); | |
| 199 | + } catch (\Throwable $e) { | |
| 200 | + error_log(sprintf( | |
| 201 | + 'FluentBoards: Failed to delete committed task attachment file: %s', | |
| 202 | + sanitize_text_field($e->getMessage()) | |
| 203 | + )); | |
| 204 | + } | |
| 205 | + }); | |
| 206 | + | |
| 207 | + return; | |
| 208 | + } | |
| 209 | + | |
| 176 | 210 | try { |
| 177 | - $deleteUrl = $deletedAttachment->full_url; | |
| 178 | - $this->fileHandler->deleteFileByUrl($deleteUrl); | |
| 211 | + $this->fileHandler->deleteAttachmentFile($deletedAttachment, $boardId); | |
| 179 | 212 | } catch (Exception $e) { |
| 180 | 213 | wp_send_json_error($e->getMessage()); |
| 181 | 214 | } |
| 182 | 215 | } |
| @@ -185,10 +218,16 @@ | ||
| 185 | 218 | * Auto-watch newly created tasks when the board preference allows it. |
| 186 | 219 | */ |
| 187 | 220 | public function onTaskCreated($task) |
| 188 | 221 | { |
| 222 | + $userId = get_current_user_id(); | |
| 223 | + | |
| 224 | + if (!$userId) { | |
| 225 | + return; | |
| 226 | + } | |
| 227 | + | |
| 189 | 228 | if ($this->shouldAutoWatchForBoard($task->board_id, Constant::GLOBAL_EMAIL_NOTIFICATION_CREATING_TASK)) { |
| 190 | - $task->watchers()->syncWithoutDetaching([get_current_user_id() => ['object_type' => Constant::OBJECT_TYPE_USER_TASK_WATCH]]); | |
| 229 | + $task->watchers()->syncWithoutDetaching([$userId => ['object_type' => Constant::OBJECT_TYPE_USER_TASK_WATCH]]); | |
| 191 | 230 | } |
| 192 | 231 | } |
| 193 | 232 | |
| 194 | 233 | /** |
| @@ -196,10 +235,16 @@ | ||
| 196 | 235 | */ |
| 197 | 236 | public function onCommentCreated($comment) |
| 198 | 237 | { |
| 199 | 238 | $task = $comment->task; |
| 239 | + $userId = get_current_user_id(); | |
| 240 | + | |
| 241 | + if (!$userId) { | |
| 242 | + return; | |
| 243 | + } | |
| 244 | + | |
| 200 | 245 | if ($this->shouldAutoWatchForBoard($task->board_id, Constant::GLOBAL_EMAIL_NOTIFICATION_COMMENTING)) { |
| 201 | - $task->watchers()->syncWithoutDetaching([get_current_user_id() => ['object_type' => Constant::OBJECT_TYPE_USER_TASK_WATCH]]); | |
| 246 | + $task->watchers()->syncWithoutDetaching([$userId => ['object_type' => Constant::OBJECT_TYPE_USER_TASK_WATCH]]); | |
| 202 | 247 | } |
| 203 | 248 | } |
| 204 | 249 | |
| 205 | 250 | /** |