change_id < 1 ? -1 : $this->change_id; } public function getChange(): ChangelogChange { if($this->change === null) $this->change = ChangelogChange::byId($this->getChangeId()); return $this->change; } public function getTagId(): int { return $this->tag_id < 1 ? -1 : $this->tag_id; } public function getTag(): ChangelogTag { if($this->tag === null) $this->tag = ChangelogTag::byId($this->getTagId()); return $this->tag; } public static function create(ChangelogChange $change, ChangelogTag $tag, bool $return = false): ?self { $createRelation = DB::prepare( 'REPLACE INTO `' . DB::PREFIX . self::TABLE . '` (`change_id`, `tag_id`)' . ' VALUES (:change, :tag)' )->bind('change', $change->getId())->bind('tag', $tag->getId()); if(!$createRelation->execute()) throw new ChangelogChangeCreationFailedException; if(!$return) return null; return self::byExact($change, $tag); } public static function purgeChange(ChangelogChange $change): void { DB::prepare( 'DELETE FROM `' . DB::PREFIX . self::TABLE . '` WHERE `change_id` = :change' )->bind('change', $change->getId())->execute(); } private static function countQueryBase(string $column): string { return sprintf(self::QUERY_SELECT, sprintf('COUNT(%s.`%s`)', self::TABLE, $column)); } public static function countByTag(ChangelogTag $tag): int { return (int)DB::prepare( self::countQueryBase('change_id') . ' WHERE `tag_id` = :tag' )->bind('tag', $tag->getId())->fetchColumn(); } private static function byQueryBase(): string { return sprintf(self::QUERY_SELECT, sprintf(self::SELECT, self::TABLE)); } public static function byExact(ChangelogChange $change, ChangelogTag $tag): self { $tag = DB::prepare(self::byQueryBase() . ' WHERE `tag_id` = :tag') ->bind('change', $change->getId()) ->bind('tag', $tag->getId()) ->fetchObject(self::class); if(!$tag) throw new ChangelogChangeTagNotFoundException; return $tag; } public static function byChange(ChangelogChange $change): array { return DB::prepare( self::byQueryBase() . ' WHERE `change_id` = :change' )->bind('change', $change->getId())->fetchObjects(self::class); } }