Skip to content

Commit 9ca4061

Browse files
committed
Introducing group external attributes in the data model (migration included).
1 parent 4889f1e commit 9ca4061

File tree

6 files changed

+176
-0
lines changed

6 files changed

+176
-0
lines changed

app/config/config.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,7 @@ services:
426426
- App\Model\Repository\Assignments
427427
- App\Model\Repository\ExternalLogins
428428
- App\Model\Repository\Groups
429+
- App\Model\Repository\GroupExternalAttributes
429430
- App\Model\Repository\GroupInvitations
430431
- App\Model\Repository\GroupExams
431432
- App\Model\Repository\GroupExamLocks

app/model/entity/Group.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public function __construct(
4949
$this->exercises = new ArrayCollection();
5050
$this->localizedTexts = new ArrayCollection();
5151
$this->exams = new ArrayCollection();
52+
$this->externalAttributes = new ArrayCollection();
5253

5354
if ($admin !== null) {
5455
$this->addPrimaryAdmin($admin);
@@ -86,6 +87,7 @@ public function __construct(
8687

8788
/**
8889
* @ORM\Column(type="string", nullable=true)
90+
* DEPRECATED in favor of external attributes
8991
*/
9092
protected $externalId;
9193

@@ -297,6 +299,12 @@ public function isExamLockStrict(): bool
297299
return $this->examLockStrict;
298300
}
299301

302+
/**
303+
* @var Collection
304+
* @ORM\OneToMany(targetEntity="GroupExternalAttribute", mappedBy="group", cascade={"all"}, orphanRemoval=true)
305+
*/
306+
protected $externalAttributes;
307+
300308
/**
301309
* @ORM\ManyToOne(targetEntity="Group", inversedBy="childGroups")
302310
*/
@@ -1020,4 +1028,9 @@ public function getExams(): Collection
10201028
{
10211029
return $this->exams;
10221030
}
1031+
1032+
public function getExternalAttributes(): Collection
1033+
{
1034+
return $this->externalAttributes;
1035+
}
10231036
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<?php
2+
3+
namespace App\Model\Entity;
4+
5+
use Doctrine\ORM\Mapping as ORM;
6+
use App\Exceptions\InvalidArgumentException;
7+
use Nette\Utils\Validators;
8+
use JsonSerializable;
9+
10+
/**
11+
* @ORM\Entity
12+
* @ORM\Table(uniqueConstraints={@ORM\UniqueConstraint(columns={"group_id", "service", "key", "value"})},
13+
* indexes={@ORM\Index(name="keys_idx", columns={"service", "key"})})
14+
*
15+
* Key-value attributes assigned to groups to connect them to 3rd party systems to simplify
16+
* external group management (creation, archiving) and student membership management.
17+
*/
18+
class GroupExternalAttribute implements JsonSerializable
19+
{
20+
use CreateableEntity;
21+
22+
/**
23+
* @ORM\Id
24+
* @ORM\Column(type="uuid", unique=true)
25+
* @ORM\GeneratedValue(strategy="CUSTOM")
26+
* @ORM\CustomIdGenerator(class=\Ramsey\Uuid\Doctrine\UuidGenerator::class)
27+
* @var \Ramsey\Uuid\UuidInterface
28+
*/
29+
protected $id;
30+
31+
/**
32+
* @ORM\ManyToOne(targetEntity="Group", inversedBy="externalAttributes")
33+
*/
34+
protected $group;
35+
36+
/**
37+
* @ORM\Column(type="string", length=32)
38+
* Identifies 3rd party service which assigned the attribute. This is basically a namespace for keys.
39+
*/
40+
protected $service;
41+
42+
/**
43+
* @ORM\Column(type="string", length=32)
44+
* Key of the attribute under which it can be searched.
45+
*/
46+
protected $key;
47+
48+
/**
49+
* @ORM\Column(type="string")
50+
*/
51+
protected $value;
52+
53+
/**
54+
* Constructor initializes all fields.
55+
* @param Group $group
56+
* @param string $service
57+
* @param string $key
58+
* @param string $value
59+
*/
60+
public function __construct(Group $group, string $service, string $key, string $value)
61+
{
62+
$this->group = $group;
63+
$this->service = $service;
64+
$this->key = $key;
65+
$this->value = $value;
66+
$this->createdNow();
67+
}
68+
69+
public function jsonSerialize(): mixed
70+
{
71+
return [
72+
"id" => $this->getId(),
73+
"createdAt" => $this->createdAt->getTimestamp(),
74+
"group" => $this->getGroup()->getId(),
75+
"service" => $this->getService(),
76+
"key" => $this->getKey(),
77+
"value" => $this->getValue(),
78+
];
79+
}
80+
81+
/*
82+
* Accessors
83+
*/
84+
85+
public function getId(): ?string
86+
{
87+
return $this->id === null ? null : (string)$this->id;
88+
}
89+
90+
public function getGroup(): Group
91+
{
92+
return $this->group;
93+
}
94+
95+
public function getService(): string
96+
{
97+
return $this->service;
98+
}
99+
100+
public function getKey(): string
101+
{
102+
return $this->key;
103+
}
104+
105+
public function getValue(): string
106+
{
107+
return $this->value;
108+
}
109+
}

app/model/entity/SisGroupBinding.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
/**
88
* @ORM\Entity
9+
* DEPRECATED will be replaced by group external attributes
910
*/
1011
class SisGroupBinding
1112
{
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace App\Model\Repository;
4+
5+
use App\Model\Entity\Group;
6+
use App\Model\Entity\GroupExternalAttribute;
7+
use App\Model\Entity\User;
8+
use Doctrine\ORM\EntityManagerInterface;
9+
10+
/**
11+
* @extends BaseRepository<GroupExternalAttribute>
12+
*/
13+
class GroupExternalAttributes extends BaseRepository
14+
{
15+
public function __construct(EntityManagerInterface $em)
16+
{
17+
parent::__construct($em, GroupExternalAttribute::class);
18+
}
19+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Migrations;
6+
7+
use Doctrine\DBAL\Schema\Schema;
8+
use Doctrine\Migrations\AbstractMigration;
9+
10+
/**
11+
* Auto-generated Migration: Please modify to your needs!
12+
*/
13+
final class Version20240831212234 extends AbstractMigration
14+
{
15+
public function getDescription(): string
16+
{
17+
return '';
18+
}
19+
20+
public function up(Schema $schema): void
21+
{
22+
// this up() migration is auto-generated, please modify it to your needs
23+
$this->addSql('CREATE TABLE group_external_attribute (id CHAR(36) NOT NULL COMMENT \'(DC2Type:uuid)\', group_id CHAR(36) DEFAULT NULL COMMENT \'(DC2Type:uuid)\', service VARCHAR(32) NOT NULL, `key` VARCHAR(32) NOT NULL, value VARCHAR(255) NOT NULL, created_at DATETIME NOT NULL, INDEX IDX_F1907847FE54D947 (group_id), INDEX keys_idx (service, `key`), UNIQUE INDEX UNIQ_F1907847FE54D947E19D9AD28A90ABA91D775834 (group_id, service, `key`, value), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
24+
$this->addSql('ALTER TABLE group_external_attribute ADD CONSTRAINT FK_F1907847FE54D947 FOREIGN KEY (group_id) REFERENCES `group` (id)');
25+
}
26+
27+
public function down(Schema $schema): void
28+
{
29+
// this down() migration is auto-generated, please modify it to your needs
30+
$this->addSql('ALTER TABLE group_external_attribute DROP FOREIGN KEY FK_F1907847FE54D947');
31+
$this->addSql('DROP TABLE group_external_attribute');
32+
}
33+
}

0 commit comments

Comments
 (0)