Skip to content

Commit 55c7099

Browse files
committed
Implement tags
1 parent 8acafa3 commit 55c7099

File tree

14 files changed

+337
-10
lines changed

14 files changed

+337
-10
lines changed

src/Libraries/Comment.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
use \BNETDocs\Libraries\Core\DateTimeImmutable;
66
use \BNETDocs\Libraries\Db\MariaDb;
77
use \BNETDocs\Libraries\EventLog\EventTypes;
8+
use \BNETDocs\Libraries\Tag\Tag;
9+
use \BNETDocs\Libraries\Tag\Types as TagTypes;
810
use \BNETDocs\Libraries\User\User;
911
use \DateTimeInterface;
1012
use \DateTimeZone;
@@ -325,6 +327,12 @@ public function getParentUrl(): string|false
325327
return \BNETDocs\Libraries\Core\UrlFormatter::format(sprintf('/%s/%d', $pts, $this->getParentId()));
326328
}
327329

330+
public function getTags(): array
331+
{
332+
$id = $this->getId();
333+
return is_null($id) ? [] : (Tag::allocateAll(TagTypes::Comment, $this->getId()) ?? []);
334+
}
335+
328336
public function getUser(): ?User
329337
{
330338
return is_null($this->user_id) ? null : new User($this->user_id);

src/Libraries/Document.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
use \BNETDocs\Libraries\Core\DateTimeImmutable;
66
use \BNETDocs\Libraries\Db\MariaDb;
7+
use \BNETDocs\Libraries\Tag\Tag;
8+
use \BNETDocs\Libraries\Tag\Types as TagTypes;
79
use \BNETDocs\Libraries\User\User;
810
use \DateTimeInterface;
911
use \DateTimeZone;
@@ -308,6 +310,12 @@ public function getPublishedDateTime(): ?DateTimeInterface
308310
);
309311
}
310312

313+
public function getTags(): array
314+
{
315+
$id = $this->getId();
316+
return is_null($id) ? [] : (Tag::allocateAll(TagTypes::Document, $this->getId()) ?? []);
317+
}
318+
311319
public function getTitle(): string
312320
{
313321
return $this->title;

src/Libraries/News/Post.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
use \BNETDocs\Libraries\Core\DateTimeImmutable;
66
use \BNETDocs\Libraries\Db\MariaDb;
77
use \BNETDocs\Libraries\News\Category as NewsCategory;
8+
use \BNETDocs\Libraries\Tag\Tag;
9+
use \BNETDocs\Libraries\Tag\Types as TagTypes;
810
use \BNETDocs\Libraries\User\User;
911
use \DateTimeInterface;
1012
use \DateTimeZone;
@@ -293,6 +295,12 @@ public function getPublishedDateTime(): DateTimeInterface
293295
return $this->getEditedDateTime() ?? $this->getCreatedDateTime();
294296
}
295297

298+
public function getTags(): array
299+
{
300+
$id = $this->getId();
301+
return is_null($id) ? [] : (Tag::allocateAll(TagTypes::NewsPost, $this->getId()) ?? []);
302+
}
303+
296304
public function getTitle(): string
297305
{
298306
return $this->title;

src/Libraries/Packet/Packet.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
use \BNETDocs\Libraries\Packet\Application as ApplicationLayer;
88
use \BNETDocs\Libraries\Packet\Transport as TransportLayer;
99
use \BNETDocs\Libraries\Product;
10+
use \BNETDocs\Libraries\Tag\Tag;
11+
use \BNETDocs\Libraries\Tag\Types as TagTypes;
1012
use \BNETDocs\Libraries\User\User;
1113
use \DateTimeInterface;
1214
use \DateTimeZone;
@@ -432,6 +434,12 @@ public function getRemarks(bool $format): string
432434
return $md->text($this->remarks);
433435
}
434436

437+
public function getTags(): array
438+
{
439+
$id = $this->getId();
440+
return is_null($id) ? [] : (Tag::allocateAll(TagTypes::Packet, $this->getId()) ?? []);
441+
}
442+
435443
public function getTransportLayer(): TransportLayer
436444
{
437445
return new TransportLayer($this->transport_layer_id);

src/Libraries/Server/Server.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
use \BNETDocs\Libraries\Core\DateTimeImmutable;
66
use \BNETDocs\Libraries\Db\MariaDb;
77
use \BNETDocs\Libraries\Server\Type as ServerType;
8+
use \BNETDocs\Libraries\Tag\Tag;
9+
use \BNETDocs\Libraries\Tag\Types as TagTypes;
810
use \BNETDocs\Libraries\User\User;
911
use \DateTimeInterface;
1012
use \DateTimeZone;
@@ -253,6 +255,12 @@ public function getStatusBitmask(): int
253255
return $this->status_bitmask;
254256
}
255257

258+
public function getTags(): array
259+
{
260+
$id = $this->getId();
261+
return is_null($id) ? [] : (Tag::allocateAll(TagTypes::Server, $this->getId()) ?? []);
262+
}
263+
256264
public function getType(): ServerType
257265
{
258266
return new ServerType($this->type_id);

src/Libraries/Tag/Tag.php

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
<?php
2+
3+
namespace BNETDocs\Libraries\Tag;
4+
5+
use \BNETDocs\Libraries\Db\MariaDb;
6+
use \BNETDocs\Libraries\Tag\Types;
7+
use \OutOfBoundsException;
8+
9+
class Tag implements \BNETDocs\Interfaces\DatabaseObject, \JsonSerializable
10+
{
11+
public const MAX_REFERENCE_ID = 0x7FFFFFFFFFFFFFFF;
12+
public const MAX_REFERENCE_TYPE = 0x7FFFFFFFFFFFFFFF;
13+
14+
private ?int $reference_id = null;
15+
private ?Types $reference_type = null;
16+
private ?string $tag_string = null;
17+
18+
public function __construct(?object $value)
19+
{
20+
if (is_object($value))
21+
{
22+
$this->allocateObject($value);
23+
}
24+
}
25+
26+
public function allocate(): bool
27+
{
28+
$p = [
29+
'refid' => $this->getReferenceId(),
30+
'reftype' => $this->getReferenceType(),
31+
'tagstr' => $this->getTagString(),
32+
];
33+
if ($p['reftype'] instanceof Types) $p['reftype'] = $p['reftype']->toInt();
34+
35+
try
36+
{
37+
$q = MariaDb::instance()->prepare('
38+
SELECT
39+
`reference_id`,
40+
`reference_type`,
41+
`tag_string`
42+
FROM `tags` WHERE
43+
`reference_id` = :refid AND
44+
`reference_type` = :reftype AND
45+
`tag_string` = :tagstr
46+
LIMIT 1;
47+
');
48+
if (!$q || !$q->execute($p) || $q->rowCount() !== 1) return false;
49+
$this->allocateObject($q->fetchObject());
50+
return true;
51+
}
52+
finally
53+
{
54+
if ($q) $q->closeCursor();
55+
}
56+
}
57+
58+
public static function allocateAll(int|Types $reference_type, int $reference_id): ?array
59+
{
60+
$p = [
61+
'refid' => $reference_id,
62+
'reftype' => $reference_type,
63+
];
64+
if ($p['reftype'] instanceof Types) $p['reftype'] = $p['reftype']->toInt();
65+
66+
try
67+
{
68+
$q = MariaDb::instance()->prepare('
69+
SELECT
70+
`reference_id`,
71+
`reference_type`,
72+
`tag_string`
73+
FROM `tags` WHERE
74+
`reference_id` = :refid AND
75+
`reference_type` = :reftype;
76+
');
77+
if (!$q || !$q->execute($p)) return null;
78+
$rows = [];
79+
while ($row = $q->fetchObject()) $rows[] = new self($row);
80+
return $rows;
81+
}
82+
finally
83+
{
84+
if ($q) $q->closeCursor();
85+
}
86+
}
87+
88+
public function allocateObject(object $value): void
89+
{
90+
$this->setReferenceId($value->reference_id ?? null);
91+
$this->setReferenceType($value->reference_type ?? null);
92+
$this->setTagString($value->tag_string ?? null);
93+
}
94+
95+
public function commit(): bool
96+
{
97+
$p = [
98+
'refid' => $this->getReferenceId(),
99+
'reftype' => $this->getReferenceType(),
100+
'tagstr' => $this->getTagString(),
101+
];
102+
if ($p['reftype'] instanceof Types) $p['reftype'] = $p['reftype']->toInt();
103+
104+
try
105+
{
106+
$q = MariaDb::instance()->prepare('
107+
INSERT INTO `tags` (
108+
`reference_id`,
109+
`reference_type`,
110+
`tag_string`
111+
) VALUES (
112+
`reference_id` = :refid,
113+
`reference_type` = :reftype,
114+
`tag_string` = :tagstr
115+
) ON DUPLICATE KEY UPDATE
116+
`tag_string` = :tagstr;
117+
');
118+
119+
if ($q && $q->execute($p))
120+
{
121+
if ($q->rowCount() === 1)
122+
{
123+
$this->allocateObject($q->fetchObject());
124+
}
125+
return true;
126+
}
127+
else
128+
{
129+
return false;
130+
}
131+
}
132+
finally
133+
{
134+
if ($q) $q->closeCursor();
135+
}
136+
}
137+
138+
public function deallocate(): bool
139+
{
140+
$p = [
141+
'refid' => $this->getReferenceId(),
142+
'reftype' => $this->getReferenceType(),
143+
'tagstr' => $this->getTagString(),
144+
];
145+
if ($p['reftype'] instanceof Types) $p['reftype'] = $p['reftype']->toInt();
146+
147+
try
148+
{
149+
$q = MariaDb::instance()->prepare('
150+
DELETE FROM `tags` WHERE
151+
`reference_id` = :refid AND
152+
`reference_type` = :reftype AND
153+
`tag_string` = :tagstr
154+
LIMIT 1;
155+
');
156+
return $q && $q->execute($p);
157+
}
158+
finally
159+
{
160+
if ($q) $q->closeCursor();
161+
}
162+
}
163+
164+
public function getReferenceId(): ?int
165+
{
166+
return $this->reference_id;
167+
}
168+
169+
public function getReferenceType(): int|null|Types
170+
{
171+
return $this->reference_type;
172+
}
173+
174+
public function getTagString(): ?string
175+
{
176+
return $this->tag_string;
177+
}
178+
179+
public function jsonSerialize(): mixed
180+
{
181+
return [
182+
'reference_id' => $this->getReferenceId(),
183+
'reference_type' => $this->getReferenceType(),
184+
'tag_string' => $this->getTagString(),
185+
];
186+
}
187+
188+
public function setReferenceId(?int $value): void
189+
{
190+
if (!is_null($value) && ($value < 0 || $value > self::MAX_REFERENCE_ID))
191+
{
192+
throw new OutOfBoundsException(sprintf(
193+
'value must be null or an integer between 0-%d', self::MAX_REFERENCE_ID
194+
));
195+
}
196+
197+
$this->reference_id = $value;
198+
}
199+
200+
public function setReferenceType(int|null|Types $value): void
201+
{
202+
if (!is_null($value) && !($value instanceof Types)
203+
&& ($value < 0 || $value > self::MAX_REFERENCE_TYPE))
204+
{
205+
throw new OutOfBoundsException(sprintf(
206+
'value must be null, Types enum, or an integer between 0-%d', self::MAX_REFERENCE_TYPE
207+
));
208+
}
209+
210+
$this->reference_type = is_null($value) ? null : (is_int($value) ? Types::fromInt($value) : $value);
211+
}
212+
213+
public function setTagString(?string $value): void
214+
{
215+
$this->tag_string = $value;
216+
}
217+
}

src/Libraries/Tag/Types.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace BNETDocs\Libraries\Tag;
4+
5+
enum Types: int
6+
{
7+
case Document = 0;
8+
case Comment = 1;
9+
case NewsPost = 2;
10+
case Packet = 3;
11+
case Server = 4;
12+
case User = 5;
13+
14+
public static function fromInt(int $value): self
15+
{
16+
return match($value) {
17+
0 => self::Document,
18+
1 => self::Comment,
19+
2 => self::NewsPost,
20+
3 => self::Packet,
21+
4 => self::Server,
22+
5 => self::User,
23+
default => throw new \ValueError("Invalid Types enum value: $value"),
24+
};
25+
}
26+
27+
public function toInt(): int
28+
{
29+
return $this->value;
30+
}
31+
}

0 commit comments

Comments
 (0)