Symfony 2 - FOSCommentBundle : add attachment feature - symfony

I need to add functionality to attach a file to a comment. The upload of the image would automatically when the user drops the file into the form (in the same way that you attach a file with gmail). My question is how do I do to find the file that was previously sent to the server when the comment is submitted and to delete the comment if the document is never submitted.
Do any of you have already done something similar?
Here's the association I have between my classes Comment and Document.
class Comment extends BaseComment
{
/** ... */
/**
* #ORM\ManyToMany(targetEntity="Document", cascade={"persist","remove"})
* #ORM\JoinTable(name="fls_comment_and_documents",
* joinColumns={#ORM\JoinColumn(name="comment_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="document_id", referencedColumnName="id", unique=true)}
* )
*
* #var ArrayCollection $documents
*/
protected $documents;
/** ... */
}
Thanks in advance !

Related

Sonata Media Bundle delete image programmatically

It seems that there is no documentation about how to delete images programmatically with Sonata Media Bundle.
I found another post saying that you need to call delete on the media manager.
Here is my mapping:
/**
* #var Application\Sonata\MediaBundle\Entity\Media
*
* #ORM\ManyToOne(targetEntity="Application\Sonata\MediaBundle\Entity\Media", cascade={"persist", "remove"}, fetch="LAZY")
* #ORM\JoinColumn(name="image_id", referencedColumnName="id", onDelete="SET NULL")
*/
protected $image;
And this is the code I use to delete:
$this->mediaManager = $this->getContainer()->get('sonata.media.manager.media');
$previousMedia = $myEntity->getImage();
$provider = $this->getContainer()->get($previousMedia->getProviderName());
$provider->removeThumbnails($previousMedia);
$this->mediaManager->delete($previousMedia);
The association is correctly remove (the entity image field is now null) but on my gallery the object still exists and looks like this:
What am I doing wrong?

Symfony2, Sonata : Customize title of collection

I've been able to translate most of the titles but i still have some non-friendly titles on collections (Table of relation)
Aire\AppBundle\Entity\ProjectSupported:000000002d1a645a000000015441bb1f
How could i custom them?
At best it could be the name of the related object ($investor->getName() and $project->getName() for exemple), at worst just a string.
In that case i'm using en entity with 2 relations
/**
* Owning Side
*
* #ORM\ManyToOne(targetEntity="Investor", inversedBy="supportedProject")
* #ORM\JoinColumn(name="investor_id", referencedColumnName="id")
**/
private $investor;
/**
* Owning Side
*
* #ORM\ManyToOne(targetEntity="Project", inversedBy="supportedProject")
* #ORM\JoinColumn(name="project_id", referencedColumnName="id")
**/
private $project;
Any hints or solutions?
Sonata is using the __toString method for text representation of objects.

Doctrine2 - Custom persister

I'm busy working on a project and I've ran into a slight issue. I was just wondering whether there is any way to customize the persist action of a specific entity? In my case specifically I want to, on update, remove some fields from other tables before re-saving the entity.
Let's, for arguments sake, say my entity that I want a custom persist action on looks like this:
/**
* #ORM\Table()
* #ORM\Entity
*/
class A {
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="B", mappedBy="bar")
* #ORM\Column(name="foo")
*/
private $foo;
//Some additional getters and setters here
}
/**
* #ORM\Table()
* #ORM\Entity
*/
class B {
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="A", inversedBy="foo")
* #ORM\JoinColumn(name="bar", referencedColumn="id")
*/
private $bar;
//Getters and setters here.
}
Now I know with a simple example like this doctrine will automatically just update $bar in class B if you update that, but let's just say I'd like to first remove $bar completely (not just update it) and re-save it with the new value? Is this possible?
This could also just be done manually before persisting in my update action, but that feels a bit hacky?
The actual code I want to do this with is much too long to post here, so I'm just opting for a simple proof-of-concept here.
Thanks for any assist!
EDIT
Technically the other entities will be related to the current one, via a OneToMany/ManyToMany/ManyToOne relationship, as in the example above. So isn't there something like preHydrate that I can use to clear current data before hydrating the entity with the submitted data?
You should use event-listeners or -subscribers instead of LifecycleCallbacks (i.e. #PrePersist ) as recommended in Cyrus's answer.
Using LifecycleCallbacks you don't have access to unrelated entities while you can change/remove these with a listener/subscriber where you have direct access to the entity-manager with dependency injection.
Please see the documentation chapter How to Register Event Listeners and Subscribers.
You can use prepersist:
/**
* #ORM\PrePersist
*/
There are preupdate, preremove, etc.
Here you have all the info to do that: http://symfony.com/doc/current/book/doctrine.html

ManyToMany on same table

I have a project in which I have a OneToMany relationship on the same database.
Currently it is designed like this:
/**
* #ORM\OneToMany(targetEntity="MyEntity", mappedBy="myCopiedItem")
*/
protected $mySource;
/**
* #ORM\ManyToOne(targetEntity="MyEntity", inversedBy="mySource")
* #ORM\JoinColumn(name="selected_myentity_copy_id", referencedColumnName="id")
*/
protected $myCopiedItem;
But now I have to make this relationship ManyToMany. So I did this:
/**
* #ORM\ManyToMany(targetEntity="MyEntity", mappedBy="myCopiedItem")
*/
protected $mySource;
/**
* #ORM\ManyToMany(targetEntity="MyEntity", inversedBy="mySource")
* #ORM\JoinTable(name="entity_has_copy")
*/
protected $myCopiedItem;
but the "entity_has_copy" table that symfony created has only 1 item (myentity_id) and I want to have 2 fields "myentity_id" & "selected_myentity_copy_id" which are both actualy id's from my "myentity" table...
What do I have to modify in order to have both id's in my generated table?
I'm sure I've missed something, but I cannot figure out WHAT :(
Note: Entity / table names were renamed for privacy
Solved this!
I had to add the relationship inside the definition...
So this is the correct definition for the JoinTable part:
/**
* #ORM\ManyToMany(targetEntity="MyEntity", inversedBy="mySource")
* #ORM\JoinTable(name="entity_has_copy",
* joinColumns={#ORM\JoinColumn(name="entity_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="entity_copy_id", referencedColumnName="id")}
* )
*/
protected $myCopiedItem;
Hope this will help others that are having same issue...
If you want to read more about how associations between entities are mapped with Doctrine, here's a good URL!

JMSSerializerBundle serialization groups in entities with relations

I have a problem with serializing entity with many relations using groups.
I have a problem with serializing related entities this way.
Let's say I have two entities: Product and related Element.
/**
*
* #Serializer\ExclusionPolicy("none")
*/
class Product {
/**
* Primary key
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*
* #Serializer\Groups({"list","details"})
* #Serializer\Type("integer")
*/
protected $id;
/**
* #Serializer\Groups({"list","details"})
* #Serializer\Type("string")
*/
protected $name;
/**
* #ORM\Column(name="description", type="string", length=4096, nullable=true)
*
* #Serializer\Groups({"details"})
* #Serializer\Type("string")
*/
protected $description;
/**
* #var ArrayCollection
*
* #ORM\OneToMany(targetEntity="Madden\ProjectBundle\Entity\ProjectResource", mappedBy="project")
* #Serializer\Groups({"details"})
* #Serializer\Type("ArrayCollection<Element>")
*/
protected $details1;
/**
* Relation to project tasks
* #ORM\OneToMany(targetEntity="Madden\ProjectBundle\Entity\ProjectTask", mappedBy="project")
* #Serializer\Exclude()
* #Serializer\Type("ArrayCollection<Element>")
*/
protected $details2;
...
}
Element entity has a similar structure:
/**
*
* #Serializer\ExclusionPolicy("none")
*/
class Element {
/**
* Primary key
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*
* #Serializer\Groups({"list","details"})
* #Serializer\Type("integer")
*/
protected $id;
/**
* #Serializer\Groups({"list","details"})
* #Serializer\Type("string")
*/
protected $name;
/**
* #ORM\Column(name="description", type="string", length=4096, nullable=true)
*
* #Serializer\Groups({"details"})
* #Serializer\Type("string")
*/
protected $description;
...
}
My problem is that when I'm serializing Product with 'details' group entity I want to serialize only id's of Elements but as you see entity has defined same groups as Product (in case that I would need details of element object) because I want have unified groups on all my entities and prevent making hundreds of groups like 'product_details','element_details', and so on.
Is there a way to eventualy change serialization group when I visit relation or something like that? Handler maybe or something like that?
Regards and thanks for any help
Unfortunately, you can't really (but keep reading ;-)), well at least not without changes to the serializer library. The culprit is that the list of groups is fixed within a GroupExclusionStrategy (which is referenced by the Context) the minute you start the serialization process. There is actually an assertion within the code that prevents modification of the exclusion strategy once the (de-)serialization is running.
But as it happens, I had the exact same problem in a project of mine as well, and I hacked the necessary changes into the serializer code. I have cleaned the code up a bit and uploaded it to Github (https://github.com/andreasferber/serializer/tree/recursion-groups).
It adds new property metadata with which you can add, remove or override the groups when descending into subobjects. With annotations it looks like this:
/**
* #Serializer\RecursionGroups(set={"foo", "bar"}, add={"baz"}, remove={"Default"})
*/
private $myProperty;
You should be able to use XML or Yaml metadata as well, however this is untested since I don't use them and I haven't added test cases yet. Have a look at the reference documentation. Since I haven't done any optimizations yet either, if your entities are really large and deeply nested, it might have a noticable performance impact.
Please let me know if you find this useful, or if you have any suggestions, because if this isn't only needed by me, I will add some tests and try to submit it upstream.
A solution for this is actually described in the official documentation.
That being said the solution proposed by #aferber seems better on many points: easier to maintain, less verbose, more flexible...
You need to use setGroups.
The _group suffix used in the official documentation is not needed.
$context->setGroups([
'Default', //if you want
// use this linked entity but show only its id
'group_of_linked_field',
'group_of_linked_field' => [
'id' // you will need to define this group first
],
// use this linked entity and show fields as described
'group_of_other_linked_field',
'group_of_other_linked_field' => [
// just as an example
'Default',
'details',
],
]);
This does not work with addGroup or addGroups! Both of them won't accept associative arrays. setGroups is your (only?) solution.

Resources