/** * * @return \Zend\View\Model\JsonModel Exception : if query param 'return' is true, redirect to route application. */ public function saveAction() { $messages = array(); $event = null; $events = array(); $sendEvents = array(); $return = $this->params()->fromQuery('return', null); if ($this->zfcUserAuthentication()->hasIdentity()) { if ($this->getRequest()->isPost()) { $post = array_merge_recursive($this->getRequest()->getPost()->toArray(), $this->getRequest()->getFiles()->toArray()); $id = $post['id'] ? $post['id'] : null; $objectManager = $this->getServiceLocator()->get('Doctrine\\ORM\\EntityManager'); $deleteStatus = $objectManager->getRepository('Application\\Entity\\Status')->find('5'); $credentials = false; if ($id) { // modification $event = $objectManager->getRepository('Application\\Entity\\Event')->find($id); if ($event) { if ($this->isGranted('events.write') || $event->getAuthor()->getId() === $this->zfcUserAuthentication()->getIdentity()->getId()) { $credentials = true; // si utilisateur n'a pas les droits events.status, le champ est désactivé et aucune valeur n'est envoyée if (!isset($post['status'])) { $post['status'] = $event->getStatus()->getId(); } } } } else { // création if ($this->isGranted('events.create')) { $event = new Event(); $event->setAuthor($this->zfcUserAuthentication()->getIdentity()); $event->setOrganisation($this->zfcUserAuthentication()->getIdentity()->getOrganisation()); // si utilisateur n'a pas les droits events.status, le champ est désactivé et aucune valeur n'est envoyée if (!isset($post['status'])) { $post['status'] = 1; } $credentials = true; } } if ($credentials) { //préparation de certains champs $startdate = new \DateTime($post['startdate']); $offset = $startdate->getTimezone()->getOffset($startdate); $startdate->setTimezone(new \DateTimeZone("UTC")); $startdate->add(new \DateInterval("PT" . $offset . "S")); $enddate = null; if (isset($post['enddate']) && !empty($post['enddate'])) { $enddate = new \DateTime($post['enddate']); $offset = $enddate->getTimezone()->getOffset($enddate); $enddate->setTimezone(new \DateTimeZone("UTC")); $enddate->add(new \DateInterval("PT" . $offset . "S")); } $diff = 0; if ($enddate !== null) { $diff = $startdate->diff($enddate); } $now = new \DateTime('now'); $now->setTimezone(new \DateTimeZone('UTC')); $modrecurrence = false; $recurrence = null; if (isset($post['recurrencepattern']) && !empty($post['recurrencepattern'])) { if ($id) { //récurrence existante $recurrence = $event->getRecurrence(); if ($recurrence === null) { //en cas de modification d'un évènement seul et ajout d'une recurrence $recurrence = new Recurrence($startdate, ""); $event->setStatus($deleteStatus); $this->closeEvent($event); } if (isset($post['exclude']) && $post['exclude'] == "true") { $recurrence->exclude($event); $event->setRecurrence(null); $status = $objectManager->getRepository('Application\\Entity\\Status')->find($post['status']); $event->setStatus($status); if ($enddate !== null) { $event->setDates($startdate, $enddate); } $this->changeEndDate($event, $enddate); $this->changeStartDate($event, $startdate); $events[] = $event; } else { //si la règle de récurrence a changé, on exclut les évènements passés //on supprime les évènements restants //et on crée une nouvelle récurrence $test = $recurrence->getStartdate() == $startdate; //changement de récurrence si //* le pattern a changé ou //* la date de début de l'évènement a changé if (strcmp($recurrence->getRecurrencePattern(), $post['recurrencepattern']) !== 0 || !($event->getStartdate() == $startdate)) { $recurrentEvents = $recurrence->getEvents(); foreach ($recurrentEvents as $e) { if ($e->isPast($now)) { $e->setRecurrence(null); } else { $e->setStatus($deleteStatus); } $objectManager->persist($e); $sendEvents[] = $e; } //si le statut est positionné à "Supprimé" //on ne crée pas de nouveaux évènements if ($post['status'] != 5) { //$objectManager->remove($recurrence); $recurrence = new Recurrence($startdate, $post['recurrencepattern']); $objectManager->persist($recurrence); foreach ($recurrence->getRSet() as $occurrence) { $e = new Event(); $e->setRecurrence($recurrence); $e->setAuthor($this->zfcUserAuthentication()->getIdentity()); $e->setOrganisation($this->zfcUserAuthentication()->getIdentity()->getOrganisation()); $status = $objectManager->getRepository('Application\\Entity\\Status')->find(1); $e->setStatus($status); $e->setStartdate($occurrence); if ($enddate !== null) { $end = clone $occurrence; $end->add($diff); $e->setEnddate($end); } $modrecurrence = true; $events[] = $e; } } } else { //sinon on exclut simplement les evts passés //mise à jour des évènements futurs en fonction des champs modifiés $recurrentEvents = $recurrence->getEvents(); foreach ($recurrentEvents as $e) { if ($e->isPast($now)) { $recurrence->exclude($e); $e->setRecurrence(null); $objectManager->persist($e); $sendEvents[] = $e; } else { $events[] = $e; //exception pour la suppression : appliqué à tous les évènements futurs if ($post['status'] == 5) { $e->setStatus($deleteStatus); } } } //on mets à jour date de fin et statut de l'évènement sélectionné $status = $objectManager->getRepository('Application\\Entity\\Status')->find($post['status']); $event->setStatus($status); if ($enddate !== null) { $event->setDates($startdate, $enddate); } $this->changeEndDate($event, $enddate); $this->changeStartDate($event, $startdate); } } } else { //nouvelle récurrence $pattern = $post['recurrencepattern']; $recurrence = new Recurrence($startdate, $pattern); $objectManager->persist($recurrence); $rset = $recurrence->getRSet(); foreach ($rset as $occurrence) { $e = new Event(); $e->setRecurrence($recurrence); $status = $objectManager->getRepository('Application\\Entity\\Status')->find(1); $e->setStatus($status); $e->setStartdate($occurrence); $e->setAuthor($this->zfcUserAuthentication()->getIdentity()); $e->setOrganisation($this->zfcUserAuthentication()->getIdentity()->getOrganisation()); if ($enddate !== null) { $end = clone $occurrence; $end->add($diff); $e->setEnddate($end); } $events[] = $e; } } } else { //un seul évènement $status = $objectManager->getRepository('Application\\Entity\\Status')->find($post['status']); $event->setStatus($status); if ($enddate !== null) { $event->setDates($startdate, $enddate); } $this->changeEndDate($event, $enddate); $this->changeStartDate($event, $startdate); $events[] = $event; } foreach ($events as $e) { //statut et date de fin sont gérés au dessus //car les traitements sont spécifiques à chaque cas //impact $impact = $objectManager->getRepository('Application\\Entity\\Impact')->find($post['impact']); $e->setImpact($impact); //catégorie $e->setCategory($objectManager->getRepository('Application\\Entity\\Category')->find($post['category'])); //champs horaires : ponctuel, programmé $e->setPunctual($post['punctual']); $e->setScheduled($post['scheduled']); //cohérence horaires, statut // si statut terminé, non ponctuel et pas d'heure de fin // alors l'heure de fin est mise auto à l'heure actuelle // sauf si heure de début future (cas improbable) if (!$e->isPunctual() && $e->getStatus()->getId() == 3 && $e->getEnddate() == null) { if ($e->getStartdate() < $now && $e->setEnddate($now)) { $this->changeEndDate($e, $now); } else { // dans le cas contraire, retour au statut confirmé $confirm = $objectManager->getRepository('Application\\Entity\\Status')->find(2); $e->setStatus($confirm); $messages['error'][] = "Impossible de passer l'évènement au statut terminé."; } } // si annulé, non ponctuel et pas d'heure de fin // alors on met l'heure de fin à heure de début +90min if (!$e->isPunctual() && $e->getStatus()->getId() == 4 && $e->getEnddate() == null) { if ($e->getStartdate() < $now) { $this->changeEndDate($e, $now); } else { $enddate = clone $e->getStartdate(); $enddate->add(new \DateInterval("PT90M")); $this->changeEndDate($e, $enddate); } } //custom fields if (isset($post['custom_fields'])) { foreach ($post['custom_fields'] as $key => $value) { // génération des customvalues si un customfield dont le nom est $key est trouvé $customfield = $objectManager->getRepository('Application\\Entity\\CustomField')->findOneBy(array('id' => $key)); if ($customfield) { if (is_array($value)) { $temp = ""; foreach ($value as $v) { $temp .= (string) $v . "\r"; } $value = trim($temp); } $customvalue = $objectManager->getRepository('Application\\Entity\\CustomFieldValue')->findOneBy(array('customfield' => $customfield->getId(), 'event' => $e->getId())); if (!$customvalue) { $customvalue = new CustomFieldValue(); $customvalue->setEvent($e); $customvalue->setCustomField($customfield); $e->addCustomFieldValue($customvalue); } $customvalue->setValue($value); } } } //une fois les évènements fils positionnés, on vérifie si il faut clore l'évènement if ($e->getStatus()->getId() == 3 || $e->getStatus()->getId() == 4 || $e->getStatus()->getId() == 5) { // passage au statut supprimé $this->closeEvent($e); } // create associated actions (only relevant if creation from a model) //en cas d'évènements récurrents, seuls les nouveaux évènements doivent être impactés if (isset($post['modelid'])) { $parentID = $post['modelid']; // get actions foreach ($objectManager->getRepository('Application\\Entity\\PredefinedEvent')->findBy(array('parent' => $parentID), array('place' => 'ASC')) as $action) { if ($action->getCategory() instanceof ActionCategory) { $child = new Event(); $child->setAuthor($e->getAuthor()); $child->setParent($e); $child->setOrganisation($e->getOrganisation()); $child->createFromPredefinedEvent($action); $child->setStatus($objectManager->getRepository('Application\\Entity\\Status')->findOneBy(array('defaut' => true, 'open' => true))); // customfields foreach ($action->getCustomFieldsValues() as $customvalue) { $newcustomvalue = new CustomFieldValue(); $newcustomvalue->setEvent($child); $newcustomvalue->setCustomField($customvalue->getCustomField()); $newcustomvalue->setValue($customvalue->getValue()); $objectManager->persist($newcustomvalue); } $e->addChild($child); $objectManager->persist($child); } } } //en cas de mod de récurrence, les actions et fichiers ne sont as inclus dans le formulaire //on les reprend de l'évènement modifié if ($modrecurrence) { //actions et alarmes foreach ($event->getChildren() as $child) { $newchild = new Event(); $newchild->createFromEvent($child); $newchild->setParent($e); $newchild->setStatus($objectManager->getRepository('Application\\Entity\\Status')->findOneBy(array('defaut' => true, 'open' => true))); foreach ($child->getCustomFieldsValues() as $value) { $newcustomvalue = new CustomFieldValue(); $newcustomvalue->setEvent($newchild); $newcustomvalue->setCustomField($value->getCustomField()); $newcustomvalue->setValue($value->getValue()); $objectManager->persist($newcustomvalue); } if ($child->getCategory() instanceof AlarmCategory) { $start = clone $e->getStartdate(); $diff = $event->getStartdate()->diff($child->getStartdate()); $start->add($diff); $newchild->setStartdate($start); } $e->addChild($newchild); $objectManager->persist($newchild); } //fichiers foreach ($event->getFiles() as $f) { $f->addEvent($e); $objectManager->persist($f); } } // associated actions to be copied if (isset($post['fromeventid'])) { $parentID = $post['fromeventid']; foreach ($objectManager->getRepository('Application\\Entity\\Event')->findBy(array('parent' => $parentID), array('place' => 'DESC')) as $action) { if ($action->getCategory() instanceof \Application\Entity\ActionCategory) { $child = new Event(); $child->setAuthor($e->getAuthor()); $child->setParent($e); $child->setOrganisation($event->getOrganisation()); $child->setCategory($action->getCategory()); $child->setImpact($action->getImpact()); $child->setPunctual($action->isPunctual()); $child->setStatus($objectManager->getRepository('Application\\Entity\\Status')->findOneBy(array('defaut' => true, 'open' => true))); foreach ($action->getCustomFieldsValues() as $customvalue) { $newcustomvalue = new CustomFieldValue(); $newcustomvalue->setEvent($child); $newcustomvalue->setCustomField($customvalue->getCustomField()); $newcustomvalue->setValue($customvalue->getValue()); $child->addCustomFieldValue($newcustomvalue); //$objectManager->persist($newcustomvalue); } $e->addChild($child); //$objectManager->persist($child); } } } // fichiers if (isset($post['fichiers']) && is_array($post['fichiers'])) { foreach ($post['fichiers'] as $key => $f) { $file = $objectManager->getRepository('Application\\Entity\\File')->find($key); if ($file) { $file->addEvent($e); // $e->addFile($file); //$objectManager->persist($file); } } } // alertes if (isset($post['alarm']) && is_array($post['alarm'])) { foreach ($post['alarm'] as $key => $alarmpost) { // les modifications d'alarmes existantes sont faites en direct // et ne passent pas par le formulaire // voir AlarmController.php $alarm = new Event(); $alarm->setCategory($objectManager->getRepository('Application\\Entity\\AlarmCategory')->findAll()[0]); $alarm->setAuthor($this->zfcUserAuthentication()->getIdentity()); $alarm->setOrganisation($e->getOrganisation()); $alarm->setParent($e); $alarm->setStatus($objectManager->getRepository('Application\\Entity\\Status')->findOneBy(array('open' => true, 'defaut' => true))); $startdate = new \DateTime($alarmpost['date']); $offset = $startdate->getTimezone()->getOffset($startdate); $startdate->setTimezone(new \DateTimeZone("UTC")); $startdate->add(new \DateInterval("PT" . $offset . "S")); $alarm->setStartdate($startdate); $alarm->setPunctual(true); $alarm->setImpact($objectManager->getRepository('Application\\Entity\\Impact')->find(5)); $name = new CustomFieldValue(); $name->setCustomField($alarm->getCategory()->getNamefield()); $name->setValue($alarmpost['name']); $name->setEvent($alarm); $alarm->addCustomFieldValue($name); $comment = new CustomFieldValue(); $comment->setCustomField($alarm->getCategory()->getTextfield()); $comment->setValue($alarmpost['comment']); $comment->setEvent($alarm); $alarm->addCustomFieldValue($comment); $deltabegin = new CustomFieldValue(); $deltabegin->setCustomField($alarm->getCategory()->getDeltaBeginField()); $deltabegin->setValue($alarmpost['deltabegin']); $deltabegin->setEvent($alarm); $alarm->addCustomFieldValue($deltabegin); $deltaend = new CustomFieldValue(); $deltaend->setCustomField($alarm->getCategory()->getDeltaEndField()); $deltaend->setValue($alarmpost['deltaend']); $deltaend->setEvent($alarm); $alarm->addCustomFieldValue($deltaend); $e->addChild($alarm); //$objectManager->persist($name); //$objectManager->persist($comment); //$objectManager->persist($deltabegin); //$objectManager->persist($deltaend); $objectManager->persist($alarm); } } //certains évènements induisent des évènements fils //il faut les créer à ce moment if (!$id) { //uniquement lors d'une création d'évènement if ($e->getCategory() instanceof AntennaCategory) { $frequencies = $e->getCustomFieldValue($e->getCategory()->getFrequenciesField()); $antennaState = $e->getCustomFieldValue($e->getCategory()->getStatefield())->getValue(); $antennaId = $e->getCustomFieldValue($e->getCategory()->getAntennafield())->getValue(); $antenna = $objectManager->getRepository('Application\\Entity\\Antenna')->find($antennaId); $freqs = array(); if ($frequencies) { $freqids = explode("\r", $frequencies->getValue()); foreach ($freqids as $freqid) { $freq = $objectManager->getRepository('Application\\Entity\\Frequency')->find($freqid); if ($freq) { $freqs[] = $freq; } } } if (!$frequencies || count($freqs) == 0) { //pas d'info sur les fréquences impactées : toutes les fréquences de l'antenne sont en panne foreach ($antenna->getMainfrequencies() as $freq) { $freqs[] = $freq; } foreach ($antenna->getMainfrequenciesclimax() as $freq) { $freqs[] = $freq; } } if ($antenna && $antennaState == 1) { //antenne indisponible : il faut créer les changements de couverture //pour les fréquences impactées foreach ($freqs as $freq) { if ($freq->hasMainAntenna($antenna) || $freq->hasMainClimaxAntenna($antenna)) { $objectManager->getRepository('Application\\Entity\\Event')->addChangeFrequencyCovEvent($freq, 1, 0, "Antenne principale indisponible", $e->getStartdate(), $e->getEnddate(), $this->zfcUserAuthentication()->getIdentity(), $e, $messages); } } } } } //mises en cohérence des alarmes $e->updateAlarms(); $objectManager->persist($e); } try { if ($recurrence !== null) { $objectManager->persist($recurrence); $messages['success'][] = "Récurrence correctement enregistrée."; } $objectManager->flush(); $messages['success'][] = $id ? "Evènement modifié" : "Évènement enregistré"; } catch (\Exception $e) { $messages['error'][] = "Impossible d'enregistrer l'évènement."; $messages['error'][] = $e->getMessage(); $events = array(); } } else { $messages['error'][] = "Création ou modification impossible, droits insuffisants."; } } else { $messages['error'][] = "Requête illégale."; } } else { $messages['error'][] = "Utilisateur non authentifié, action impossible."; } if ($return) { foreach ($messages['success'] as $message) { $this->flashMessenger()->addSuccessMessage($message); } foreach ($messages['error'] as $message) { $this->flashMessenger()->addErrorMessage($message); } return $this->redirect()->toRoute('application'); } else { $json = array(); $json['messages'] = $messages; $jsonevents = array(); foreach ($events as $e) { $jsonevents[$e->getId()] = $this->getEventJson($e); } foreach ($sendEvents as $e) { $jsonevents[$e->getId()] = $this->getEventJson($e); } if (count($jsonevents) > 0) { $json['events'] = $jsonevents; } return new JsonModel($json); } }