{"action":"created","issue":{"url":"https://api.github.com/repos/xiidea/EasyAuditBundle/issues/27","repository_url":"https://api.github.com/repos/xiidea/EasyAuditBundle","labels_url":"https://api.github.com/repos/xiidea/EasyAuditBundle/issues/27/labels{/name}","comments_url":"https://api.github.com/repos/xiidea/EasyAuditBundle/issues/27/comments","events_url":"https://api.github.com/repos/xiidea/EasyAuditBundle/issues/27/events","html_url":"https://github.com/xiidea/EasyAuditBundle/issues/27","id":335356855,"node_id":"MDU6SXNzdWUzMzUzNTY4NTU=","number":27,"title":"Saving collection of entity form types problem: PreUpdateEventArgs::__construct() must be of the type array, null given","user":{"login":"pribeirojtm","id":18724236,"node_id":"MDQ6VXNlcjE4NzI0MjM2","avatar_url":"https://avatars0.githubusercontent.com/u/18724236?v=4","gravatar_id":"","url":"https://api.github.com/users/pribeirojtm","html_url":"https://github.com/pribeirojtm","followers_url":"https://api.github.com/users/pribeirojtm/followers","following_url":"https://api.github.com/users/pribeirojtm/following{/other_user}","gists_url":"https://api.github.com/users/pribeirojtm/gists{/gist_id}","starred_url":"https://api.github.com/users/pribeirojtm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pribeirojtm/subscriptions","organizations_url":"https://api.github.com/users/pribeirojtm/orgs","repos_url":"https://api.github.com/users/pribeirojtm/repos","events_url":"https://api.github.com/users/pribeirojtm/events{/privacy}","received_events_url":"https://api.github.com/users/pribeirojtm/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":6,"created_at":"2018-06-25T10:56:25Z","updated_at":"2018-06-28T15:02:17Z","closed_at":null,"author_association":"NONE","body":"Hi,\r\n\r\n- I have a form type based on a entity that has a collection type of forms and each one has also entities related with other form types. \r\n- In my _config.yml_ I am tracking all the events (created, updated, deleted) to the affected entities and also their correspondent proxy classes (just for guaranteeing not having any problem: [#23](https://github.com/xiidea/EasyAuditBundle/issues/23) )\r\n- When I do not make use of logging capabilities (comment those entities in _config.yml_ to not track changes on those entities,from EasyAuditBundle, **the form is saved without any problem! -> This is very important for the case!**\r\n- When I make use of entity logging capabilities of this bundle (uncomenting those entities from config.yml) and I try to save that form, it gives me the following error:\r\n\r\n> Uncaught PHP Exception Symfony\\Component\\Debug\\Exception\\FatalThrowableError: \"Type error: Argument 3 passed to Doctrine\\ORM\\Event\\PreUpdateEventArgs::__construct() must be of the type array, null given, called in /var/www/app/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php on line 1060\" at /var/www/app/vendor/doctrine/orm/lib/Doctrine/ORM/Event/PreUpdateEventArgs.php line 46 {\"exception\":\"[object] (Symfony\\\\Component\\\\Debug\\\\Exception\\\\FatalThrowableError(code: 0): Type error: Argument 3 passed to Doctrine\\\\ORM\\\\Event\\\\PreUpdateEventArgs::__construct() must be of the type array, null given, called in /var/www/app/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php on line 1060 at /var/wwwapp/vendor/doctrine/orm/lib/Doctrine/ORM/Event/PreUpdateEventArgs.php:46)\"}\r\n\r\n- Is the problem related with the internal flush of your bundle?\r\n`in vendor/xiidea/easy-audit/Logger/Logger.php (line 38)\r\n        if(empty($event)) {            return;        }        $this->getEntityManager()->persist($event);        $this->getEntityManager()->flush($event);    }    /**     * @return EntityManager     */`\r\n- Can we have flush() inside flush()? How the transaction flush created by my instruction in the controller and the flush that is executed in the beetweens of the transaction I think, to save the record in the audit_log table  are handled? \r\n- The exception passes here:\r\n> public function postUpdate(LifecycleEventArgs $args)    {        $this->handleEvent(DoctrineEvents::ENTITY_UPDATED, $args);    }\r\n- Can be any chance of conflicts with my PreUpdate /PrePersist events?\r\n\r\n- Other notes 1: I have a _CustomEntityEventResolver_ which was built based in your example, and that has minor changes, just to tracking changeSets that are serialized to a audit_log new field (`$this->getChangeSets($this->entity);`) and getEventLogInfo(Event $event, $eventName) returns a AuditLog entity \r\n- Other notes 2: So, I have a custom AuditLog entity with that new field for tracking changes (the deltas)\r\n```php\r\n<?php\r\nnamespace AppBundle\\Entity;\r\nuse Doctrine\\ORM\\Mapping as ORM;\r\nuse Xiidea\\EasyAuditBundle\\Entity\\BaseAuditLog;\r\n/**\r\n * @ORM\\Entity)\r\n * @ORM\\Table(name=\"audit_log\")\r\n */\r\nclass AuditLog extends BaseAuditLog\r\n{ \r\n    /**\r\n     * @ORM\\Id\r\n     * @ORM\\Column(type=\"integer\")\r\n     * @ORM\\GeneratedValue(strategy=\"AUTO\")\r\n     */\r\n    protected $id;\r\n/*...*/ \r\n\r\n    /**\r\n     * @var string\r\n     * @ORM\\Column(name=\"change_sets\", type=\"text\", nullable=true, unique=false, nullable=true)\r\n     */\r\n    protected $changeSets;\r\n\r\n}\r\n```\r\n- I'm posting here the simplest code and clear as possible to you get a quick understand:\r\n```php\r\n<?php \r\n// MyController.php Class:\r\nclass MyController extends Controller\r\n{\r\n\t//....\r\n\t\r\n\tpublic function editMawbFlightsFactModalAction(Mawb $mawb, Request $request) {\r\n\t\t\r\n\t\t$entityManager = $this->getDoctrine()->getManager();\r\n\r\n\t\t$form = $this->createForm(MawbFlightsFactType::class, $mawb);\r\n\r\n\t\tif ($request->isMethod('POST')) {\r\n\r\n\t\t\t$form->submit($request->request->get($form->getName()), false);\r\n\r\n\t\t\t// - Handle submitted data\r\n\t\t\tif ($form->isSubmitted() && $form->isValid()) {\r\n\r\n\t\t\t\t// @var Mawb $mawb\r\n\t\t\t\t$mawb = $form->getData();\r\n\r\n\t\t\t\t$entityManager = $this->getDoctrine()->getManager();\r\n\t\t\t\t$entityManager->persist($mawb);\r\n\t\t\t\t$entityManager->flush();\r\n\r\n\t\t\t\treturn new JsonResponse(['msg' => 'ok']);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn $this->render('app/editMawbFlightsFact.html.twig',\r\n\t\t\tarray(\r\n\t\t\t\t'form' => $form->createView(),\r\n\t\t\t\t'mawb' => $mawb\r\n\t\t\t)\r\n\t\t);\r\n\t}\r\n}\r\n\r\n//-----------------------------------------------------------------------------------------\r\n//Mawb.php Entity Class:\r\nnamespace AppBundle\\Entity;\r\nuse Doctrine\\ORM\\Mapping as ORM;\r\n\r\n/**\r\n * Mawb\r\n *\r\n * @ORM\\Table(name=\"mawb\")\r\n * @ORM\\Entity\r\n */\r\nclass Mawb\r\n{\r\n\t/**\r\n     * @var integer\r\n     *\r\n     * @ORM\\Column(name=\"id_mawb\", type=\"integer\", nullable=false, unique=false)\r\n     * @ORM\\Id\r\n     * @ORM\\GeneratedValue(strategy=\"IDENTITY\")\r\n     */\r\n    private $idMawb;\r\n\t\r\n\t\r\n\t//... other entity properties......\r\n\t\r\n\t/**\r\n     * @var \\Doctrine\\Common\\Collections\\Collection\r\n     *\r\n     * @ORM\\OneToMany(targetEntity=\"FlightsFactMawb\", mappedBy=\"mawb\", orphanRemoval=true, cascade={\"persist\"})\r\n     */\r\n    private $flightsFactMawbCollection;\r\n\t\r\n    public function __construct() {\r\n        $this->flightsFactMawbCollection = new ArrayCollection();\r\n    }\r\n\t\r\n\t//...getters and setters..\r\n}\r\n\r\n//-----------------------------------------------------------------------------------------\r\n//MawbFlightsFactType.php form Type\r\nclass MawbFlightsFactType extends AbstractType\r\n{\r\n    public function buildForm(FormBuilderInterface $builder, array $options) {\r\n        $builder\r\n            ->add('flightsFactMawbCollection', CollectionType::class, array(\r\n                'entry_type' => FlightFactMawbType::class,\r\n                'by_reference' => false,\r\n                'prototype' => true\r\n            ));\r\n    }\r\n\r\n    public function configureOptions(OptionsResolver $resolver) {\r\n        $resolver->setDefaults(['data_class' => Mawb::class]);\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------------------\r\n//FlightFactMawbType.php form Type\r\nclass FlightFactMawbType extends AbstractType\r\n{\r\n    public function buildForm(FormBuilderInterface $builder, array $options) {\r\n        $builder\r\n            ->add('flightFact', FlightFactType::class,['data_class' => FlightsFact::class])\r\n            ->add('assigned');   \r\n    }\r\n\r\n    public function configureOptions(OptionsResolver $resolver) {\r\n        $resolver->setDefaults(['data_class' => FlightsFactMawb::class]);\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------------------\r\n//FlightsFactMawb.php Entity Class:\r\nnamespace AppBundle\\Entity;\r\nuse Doctrine\\ORM\\Mapping as ORM;\r\nuse AppBundle\\Entity\\Traits\\CreatedUpdatedAtTrait;\r\n\r\n/**\r\n * FlightsFactMawb\r\n *\r\n * @ORM\\Table(name=\"flights_fact_mawb\")\r\n * @ORM\\Entity\r\n * @ORM\\HasLifecycleCallbacks\r\n */\r\nclass FlightsFactMawb\r\n{\r\n    use CreatedUpdatedAtTrait;\r\n\t\r\n\t/**\r\n     * @var integer\r\n     *\r\n     * @ORM\\Column(name=\"id\", type=\"integer\", nullable=false)\r\n     * @ORM\\Id\r\n     * @ORM\\GeneratedValue(strategy=\"IDENTITY\")\r\n     */\r\n    private $id;\r\n\t\r\n\t/**\r\n     * @var boolean\r\n     *\r\n     * @ORM\\Column(name=\"assigned\", type=\"boolean\", nullable=false, unique=false, options={\"default\" : \"1\"})\r\n     */\r\n    private $assigned;\r\n\t\r\n\t// .... other entity properties.....\r\n\r\n    /**\r\n     * @var FlightsFact\r\n     *\r\n     * @ORM\\ManyToOne(targetEntity=\"FlightsFact\", cascade={\"persist\"})\r\n     * @ORM\\JoinColumns({\r\n     *   @ORM\\JoinColumn(name=\"id_flights_fact\", referencedColumnName=\"id_flights_fact\", nullable=false, onDelete=\"CASCADE\")\r\n     * })\r\n     */\r\n    private $flightFact;\r\n\t\r\n\t//...getters and setters..\r\n}\r\n\r\n//-----------------------------------------------------------------------------------------\r\n//FlightsFact.php Entity Class:\r\nnamespace AppBundle\\Entity;\r\nuse Doctrine\\ORM\\Mapping as ORM;\r\nuse AppBundle\\Entity\\Traits\\CreatedUpdatedAtTrait;\r\n\r\n/**\r\n * @ORM\\Table(name=\"flights_fact\")\r\n * @ORM\\Entity\r\n * @ORM\\HasLifecycleCallbacks\r\n */\r\nclass FlightsFact\r\n{\r\n    use CreatedUpdatedAtTrait;\r\n\r\n    /**\r\n     * @var integer\r\n     *\r\n     * @ORM\\Column(name=\"id_flights_fact\", type=\"integer\", nullable=false, unique=false)\r\n     * @ORM\\Id\r\n     * @ORM\\GeneratedValue(strategy=\"IDENTITY\")\r\n     */\r\n    private $idFlightFact;\r\n\r\n    /**\r\n     * @var string\r\n     *\r\n     * @ORM\\Column(name=\"number\", type=\"string\", length=5, nullable=true, unique=false)\r\n     */\r\n    private $number;\r\n\t\r\n\t//...\r\n\r\n    /**\r\n     * @ORM\\PreUpdate\r\n     */\r\n    public function preUpdateScheduledEpochs() {\r\n        if(!empty($this->getNumber()) {\r\n            $this->setNumber($this->getNumber().'*');\r\n        }\r\n    }\r\n}\r\n\r\n//-----------------------------------------------------------------------------------------\r\n//FlightFactMawbType.php form Type\r\nclass FlightFactType extends AbstractType\r\n{\r\n    public function buildForm(FormBuilderInterface $builder, array $options) {\r\n\t\t\r\n        $builder\r\n            ->add('number', null, ['required' => true]);\r\n    }\r\n\t\r\n    public function configureOptions(OptionsResolver $resolver) {\r\n        $resolver->setDefaults(array('data_class' => FlightsFact::class));\r\n    }\r\n}\r\n\r\n//------------------------------------------------------------------------------------------\r\n// CreatedUpdatedAtTrait.php\r\nnamespace AppBundle\\Entity\\Traits;\r\n\r\nuse Doctrine\\ORM\\Event\\PreUpdateEventArgs;\r\nuse Doctrine\\ORM\\Mapping as ORM;\r\n\r\ntrait CreatedUpdatedAtTrait\r\n{\r\n    /**\r\n     * @var \\DateTime\r\n     * @ORM\\Column(name=\"created_at\", type=\"datetime\", nullable=false)\r\n     */\r\n    protected $createdAt;\r\n\r\n    /**\r\n     * @var \\DateTime\r\n     * @ORM\\Column(name=\"updated_at\", type=\"datetime\", nullable=false)\r\n     */\r\n    protected $updatedAt;\r\n\r\n\r\n    /**\r\n     * @ORM\\PrePersist\r\n     */\r\n    public function onPrePersist() {\r\n        $this->updatedAt = new \\DateTime('now');\r\n        $this->createdAt = $this->createdAt == null ? $this->updatedAt : $this->createdAt;\r\n    }\r\n\r\n    /**\r\n     * @ORM\\PreUpdate\r\n     */\r\n    public function onPreUpdate() {\r\n        $this->updatedAt = new \\DateTime('now');\r\n        if (!$this->createdAt) {\r\n            $this->createdAt = new \\DateTime('now');\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @return \\DateTime\r\n     */\r\n    public function getCreatedAt() {\r\n        return $this->createdAt;\r\n    }\r\n\r\n    /**\r\n     * @param \\DateTime $createdAt\r\n     * @return $this\r\n     */\r\n    public function setCreatedAt($createdAt) {\r\n        $this->createdAt = $createdAt;\r\n        return $this;\r\n    }\r\n\r\n    /**\r\n     * @return \\DateTime\r\n     */\r\n    public function getUpdatedAt() {\r\n        return $this->updatedAt;\r\n    }\r\n\r\n    /**\r\n     * @param \\DateTime $updatedAt\r\n     * @return $this\r\n     */\r\n    public function setUpdatedAt($updatedAt) {\r\n        $this->updatedAt = $updatedAt;\r\n        return $this;\r\n    }\r\n}\r\n```\r\n- Other note: Audit Log works nice if I just save a single entity\r\n- Also, I've tested with master branch and also with the latest tag, giving the same problem.\r\n\r\nCan you give a hand on this? Can you reproduce the error? Thanks.\r\n\r\n\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/xiidea/EasyAuditBundle/issues/comments/401065972","html_url":"https://github.com/xiidea/EasyAuditBundle/issues/27#issuecomment-401065972","issue_url":"https://api.github.com/repos/xiidea/EasyAuditBundle/issues/27","id":401065972,"node_id":"MDEyOklzc3VlQ29tbWVudDQwMTA2NTk3Mg==","user":{"login":"pribeirojtm","id":18724236,"node_id":"MDQ6VXNlcjE4NzI0MjM2","avatar_url":"https://avatars0.githubusercontent.com/u/18724236?v=4","gravatar_id":"","url":"https://api.github.com/users/pribeirojtm","html_url":"https://github.com/pribeirojtm","followers_url":"https://api.github.com/users/pribeirojtm/followers","following_url":"https://api.github.com/users/pribeirojtm/following{/other_user}","gists_url":"https://api.github.com/users/pribeirojtm/gists{/gist_id}","starred_url":"https://api.github.com/users/pribeirojtm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pribeirojtm/subscriptions","organizations_url":"https://api.github.com/users/pribeirojtm/orgs","repos_url":"https://api.github.com/users/pribeirojtm/repos","events_url":"https://api.github.com/users/pribeirojtm/events{/privacy}","received_events_url":"https://api.github.com/users/pribeirojtm/received_events","type":"User","site_admin":false},"created_at":"2018-06-28T15:02:17Z","updated_at":"2018-06-28T15:02:17Z","author_association":"NONE","body":"Hi @ronisaha ,\r\n\r\nI've tested now with your **DoctrineSubscriber**, without my modifications, and with my custom logger and..... **it works**!\r\n\r\nSo, sorry If I was suggesting unwanted/unneeded/unnecessary changes regarding preUpdate events... I thought it was because of that it wasn't working. PreUpdatedEventArgs exception name suggested me that. \r\n\r\nSo, now I have a custom Logger, deactivated yours, In this logger, in log method I am just \"storing\" in an array the baseAuditLog events... that will be executed in `CustomDoctrineEventLoggerSubscriber` and onKernelResponse I proccess the savePendingLogs...  This way I can solve the problem.\r\n\r\nThanks for your help @ronisaha "}}
{"actor":{"display_login":"pribeirojtm"}}