Symfony form save duplicated old data - php

The users can create projects with a form on a pop-up using ajax. They use Chrome to get to the tool.
The problem is that some times when they create a new project, the form saves the information of a former project, so they loose the new project's data.
Does someone already have this issue and know how to fix it ? Is it a problem with the browser's cache ?
Thank you for your help !
EDIT this is my code
Twig view
<!-- Formulaire de création d'un nouveau projet -->
{{ form_start(form, { 'attr': {'class': 'form-horizontal'} }) }}
{{ form_start(formGroupe, { 'attr': {'class': 'form-horizontal'} }) }}
<div class="row">
<div class="col-sm-offset-1 sous-titre-cartouche cartouche-1">
<p>Le groupe de projets</p>
<hr>
</div>
</div>
<br>
<!-- Choix du groupe -->
<div class="row">
<div class="col-sm-offset-1">
<label for="choixGroupe"><img src="{{ asset('picto/commercial/1-1.png') }}" class="picto-number"> Ce projet fait-il partie d'un groupe de projets ? <span class="required">*</span></label>
<input type="radio" name="choixGroupe" id="radioOui" value="1" {% if projet is defined and projet.groupe != null %}checked{% endif %}>
<label for="radioOui" class="required">Oui</label>
<input type="radio" name="choixGroupe" id="radioNon" value="0" {% if projet is not defined or (projet is defined and projet.groupe == null) %}checked{% endif %}>
<label for="radioNon" class="required">Non</label>
</div>
</div>
<br>
<!-- Choix du groupe2 -->
<div class="row group-choixGroupe2">
<div class="col-sm-offset-1">
<label for="choixGroupe2"><img src="{{ asset('picto/commercial/1-2.png') }}" class="picto-number"> Voulez-vous choisir un groupe de projets déjà existant ? <span class="required">*</span></label>
<input type="radio" name="choixGroupe2" id="radioOui2" value="1" {% if choixGroupe is defined and choixGroupe == '1' %}checked{% endif %}>
<label for="radioOui2" class="required">Oui</label>
<input type="radio" name="choixGroupe2" id="radioNon2" value="0" {% if choixGroupe is defined and choixGroupe == '0' %}checked{% endif %}>
<label for="radioNon2" class="required">Non</label>
</div>
</div>
<br class="group-existant">
<!-- Groupe existant -->
<div class="row group-existant">
<div class="col-sm-offset-1">
<label for="groupeExistant"><img src="{{ asset('picto/commercial/1-3.png') }}" class="picto-number"> Sélectionner le groupe de projets existant : <span class="required">*</span></label>
{{ form_widget(formGroupe.groupeExistant) }}
</div>
</div>
<br class="group-nouveau">
<!-- Nouveau groupe -->
<div class="row group-nouveau">
<div class="col-sm-offset-1">
<label for="groupeNom"><img src="{{ asset('picto/commercial/1-3.png') }}" class="picto-number"> Créer un nouveau groupe de projets : <span class="required">*</span></label>
{{ form_widget(formGroupe.objet, { 'attr': {'placeholder': 'Champ à définir'} }) }}
</div>
</div>
<br>
<!-- Groupe description -->
<div class="row group-description">
<div class="col-sm-offset-1">
<label for="groupeDescription"><img src="{{ asset('picto/commercial/1-4.png') }}" class="picto-number"> Description du groupe de projets : <span class="required">*</span></label>
<br>
<br>
<textarea name="groupeDescription" class="description">{% if projet is defined and projet.groupe != null %}{{ projet.groupe.description }}{% endif %}</textarea>
</div>
</div>
<br>
<div class="row">
<div class="col-sm-offset-1 sous-titre-cartouche cartouche-2">
<p>Le client</p>
<hr>
</div>
</div>
<br>
<div class="row">
<div class="col-sm-offset-1">
<label for="groupe_client"><img src="{{ asset('picto/commercial/2-1.png') }}" class="picto-number"> Sélectionner les champs suivants : <span class="required">*</span></label>
</div>
</div>
<br>
<div class="row">
<!-- Groupe -->
<div class="col-sm-offset-1 projet-client">
{{ form_widget(form.client, { 'attr': {'class': 'col-sm-2'} }) }}
<input type="hidden" name="creationProjet[client]" id="hiddenClient" disabled>
</div>
<!-- Filiale -->
<div class="projet-filiale">
{{ form_widget(form.filiale, { 'attr': {'class': 'col-sm-offset-1 col-sm-2'} }) }}
<input type="hidden" name="creationProjet[filiale]" id="hiddenFiliale" disabled>
</div>
<!-- Contact -->
<div class="projet-contact">
{{ form_widget(form.contact, { 'attr': {'class': 'col-sm-offset-1 col-sm-2'} }) }}
<input type="hidden" name="creationProjet[contact]" id="hiddenContact" disabled>
</div>
</div>
<br>
<div class="row">
<div class="col-sm-offset-1 sous-titre-cartouche cartouche-3">
<p>Le projet</p>
<hr>
</div>
</div>
<br>
<div class="row">
<!-- Expertise -->
<div class="col-sm-offset-1 col-sm-5 col-expertise">
<label for="expertise"><img src="{{ asset('picto/commercial/3-1.png') }}" class="picto-number"> Sélectionner le type d'expertise : <span class="required">*</span></label>
<br>
<br>
{{ form_widget(form.expertise, { 'attr': {'class': 'col-sm-5'} }) }}
</div>
<!-- Objet -->
<div class="col-sm-5">
<label for="objet"><img src="{{ asset('picto/commercial/3-4.png') }}" class="picto-number"> Remplir l'intitulé et la description du projet : <span class="required">*</span></label>
<br>
<br>
{{ form_widget(form.objet, { 'attr': {'placeholder': 'Champ à remplir' , 'class': 'col-sm-11'} }) }}
</div>
</div>
<br>
<div class="row">
<div class="col-sm-offset-1 col-sm-5">
<!-- Impression -->
<div class="row group-impression">
<label for="impression"><img src="{{ asset('picto/commercial/3-2.png') }}" class="picto-number"> Ce projet est-il imprimé ? <span class="required">*</span> </label>
{{ form_widget(form.impression) }}
</div>
<br>
<div class="row datesProjet">
<label for="dates"><img src="{{ asset('picto/commercial/3-3.png') }}" class="picto-number"> Choisir les dates de début et de fin : <span class="required">*</span> </label>
<br>
<br>
<!-- Date de début -->
<div class="col-sm-6 group-dateDebut">
<label for="dateDebut">Date de début : </label>
{{ form_widget(form.dateDebut) }}
</div>
<!-- Date de fin -->
<div class="col-sm-6 group-dateFin">
<label for="dateFin">Date de fin : <span class="required">*</span></label>
{{ form_widget(form.dateFin) }}
</div>
</div>
<br>
<div class="row datesImpression">
<!-- Date de mise en impression -->
<div class="col-sm-6">
<label for="dateImpression">Date de mise en impression : </label>
{{ form_widget(form.dateImpression) }}
</div>
</div>
</div>
<!-- Description -->
<div class="col-sm-5">
<textarea name="projetDescription" class="description">{% if projet is defined %}{{ projet.description }}{% endif %}</textarea>
</div>
</div>
<br>
<!-- Message d'erreur -->
<div class="row">
<div class="col-sm-offset-1 col-sm-10">
<span class="error date-erreur"></span>
</div>
</div>
<br>
<div class="row">
<div class="col-sm-offset-1 col-sm-10 hr-footer">
<hr>
</div>
</div>
<br>
<!-- Bouton Enregistrer ou Modifier -->
<div class="row">
<div class="col-sm-offset-8 col-sm-1">
<span class="glyphicon glyphicon-repeat spinner noactive"></span>
</div>
<div class="col-sm-2">
{{ form_widget(form._token) }}
{{ form_widget(formGroupe._token) }}
{% if projet is defined %}
<input type="submit" class="modifier-submit">
{% else %}
<input type="submit" class="creer-submit cursor">
{% endif %}
</div>
</div>
{{ form_end(formGroupe) }}
{{ form_end(form) }}
Controller
/**
* Action pour le formulaire de création d'un projet
*/
public function indexAction()
{
$request = $this->getRequest();
$em = $this->getDoctrine()->getManager();
/* On crée un nouveau projet */
$projet = new Projet();
/* On crée un nouveau groupe */
$groupe = new Groupe();
/* On récupère le formulaire */
$form = $this->createForm(new CreationProjetType($this->getDoctrine()->getManager()), $projet);
$formGroupe = $this->createForm(new CreationGroupeType());
/* On redirige vers le formulaire de création du projet */
return $this->render('CommercialBundle:CreationProjet:index.html.twig',
array('utilisateur' => $this->getUser() ,
'form' => $form->createView() ,
'formGroupe' => $formGroupe->createView() ));
}
/**
* Action pour la création d'un projet + Modification d'un projet
*/
public function creerAjaxAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$manager = new Manager($em);
/* On crée un nouveau projet */
$projet = new Projet();
/* On crée un nouveau groupe */
$groupe = new Groupe();
/* On récupère le groupe du projet */
$choixGroupe = $request->request->get('choixGroupe');
$choixGroupe2 = $request->request->get('choixGroupe2');
$groupeDescription = $request->request->get('groupeDescription');
/* On récupère les formulaires */
$form = $this->createForm(new CreationProjetType($this->getDoctrine()->getManager()), $projet);
$formGroupe = $this->createForm(new CreationGroupeType());
if($request->isXmlHttpRequest()) {
$form->bind($request);
$formGroupe->bind($request);
if($form->isValid()) {
/* On récupère les données du formulaire */
$dataProjet = $this->getRequest()->request->get('creationProjet');
$dataGroupe = $this->getRequest()->request->get('creationGroupe');
/* On enregistre l'objet */
$projet->setObjet($manager->pregSlash($dataProjet['objet']));
/* On enregistre l'expertise */
$expertise = new Expertise();
$expertise = $em->getRepository('CommercialBundle:Expertise')->find($dataProjet['expertise']);
$projet->setExpertise($expertise);
/* On enregistre la description */
$projet->setDescription($request->request->get('projetDescription'));
/* On enregistre la date de création */
$projet->setDateCreation(new \DateTime(date('Y-m-d')));
/* On enregistre l'état du projet */
$etat = new Etat();
$etat = $em->getRepository('CommercialBundle:Etat')->find(10);
$projet->setEtat($etat);
/* On enregistre le chef de projet */
$user = new Utilisateur();
$user = $em->getRepository('UtilisateurBundle:Utilisateur')->find($this->getUser());
$projet->setCreateur($user);
/* Si le nouveau projet ne fait pas parti d'un groupe */
if($choixGroupe == '0') {
/* On enregistre le contact */
$contact = new Contact();
$contact = $em->getRepository('ClientBundle:Contact')->find($dataProjet['contact']);
$projet->setContact($contact);
/* On enregistre la filiale */
$filiale = new Filiale();
$filiale = $em->getRepository('ClientBundle:Filiale')->find($dataProjet['filiale']);
$projet->setFiliale($filiale);
/* On récupère le dernier projet créé */
$projetLast = $em->getRepository('CommercialBundle:Projet')->findOneBy(array(), array('numeroDossier' => 'DESC'));
/* S'il a au moins un projet créé */
if($projetLast != null) {
/* On incrémente le numéro de dossier de dernier projet créé */
$numeroDossier = $projetLast->getNumeroDossier() + 1;
if($numeroDossier < 10)
$numeroDossier = '00'.$numeroDossier;
else
$numeroDossier = '0'.$numeroDossier;
/* On enregistre le numéro de dossier */
$projet->setNumeroDossier($numeroDossier);
}
else {
/* On enregistre le numéro de dossier à 1 */
$projet->setNumeroDossier('001');
}
}
/* Si le nouveau projet fait parti d'un groupe de projets */
else {
/* Si le projet fait partie d'un nouveau groupe */
if($choixGroupe2 == '0') {
/* On enregistre le contact */
$contact = new Contact();
$contact = $em->getRepository('ClientBundle:Contact')->find($dataProjet['contact']);
$projet->setContact($contact);
/* On enregistre la filiale */
$filiale = new Filiale();
$filiale = $em->getRepository('ClientBundle:Filiale')->find($dataProjet['filiale']);
$projet->setFiliale($filiale);
/* On enregistre l'état */
$groupe->setEtat('1');
/* On enregistre l'objet */
$groupe->setObjet($manager->pregSlash($dataGroupe['objet']));
/* On enregistre la description */
$groupe->setDescription($groupeDescription);
/* On enregistre le contact */
$groupe->setContact($contact);
/* On enregistre la filiale */
$groupe->setFiliale($filiale);
/* On enregistre la date de création */
$groupe->setDateCreation(new \DateTime(date('Y-m-d')));
/* On récupère le dernier projet créé */
$projetLast = $em->getRepository('CommercialBundle:Projet')->findOneBy(array(), array('numeroDossier' => 'DESC'));
/* S'il a au moins un projet créé */
if($projetLast != null) {
/* On incrémente le numéro de dossier de dernier projet créé */
$numeroDossier = $projetLast->getNumeroDossier() + 1;
if($numeroDossier < 10)
$numeroDossier = '00'.$numeroDossier;
else
$numeroDossier = '0'.$numeroDossier;
}
else {
$numeroDossier = '001';
}
/* On enregistre le numéro de dossier du groupe */
$groupe->setNumeroDossier($numeroDossier);
/* On enregistre le numéro de dossier du projet */
$projet->setNumeroDossier($numeroDossier);
$projet->setNumeroProjet('001');
/* On enregistre le groupe */
$projet->setGroupe($groupe);
$em->persist($groupe);
}
/* Si le projet fait partie d'un groupe de projets déjà existant */
else {
/* On récupère le groupe */
$groupe = $em->getRepository('CommercialBundle:Groupe')->find($dataGroupe['groupeExistant']);
/* On enregistre le contact */
$contact = new Contact();
$contact = $em->getRepository('ClientBundle:Contact')->find($groupe->getContact()->getId());
$projet->setContact($contact);
/* On enregistre la filiale */
$filiale = new Filiale();
$filiale = $em->getRepository('ClientBundle:Filiale')->find($groupe->getFiliale()->getId());
$projet->setFiliale($filiale);
/* On enregistre le numéro de dossier du projet */
$projet->setNumeroDossier($groupe->getNumeroDossier());
/* On récupère les projets du groupe */
$projetDuGroupe = $em->getRepository('CommercialBundle:Projet')->findBy(array('groupe' => $groupe));
$m = '001';
if(sizeof($projetDuGroupe) != 0) {
$m = sizeof($projetDuGroupe) + 1;
if($m < 10)
$m = '00'.$m;
else
$m = '0'.$m;
}
/* On enregistre le numéro de projet du projet */
$projet->setNumeroProjet($m);
/* On enregistre le groupe */
$projet->setGroupe($groupe);
}
}
/* On enregistre l'impression */
if($dataProjet['impression'] != null) {
$projet->setImpression($dataProjet['impression']);
}
$em->persist($projet);
$em->flush();
return $response;
}
Ajax
/**
* Affichage du pop-up
*/
function nouveauProjet() {
var route = '{{ path("nouveau_projet") }}';
return $.ajax({
type: 'GET',
url: route,
success: function(data) {
$('.modal.modal-creation-projet-active')
.modal('show');
$('.modal-creation-projet-active .modal-body')
.empty()
.append(data);
/* Fonction editeurTexte() */
editeurTexte();
/* Fonction clientFiliale() */
$('#creationProjet_client').change(function(){
/* Id du groupe sélectionné */
var client = $(this).val();
clientFiliale(client,'#creationProjet_filiale');
});
/* Fonction clientContact() */
$('#creationProjet_filiale').change(function(){
/* Id de la filiale sélectionnée */
var filiale = $(this).val();
clientContact(filiale,'#creationProjet_contact');
});
/* Gestion des éléments du groupe de projet */
formElement();
/* On bloque l'envoi du formulaire par la touche Entrée */
$('.noEnterSubmit').keypress(function(e){
if ( e.which == 13 ) return false;
});
/* A l'envoi du formulaire */
$('form[name=creationProjet]').submit(function (e) {
e.preventDefault();
/* Fonction formErrorDate() */
if(!formErrorDate()) {
/* Fonction creationProjetSubmit() */
creationProjetSubmit();
}
});
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(textStatus, errorThrown);
}
});
}
/**
* Action à l'envoi du formulaire (création)
*/
function creationProjetSubmit() {
/* On initialise la route */
var url = '{{ path("nouveau_projet_ajax") }}';
return $.ajax({
type: "POST",
data: $('form[name=creationProjet]').serialize(),
url: url,
cache: false,
success: function(data){
$('.modal.modal-creation-projet-active')
.modal('show');
$('.modal-creation-projet-active .modal-body')
.empty()
.append(data);
$('.close-modal').css('display','none');
$('.btn-modifier-projet').click(function (e) {
e.preventDefault();
/* On récupère l'id du projet dans le bouton modifier */
var id = $(this).attr('id');
/* On récupère le choix du projet : nouveau (=0) ou existant (=1) */
var choixGroupe = $(this).attr('choixGroupe');
/* On active le loader */
$('.glyphicon.spinner').removeClass('noactive').addClass('active');
/* Fonction modifierProjet(id) */
modifierProjet(id,choixGroupe);
});
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(textStatus, errorThrown);
}
});
}

Your question is very poor quality.
Does someone already have this issue and know how to fix it ?
It sounds like very bad code. check than the ajax new popup is really offering a new form (hidden inputs etc...). Check how the id of the project persisted is get, it shouldn't be contained in the form data.
Is it a problem with the browser's cache ?
No (Post Request are not cached)

in my controller, I call my form this way :
$projet = new Projet();
$form = $this->createForm(new CreationProjetType($this->getDoctrine()->getManager()), $projet);
Do you think it can get a former $project ?

Related

Symfony Check if user exist in database

I am looking for a solution in my controller to check before sending a form if the user already exists in the database. Here is my action on which I would like to implement this.
/**
* Creates a new invite entity.
*
* #Route("/inscription", name="invite_new")
* #Method({"GET", "POST"})
*/
public function newAction(Request $request)
{
$invite = new Invite();
$form = $this->createForm(InviteType::class, $invite);
if ($request->isMethod('POST')) {
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($invite);
$em->flush();
$this->get('app_mailer')->sendMailInscriptionMjml($invite, $this->getParameter('client_mail_to'));
$this->get('session')->getFlashBag()->add('success', 'Votre inscription à été pris en compte.');
} else {
$this->get('session')->getFlashBag()->add('error', 'Une erreur est survenue.');
}
return $this->redirect($this->generateUrl('invite_show', array('id' => $invite->getId())));
}
return $this->render('#App/invite/new.html.twig', array(
'invite' => $invite,
'form' => $form->createView(),
));
}
Thank you for your help
You shouldn't need to do this in the controller. This is basic entity validation and Symfony comes with built in constraints to handle this sort of thing.
Assuming you are using a User Entity similar to below in your Symfony application you need only apply a unique validation constraint to the user class and specify which properties you want to test against for uniqueness. This example will validate that the user is unique by email, and throw an exception if not.
// src/AppBundle/Entity/User.php
namespace AppBundle\Entity;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/** #UniqueEntity(
* fields={"email"},
* errorPath="email",
* message="It appears you have already registered with this email."
*)
*/
class User
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string $email
*
* #ORM\Column(name="email", type="string", length=255, unique=true)
* #Assert\Email()
*/
protected $email;
// ...
}
Pay notice to the #UniqueEntity("email") annotation on the class and the use statements. Of course you'll need to adopt this logic to your user class.
// controller action
public function newAction(Request $request)
{
$invite = new Invite();
$form = $this->createForm(InviteType::class, $invite);
if ($request->isMethod('POST')) {
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($invite);
$em->flush();
$this->get('app_mailer')->sendMailInscriptionMjml(
$invite, $this->getParameter('client_mail_to')
);
$this->get('session')->getFlashBag()
->add('success', 'Votre inscription à été pris en compte.');
return $this->redirect(
$this->generateUrl(
'invite_show', array(
'id' => $invite->getId()
)
)
);
}
}
return $this->render('#App/invite/new.html.twig', array(
'invite' => $invite,
'form' => $form->createView(),
));
}
For more on this:
https://symfony.com/doc/current/reference/constraints/UniqueEntity.html
// Pass in the entity manager to your form via options
// Do this before you call $this->createForm:
// $options['entityManager'] = $this->getDoctrine()->getManager();
// then call $form = $this->createForm(InviteType::class, $invite, $options);
// Inside your form type i.e. InviteType
$em = $options['entityManager'];
$builder->addEventListener(
FormEvents::PRE_SUBMIT,
function (FormEvent $event) {
$data = $event->getData();
$form = $event->getForm();
$user = $data['user']; // this needs to be whatever you called user in your form
$userRepo = $em->getRepository('User'); // this needs to be the location of your user repository
if ($userRepo->findOneBy(['user' => $user])) { // you need to pick a field that determines how you will search for the user via the repository
$form->addError(new FormError('User already exists'));
}
}
);
<div class="container accroche">
<h5>{{ 'Inscription aux évenements'|trans }}</h5>
<p>Le Lorem Ipsum est simplement du faux texte employé dans la composition et la mise en page avant impression. Le Lorem Ipsum est le faux texte standard de l'imprimerie depuis les années 1500,
quand un peintre anonyme assembla ensemble des morceaux de texte pour réaliser un livre spécimen de polices de texte. Il n'a pas fait que survivre cinq siècles, mais s'est aussi adapté à la bureautique informatique,
sans que son contenu n'en soit modifié. Il a été popularisé dans les années 1960 grâce à la vente de feuilles Letraset contenant des passages du Lorem Ipsum, et, plus récemment,
par son inclusion dans des applications de mise en page de texte, comme Aldus PageMaker.
</p>
</div>
{{ form_start(form, {attr: {novalidate: 'novalidate','id':'formValidate'}}) }}
<div class="middle">
<div class="middle_form">
<div class="container">
<div class="stepwizard">
<div class="stepwizard-row setup-panel col-md-12 text-center">
<div class="stepwizard-step col-md-3">
1
</div>
<div class="stepwizard-step col-md-3">
2
</div>
<div class="stepwizard-step col-md-3">
3
</div>
<div class="stepwizard-step col-md-3">
4
</div>
</div>
</div>
<div class="row setup-content" id="step-1">
<div class="col-md-12">
<h3>{{ 'Informations invités'|trans }}</h3>
<div class="row">
<div class="input-field col-12">
{{ form_widget(form.name, {'attr': {'class': 'validate', 'id': 'last_name'}}) }}
{{ form_errors(form.name) }}
<label for="last_name">{{ 'Nom'|trans }} <sup>*</sup></label>
</div>
</div>
<div class="row">
<div class="input-field col-12">
{{ form_widget(form.surname, {'attr': {'class': 'validate', 'id': 'surname'}}) }}
{{ form_errors(form.surname) }}
<label for="surname">{{ 'Prénom'|trans }} <sup>*</sup></label>
</div>
</div>
<div class="row">
<div class="input-field col-12">
{{ form_widget(form.email, {'attr': {'class': 'validate', 'id': 'email'}}) }}
{{ form_errors(form.email) }}
<label for="email">{{ 'E-mail'|trans }} <sup>*</sup></label>
</div>
</div>
<div class="row">
<div class="col-12">
<label>{{ 'Présence'|trans }} <sup>*</sup></label>
{{ form_widget(form.dispo, {'attr': {'class': 'validate', 'id': 'dispo'}}) }}
{{ form_errors(form.dispo) }}
</div>
</div>
<button class="btn btn-primary nextBtn btn-lg pull-right" type="button">{{ 'SUIVANT'|trans }}</button>
</div>
</div>
<div class="row setup-content" id="step-2">
<div class="col-md-12">
<h3>{{ 'Informations participants'|trans }}</h3>
<div class="row">
<ul class="customers"
data-prototype="{{ form_widget(form.customers.vars.prototype)|e('html_attr') }}">
{% for customers in form.customers %}
<div class="row">
<div class="input-field col-12">
{{ form_row(customers.name, {'attr': {'class': 'validate', 'id': 'name'}}) }}
{{ form_errors(customers.name) }}
</div>
</div>
<div class="row">
<div class="input-field col-12">
{{ form_row(customers.surname, {'attr': {'class': 'validate', 'id': 'surname'}}) }}
{{ form_errors(customers.surname) }}
</div>
</div>
<div class="row">
<div class="input-field col-12">
{{ form_row(customers.old) }}
{{ form_errors(customers.old) }}
</div>
</div>
{% endfor %}
</ul>
</div>
<button class="btn btn-primary prevBtn btn-lg pull-left" type="button">{{ 'PRECEDENT'|trans }}</button>
<button class="btn btn-primary nextBtn btn-lg pull-right" type="button">{{ 'SUIVANT'|trans }}</button>
</div>
</div>
<div class="row setup-content" id="step-3">
<div class="col-md-12">
<h3>Logements</h3>
<div class="row">
<div class="input-field col-12">
{{ form_widget(form.housing, {'attr': {'class':'validate'}}) }}
{{ form_errors(form.housing) }}
<label>{{ 'Comment allez vous vous logez ?'|trans }} <sup>*</sup></label>
</div>
</div>
<div class="row">
<div class="input-field col-12">
{{ form_widget(form.hotel, {'attr': {'class':'validate'}}) }}
{{ form_errors(form.hotel) }}
<label>{{ 'Hôtel'|trans }} <sup>*</sup></label>
</div>
</div>
<button class="btn btn-primary prevBtn btn-lg pull-left" type="button">{{ 'PRECEDENT'|trans }}</button>
<button class="btn btn-primary nextBtn btn-lg pull-right" type="button">{{ 'SUIVANT'|trans }}</button>
</div>
</div>
<div class="row setup-content" id="step-4">
<div class="col-md-12">
<h3>{{ 'Arrivée/Départ'|trans }}</h3>
<div class="row">
<div class="col-12">
<label>{{ 'Date d\'arrivée'|trans }} <sup>*</sup></label>
{#<input class="datepicker" type="text" id="dateArrival" name="form[dateArrival]"/>#}
{{ form_widget(form.dateArrival, {'attr': {'class': 'datepicker validate'}}) }}
{{ form_errors(form.dateArrival) }}
</div>
</div>
<div class="row">
<div class="col-12">
<label>{{ 'Date de départ'|trans }} <sup>*</sup></label>
{#<input class="datepicker" type="text" id="dateDeparture" name="form[dateDeparture]"/>#}
{{ form_widget(form.dateDeparture, {'attr': {'class': 'datepicker validate'}}) }}
{{ form_errors(form.dateDeparture) }}
</div>
</div>
<div class="row">
<div class="input-field col-12">
{{ form_widget(form.transport, {'attr': {'class':'validate'}}) }}
{{ form_errors(form.transport) }}
<label>{{ 'Transport utilisé'|trans }} <sup>*</sup></label>
</div>
</div>
<div class="btn-center">
<button class="btn btn-primary prevBtn btn-lg pull-left" type="button">{{ 'PRECEDENT'|trans }}</button>
{{ form_widget(form.save, {'attr': {'class':'btn btn-success', 'id':'SaveAccount'}}) }}
</div>
</div>
</div>
</div>
</div>
</div>
{{ form_widget(form.dateArrival, {'attr': {'class': 'hidden'}}) }}
{{ form_widget(form.dateDeparture, {'attr': {'class': 'hidden'}}) }}
{{ form_end(form) }}
First, get the id $id = #YourId;. You can then select the user using SQL. SELECT * FROM [user_table] WHERE id = $id; If the result holds a user, then the user exists.

Copy DIV content to another page - PHP

I want to copy the content of a div (.boxes) to another page (drills.php) when I click on one of them.
Here is my HTML
<div class="boxes le8">
<div class="img" style="background-image:url(http://charlesfstcyr.890m.com/coaching/img/drills/le8.png)"></div>
<h1>Le 8</h1>
<p class="date">Octobre 2016 - Dany Dubé</p>
<div style="display:none">
<p class="description">Patinage en 8 autour des cônes.</p>
<p class="enseignement">Virage brusques, Contrôle de rondelle, Croisement en sortie de virage.</p>
<p class="variantes">Départ au sifflet pour 10 virages le plus rapidement possible, Rapprocher les cônes jusqu’à une distance de 1 bâton entre les cônes,Passes à l’entraineur en sortie de virage.</p>
<video src="img/drillsVid/Le8.mp4" autoplay controls muted loop></video>
</div>
</div>
<div class="boxes chandelle">
<div class="img" style="background-image:url(http://charlesfstcyr.890m.com/coaching/img/drills/chandelle.png)"></div>
<h1>La Chandelle</h1>
<p class="date">Octobre 2016 - Dany Dubé</p>
<div style="display:none">
<p class="description">Départ au centre du cercle de mise-en-jeu avec une rondelle. Contourner le premier cône et remonter vers le cône en haut de zone pour effectuer un virage brusque. Revenir contourner le troisième cône et par la suite revenir au point d’origine par l’extérieur des cônes en laissant la rondelle à son point d’origine avant de récupérer une rondelle de l’autre côté. Effectuer le trajet inverse avec la deuxième rondelle.</p>
<p class="enseignement">Croisement lors des virages, </p>
<p class="enseignement">Changement de direction rapide, </p>
<p class="enseignement">Protection de rondelle.</p>
<p class="variantes">Passe à l’entraineur situé sur la ligne bleu, </p>
<p class="variantes">Lancer au but(2 lancers), </p>
<p class="variantes">Tour complet de chacun des cônes dans la première portion du parcours.</p>
<video src="img/drillsVid/chandelle.mp4" autoplay controls muted loop></video>
</div>
</div>
<div class="boxes pcoin">
<div class="img" style="background-image:url(http://charlesfstcyr.890m.com/coaching/img/drills/pcoin.png)"></div>
<h1>Le Petit Coin</h1>
<p class="date">Octobre 2016 - Dany Dubé</p>
<div style="display:none">
<p class="description">Départ sur le point de mise-en-jeu en poussant la rondelle dans le coin. Le joueur récupère la rondelle et se dirige le long de la bande pour passer entre le cône et le but. Patiner entre le cône pour aller contourner le second cône. Se diriger au filet pour prendre un lancer.</p>
<p class="enseignement">Récupération de rondelle, </p>
<p class="enseignement">Récupération de rondelle, </p>
<p class="enseignement">Récupération de rondelle</p>
<p class="variantes">Remonter vers le haut de la zone au départ pour effectuer le trajet en sens inverse, </p>
<p class="variantes">Passe à l’entraineur situé sur le haut du cercle de mise-en-jeu.</p>
<video src="img/drillsVid/pcoin.mp4" autoplay controls muted loop></video>
</div>
</div>
<div class="boxes gcoin">
<div class="img" style="background-image:url(http://charlesfstcyr.890m.com/coaching/img/drills/gcoin.png)"></div>
<h1>Le Grand Coin</h1>
<p class="date">Octobre 2016 - Dany Dubé</p>
<div style="display:none">
<p class="description">Départ sur le point de mise-en-jeu, le joueur lance la rondelle dans le coin. Le joueur la récupère, se dirige le long de la bande pour remonter entre le cône et le but. Il se dirige ensuite vers la gauche pour contourner les deux autres cônes de l’extérieur. Il redescend en fond de zone pour contourner le cône à partir de la droite et revenir devant le filet pour prendre un lancer.</p>
<p class="enseignement">Récupération de rondelle, </p>
<p class="enseignement">Virages brusques, </p>
<p class="enseignement">Lancer en espace restreint</p>
<p class="variantes">Passe à un joueur 2 devant le filet pour lancer sur réception, </p>
<p class="variantes">Tour complet de chacun des cônes</p>
<video src="img/drillsVid/gcoin.mp4" autoplay controls muted loop></video>
</div>
</div>
<div class="boxes fleur">
<div class="img" style="background-image:url(http://charlesfstcyr.890m.com/coaching/img/drills/fleur.png)"></div>
<h1>La Fleur</h1>
<p class="date">Octobre 2016 - Dany Dubé</p>
<div style="display:none">
<p class="description">Départ au centre. Contourner chacun des cônes en revenant toujours au point de mis-en-jeu. Après le 4ième cône, repasser au point de mise-en-jeu et se diriger au filet pour un lancer. Lors des diagonales, s’assurer de croiser le centre pour contourner les cônes autant du revers que du coup droit.</p>
<p class="enseignement">Virages brusques, </p>
<p class="enseignement">Protection de rondelle, </p>
<p class="enseignement">Croisement en sortie de virage.</p>
<p class="variantes">Course avec des joueurs dans chacun des cercles.</p>
<video src="img/drillsVid/fleur.mp4" autoplay controls muted loop></video>
</div>
</div>
<div class="boxes model final">
<div class="img" style="background-image:url(../img/drills/.png)"></div>
<h1>Nom</h1>
<p class="date">Date - Auteur</p>
<div style="display:none">
<p class="description">Description</p>
<p class="enseignement">Item1 /\n/ Item2 /\n/ Item3</p>
<p class="variantes">Item1 /\n/ Item2 /\n/ Item3</p>
<video src="img/drillsVid/.mp4" autoplay controls muted loop></video>
</div>
</div>
I have done something similar with Javascript to copy it in a DIV but I really want to copy it on another page.
For now, here's the result with the Javascript

Gregwar Bundle on MAMP vs online

I'm trying to figuring out what might be the reason why Gregwar Bundle is throwing an exception online while on my local development environment everything is fine.
Locally:
vs
online:
Please note that on my local machine I'm using MAMP (Apache 2.2.29 / PHP 7.0.0) and on the server side I have Linux (PHP 5.6.24). I'm surprised with this issue because I'm used to deploying Symfony2-based websites online on Linux environment with Gregwar bundle in them without having to deal with this kind of issue.
Any clues or suggestions please?
Check out the way Gregwar bundle's methods are being called in my template:
{% extends "APPlatformBundle::layout.html.twig" %}
{% block title %}Accueil - {{ parent() }}{% endblock %}
{% block platform_body %}
{% block header %}
{% include('APPlatformBundle:Common:header.html.twig') with { active :'home'} %}
{% endblock %}
{% block carousel %}
{#{% include('APPlatformBundle:Common:carousel.html.twig') %}#}
{% endblock %}
{% block content %}
<div class="container">
<div class="line section-title center" style="text-align: center;color:white;text-shadow: 2px 2px 2px #f58222, 0 0 25px green, 0 0 5px #f58222;">
<!--<hr class="styledLine">-->
<h2>CONSULTEZ NOS MODULES CI-DESSOUS OU TOUT LE CATALOGUE COMPLET</h2>
<hr class="styledLine">
<div class="row pull-right">
Le Catalogue complet : <img src="{{ image('bundles/applatform/images/PDFicon.png').cropResize(32,32) }}">
</div>
</div>
<div class="row">
<div class="col-sm-offset-3 col-sm-6 heading-colored"><p style="margin-bottom: 50px;"></p></div><br><br>
<div class="col-sm-3"></div>
</div>
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-4">
<div class="panel panel-default panel-home">
<div class="panel-heading thumbnail">
<div class="caption">
<h4 class="">En savoir plus</h4>
<p class="">
<a class="btn btn-success" href="https://gallery.mailchimp.com/d93866a99a15e6ad3c79732a1/files/Module_8_Communication_Te_le_communication_Marketing_et_De_veloppement_commercial.pdf" data-toggle="tooltip" data-placement="bottom" title="Vous pouvez consulter et/ou télécharger ce module"><i class="glyphicon glyphicon-save-file" style="color:#f58222;"></i> Consulter ce module</a><br/><br/>
<a class="btn btn-primary" href="https://gallery.mailchimp.com/d93866a99a15e6ad3c79732a1/files/Fiche_d_inscription_modifie_.pdf" data-toggle="tooltip" data-placement="bottom" title="Téléchargez, remplissez puis renvoyez-nous cette fiche par mail"><i class="glyphicon glyphicon-save-file" style="color:#f58222;"></i> Télécharger la fiche d'inscription</a>
</p>
</div>
<img src="{{ image('bundles/applatform/images/com-telecom-marketing.png').cropResize(275,183) }}" alt="" height="">
</div>
<div class="panel-body panel-body-home">
<h5 id="modules" class="heading-colored">Communication –Télécommunication – Marketing & Développement commercial</h5>
<div>
<!--
<p>
<p>La FONCTION COMMUNICATION d'entreprise repose sur trois enjeux :</p>
<ul>
<li>donner du sens à la stratégie de l'entreprise et permettre à chacun de se l'approprier et de la décliner au quotidien ;</li>
<li>concourir au développement de l'activité par la mise en œuvre d'outils et de techniques de communication ;</li>
<li>faciliter les relations de coopération et de confiance entre les acteurs internes et externes.</li>
</ul>
<p>Chyqat, à travers les Modules qui vous sont proposés ici, vous offre la possibilité de maitriser tous les contours de cette Fonction essentielle, de positionner votre entreprise et de posséder toutes armes de succès de votre profession de spécialiste de la Communication acteurs internes et externes.</p>
</p>
-->
</div>
</div>
<div class="panel-footer heading-colored"><a class="btn btn-default" data-toggle="tooltip" data-placement="top" title="Vous pouvez consulter et/ou télécharger ce module"><i class="glyphicon glyphicon-plus-sign" style="color: #f58222;"></i> En savoir plus</a> </div>
</div>
</div>
<div class="col-xs-12 col-sm-6 col-md-4">
<div class="panel panel-default panel-home">
<div class="panel-heading thumbnail">
<div class="caption">
<h4 class="">En savoir plus</h4>
<p class="">
<a class="btn btn-success" href="https://gallery.mailchimp.com/d93866a99a15e6ad3c79732a1/files/Module_10_Budget_Conto_le_budge_taire_et_Conto_le_de_gestion.pdf" data-toggle="tooltip" data-placement="bottom" title="Vous pouvez consulter et/ou télécharger ce module"><i class="glyphicon glyphicon-file" style="color:#f58222;"></i> Consulter ce module</a><br/><br/>
<a class="btn btn-primary" href="https://gallery.mailchimp.com/d93866a99a15e6ad3c79732a1/files/Fiche_d_inscription_modifie_.pdf" data-toggle="tooltip" data-placement="bottom" title="Téléchargez, remplissez puis renvoyez-nous cette fiche par mail"><i class="glyphicon glyphicon-file" style="color:#f58222;"></i> Télécharger la fiche d'inscription</a>
</p>
</div>
<img src="{{ image('bundles/applatform/images/budget2.jpg').forceResize(275,183) }}" alt="">
</div>
<div class="panel-body panel-body-home">
<h5 class="heading-colored">Budget - Contôle budgétaire & Contrôle de gestion </h5>
<!--<p>
En cette période de crise économique et financière, les entreprises surveillent plus que jamais les aspects financiers de leurs activités. En tant que garants de la rentabilité, les services comptables et financiers sont particulièrement exposés. La prise en compte, le plus tôt possible, des désirs des utilisateurs d’information financière dans l’élaboration des outils et des procédures est une étape indispensable dans la construction d’un système financier stable et efficace.
Aussi convient-il de se montrer réactif et de s’adapter à l’exigence accrue demandée à tous les membres des directions financières bien au-delà de la simple logique de réduction des coûts exigée par la crise.
</p>-->
</div>
<div class="panel-footer heading-colored"><a class="btn btn-default" data-toggle="tooltip" data-placement="top" title="Vous pouvez consulter et/ou télécharger ce module"><i class="glyphicon glyphicon-plus-sign" style="color: #f58222;"></i> En savoir plus</a></div>
</div>
</div>
Finally I was able to figure out what was wrong. Actually, I had to make sure the images files were available online. Since I used symlink option on my local environment et used
{{ image('bundles/app/images/img.jpg').forceResize(x,y) }}
code to make a link to my images, after uploading my images from /public folder, I had to make a hard copy of my images on /web/bundles/app/images/ folder. I tried to run assets:install --symlink online, but for some reason it didn't work.

ErrorException, array_merge(): Argument #2 is not an array when i work a call Ajax

In my users page, I use a div with two tabs "Products" and "Followers", in the second tab, I've a pagination for the list of followers.
Not return to the tab "Products" when I try the pagination, I user a call Ajax.
But when I try to run it, I have a error 500, and the response of the get is :
{"error":{"type":"ErrorException","message":"array_merge(): Argument #2 is not an
array","file":"\/Users\/utilisateur\/Desktop\/mamp\/ptf-l4\/vendor\/laravel\/framework\
/src\/Illuminate\/View\/Environment.php","line":117}}
I don't know why and I don't know how to find a solution.
This is my controller :
public function show($id){
// récupère les données de l'user et les produis qu'il partage
$show = $this->api->show($id);
// décode le json pour qu'il se réaffiche en array pour pouvoir l'exploiter
$json = json_decode($show->getContent());
$json->followed = User::userFollowedPaginate($id);
LaravelMixpanel::identify(Auth::user()->mixpanel_id);
LaravelMixpanel::track('User show view');
if(Request::ajax())
{
$html = View::make('users.show', $json)->render();
return Response::json(['html' => $html]);
}
return View::make('users.show')
->with('user', $json);
}
My API/Controller :
public function show($id){
// récupère donnée de l'user et les produits qu'il échange
$data = User::with(array('products' => function($query){
$query->whereNull('shared_at');
$query->whereNull('deleted_at');
}))->findOrFail($id)->toArray();
// récupère le nb de produits qu'il échange en ce moment
$data['nbShareCurrently'] = Product::where('user_id', $id)->whereNull('shared_at')->whereNull('deleted_at')->count();
// récupère le nb de produits qu'il a échangé depuis le début
$data['nbShared'] = Product::where('user_id', $id)->whereNotNull('shared_at')->count();
return Response::json($data, 200);
}
My JS :
function callAjaxUser(url) {
$.ajax ({
type: "GET",
url: url ,
success: function() {
console.log('Success ');
},
error: function() {
console.log('Error ');
}
});
}
$(document).ready(function(){
$('body').on('click', ' .pagination a ', function(event){
event.preventDefault();
var url=$(this).attr('href');
callAjaxUser(url);
});
});
And my view :
#extends('default')
#section('title')
Fiche de {{ $user->name }}
#stop
#section('contenu')
<section class="panel col-lg-8 col-sm-8 m-t-large">
<header class="panel-heading m-l-n m-r-n">
<ul class="nav nav-tabs pull-right">
<li class="active"><i class="icon-list icon-large text-default"></i>Mes produits en cours de partage</li>
<li><i class="icon-group icon-large text-default"></i>Mes abonnés</li>
</ul>
<span class="hidden-sm">Fiche technique du frigo</span>
</header>
<div class="panel-body">
<div class="tab-content">
<div class="tab-pane active" id="product">
<div class="col-lg-3">
{{-- dd($user) --}}
<h4>{{{ $user->name }}}</h4>
#if($user->photo && File::exists(public_path().'/uploads/photos/users/'.e($user->photo)))
{{ HTML::image('uploads/photos/users/'.e($user->photo), e($user->name)) }}
#else
{{ HTML::image('template/images/avatar.jpg', e($user->name)) }}
#endif
#if($user->id!=Auth::user()->id)
#if(DB::table('user_followers')->where('user_followed', $user->id)->where('user_following', Auth::user()->id)->count()==0)
{{ HTML::decode(HTML::linkAction('UserFollowersController#follow', '<i class="icon-heart">S\'abonner</i>', array('id' => $user->id), array('class' => 'btn btn-info m-t-large m-b-small'))) }}
#else
{{ HTML::decode(HTML::linkAction('UserFollowersController#unfollow', '<i class="icon-heart">Se désabonner</i>', array('id' => $user->id), array('class' => 'btn btn-danger m-t-large m-b-small '))) }}
#endif
#endif
</div>
<div class="col-lg-9">
<h4>Le frigo contient en ce moment :</h4>
<ul class="list-unstyled">
#foreach($user->products as $product)
<li class="list-group-item bg m-b-small">
<div class="media">
#if(e($product->photo) && File::exists(public_path().'/uploads/photos/products/'.e($product->photo)))
<span class="pull-left img-product">
<a href="{{ URL::action('ProductsController#show', $product->id) }}">
{{ HTML::image('uploads/photos/products/'.e($product->photo), e($product->title), array('class' => 'img-rounded')) }}
</a>
</span>
#endif
<div class="media-body">
<div>{{{ $product->title }}}</div>
<p>{{{ $product->description }}}</p>
<p class="pull-left">Quantité : <span class="label label-info">{{{ $product->quantity }}}</span></p>
<p class="pull-right">Prix : <span class="badge bg-danger">{{{ $product->price }}} €</span></p>
</div>
</div>
</li>
#endforeach
</ul>
<div class="pagination">
{{-- $users->products->links() --}}
</div>
</div>
</div>
<div class="tab-pane" id="follow">
<div class="row m-b-large">
#if($user->followed!=NULL)
#foreach($user->followed as $user_followed)
<div class="panel col-lg-2 m-l-large m-t-large ">
<div class="col-lg-8 m-b-n-small col-md-offset-2 m-t-large text-center">
#if($user_followed->photo && File::exists(public_path().'/uploads/photos/users/'.e($user_followed->photo)))
{{ HTML::image('uploads/photos/users/'.e($user_followed->photo), e($user_followed->name), array ( 'class' => 'img-circle')) }}
#else
{{ HTML::image('template/images/avatar.jpg', e($user_followed->name), array ( 'class' => 'img-circle')) }}
#endif
<h3>{{{ $user_followed->name }}}</h3>
</div>
<div class="col-lg-10 m-b-small center ">
#if(DB::table('user_followers')->where('user_followed', $user_followed->id)->where('user_following', Auth::user()->id)->count()==0)
{{ HTML::decode(HTML::linkAction('UserFollowersController#follow', '<i class="icon-heart">S\'abonner</i>', array('id' => $user_followed->id), array('class' => 'btn btn-info btn-group-justified m-t-large m-b-small'))) }}
#else
{{ HTML::decode(HTML::linkAction('UserFollowersController#unfollow', '<i class="icon-heart">Se désabonner</i>', array('id' => $user_followed->id), array('class' => 'btn btn-danger btn-group-justified m-t-large m-b-small '))) }}
#endif
</div>
</div>
#endforeach
#else
<div class="panel col-lg-8 col-lg-offset-2 m-t-large">
<h4> Tu ne suis actuellement personne </h4>
</div>
#endif
</div>
<div class="col-lg-12">
{{ $user->followed->links() }}
</div>
</div>
</div>
</div>
</section>
#stop
#section('js')
{{ Basset::show('usersPaginate.js') }}
#endsection
I stumbled upon this question because it is the first Google search result for laravel ErrorException, array_merge(): Argument #2 is not an array.
Even though the question is a year old, it is still relevant, because this happened to me in Laravel 5.0 today.
Without taking the time to digest all of your code, the problem is likely the same in your case as it was in mine: you are passing a non-array as the second argument to view::make() (whether intentionally or not) when you must pass an array.
The problem line is this one, in your controller:
$html = View::make('users.show', $json)->render();
Given that $json appears to be an object, the fix is simple:
$html = View::make('users.show', compact('json'))->render();
Hopefully, this answer will help somebody else in the future.

parse php for strings to translate

I have many php files full of html markup. I would like to extract all the strings (html node content and attribute values), to generate a text document to review then send for translation.
I'm wondering, is there a reliable way (a tool or a script perhaps) that would do that automatically?
Example code i have:
<div class="row">
<div class="medium-11 columns medium-centered">
<p style="font-weight:bold;">Bienvenue sur votre compte, vous permettant
de répondre aux offres d'emploi. Tenez à jour vos données
personnelles et vos documents officiels tels que CV, diplôme ou
permis de conduire, et retrouvez l'historique des offres auxquelles
vous aviez postulé.</p>
</div>
</div>
<dl class="tabs" data-tab="">
<dd class="active">
<i class="fi-torso"></i> Votre profil
</dd>
<dd>
<i class="fi-bookmark"></i> Formation
</dd>
<dd>
<i class="fi-shuffle"></i> Expérience
</dd>
<dd>
<i class="fi-paperclip"></i> Documents
</dd>
<dd>
<i class="fi-foundation"></i> Historique
</dd>
</dl>
<input type="hidden" name="user_id" value="USERID">
<input type="radio" name="sexe" value="2" id="Monsieur" title="veuillez indiquer votre genre">
What i would like to extract:
Bienvenue sur votre compte, vous permettant de répondre aux offres d'emploi. Tenez à jour vos données personnelles et vos documents officiels tels que CV, diplôme ou permis de conduire, et retrouvez l'historique des offres auxquelles vous aviez postulé.
Votre profil
Formation
Expérience
Documents
Historique
veuillez indiquer votre genre
To remove all the tags in the HTML, you can use strip_tags():
$text_only = strip_tags($html_codes);
For document generation part, it depends what kind of document you want to generate.

Categories