. * * @copyright (c) Visman * @license The MIT License (MIT) */ declare(strict_types=1); namespace ForkBB\Models\PM; use ForkBB\Models\Method; use ForkBB\Models\DataModel; use ForkBB\Models\PM\Cnst; use ForkBB\Models\PM\PPost; use ForkBB\Models\PM\PTopic; use ForkBB\Models\User\User; use InvalidArgumentException; use RuntimeException; class Delete extends Method { protected function deletePTopics(array $ids): void { if ($ids) { $vars = [ ':ids' => $ids, ]; $query = 'DELETE FROM ::pm_topics WHERE id IN (?ai:ids)'; $this->c->DB->exec($query, $vars); $query = 'DELETE FROM ::pm_posts WHERE topic_id IN (?ai:ids)'; $this->c->DB->exec($query, $vars); } } public function delete(DataModel ...$args): void { if (empty($args)) { throw new InvalidArgumentException('No arguments, expected User(s), PPost(s) or PTopic(s)'); } $users = []; $posts = []; $topics = []; $isUser = 0; $isPost = 0; $isTopic = 0; $calcUsers = []; foreach ($args as $arg) { if ($arg instanceof User) { if ($arg->isGuest) { throw new RuntimeException('Guest can not be deleted'); } $users[$arg->id] = $arg; $isUser = 1; } elseif ($arg instanceof PPost) { if (! $arg->parent instanceof PTopic) { throw new RuntimeException('Bad ppost'); } $posts[$arg->id] = $arg; $isPost = 1; } elseif ($arg instanceof PTopic) { if (! $this->model->accessTopic($arg->id)) { throw new RuntimeException('Bad ptopic'); } $topics[$arg->id] = $arg; $isTopic = 1; } else { throw new InvalidArgumentException('Expected User(s), PPost(s) or PTopic(s)'); } } if ($isUser + $isPost + $isTopic > 1) { throw new InvalidArgumentException('Expected only User(s), PPost(s) or PTopic(s)'); } if ($topics) { $ids = []; foreach ($topics as $topic) { $calcUsers[$topic->zpUser->id] = $topic->zpUser; if ($topic->isFullDeleted) { $ids[] = $topic->id; } else { $this->model->update(Cnst::PTOPIC, $topic); } } $this->deletePTopics($ids); } if ($posts) { $calcTopics = []; foreach ($posts as $post) { $topic = $post->parent; $calcTopics[$topic->id] = $topic; if ($topic->last_post_id === $post->id) { $calcUsers[$topic->ztUser->id] = $topic->ztUser; } } $vars = [ ':ids' => \array_keys($posts), ]; $query = 'DELETE FROM ::pm_posts WHERE id IN (?ai:ids)'; $this->c->DB->exec($query, $vars); foreach ($calcTopics as $topic) { $this->model->update(Cnst::PTOPIC, $topic->calcStat()); } } if ($users) { $vars = [ ':ids' => \array_keys($users), ':status' => Cnst::PT_DELETED, ]; $query = 'DELETE FROM ::pm_block WHERE bl_first_id IN (?ai:ids)'; $this->c->DB->exec($query, $vars); $query = 'DELETE FROM ::pm_block WHERE bl_second_id IN (?ai:ids)'; $this->c->DB->exec($query, $vars); $query = 'UPDATE ::pm_topics SET poster_id=0, poster_status=?i:status WHERE poster_id IN (?ai:ids)'; $this->c->DB->exec($query, $vars); $query = 'UPDATE ::pm_topics SET target_id=0, target_status=?i:status WHERE target_id IN (?ai:ids)'; $this->c->DB->exec($query, $vars); $query = 'UPDATE ::pm_posts SET poster_id=0 WHERE poster_id IN (?ai:ids)'; $this->c->DB->exec($query, $vars); $vars = [ ':st1' => Cnst::PT_DELETED, ':st2' => Cnst::PT_NOTSENT, ]; $query = 'SELECT id, poster_id, target_id FROM ::pm_topics WHERE (poster_status=?i:st1 AND target_status=?i:st1) OR (poster_status=?i:st1 AND target_status=?i:st2) OR (poster_status=?i:st2 AND target_status=?i:st1) OR (poster_status=?i:st2 AND target_status=?i:st2)'; $stmt = $this->c->DB->query($query, $vars); $ids = []; $uids = []; while ($row = $stmt->fetch()) { $ids[$row['id']] = $row['id']; $uids[$row['poster_id']] = $row['poster_id']; $uids[$row['target_id']] = $row['target_id']; } $this->deletePTopics($ids); foreach ($this->c->users->loadByIds($uids) as $user) { if ($user instanceof User) { $calcUsers[$user->id] = $user; } } } foreach ($calcUsers as $user) { $this->model->recalculate($user); } } }