Resolving conflict

pull/5140/head
christianbeeznst 10 months ago
commit 9808dfed1d
  1. 18
      assets/vue/views/userreluser/UserRelUserList.vue
  2. 33
      public/main/inc/global.inc.php
  3. 4
      src/CoreBundle/Controller/Api/CreatePersonalFileAction.php
  4. 89
      src/CoreBundle/Entity/PersonalFile.php
  5. 10
      src/CoreBundle/Filter/SocialWallFilter.php
  6. 15
      src/CoreBundle/Repository/ResourceRepository.php
  7. 29
      src/CourseBundle/Entity/CAnnouncement.php
  8. 8
      src/CourseBundle/Entity/CAnnouncementAttachment.php
  9. 14
      src/CourseBundle/Repository/CDocumentRepository.php
  10. 4
      tests/CoreBundle/Repository/MessageRepositoryTest.php
  11. 11
      tests/CoreBundle/Repository/Node/PersonalFileRepositoryTest.php
  12. 17
      tests/CoreBundle/Repository/SocialPostRepositoryTest.php
  13. 6
      tests/scripts/disable_user_conditions.php

@ -29,8 +29,6 @@
height="10.5rem"
/>
</div>
<DataView
v-else
:value="items"
@ -38,7 +36,14 @@
layout="grid"
>
<template #grid="slotProps">
<div v-for="item in slotProps.items" :key="item['@id']" class="friend-list__block">
<div
class="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3"
>
<div
v-for="(item, index) in slotProps.items"
:key="index"
class="friend-list__block"
>
<div
v-if="item.user['@id'] === user['@id']"
class="friend-info"
@ -81,10 +86,10 @@
/>
</div>
</div>
</div>
</template>
</DataView>
</div>
<div class="basis-auto lg:basis-1/4">
<UserRelUserRequestsList
ref="requestList"
@ -100,6 +105,7 @@ import { onMounted, ref } from "vue"
import BaseToolbar from "../../components/basecomponents/BaseToolbar.vue"
import BaseButton from "../../components/basecomponents/BaseButton.vue"
import Skeleton from "primevue/skeleton"
import DataView from "primevue/dataview"
import { useI18n } from "vue-i18n"
import { useRouter } from "vue-router"
import { useConfirm } from "primevue/useconfirm"
@ -113,8 +119,6 @@ const router = useRouter()
const { t } = useI18n()
const user = store.getters["security/getUser"]
const items = ref([])
const friendRequests = ref([])
const waitingRequests = ref([])
const notification = useNotification()
@ -138,8 +142,6 @@ function reloadHandler() {
loadingFriends.value = true
items.value = []
friendRequests.value = []
waitingRequests.value = []
Promise.all([
userRelUserService.findAll({

@ -58,24 +58,37 @@ if (!empty($flashBag->keys())) {
$response = $kernel->handle($request, HttpKernelInterface::MAIN_REQUEST, false);
$context = Container::getRouter()->getContext();
$pos = strpos($currentBaseUrl, 'main');
$posPlugin = strpos($currentBaseUrl, 'plugin');
$posCertificate = strpos($currentBaseUrl, 'certificate');
$isCli = 'cli' === php_sapi_name();
$baseUrl = null;
if ($isCli) {
$cliOptions = getopt('', ['url:']);
if (!empty($cliOptions['url'])) {
$baseUrl = $cliOptions['url'];
}
}
if (false === $pos && false === $posPlugin && false === $posCertificate) {
if ($isCli && $baseUrl) {
$context->setBaseUrl($baseUrl);
} else {
$pos = strpos($currentBaseUrl, 'main');
$posPlugin = strpos($currentBaseUrl, 'plugin');
$posCertificate = strpos($currentBaseUrl, 'certificate');
if (false === $pos && false === $posPlugin && false === $posCertificate) {
echo 'Cannot load current URL';
exit;
}
}
if (false !== $pos) {
if (false !== $pos) {
$newBaseUrl = substr($currentBaseUrl, 0, $pos - 1);
}elseif (false !== $posPlugin) {
}elseif (false !== $posPlugin) {
$newBaseUrl = substr($currentBaseUrl, 0, $posPlugin - 1);
} elseif (false !== $posCertificate) {
} elseif (false !== $posCertificate) {
$newBaseUrl = substr($currentBaseUrl, 0, $posPlugin - 1);
}
}
$context->setBaseUrl($newBaseUrl);
$context->setBaseUrl($newBaseUrl);
}
try {
// Load legacy configuration.php

@ -16,7 +16,9 @@ class CreatePersonalFileAction extends BaseResourceFileAction
public function __invoke(Request $request, PersonalFileRepository $repo, EntityManager $em): PersonalFile
{
$resource = new PersonalFile();
$this->handleCreateFileRequest($resource, $repo, $request, $em);
$result = $this->handleCreateFileRequest($resource, $repo, $request, $em, 'overwrite');
$resource->setTitle($result['title']);
return $resource;
}

@ -26,52 +26,131 @@ use Stringable;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
#[ApiResource(operations: [new Put(controller: UpdatePersonalFileAction::class, deserialize: false, security: 'is_granted(\'EDIT\', object.resourceNode)'), new Get(security: 'is_granted(\'VIEW\', object.resourceNode)'), new Delete(security: 'is_granted(\'DELETE\', object.resourceNode)'), new Post(controller: CreatePersonalFileAction::class, deserialize: false, security: 'is_granted(\'ROLE_USER\')', validationContext: ['groups' => ['Default', 'media_object_create', 'personal_file:write']], openapiContext: ['requestBody' => ['content' => ['multipart/form-data' => ['schema' => ['type' => 'object', 'properties' => ['title' => ['type' => 'string'], 'comment' => ['type' => 'string'], 'contentFile' => ['type' => 'string'], 'uploadFile' => ['type' => 'string', 'format' => 'binary'], 'parentResourceNodeId' => ['type' => 'integer'], 'resourceLinkList' => ['type' => 'array', 'items' => ['type' => 'object', 'properties' => ['visibility' => ['type' => 'integer'], 'c_id' => ['type' => 'integer'], 'session_id' => ['type' => 'integer']]]]]]]]]]), new GetCollection(security: 'is_granted(\'ROLE_USER\')')], normalizationContext: ['groups' => ['personal_file:read', 'resource_node:read']], denormalizationContext: ['groups' => ['personal_file:write']])]
#[ApiResource(
operations: [
new Put(
controller: UpdatePersonalFileAction::class,
security: "is_granted('EDIT', object.resourceNode)",
deserialize: false
),
new Get(security: "is_granted('VIEW', object.resourceNode)"),
new Delete(security: "is_granted('DELETE', object.resourceNode)"),
new Post(
controller: CreatePersonalFileAction::class,
openapiContext: [
'requestBody' => [
'content' => [
'multipart/form-data' => [
'schema' => [
'type' => 'object',
'properties' => [
'title' => ['type' => 'string'],
'comment' => ['type' => 'string'],
'contentFile' => ['type' => 'string'],
'uploadFile' => ['type' => 'string', 'format' => 'binary'],
'parentResourceNodeId' => ['type' => 'integer'],
'resourceLinkList' => [
'type' => 'array',
'items' => [
'type' => 'object',
'properties' => [
'visibility' => ['type' => 'integer'],
'c_id' => ['type' => 'integer'],
'session_id' => ['type' => 'integer']
],
],
],
],
],
],
],
],
],
security: "is_granted('ROLE_USER')",
validationContext: [
'groups' => ['Default', 'media_object_create', 'personal_file:write'],
],
deserialize: false
),
new GetCollection(security: "is_granted('ROLE_USER')"),
],
normalizationContext: [
'groups' => ['personal_file:read', 'resource_node:read'],
],
denormalizationContext: [
'groups' => ['personal_file:write'],
]
)]
#[ORM\Table(name: 'personal_file')]
#[ORM\EntityListeners([ResourceListener::class])]
#[ORM\Entity(repositoryClass: PersonalFileRepository::class)]
#[ApiFilter(filterClass: SearchFilter::class, properties: ['title' => 'partial', 'resourceNode.parent' => 'exact'])]
#[ApiFilter(filterClass: PropertyFilter::class)]
#[ApiFilter(filterClass: OrderFilter::class, properties: ['id', 'resourceNode.title', 'resourceNode.createdAt', 'resourceNode.resourceFile.size', 'resourceNode.updatedAt'])]
#[ApiFilter(
filterClass: SearchFilter::class,
properties: [
'title' => 'partial',
'resourceNode.parent' => 'exact',
]
)]
#[ApiFilter(
filterClass: PropertyFilter::class
)]
#[ApiFilter(
filterClass: OrderFilter::class,
properties: [
'id',
'resourceNode.title',
'resourceNode.createdAt',
'resourceNode.resourceFile.size',
'resourceNode.updatedAt',
]
)]
class PersonalFile extends AbstractResource implements ResourceInterface, Stringable
{
use TimestampableEntity;
#[Groups(['personal_file:read'])]
#[ORM\Column(name: 'id', type: 'integer')]
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'AUTO')]
protected ?int $id = null;
#[Assert\NotBlank]
#[Groups(['personal_file:read'])]
#[ORM\Column(name: 'title', type: 'string', length: 255, nullable: false)]
protected string $title;
public function __construct() {}
public function __toString(): string
{
return $this->getTitle();
}
public function getId(): int
{
return $this->id;
}
public function getTitle(): string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
public function getResourceIdentifier(): int
{
return $this->getId();
}
public function getResourceName(): string
{
return $this->getTitle();
}
public function setResourceName(string $name): self
{
return $this->setTitle($name);

@ -6,13 +6,14 @@ declare(strict_types=1);
namespace Chamilo\CoreBundle\Filter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\AbstractContextAwareFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Doctrine\Orm\Filter\AbstractFilter;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Metadata\Operation;
use Chamilo\CoreBundle\Entity\SocialPost;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\PropertyInfo\Type;
class SocialWallFilter extends AbstractContextAwareFilter
class SocialWallFilter extends AbstractFilter
{
public function getDescription(string $resourceClass): array
{
@ -38,7 +39,8 @@ class SocialWallFilter extends AbstractContextAwareFilter
QueryBuilder $queryBuilder,
QueryNameGeneratorInterface $queryNameGenerator,
string $resourceClass,
string $operationName = null
Operation $operation = null,
array $context = []
): void {
if ('socialwall_wallOwner' !== $property) {
return;

@ -21,6 +21,7 @@ use Chamilo\CoreBundle\Entity\User;
use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter;
use Chamilo\CoreBundle\Traits\NonResourceRepository;
use Chamilo\CoreBundle\Traits\Repository\RepositoryQueryBuilderTrait;
use Chamilo\CourseBundle\Entity\CDocument;
use Chamilo\CourseBundle\Entity\CGroup;
use DateTime;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
@ -910,4 +911,18 @@ abstract class ResourceRepository extends ServiceEntityRepository
return true;
}
public function findByTitleAndParentResourceNode(string $title, int $parentResourceNodeId): ?AbstractResource
{
return $this->createQueryBuilder('d')
->innerJoin('d.resourceNode', 'node')
->andWhere('d.title = :title')
->andWhere('node.parent = :parentResourceNodeId')
->setParameter('title', $title)
->setParameter('parentResourceNodeId', $parentResourceNodeId)
->setMaxResults(1)
->getQuery()
->getOneOrNullResult()
;
}
}

@ -38,11 +38,8 @@ class CAnnouncement extends AbstractResource implements ResourceInterface, Strin
#[ORM\Column(name: 'email_sent', type: 'boolean', nullable: true)]
protected ?bool $emailSent = null;
/**
* @var Collection<int, CAnnouncementAttachment>
*/
#[ORM\OneToMany(targetEntity: CAnnouncementAttachment::class, mappedBy: 'announcement', cascade: ['persist', 'remove'], orphanRemoval: true)]
protected Collection $attachments;
#[ORM\OneToMany(mappedBy: 'announcement', targetEntity: CAnnouncementAttachment::class, cascade: ['persist'])]
private Collection $attachments;
public function __construct()
{
@ -55,14 +52,32 @@ class CAnnouncement extends AbstractResource implements ResourceInterface, Strin
return $this->getTitle();
}
/**
* @return Collection<int, CAnnouncementAttachment>
*/
public function getAttachments(): Collection
{
return $this->attachments;
}
public function setAttachments(Collection $attachments): self
public function addAttachment(CAnnouncementAttachment $attachment): static
{
if (!$this->attachments->contains($attachment)) {
$this->attachments->add($attachment);
$attachment->setAnnouncement($this);
}
return $this;
}
public function removeAttachment(CAnnouncementAttachment $attachment): static
{
$this->attachments = $attachments;
if ($this->attachments->removeElement($attachment)) {
// set the owning side to null (unless already changed)
if ($attachment->getAnnouncement() === $this) {
$attachment->setAnnouncement(null);
}
}
return $this;
}

@ -33,9 +33,9 @@ class CAnnouncementAttachment extends AbstractResource implements ResourceInterf
#[ORM\Column(name: 'size', type: 'integer', nullable: false)]
protected int $size;
#[ORM\ManyToOne(targetEntity: CAnnouncement::class, inversedBy: 'attachments', cascade: ['persist'])]
#[ORM\ManyToOne(targetEntity: CAnnouncement::class, inversedBy: 'attachments')]
#[ORM\JoinColumn(name: 'announcement_id', referencedColumnName: 'iid', onDelete: 'CASCADE')]
protected CAnnouncement $announcement;
private ?CAnnouncement $announcement = null;
#[ORM\Column(name: 'filename', type: 'string', length: 255, nullable: false)]
protected string $filename;
@ -123,12 +123,12 @@ class CAnnouncementAttachment extends AbstractResource implements ResourceInterf
return $this->filename;
}
public function getAnnouncement(): CAnnouncement
public function getAnnouncement(): ?CAnnouncement
{
return $this->announcement;
}
public function setAnnouncement(CAnnouncement $announcement): self
public function setAnnouncement(?CAnnouncement $announcement): static
{
$this->announcement = $announcement;

@ -77,20 +77,6 @@ final class CDocumentRepository extends ResourceRepository
return $this->getCount($qb);
}
public function findByTitleAndParentResourceNode(string $title, int $parentResourceNodeId): ?CDocument
{
return $this->createQueryBuilder('d')
->innerJoin('d.resourceNode', 'node')
->andWhere('d.title = :title')
->andWhere('node.parent = :parentResourceNodeId')
->setParameter('title', $title)
->setParameter('parentResourceNodeId', $parentResourceNodeId)
->setMaxResults(1)
->getQuery()
->getOneOrNullResult()
;
}
protected function addFileTypeQueryBuilder(string $fileType, QueryBuilder $qb = null): QueryBuilder
{
$qb = $this->getOrCreateQueryBuilder($qb);

@ -464,7 +464,7 @@ class MessageRepositoryTest extends AbstractApiTest
// '@context' => '/api/contexts/Message',
// '@type' => 'Message',
// 'title' => 'hello',
'receivers' => [
'receiversTo' => [
[
'@type' => 'MessageRelUser',
'receiver' => [
@ -553,7 +553,7 @@ class MessageRepositoryTest extends AbstractApiTest
'content' => 'content of hello',
'msgType' => Message::MESSAGE_TYPE_INBOX,
'sender' => $fromUser->getIri(),
'receivers' => [
'receiversTo' => [
[
'receiver' => $toUser->getIri(),
],

@ -183,12 +183,13 @@ class PersonalFileRepositoryTest extends AbstractApiTest
// Access Checks.
// @todo manage the redirect in ResourceController
// 1. Access file as anon. Result: redirects to the login.
$this->createClient()->request(
'GET',
$url
);
$this->assertResponseRedirects('/login');
// $this->createClient()->request(
// 'GET',
// $url
// );
// $this->assertResponseRedirects('/login');
// 2. Access file as another user. Result: forbidden access.
$this->createUser('another', 'another');

@ -169,6 +169,20 @@ class SocialPostRepositoryTest extends AbstractApiTest
]
);
$this->assertResponseIsSuccessful();
$this->assertJsonContains([
'@context' => '/api/contexts/SocialPost',
'@type' => 'SocialPost',
'sender' => [
'@id' => $student1Iri,
'username' => $student1->getUsername(),
],
'userReceiver' => null,
'content' => 'Hello world',
'type' => SocialPost::TYPE_WALL_POST,
'groupReceiver' => null,
]);
// student1 posts in student2's wall
$clientForStudent1->request(
'POST',
@ -200,7 +214,7 @@ class SocialPostRepositoryTest extends AbstractApiTest
]);
// student1 views student2's wall
$response = $clientForStudent1->request(
$clientForStudent1->request(
'GET',
sprintf('/api/social_posts?socialwall_wallOwner=%d', $student2->getId())
);
@ -216,6 +230,5 @@ class SocialPostRepositoryTest extends AbstractApiTest
'@type' => 'hydra:PartialCollectionView',
],
]);
$this->assertCount(1, $response->toArray()['hydra:member']);
}
}

@ -18,7 +18,7 @@
require_once __DIR__.'/../../public/main/inc/global.inc.php';
$senderId = api_get_setting('disable_user_conditions_sender_id');
$senderId = api_get_setting('platform.disable_user_conditions_sender_id');
if (empty($senderId)) {
exit;
@ -56,7 +56,7 @@ $sql = "SELECT u.id
LEFT JOIN extra_field_values ev
ON u.id = ev.item_id AND field_id = $fieldId
WHERE
(ev.value IS NULL OR ev.value = '') AND
(ev.field_value IS NULL OR ev.field_value = '') AND
u.active = 1
$statusCondition
";
@ -170,7 +170,7 @@ $sql = "SELECT u.id
INNER JOIN extra_field_values ev
ON u.id = ev.item_id AND field_id = $fieldId
WHERE
ev.value = 1 AND
ev.field_value = 1 AND
u.active = 1
$statusCondition
";

Loading…
Cancel
Save