add workflow on evaluationdocument in UI

This commit is contained in:
Julien Fastré 2022-02-27 02:38:08 +01:00
parent af0d7765ff
commit a9694da557
16 changed files with 244 additions and 66 deletions

View File

@ -144,6 +144,7 @@ export default {
this.$toast.open({message: v }); this.$toast.open({message: v });
} }
} else { } else {
console.error(error);
this.$toast.open({message: 'An error occurred'}); this.$toast.open({message: 'An error occurred'});
} }
}); });

View File

@ -13,13 +13,15 @@ namespace Chill\DocStoreBundle\Serializer\Normalizer;
use Chill\DocStoreBundle\Entity\StoredObject; use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\DocStoreBundle\Repository\StoredObjectRepository; use Chill\DocStoreBundle\Repository\StoredObjectRepository;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\ObjectToPopulateTrait;
use function array_key_exists; use function array_key_exists;
use function is_array; use function is_array;
class StoredObjectDenormalizer implements DenormalizerInterface class StoredObjectDenormalizer implements DenormalizerInterface
{ {
use ObjectToPopulateTrait;
private StoredObjectRepository $storedObjectRepository; private StoredObjectRepository $storedObjectRepository;
public function __construct(StoredObjectRepository $storedObjectRepository) public function __construct(StoredObjectRepository $storedObjectRepository)
@ -29,8 +31,10 @@ class StoredObjectDenormalizer implements DenormalizerInterface
public function denormalize($data, $type, $format = null, array $context = []) public function denormalize($data, $type, $format = null, array $context = [])
{ {
if (array_key_exists(AbstractNormalizer::OBJECT_TO_POPULATE, $context)) { $object = $this->extractObjectToPopulate(StoredObject::class, $context);
return $context[AbstractNormalizer::OBJECT_TO_POPULATE];
if (null !== $object) {
return $object;
} }
return $this->storedObjectRepository->find($data['id']); return $this->storedObjectRepository->find($data['id']);

View File

@ -12,6 +12,8 @@
:relatedEntityClass="this.relatedEntityClass" :relatedEntityClass="this.relatedEntityClass"
:relatedEntityId="this.relatedEntityId" :relatedEntityId="this.relatedEntityId"
:workflowsAvailables="workflowsAvailables" :workflowsAvailables="workflowsAvailables"
:preventDefaultMoveToGenerate="this.$props.preventDefaultMoveToGenerate"
:goToGenerateWorkflowPayload="this.goToGenerateWorkflowPayload"
@go-to-generate-workflow="goToGenerateWorkflow" @go-to-generate-workflow="goToGenerateWorkflow"
></pick-workflow> ></pick-workflow>
@ -36,6 +38,7 @@
:relatedEntityId="this.relatedEntityId" :relatedEntityId="this.relatedEntityId"
:workflowsAvailables="workflowsAvailables" :workflowsAvailables="workflowsAvailables"
:preventDefaultMoveToGenerate="this.$props.preventDefaultMoveToGenerate" :preventDefaultMoveToGenerate="this.$props.preventDefaultMoveToGenerate"
:goToGenerateWorkflowPayload="this.goToGenerateWorkflowPayload"
@go-to-generate-workflow="this.goToGenerateWorkflow" @go-to-generate-workflow="this.goToGenerateWorkflow"
></pick-workflow> ></pick-workflow>
</template> </template>
@ -83,6 +86,10 @@ export default {
required: false, required: false,
default: false, default: false,
}, },
goToGenerateWorkflowPayload: {
required: false,
default: {}
},
}, },
data() { data() {
return { return {
@ -105,7 +112,7 @@ export default {
this.modal.showModal = true; this.modal.showModal = true;
}, },
goToGenerateWorkflow(data) { goToGenerateWorkflow(data) {
console.log('go to generate workflow intercepted'); console.log('go to generate workflow intercepted', data);
this.$emit('goToGenerateWorkflow', data); this.$emit('goToGenerateWorkflow', data);
} }
}, },

View File

@ -37,6 +37,10 @@ export default {
required: false, required: false,
default: false, default: false,
}, },
goToGenerateWorkflowPayload: {
required: false,
default: {}
},
}, },
emits: ['goToGenerateWorkflow'], emits: ['goToGenerateWorkflow'],
methods: { methods: {
@ -51,7 +55,7 @@ export default {
window.location.assign(this.makeLink(workflowName)); window.location.assign(this.makeLink(workflowName));
} }
this.$emit('goToGenerateWorkflow', {event, workflowName, link: this.makeLink(workflowName)}); this.$emit('goToGenerateWorkflow', {event, workflowName, link: this.makeLink(workflowName), payload: this.goToGenerateWorkflowPayload});
} }
} }
} }

View File

@ -4,14 +4,9 @@
{% block display_content %} {% block display_content %}
<h2> <h2>
{{ 'workflow_'|trans }} {{ handler.entityTitle(entityWorkflow) }}
</h2> </h2>
{% include handler.templateTitle(entityWorkflow) with handler.templateTitleData(entityWorkflow)|merge({
'description': true,
'add_classes': 'ms-3 h3'
}) %}
{% include handler.template(entityWorkflow) with handler.templateData(entityWorkflow)|merge({ {% include handler.template(entityWorkflow) with handler.templateData(entityWorkflow)|merge({
'display_action': false 'display_action': false
}) %} }) %}

View File

@ -250,10 +250,7 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues
return $this->accompanyingPeriod; return $this->accompanyingPeriod;
} }
/** public function getAccompanyingPeriodWorkEvaluations(): Collection
* @return Collection
*/
public function getAccompanyingPeriodWorkEvaluations()
{ {
return $this->accompanyingPeriodWorkEvaluations; return $this->accompanyingPeriodWorkEvaluations;
} }

View File

@ -67,13 +67,17 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU
private ?User $createdBy = null; private ?User $createdBy = null;
/** /**
* **Note on deserialization/denormalization**: denormalization of documents is handled by.
*
* @see{Chill\PersonBundle\Serializer\Normalizer\AccompanyingPeriodWorkEvaluationDenormalizer}
*
* @ORM\OneToMany( * @ORM\OneToMany(
* targetEntity=AccompanyingPeriodWorkEvaluationDocument::class, * targetEntity=AccompanyingPeriodWorkEvaluationDocument::class,
* mappedBy="accompanyingPeriodWorkEvaluation", * mappedBy="accompanyingPeriodWorkEvaluation",
* cascade={"remove", "persist"} * cascade={"remove", "persist"},
* orphanRemoval=true
* ) * )
* @Serializer\Groups({"read", "write"}) * @Serializer\Groups({"read"})
* @Serializer\Groups({"accompanying_period_work_evaluation:create"})
*/ */
private Collection $documents; private Collection $documents;
@ -262,6 +266,7 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU
public function removeDocument(AccompanyingPeriodWorkEvaluationDocument $document): self public function removeDocument(AccompanyingPeriodWorkEvaluationDocument $document): self
{ {
$this->documents->removeElement($document); $this->documents->removeElement($document);
$document->setAccompanyingPeriodWorkEvaluation(null);
return $this; return $this;
} }

View File

@ -41,6 +41,7 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct
/** /**
* @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) * @ORM\Column(type="date_immutable", nullable=true, options={"default": null})
* @Serializer\Groups({"read"}) * @Serializer\Groups({"read"})
* @Serializer\Groups({"accompanying_period_work_evaluation:create"})
*/ */
private ?\DateTimeImmutable $createdAt = null; private ?\DateTimeImmutable $createdAt = null;
@ -49,6 +50,7 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct
* targetEntity=User::class * targetEntity=User::class
* ) * )
* @Serializer\Groups({"read"}) * @Serializer\Groups({"read"})
* @Serializer\Groups({"accompanying_period_work_evaluation:create"})
*/ */
private ?User $createdBy = null; private ?User $createdBy = null;
@ -60,13 +62,28 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct
* @internal the default name exceeds 64 characters, we must set manually: * @internal the default name exceeds 64 characters, we must set manually:
* @ORM\SequenceGenerator(sequenceName="chill_person_social_work_eval_doc_id_seq", allocationSize=1, initialValue=1000) * @ORM\SequenceGenerator(sequenceName="chill_person_social_work_eval_doc_id_seq", allocationSize=1, initialValue=1000)
* @Serializer\Groups({"read"}) * @Serializer\Groups({"read"})
* @Serializer\Groups({"accompanying_period_work_evaluation:create"})
*/ */
private ?int $id = null; private ?int $id = null;
/**
* This is a workaround for client, to allow them to assign arbitrary data
* dedicated to their job.
*
* This data is not persisted into database, but will appears on the data
* normalized during the same request (like PUT/PATCH request)
*
* @Serializer\Groups({"read"})
* @Serializer\Groups({"write"})
* @Serializer\Groups({"accompanying_period_work_evaluation:create"})
*
* @var mixed
*/
private $key;
/** /**
* @ORM\ManyToOne( * @ORM\ManyToOne(
* targetEntity=StoredObject::class, * targetEntity=StoredObject::class,
* cascade={"remove"},
* ) * )
* @Serializer\Groups({"read"}) * @Serializer\Groups({"read"})
* @Serializer\Groups({"write"}) * @Serializer\Groups({"write"})
@ -79,6 +96,7 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct
* targetEntity=DocGeneratorTemplate::class * targetEntity=DocGeneratorTemplate::class
* ) * )
* @Serializer\Groups({"read"}) * @Serializer\Groups({"read"})
* @Serializer\Groups({"accompanying_period_work_evaluation:create"})
*/ */
private ?DocGeneratorTemplate $template = null; private ?DocGeneratorTemplate $template = null;
@ -93,6 +111,7 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct
/** /**
* @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) * @ORM\Column(type="date_immutable", nullable=true, options={"default": null})
* @Serializer\Groups({"read"}) * @Serializer\Groups({"read"})
* @Serializer\Groups({"accompanying_period_work_evaluation:create"})
*/ */
private ?\DateTimeImmutable $updatedAt = null; private ?\DateTimeImmutable $updatedAt = null;
@ -101,6 +120,7 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct
* targetEntity=User::class * targetEntity=User::class
* ) * )
* @Serializer\Groups({"read"}) * @Serializer\Groups({"read"})
* @Serializer\Groups({"accompanying_period_work_evaluation:create"})
*/ */
private ?User $updatedBy = null; private ?User $updatedBy = null;
@ -127,6 +147,14 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct
return $this->id; return $this->id;
} }
/**
* @return mixed
*/
public function getKey()
{
return $this->key;
}
public function getStoredObject(): ?StoredObject public function getStoredObject(): ?StoredObject
{ {
return $this->storedObject; return $this->storedObject;
@ -186,6 +214,18 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct
return $this; return $this;
} }
/**
* @param mixed $key
*
* @return AccompanyingPeriodWorkEvaluationDocument
*/
public function setKey($key)
{
$this->key = $key;
return $this;
}
public function setStoredObject(?StoredObject $storedObject): AccompanyingPeriodWorkEvaluationDocument public function setStoredObject(?StoredObject $storedObject): AccompanyingPeriodWorkEvaluationDocument
{ {
$this->storedObject = $storedObject; $this->storedObject = $storedObject;

View File

@ -65,7 +65,7 @@
<h5>{{ $t('Documents') }} :</h5> <h5>{{ $t('Documents') }} :</h5>
<div class="flex-table"> <div class="flex-table">
<div class="item-bloc" v-for="(d, i) in evaluation.documents" :key="i"> <div class="item-bloc" v-for="(d, i) in evaluation.documents" :key="d.key">
<div class="item-row"> <div class="item-row">
<div class="input-group input-group-lg mb-3"> <div class="input-group input-group-lg mb-3">
<div> <div>
@ -86,13 +86,23 @@
</div> </div>
<div class="item-col"> <div class="item-col">
<ul class="record_actions" > <ul class="record_actions" >
<li> <li v-if="d.workflows_availables.length > 0">
<a :href="buildEditLink(d.storedObject)" class="btn btn-action btn-sm"> <list-workflow-modal
<i class="fa fa-edit"></i> :workflows="d.workflows"
</a> :allowCreate="true"
relatedEntityClass="Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument"
:relatedEntityId="d.id"
:workflowsAvailables="d.workflows_availables"
:preventDefaultMoveToGenerate="true"
:goToGenerateWorkflowPayload="{doc: d}"
@go-to-generate-workflow="goToGenerateWorkflowEvaluationDocument"
></list-workflow-modal>
</li> </li>
<li> <li>
<a class="btn btn-sm btn-delete" @click="removeDocument(d)"> <a :href="buildEditLink(d.storedObject)" class="btn btn-wopilink"></a>
</li>
<li>
<a class="btn btn-delete" @click="removeDocument(d)">
</a> </a>
</li> </li>
</ul> </ul>
@ -142,6 +152,8 @@ import { mapGetters, mapState } from 'vuex';
import PickTemplate from 'ChillDocGeneratorAssets/vuejs/_components/PickTemplate.vue'; import PickTemplate from 'ChillDocGeneratorAssets/vuejs/_components/PickTemplate.vue';
import {buildLink} from 'ChillDocGeneratorAssets/lib/document-generator'; import {buildLink} from 'ChillDocGeneratorAssets/lib/document-generator';
import AddAsyncUpload from 'ChillDocStoreAssets/vuejs/_components/AddAsyncUpload.vue'; import AddAsyncUpload from 'ChillDocStoreAssets/vuejs/_components/AddAsyncUpload.vue';
import ListWorkflowModal from 'ChillMainAssets/vuejs/_components/EntityWorkflow/ListWorkflowModal.vue';
import {buildLinkCreate} from 'ChillMainAssets/lib/entity-workflow/api.js';
const i18n = { const i18n = {
messages: { messages: {
@ -175,7 +187,8 @@ export default {
components: { components: {
ckeditor: CKEditor.component, ckeditor: CKEditor.component,
PickTemplate, PickTemplate,
AddAsyncUpload AddAsyncUpload,
ListWorkflowModal,
}, },
i18n, i18n,
data() { data() {
@ -189,9 +202,6 @@ export default {
} }
} }
}, },
mounted() {
console.log(this.evaluation)
},
computed: { computed: {
...mapState([ ...mapState([
'isPosting' 'isPosting'
@ -279,7 +289,18 @@ export default {
if (window.confirm("Êtes-vous sûr·e de vouloir supprimer le document qui a pour titre \"" + document.title +"\" ?")) { if (window.confirm("Êtes-vous sûr·e de vouloir supprimer le document qui a pour titre \"" + document.title +"\" ?")) {
this.$store.commit('removeDocument', {key: this.evaluation.key, document: document}); this.$store.commit('removeDocument', {key: this.evaluation.key, document: document});
} }
} },
goToGenerateWorkflowEvaluationDocument({event, link, workflowName, payload}) {
const callback = (data) => {
let evaluation = data.accompanyingPeriodWorkEvaluations.find(e => e.key === this.evaluation.key);
let updatedDocument = evaluation.documents.find(d => d.key === payload.doc.key);
window.location.assign(buildLinkCreate(workflowName,
'Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluationDocument', updatedDocument.id));
};
return this.$store.dispatch('submit', callback)
.catch(e => { console.log(e); throw e; });
},
}, },
} }
</script> </script>

View File

@ -131,6 +131,11 @@ const store = createStore({
endDate: e.endDate !== null ? ISOToDatetime(e.endDate.datetime) : null, endDate: e.endDate !== null ? ISOToDatetime(e.endDate.datetime) : null,
maxDate: e.maxDate !== null ? ISOToDatetime(e.maxDate.datetime) : null, maxDate: e.maxDate !== null ? ISOToDatetime(e.maxDate.datetime) : null,
warningInterval: e.warningInterval !== null ? intervalISOToDays(e.warningInterval) : null, warningInterval: e.warningInterval !== null ? intervalISOToDays(e.warningInterval) : null,
documents: e.documents.map((d, dindex) => {
return Object.assign(d, {
key: index
});
}),
}); });
return k; return k;
@ -199,16 +204,22 @@ const store = createStore({
found.results = found.results.filter(r => r.id !== result.id); found.results = found.results.filter(r => r.id !== result.id);
}, },
addDocument(state, payload) { addDocument(state, payload) {
state.evaluationsPicked.find(e => e.key === payload.key).documents.push(payload.document); let evaluation = state.evaluationsPicked.find(e => e.key === payload.key);
evaluation.documents.push(Object.assign(
payload.document, {
key: evaluation.documents.length + 1,
workflows_availables: state.work.workflows_availables_evaluation_documents,
workflows: [],
}));
}, },
removeDocument(state, payload) { removeDocument(state, {key, document}) {
let evaluations = state.evaluationsPicked.find(e => e.key === payload.key); let evaluations = state.evaluationsPicked.find(e => e.key === key);
if (evaluations === undefined) { if (evaluations === undefined) {
return; return;
} }
evaluations.documents = evaluations.documents.filter(d => d.id !== payload.document.id); evaluations.documents = evaluations.documents.filter(d => d.key !== document.key);
}, },
addEvaluation(state, evaluation) { addEvaluation(state, evaluation) {
let e = { let e = {

View File

@ -1,14 +1,24 @@
<?php <?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\PersonBundle\Security\Authorization; namespace Chill\PersonBundle\Security\Authorization;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter; use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use UnexpectedValueException;
/** /**
* Voter for AccompanyingPeriodWorkEvaluationDocument * Voter for AccompanyingPeriodWorkEvaluationDocument.
* *
* Delegates to the sames authorization than for Evalution * Delegates to the sames authorization than for Evalution
*/ */
@ -26,26 +36,27 @@ class AccompanyingPeriodWorkEvaluationDocumentVoter extends Voter
protected function supports($attribute, $subject) protected function supports($attribute, $subject)
{ {
return $subject instanceof AccompanyingPeriodWorkEvaluationDocument return $subject instanceof AccompanyingPeriodWorkEvaluationDocument
&& $attribute === self::SEE; && self::SEE === $attribute;
} }
/** /**
* @param string $attribute * @param string $attribute
* @param AccompanyingPeriodWorkEvaluationDocument $subject * @param AccompanyingPeriodWorkEvaluationDocument $subject
* @param TokenInterface $token *
* @return bool|void * @return bool|void
*/ */
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
{ {
switch ($attribute){ switch ($attribute) {
case self::SEE: case self::SEE:
return $this->accessDecisionManager->decide($token, [AccompanyingPeriodWorkEvaluationVoter::SEE], return $this->accessDecisionManager->decide(
$subject->getAccompanyingPeriodWorkEvaluation()); $token,
[AccompanyingPeriodWorkEvaluationVoter::SEE],
$subject->getAccompanyingPeriodWorkEvaluation()
);
default: default:
throw new \UnexpectedValueException("The attribute $attribute is not supported"); throw new UnexpectedValueException("The attribute {$attribute} is not supported");
} }
} }
} }

View File

@ -23,7 +23,6 @@ use Symfony\Component\Serializer\Normalizer\ObjectToPopulateTrait;
use function array_key_exists; use function array_key_exists;
use function array_merge; use function array_merge;
use function in_array;
use function is_array; use function is_array;
/** /**
@ -33,6 +32,7 @@ use function is_array;
class AccompanyingPeriodWorkEvaluationDenormalizer implements ContextAwareDenormalizerInterface, DenormalizerAwareInterface class AccompanyingPeriodWorkEvaluationDenormalizer implements ContextAwareDenormalizerInterface, DenormalizerAwareInterface
{ {
use DenormalizerAwareTrait; use DenormalizerAwareTrait;
use ObjectToPopulateTrait; use ObjectToPopulateTrait;
private EntityManagerInterface $em; private EntityManagerInterface $em;
@ -54,9 +54,7 @@ class AccompanyingPeriodWorkEvaluationDenormalizer implements ContextAwareDenorm
['skip' => self::class] ['skip' => self::class]
)); ));
//if (in_array('accompanying_period_work:edit', $context['groups'] ?? [], true)) { $this->handleDocumentCollection($data, $evaluation, $format, $context);
$this->handleEvaluationCollection($data, $evaluation, $format, $context);
//}
return $evaluation; return $evaluation;
} }
@ -70,7 +68,7 @@ class AccompanyingPeriodWorkEvaluationDenormalizer implements ContextAwareDenorm
&& 'accompanying_period_work_evaluation' === $data['type']; && 'accompanying_period_work_evaluation' === $data['type'];
} }
private function handleEvaluationCollection(array $data, AccompanyingPeriodWorkEvaluation $evaluation, string $format, array $context) private function handleDocumentCollection(array $data, AccompanyingPeriodWorkEvaluation $evaluation, string $format, array $context)
{ {
$dataById = []; $dataById = [];
$dataWithoutId = []; $dataWithoutId = [];
@ -82,29 +80,21 @@ class AccompanyingPeriodWorkEvaluationDenormalizer implements ContextAwareDenorm
$dataWithoutId[] = $e; $dataWithoutId[] = $e;
} }
} }
dump($dataById);
dump($dataWithoutId);
dump($evaluation);
//partition the separate kept documents and removed one //partition the separate kept documents and removed one
[$kept, $removed] = $evaluation->getDocuments() [$kept, $removed] = $evaluation->getDocuments()
->partition( ->partition(
static fn (int $key, AccompanyingPeriodWorkEvaluationDocument $a) => array_key_exists($a->getId(), $dataById) static fn (int $key, AccompanyingPeriodWorkEvaluationDocument $a) => array_key_exists($a->getId(), $dataById)
); );
//$kept = $evaluation->getDocuments();
dump($kept);
dump($removed);
// remove the document from evaluation // remove the document from evaluation
foreach ($removed as $r) { foreach ($removed as $r) {
dump($r);
$evaluation->removeDocument($r); $evaluation->removeDocument($r);
} }
// handle the documents kept // handle the documents kept
foreach ($kept as $k) { foreach ($kept as $k) {
dump($k); // Cannot iterate over $kept which is a PersistentCollection $this->denormalizer->denormalize(
$evaluation->removeDocument($k);
dump($evaluation);
$document = $this->denormalizer->denormalize(
$dataById[$k->getId()], $dataById[$k->getId()],
AccompanyingPeriodWorkEvaluationDocument::class, AccompanyingPeriodWorkEvaluationDocument::class,
$format, $format,
@ -116,12 +106,9 @@ class AccompanyingPeriodWorkEvaluationDenormalizer implements ContextAwareDenorm
] ]
) )
); );
$evaluation->addDocument($document);
} }
// create new document // create new document
foreach ($dataWithoutId as $newData) { foreach ($dataWithoutId as $newData) {
dump($newData);
$document = $this->denormalizer->denormalize( $document = $this->denormalizer->denormalize(
$newData, $newData,
AccompanyingPeriodWorkEvaluationDocument::class, AccompanyingPeriodWorkEvaluationDocument::class,

View File

@ -0,0 +1,71 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\PersonBundle\Serializer\Normalizer;
use Chill\MainBundle\Repository\Workflow\EntityWorkflowRepository;
use Chill\MainBundle\Workflow\Helper\MetadataExtractor;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument;
use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
use Symfony\Component\Workflow\Registry;
use function array_key_exists;
class AccompanyingPeriodWorkEvaluationDocumentNormalizer implements ContextAwareNormalizerInterface, NormalizerAwareInterface
{
use NormalizerAwareTrait;
private const SKIP = 'accompanying_period_work_evaluation_document_skip';
private EntityWorkflowRepository $entityWorkflowRepository;
private MetadataExtractor $metadataExtractor;
private Registry $registry;
public function __construct(EntityWorkflowRepository $entityWorkflowRepository, MetadataExtractor $metadataExtractor, Registry $registry)
{
$this->entityWorkflowRepository = $entityWorkflowRepository;
$this->metadataExtractor = $metadataExtractor;
$this->registry = $registry;
}
public function normalize($object, ?string $format = null, array $context = []): array
{
$initial = $this->normalizer->normalize($object, $format, array_merge($context, [
self::SKIP => spl_object_hash($object),
]));
$initial['workflows_availables'] = $this->metadataExtractor->availableWorkflowFor(
AccompanyingPeriodWorkEvaluationDocument::class,
$object->getId()
);
$workflows = $this->entityWorkflowRepository->findBy([
'relatedEntityClass' => AccompanyingPeriodWorkEvaluationDocument::class,
'relatedEntityId' => $object->getId(),
]);
$initial['workflows'] = $this->normalizer->normalize($workflows, 'json', $context);
return $initial;
}
public function supportsNormalization($data, ?string $format = null, array $context = [])
{
return $data instanceof AccompanyingPeriodWorkEvaluationDocument
&& 'json' === $format
&& (
!array_key_exists(self::SKIP, $context)
|| spl_object_hash($data) !== $context[self::SKIP]
);
}
}

View File

@ -49,6 +49,15 @@ class AccompanyingPeriodWorkEvaluationNormalizer implements ContextAwareNormaliz
[self::IGNORE_EVALUATION => spl_object_hash($object)] [self::IGNORE_EVALUATION => spl_object_hash($object)]
)); ));
// due to bug: https://api-platform.com/docs/core/serialization/#collection-relation
// and also: https://github.com/symfony/symfony/issues/36965
// we have to rewrite the documents as a collection
$initial['documents'] = $this->normalizer->normalize(
$object->getDocuments()->getValues(),
$format,
$context
);
// then, we add normalization for things which are not into the entity // then, we add normalization for things which are not into the entity
$initial['workflows_availables'] = $this->metadataExtractor->availableWorkflowFor( $initial['workflows_availables'] = $this->metadataExtractor->availableWorkflowFor(

View File

@ -16,6 +16,7 @@ use Chill\MainBundle\Repository\Workflow\EntityWorkflowRepository;
use Chill\MainBundle\Workflow\Helper\MetadataExtractor; use Chill\MainBundle\Workflow\Helper\MetadataExtractor;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument;
use Symfony\Component\Serializer\Exception\ExceptionInterface; use Symfony\Component\Serializer\Exception\ExceptionInterface;
use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface; use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface; use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
@ -56,6 +57,15 @@ class AccompanyingPeriodWorkNormalizer implements ContextAwareNormalizerInterfac
[self::IGNORE_WORK => spl_object_hash($object)] [self::IGNORE_WORK => spl_object_hash($object)]
)); ));
// due to bug: https://api-platform.com/docs/core/serialization/#collection-relation
// and also: https://github.com/symfony/symfony/issues/36965
// we have to rewrite the evaluations as a collection
$initial['accompanyingPeriodWorkEvaluations'] = $this->normalizer->normalize(
$object->getAccompanyingPeriodWorkEvaluations()->getValues(),
$format,
$context
);
// then, we add normalization for things which are not into the entity // then, we add normalization for things which are not into the entity
$initial['workflows_availables'] = $this->metadataExtractor->availableWorkflowFor( $initial['workflows_availables'] = $this->metadataExtractor->availableWorkflowFor(
@ -67,10 +77,15 @@ class AccompanyingPeriodWorkNormalizer implements ContextAwareNormalizerInterfac
AccompanyingPeriodWorkEvaluation::class AccompanyingPeriodWorkEvaluation::class
); );
$initial['workflows_availables_evaluation_documents'] = $this->metadataExtractor->availableWorkflowFor(
AccompanyingPeriodWorkEvaluationDocument::class
);
$workflows = $this->entityWorkflowRepository->findBy([ $workflows = $this->entityWorkflowRepository->findBy([
'relatedEntityClass' => AccompanyingPeriodWork::class, 'relatedEntityClass' => AccompanyingPeriodWork::class,
'relatedEntityId' => $object->getId(), 'relatedEntityId' => $object->getId(),
]); ]);
$initial['workflows'] = $this->normalizer->normalize($workflows, 'json', $context); $initial['workflows'] = $this->normalizer->normalize($workflows, 'json', $context);
return $initial; return $initial;

View File

@ -17,7 +17,6 @@ use Chill\MainBundle\Workflow\EntityWorkflowHandlerInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument;
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocumentRepository; use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocumentRepository;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkEvaluationDocumentVoter; use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkEvaluationDocumentVoter;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkEvaluationVoter;
use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorInterface;
class AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler implements EntityWorkflowHandlerInterface class AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler implements EntityWorkflowHandlerInterface
@ -40,10 +39,11 @@ class AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler implements EntityW
public function getEntityData(EntityWorkflow $entityWorkflow, array $options = []): array public function getEntityData(EntityWorkflow $entityWorkflow, array $options = []): array
{ {
$evaluation = $this->getRelatedEntity($entityWorkflow); $doc = $this->getRelatedEntity($entityWorkflow);
return [ return [
'persons' => $evaluation->getAccompanyingPeriodWork()->getPersons(), 'persons' => $doc->getAccompanyingPeriodWorkEvaluation()
->getAccompanyingPeriodWork()->getPersons(),
]; ];
} }