Extend Symfony2 White October Admin Bundle Form Fields? - symfony

This question is quite specific.
I'm using Symfony2 White October Admin Bundle for generating administration for my application.
I wonder if anyone has experience with this bundle and knows how to modify specific fields added to Admin class. The bundle is not documented very well and I'd like to know, if there are methods for doing this, or does the bundle core need to be extended.
For example I've got a Speaker entity with a field storing the path to one's avatar:
/**
* #var string $picturePath
*
* #ORM\Column(name="picture_path", type="string", length=128, nullable=false)
*/
private $picturePath;
Then in the Admin class I'm adding the field:
protected function configure()
{
...
...
->addFields(array(
...
...
'picturePath'=> array("label" => "Avatar"),
));
}
Is there an easy way to tell the bundle that I'd like this field to be an upload field instead of a text field, and define extra methods to call after submitting the form? (e.g. resize the image, store it, and then just store the image path in the DB)

As I haven't found any solution yet, I had to rape my entities to do that. So I modified the basic setter methods to call other methods inside the entity that do the dirty job. This is not a solution, and I'll still be happy if I could find better answers here.

Related

Getting a list of all properties in a group in API Platform

Using API Platform 1.2.
I've simplified my setup for the purpose of this question. Please excuse lack of following standards.
I have 2 entities: Book and Category. Book properties:
/**
* #Groups({book:read})
*/
$name;
/**
* #Groups({book:read})
*/
$summary;
/**
* #Groups({book:read})
*/
$category;
The $category property is mapped to a Category entity. Category has a $categoryName property. This is also attached to the book:read group.
In the GET API call this the output contains all the Book properties plus the $categoryName property. This is great 👍
What I want to know is: Using API Platform, how would I go about getting all properties for a serialization group such as above?
I have found that I could tap into the \ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface to get the property info but this requires knowing what classes and properties to check. Looping through all entities with a metadata lookup, then looping through all properties, performing another metadata lookup seems wasteful and slow.
Is there a better way to acheieve this? I basically want the same output as what the API produces by feeding am entity name and group name.

Using htmlpurifier with annotations in symfony 2.8

I would like to use the htmlpurifier not as a form data transformer, but rather as an annotation in the entities property.
The problem: In the Symfony 2.8 project we use a lot of different types of forms, some using symfonies formbuilder, some via sonata-admin, some using twig and ajax etc ..
So using a transformer and a custom field type is not the way to go.
Also, editing every single create or update action would be overkill.
I've been playing with the idea of an event listener on prePersist, but with such a large amount of different entities in our project we would most likely incur a performance hit if this were to be called on every persist() action. Limiting it to only specific object types would also be painstaking.
Is it possible to use the htmlpurifier bundle as an annotation only on the properties that matter?
eg:
/**
* #var string
*
* #ORM\Column(name="uprename", length=20, nullable=true)
* #htmlpurifier('default')
*/
private $firstName;
Where default would be the default configuration.
bundle: https://github.com/Exercise/HTMLPurifierBundle

Polymorphic attachments using a subset of the polymorphic relationship in doctrine 2

I need some help with doctrine 2 that uses "polymorphic associations". Let me clarify myself. Entitys can support file attachments using a subset of the polymorphic relationship. the File entity is used to safekeep this relationship where reference to the files are stored as records in the files table and have a polymorphic relation to the parent model. I want to create the same functionality as https://octobercms.com/docs/database/attachments
But do not know how to make the relationship, and how, for example, put the attachment_type dynamic like attachment_id;
/**
* #var \Doctrine\Common\Collections\ArrayCollection
*
* #ORM\OneToOne(targetEntity="App\Domain\FileAttachment\Entity\FileAttachment", attachment_type="news_thumbnail")
*/
private $thumbnail;
/**
* #var \Doctrine\Common\Collections\ArrayCollection
*
* #ORM\OneToOne(targetEntity="App\Domain\FileAttachment\Entity\FileAttachment", attachment_type="news_image")
*/
private $image;
/**
* #var \Doctrine\Common\Collections\ArrayCollection
*
* #ORM\OneToMany(targetEntity="App\Domain\FileAttachment\Entity\FileAttachment", attachment_type="news_files")
*/
private $files;
An example of the files table.
I have some experience in trying to make polymorphism work (including polymorphic files) in symfony and by this time I think I can share a few of my insights with you in hopes that they would provide you with some useful information about this subject.
Firstly, I would suggest reading up on inheritance mapping in doctrine link. With doctrine inheritance mapping you would simply create one main File class and then make every other attachment extend it. Then, say you want to add a picture attachment to the user. You would simply create a oneToOne relationship between the user and the main File class. If the attachment you persist would be an instance of one of the attachment classes, Doctrine is smart enough to return you an object of that class, not the main File class.
So to answer you question, I will give you a specific example. Case:
ImageAttachment extends FileAttachment
User has a property called photo
Property photo is a OneToOne relationship to the FileAttachment entity
Code:
$image = new ImageAttachment();
$user->setPhoto($image);
$em->persist($user);
$em->flush();
Result:
Now in the database in the User table, in a column called something like photo_id the referenced ID would be the one in the FileAttachment table. When you would do $user->getPhoto(); it would return an object of class ImageAttachment since doctrine knows that you have persisted an ImageAttachment, not just a FileAttachment.
When it comes to collections, things would also be pretty simple. In this case, you would probably need to create an ManyToMany relationship between the file and the entity that you want to relate to the file. Say that a user can have many different types of attachments saved in the database. If you want to use this filesystem application wide it would probably make no sense for a file to know about the user it belongs to, because soon file would have to hold information on all different types of the relationships and that is just not a smart architecture choice if you want to have any type of modular system in place. Thats why my suggestion is to use ManyToMany relationships between some entity and the attachments. This way only user would know about the files in the database and filesystem would be agnostic and decoupled.
A third important point to be made when talking about polymorphism in doctrine is symfony support for this feature. Generally polymorphism is considered to be somewhat of a bad practice in certain cases, and especially in data persistence does not have much support in the community. So an important thing to consider is that symfony CollectionType HAS NO SUPPORT FOR POLYMORPHISM what so ever. Basically you will have to write your own Type if you were planning on using polymorphic form collections. But if you don't mind using a bit of ajax, this is not really a problem, you can simply avoid using SF forms for this purpose alone.

Symfony Login form with existing user class

I'm trying to use (and understand) how Security works in Symfony. I've created a login form and it works with hard-coded users.
Now I want to use an existing user table in my database. The table has all the requiered fields but with different column names. The entity also exists, also with different names (for example "customUserId" instead of "id").
Something like (with "MAGIC_MAPPING"):
/**
* #ORM\Table(name="custom_user_table")
* #ORM\Entity
*/
class User implements UserInterface, \Serializable
{
/**
* #ORM\Column(name="customUserId", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
* #MAGIC_MAPPING so it links this to the mandatory "id" field
*/
private $customUserId;
...
}
Is there a way to map my existing fields so Symfony uses them for login purpose? Or at least can I make it work without changing my database structure (only the entity class)?
I've tried seleveral actions, from this forum and from Symfony documentation, but it always ends with ugly error I can't fix.
Any idea or lead? Thanks a lot for your help, I've been struggling on this for several hours now...
You have to change the providers configuration inside the security.yml file
here is an example, i use the email field from my administrator entity, I think you can do the same with your entity
providers:
administrator:
entity: { class: Entity:Administrator, property: email }
Try changing the ORM file of that table.
create an ORM file using Command promt.
then edit the orm file .
<mapped-superclass name="FOS\UserBundle\Entity\User" table="your_table_name">
/.../
</mapped>
Benoît 's answer help me figure it out. I gave too much attention to Symfony documentation's creation process that I forgot the essential: the UserInterface. No need to map anything, just implement this interface and defined methods like:
public function getUsername() {
return $this->customLogin;
}
Then update the provider configuration (thanks Benoit):
providers:
db_sam_provider:
entity:
class: AppBundle:User
property: customLogin
The other parts are conform to Symfony documentation: here and here

symfony route annotation requirements constraints

Here is the simple symfony Route:
/**
* #Route("/test/{param}", requirements={"param": "(one|two)"})
*/
But how can I set dynamic requirements from the array or entity feature like:
/**
* #Route("/test/{param}", requirements={"param": "array or entity"})
*/
p.s. the problem appears about the same Routes like /products/{vendors} and /products/{models}. I want to catch valid route by the requirements of the route.
thanks in advance)
You cannot do that with requirements as they are just regular expressions, so they cannot detect things like the type of the parameter. In fact I believe there is no way to achieve what you want to do: how would you "send" an entity or an array in a URL? If you are using parameter converters, then the requirements should refer to the original, not converted, URL
I beleive next annotation will work:
/**
* #Route("/test/{param}", requirements={"param" = "one|two"})
*/

Resources