implement community basics
rvr-nextgen/pipeline/pr-master This commit looks good

This commit is contained in:
bence committed 2023-04-16 13:57:54 +02:00
1 parent 4dc08dffc9
commit d763c4344c
21 files changed
+844 -15

No files matched your search

+216
View File
@@ -0,0 +1,216 @@
<?php namespace RVR\Controller;
use DateTime;
use RVR\PersistentData\Model\Community;
use RVR\PersistentData\Model\CommunityMember;
use RVR\PersistentData\Model\User;
use RVR\Repository\CommunityRepository;
use RVR\Repository\CommunityMemberRepository;
use RVR\Repository\UserRepository;
use SokoWeb\Interfaces\Authorization\ISecured;
use SokoWeb\Interfaces\Request\IRequest;
use SokoWeb\Interfaces\Response\IContent;
use SokoWeb\PersistentData\PersistentDataManager;
use SokoWeb\Response\HtmlContent;
use SokoWeb\Response\JsonContent;
class CommunityController implements ISecured
{
private IRequest $request;
private PersistentDataManager $pdm;
private UserRepository $userRepository;
private CommunityRepository $communityRepository;
private CommunityMemberRepository $communityMemberRepository;
public function __construct(IRequest $request)
{
$this->request = $request;
$this->pdm = new PersistentDataManager();
$this->userRepository = new UserRepository();
$this->communityRepository = new CommunityRepository();
$this->communityMemberRepository = new CommunityMemberRepository();
}
public function authorize(): bool
{
return $this->request->user() !== null;
}
public function getCommunityHome(): ?IContent
{
if (!$this->checkPermission($this->request->query('communityId'), false, $community, $ownCommunityMember)) {
return null;
}
return new HtmlContent('communities/community', [
'community' => $community,
'members' => $this->getMembers($community),
'currencyNames' => [],
'upcomingEvents' => [],
'editPermission' => $ownCommunityMember->getOwner()
]);
}
public function getCommunityNew(): IContent
{
return new HtmlContent('communities/community_edit');
}
public function getCommunityEdit(): ?IContent
{
if (!$this->checkPermission($this->request->query('communityId'), true, $community, $ownCommunityMember)) {
return null;
}
return new HtmlContent('communities/community_edit', [
'community' => $community
]);
}
public function getMembersEdit(): ?IContent
{
if (!$this->checkPermission($this->request->query('communityId'), true, $community, $ownCommunityMember)) {
return null;
}
return new HtmlContent('communities/community_members', [
'community' => $community,
'members' => $this->getMembers($community)
]);
}
private function getMembers(Community $community): array
{
$members = iterator_to_array($this->communityMemberRepository->getAllByCommunity($community, true));
usort($members, function($a, $b) {
return strnatcmp($a->getUser()->getDisplayName(), $b->getUser()->getDisplayName());
});
return $members;
}
public function newMember(): ?IContent
{
if (!$this->checkPermission($this->request->query('communityId'), true, $community, $ownCommunityMember)) {
return null;
}
$user = $this->userRepository->getById($this->request->post('user_id'));
$communityMember = new CommunityMember();
$communityMember->setCommunity($community);
$communityMember->setUser($user);
$this->pdm->saveToDb($communityMember);
return new JsonContent(['success' => true]);
}
public function editMember(): ?IContent
{
if (!$this->checkPermission($this->request->query('communityId'), true, $community, $ownCommunityMember)) {
return null;
}
$communityMember = $this->communityMemberRepository->getById($this->request->post('community_member_id'));
if ($communityMember->getUserId() === $this->request->user()->getUniqueId()) {
return new JsonContent([
'error' => ['errorText' => 'Own user cannot be edited.']
]);
}
$communityMember->setOwner($this->request->post('owner'));
$this->pdm->saveToDb($communityMember);
return new JsonContent(['success' => true]);
}
public function deleteMember(): ?IContent
{
if (!$this->checkPermission($this->request->query('communityId'), true, $community, $ownCommunityMember)) {
return null;
}
$communityMember = $this->communityMemberRepository->getById($this->request->post('community_member_id'));
if ($communityMember->getUserId() === $this->request->user()->getUniqueId()) {
return new JsonContent([
'error' => ['errorText' => 'Own user cannot be deleted.']
]);
}
$this->pdm->deleteFromDb($communityMember);
return new JsonContent(['success' => true]);
}
public function saveCommunity(): ?IContent
{
$communityId = $this->request->query('communityId');
if ($communityId){
if (!$this->checkPermission($communityId, true, $community, $ownCommunityMember)) {
return null;
}
} else {
$community = new Community();
}
$name = $this->request->post('name');
$currency = $this->request->post('currency');
if (strlen($name) === 0 || strlen($currency) === 0 || strlen($currency) > 3) {
return new JsonContent([
'error' => ['errorText' => 'Please fill all required fields!']
]);
}
$community->setName($name);
$community->setCurrency($currency);
if (!$communityId) {
$community->setCreatedDate(new DateTime());
}
$this->pdm->saveToDb($community);
if (!$communityId) {
/**
* @var User $user
*/
$user = $this->request->user();
$communityMember = new CommunityMember();
$communityMember->setCommunity($community);
$communityMember->setUser($user);
$communityMember->setOwner(true);
$this->pdm->saveToDb($communityMember);
}
return new JsonContent([
'redirect' => ['target' => '/' . \Container::$routeCollection->getRoute('community')->generateLink(['communityId' => $community->getId()])]
]);
}
private function checkPermission(
int $communityId,
bool $needToBeOwner,
?Community &$community,
?CommunityMember &$ownCommunityMember): bool
{
$community = $this->communityRepository->getById($communityId);
if ($community === null) {
return false;
}
/**
* @var User $user
*/
$user = $this->request->user();
$ownCommunityMember = $this->communityMemberRepository->getByCommunityAndUser($community, $user);
if ($ownCommunityMember === null || ($needToBeOwner && !$ownCommunityMember->getOwner())) {
return false;
}
return true;
}
}
+24 -3
View File
@@ -1,18 +1,22 @@
<?php namespace RVR\Controller;
use RVR\PersistentData\Model\User;
use RVR\Repository\CommunityMemberRepository;
use SokoWeb\Interfaces\Authorization\ISecured;
use SokoWeb\Interfaces\Request\IRequest;
use SokoWeb\Interfaces\Response\IContent;
use SokoWeb\Response\HtmlContent;
use SokoWeb\Response\JsonContent;
class HomeController implements ISecured
{
private IRequest $request;
private CommunityMemberRepository $communityMemberRepository;
public function __construct(IRequest $request)
{
$this->request = $request;
$this->communityMemberRepository = new CommunityMemberRepository();
}
public function authorize(): bool
@@ -20,8 +24,25 @@ class HomeController implements ISecured
return $this->request->user() !== null;
}
public function getIndex(): IContent
public function getHome(): IContent
{
return new HtmlContent('index');
/**
* @var User $user
*/
$user = $this->request->user();
$ownCommunityMembers = $this->communityMemberRepository->getAllByUser($user, true);
$communities = [];
foreach ($ownCommunityMembers as $ownCommunityMember) {
$communities[] = $ownCommunityMember->getCommunity();
}
usort($communities, function($a, $b) {
return strnatcmp($a->getName(), $b->getName());
});
return new HtmlContent('home', [
'communities' => $communities,
'upcomingEvents' => []
]);
}
}
+42
View File
@@ -0,0 +1,42 @@
<?php namespace RVR\Controller;
use RVR\Repository\UserRepository;
use SokoWeb\Interfaces\Authorization\ISecured;
use SokoWeb\Interfaces\Request\IRequest;
use SokoWeb\Interfaces\Response\IContent;
use SokoWeb\Response\JsonContent;
class UserSearchController implements ISecured
{
private IRequest $request;
private UserRepository $userRepository;
public function __construct(IRequest $request)
{
$this->request = $request;
$this->userRepository = new UserRepository();
}
public function authorize(): bool
{
return $this->request->user() !== null;
}
public function searchUser(): IContent
{
$users = iterator_to_array($this->userRepository->searchByName($this->request->query('q')));
usort($users, function($a, $b) {
return strnatcmp($a->getDisplayName(), $b->getDisplayName());
});
$results = [];
foreach ($users as $user) {
$results[] = ['value' => $user->getId(), 'label' => $user->getFullDisplayName()];
}
return new JsonContent([
'results' => $results
]);
}
}
+57
View File
@@ -0,0 +1,57 @@
<?php namespace RVR\PersistentData\Model;
use DateTime;
use SokoWeb\PersistentData\Model\Model;
class Community extends Model
{
protected static string $table = 'communities';
protected static array $fields = ['name', 'currency', 'created'];
private string $name = '';
private string $currency = '';
private DateTime $created;
public function setName(string $name): void
{
$this->name = $name;
}
public function setCurrency(string $currency): void
{
$this->currency = $currency;
}
public function setCreatedDate(DateTime $created): void
{
$this->created = $created;
}
public function setCreated(string $created): void
{
$this->created = new DateTime($created);
}
public function getName(): string
{
return $this->name;
}
public function getCurrency(): string
{
return $this->currency;
}
public function getCreatedDate(): DateTime
{
return $this->created;
}
public function getCreated(): string
{
return $this->created->format('Y-m-d H:i:s');
}
}
@@ -0,0 +1,72 @@
<?php namespace RVR\PersistentData\Model;
use SokoWeb\PersistentData\Model\Model;
class CommunityMember extends Model
{
protected static string $table = 'community_members';
protected static array $fields = ['community_id', 'user_id', 'owner'];
protected static array $relations = ['community' => Community::class, 'user' => User::class];
private ?Community $community = null;
private ?int $communityId = null;
private ?User $user = null;
private ?int $userId = null;
private bool $owner = false;
public function setCommunity(Community $community): void
{
$this->community = $community;
}
public function setCommunityId(int $communityId): void
{
$this->communityId = $communityId;
}
public function setUser(User $user): void
{
$this->user = $user;
}
public function setUserId(int $userId): void
{
$this->userId = $userId;
}
public function setOwner(bool $owner): void
{
$this->owner = $owner;
}
public function getCommunity(): ?Community
{
return $this->community;
}
public function getCommunityId(): ?int
{
return $this->communityId;
}
public function getUser(): ?User
{
return $this->user;
}
public function getUserId(): ?int
{
return $this->userId;
}
public function getOwner(): bool
{
return $this->owner;
}
}
+5
View File
@@ -171,6 +171,11 @@ class User extends Model implements IUser
return $this->nickname ?: $this->fullName;
}
public function getFullDisplayName(): string
{
return $this->nickname ? $this->nickname . ' (' . $this->fullName . ')' : $this->fullName;
}
public function checkPassword(string $password): bool
{
if ($this->password === null) {
@@ -0,0 +1,48 @@
<?php namespace RVR\Repository;
use Generator;
use RVR\PersistentData\Model\Community;
use RVR\PersistentData\Model\CommunityMember;
use RVR\PersistentData\Model\User;
use SokoWeb\Database\Query\Select;
use SokoWeb\PersistentData\PersistentDataManager;
class CommunityMemberRepository
{
private PersistentDataManager $pdm;
public function __construct()
{
$this->pdm = new PersistentDataManager();
}
public function getById(int $id): ?CommunityMember
{
return $this->pdm->selectFromDbById($id, CommunityMember::class);
}
public function getAllByCommunity(Community $community, bool $useRelations = false): Generator
{
$select = new Select(\Container::$dbConnection);
$select->where('community_id', '=', $community->getId());
yield from $this->pdm->selectMultipleFromDb($select, CommunityMember::class, $useRelations);
}
public function getAllByUser(User $user, bool $useRelations = false): Generator
{
$select = new Select(\Container::$dbConnection);
$select->where('user_id', '=', $user->getId());
yield from $this->pdm->selectMultipleFromDb($select, CommunityMember::class, $useRelations);
}
public function getByCommunityAndUser(Community $community, User $user) : ?CommunityMember
{
$select = new Select(\Container::$dbConnection);
$select->where('community_id', '=', $community->getId());
$select->where('user_id', '=', $user->getId());
return $this->pdm->selectFromDb($select, CommunityMember::class);
}
}
+19
View File
@@ -0,0 +1,19 @@
<?php namespace RVR\Repository;
use RVR\PersistentData\Model\Community;
use SokoWeb\PersistentData\PersistentDataManager;
class CommunityRepository
{
private PersistentDataManager $pdm;
public function __construct()
{
$this->pdm = new PersistentDataManager();
}
public function getById(int $id): ?Community
{
return $this->pdm->selectFromDbById($id, Community::class);
}
}
+11
View File
@@ -1,5 +1,6 @@
<?php namespace RVR\Repository;
use Generator;
use SokoWeb\Interfaces\Repository\IUserRepository;
use SokoWeb\Database\Query\Select;
use RVR\PersistentData\Model\User;
@@ -51,4 +52,14 @@ class UserRepository implements IUserRepository
return $this->pdm->selectFromDb($select, User::class);
}
public function searchByName(string $name): Generator
{
$select = new Select(\Container::$dbConnection);
$select->where('full_name', 'LIKE', '%' . $name . '%');
$select->orWhere('nickname', 'LIKE', '%' . $name . '%');
$select->limit(10);
yield from $this->pdm->selectMultipleFromDb($select, User::class);
}
}