-
-
Save pleone/f15682baa86781ba90fb to your computer and use it in GitHub Desktop.
Sonata admin embedded form with image preview
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Acme\CoreBundle\Entity; | |
use Doctrine\ORM\Mapping as ORM; | |
use Symfony\Component\HttpFoundation\File\File; | |
use Symfony\Component\Validator\Constraints as Assert; | |
use Vich\UploaderBundle\Mapping\Annotation as Vich; | |
use Gedmo\Mapping\Annotation as Gedmo; | |
use Doctrine\Common\Collections\ArrayCollection; | |
use JMS\Serializer\Annotation as Serializer; | |
/** | |
* News | |
* | |
* @ORM\Table( name="news", indexes={ @ORM\Index(name="idxyear", columns={"year"}), @ORM\Index(name="idxcategory", columns={"category_id"}) } ) | |
* @ORM\Entity(repositoryClass="Acme\CoreBundle\Repository\NewsRepository") | |
* @Gedmo\TranslationEntity(class="Acme\CoreBundle\Entity\NewsTranslation") | |
* @Vich\Uploadable | |
* @Serializer\ExclusionPolicy("all") | |
*/ | |
class News | |
{ | |
/** | |
* @var integer | |
* | |
* @ORM\Column(name="id", type="integer") | |
* @ORM\Id | |
* @ORM\GeneratedValue(strategy="AUTO") | |
* @Serializer\Expose | |
* @Serializer\Groups({"list","details"}) | |
*/ | |
private $id; | |
/** | |
* @Assert\File( | |
* maxSize="2M", | |
* mimeTypes={"image/png", "image/jpeg", "image/pjpeg"} | |
* ) | |
* @Vich\UploadableField(mapping="news_image", fileNameProperty="visual") | |
* | |
* @var File $image | |
*/ | |
private $image; | |
/** | |
* @Assert\File( | |
* maxSize="2M", | |
* mimeTypes={"image/png", "image/jpeg", "image/pjpeg"} | |
* ) | |
* @Vich\UploadableField(mapping="news_image", fileNameProperty="listingImage") | |
* | |
* @var File $image | |
*/ | |
private $smallimage; | |
/** | |
* @var string | |
* | |
* @ORM\Column(name="visual", type="string", length=255) | |
*/ | |
private $visual; | |
/** | |
* @var string | |
* | |
* @ORM\Column(name="listingImage", type="string", length=255, nullable=true) | |
*/ | |
private $listingImage; | |
/** | |
* @var string | |
* @Gedmo\Translatable | |
* @ORM\Column(name="title", type="string", length=255,nullable=true) | |
* @Serializer\Expose | |
* @Serializer\Groups({"list","details"}) | |
*/ | |
private $title; | |
/** | |
* @var string | |
* @Gedmo\Translatable | |
* @ORM\Column(name="subtitle", type="string", length=255, nullable=true) | |
* @Serializer\Expose | |
* @Serializer\Groups({"list","details"}) | |
*/ | |
private $subtitle; | |
/** | |
* @var string | |
* @Gedmo\Translatable | |
* @ORM\Column(name="body", type="text",nullable=true) | |
* @Serializer\Expose | |
* @Serializer\Groups({"details"}) | |
*/ | |
private $body; | |
/** | |
* @var boolean | |
* | |
* @ORM\Column(name="homepage", type="boolean", nullable=true) | |
*/ | |
private $homepage; | |
/** | |
* @var \DateTime | |
* | |
* @ORM\Column(name="publishDate", type="datetime", nullable=true) | |
* @Serializer\Expose | |
* @Serializer\Groups({"list","details"}) | |
*/ | |
private $publishDate; | |
/** | |
* @var datetime $created | |
* | |
* @Gedmo\Timestampable(on="create") | |
* @ORM\Column(type="datetime") | |
*/ | |
private $created; | |
/** | |
* @var datetime $updated | |
* | |
* @Gedmo\Timestampable(on="update") | |
* @ORM\Column(type="datetime") | |
*/ | |
private $updated; | |
/** | |
* @ORM\OneToMany( | |
* targetEntity="NewsTranslation", | |
* mappedBy="object", | |
* cascade={"persist", "remove"} | |
* ) | |
*/ | |
private $translations; | |
/** | |
* @Gedmo\Translatable | |
* @Gedmo\Slug(fields={"title"}) | |
* @ORM\Column(length=128) | |
* @Serializer\Expose | |
* @Serializer\Groups({"list","details"}) | |
* | |
*/ | |
private $slug; | |
/** | |
* @var integer | |
* | |
* @ORM\Column(name="category_id", type="integer", nullable=true) | |
* @Serializer\Expose | |
* @Serializer\Groups({"list","details"}) | |
*/ | |
private $category; | |
/** | |
* @ORM\OneToMany( | |
* targetEntity="NewsSlider", | |
* mappedBy="news", | |
* orphanRemoval=true, | |
* cascade={"persist", "remove"} | |
* ) | |
* @ORM\OrderBy({"rank" = "ASC"}) | |
* | |
* orphanRemoval=true is necessary to allow the delete option in sonata | |
* The order by is a nice feature to have the slider image ordered by rank in sonata too | |
*/ | |
private $slider; | |
/** | |
* Constructor | |
*/ | |
public function __construct() | |
{ | |
$this->translations = new \Doctrine\Common\Collections\ArrayCollection(); | |
} | |
/** | |
* ... getters / setters | |
*/ | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Acme\AdminBundle\Admin; | |
use Gedmo\Sluggable\Util\Urlizer; | |
use Sonata\AdminBundle\Admin\Admin; | |
use Sonata\AdminBundle\Datagrid\ListMapper; | |
use Sonata\AdminBundle\Datagrid\DatagridMapper; | |
use Sonata\AdminBundle\Form\FormMapper; | |
use Acme\CoreBundle\Entity\NewsTranslation; | |
class NewsAdmin extends Admin | |
{ | |
protected $categories; | |
// Fields to be shown on create/edit forms | |
protected function configureFormFields(FormMapper $formMapper) | |
{ | |
$visual = $images->getVisual(); | |
// use $fileFieldOptions so we can add other options to the field | |
$fileFieldOptionsVisual = array('required' => false, 'help' => '<p>Dimensioni immagine: 1600px x 900px. </p>'); | |
if ($visual && ($webPath = $images->getWebPath())) { | |
// get the container so the full path to the image can be set | |
$container = $this->getConfigurationPool()->getContainer(); | |
$fullPath = $container->get('request')->getBasePath().'/'.$webPath.$visual; | |
// add a 'help' option containing the preview's img tag | |
$fileFieldOptionsVisual['help'] = '<p>Dimensioni: 1600px x 900px</p> <img src="'.$fullPath.'" class="admin-preview" style="max-height: 200px; max-width: 200px;" />'; | |
} | |
$formMapper | |
->add('category', 'choice', array( | |
'label' => 'Categoria', | |
'required' => false, | |
'choices' => $this->categories, | |
)) | |
->add('publishDate', 'datetime', array('label' => 'Data pubblicazione', 'required' => true)) | |
->add('title', null, array('label' => 'Titolo', 'required' => true)) | |
->add('subtitle', null, array('label' => 'Sottotitolo', 'required' => false)) | |
->add('slug', null, array('required' => false, 'help' => 'Se vuoto è autogenerato')) | |
->add('body', null, array( | |
'label' => 'Body', | |
'required' => false, | |
'attr' => array( | |
'class' => 'tinymce', | |
'style' => 'width:70%; height:250px', | |
) | |
)) | |
->add('homepage', 'checkbox', array("label" => "Show in homepage", "required" => false)) | |
->end() | |
->with('Immagini') | |
->add('image', 'file', $fileFieldOptionsVisual) | |
->end() | |
->with('Traduzioni') | |
->add('translations', 'a2lix_translations_gedmo', array( | |
'required' => true, | |
'translatable_class' => "Acme\CoreBundle\Entity\News")) | |
//http://a2lix.fr/bundles/translation-form/1.4.html | |
->add('translations', 'a2lix_translations_gedmo', array( | |
'required' => true, // [2] | |
'fields' => array( // [3] | |
'body' => array( // [3.a] | |
//'field_type' => 'ckeditor', // [4] | |
//'label' => 'Body', | |
//'config_name' => 'my_config', | |
) | |
) | |
)) | |
->end() | |
->with('Slider') | |
->add('slider', 'sonata_type_collection', array( | |
'by_reference' => true, | |
'type_options' => array('delete' => true), | |
), array( | |
'edit' => 'inline', | |
//'inline' => 'table', | |
//'sortable' => 'rank', | |
)) | |
->end() | |
; | |
} | |
// Fields to be shown on filter forms | |
protected function configureDatagridFilters(DatagridMapper $datagridMapper) | |
{ | |
$datagridMapper | |
->add('title') | |
->add('subtitle') | |
; | |
} | |
// Fields to be shown on lists | |
protected function configureListFields(ListMapper $listMapper) | |
{ | |
$listMapper | |
->addIdentifier('title') | |
->add('subtitle') | |
->add('slug') | |
//->add('image', 'image', array('label' => 'Immagine')) | |
->add('_action', 'actions', array( | |
'actions' => array( | |
'delete' => array('template' => 'AcmeAdminBundle:Admin:_delete.html.twig'), | |
'edit' => array('template' => 'AcmeAdminBundle:Admin:_edit.html.twig'), | |
))) | |
; | |
} | |
public function prePersist($obj) { | |
$this->manageFileUpload($obj); | |
$obj->setSlug($this->urlify($obj->getTitle())); | |
$this->manageTranslationSlug($obj); | |
foreach ($obj->getSlider() as $slide) { | |
$slide->setNews($obj); | |
} | |
$this->manageEmbeddedImageAdmins($obj); | |
} | |
public function preUpdate($obj) { | |
$translations= $obj->getTranslations(); | |
foreach($translations as $word){ | |
if($word->getField() == "title" && $word->getLocale() == "it"){ | |
$title = $word->getContent(); | |
} | |
} | |
$this->manageFileUpload($obj); | |
$this->manageTranslationSlug($obj); | |
//$obj->setSlug($this->urlify($title)); | |
foreach ($obj->getSlider() as $slide) { | |
$slide->setNews($obj); | |
} | |
$this->manageEmbeddedImageAdmins($obj); | |
} | |
private function manageTranslationSlug($obj) { | |
$titles = array(); | |
$slugs = array(); | |
$translations= $obj->getTranslations(); | |
foreach($translations as $word){ | |
if($word->getField() == "title"){ | |
if (!$word->getContent()) { | |
$word->setContent( $obj->getTitle() ); | |
} | |
$titles[ $word->getLocale() ] = $word->getContent(); | |
} | |
if($word->getField() == "slug"){ | |
$slugs[ $word->getLocale() ] = $word->getContent(); | |
if (!$word->getContent()) { | |
$word->setContent( Urlizer::urlize($titles[$word->getLocale()]) ); | |
} | |
} | |
} | |
} | |
private function manageFileUpload($image) { | |
if ($image->getImage()) { | |
$image->setUpdated(new \DateTime('now')); | |
} | |
} | |
private function urlify($string){ | |
return Urlizer::urlize($string); | |
} | |
public function setCategories($categories) | |
{ | |
$this->categories = $categories; | |
} | |
// https://github.com/sonata-project/SonataAdminBundle/blob/master/Resources/doc/cookbook/recipe_file_uploads.rst | |
// http://stackoverflow.com/questions/19439696/sonata-admin-collection-with-sort-and-delete | |
private function manageEmbeddedImageAdmins($news) { | |
// Cycle through each field | |
foreach ($this->getFormFieldDescriptions() as $fieldName => $fieldDescription) { | |
// detect embedded Admins that manage Images | |
if ($fieldDescription->getType() === 'sonata_type_collection' && | |
($associationMapping = $fieldDescription->getAssociationMapping()) && | |
$associationMapping['targetEntity'] === 'Acme\CoreBundle\Entity\NewsSlider' | |
) { | |
$getter = 'get' . $fieldName; | |
$setter = 'set' . ucfirst($fieldName); | |
/** @var Image $image */ | |
$images = $news->$getter(); | |
foreach($images as $image ){ | |
if ($image) { | |
if ($image->getImage()) { | |
// update the Image to trigger file management | |
$image->refreshUpdated(); | |
} elseif (!$image->getImage() ) { | |
// prevent Sf/Sonata trying to create and persist an empty Image | |
//$news->removeSlider($image); | |
$news->$setter(null); | |
} | |
} | |
} | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Acme\CoreBundle\Entity; | |
use Doctrine\ORM\Mapping as ORM; | |
use Symfony\Component\HttpFoundation\File\File; | |
use Symfony\Component\Validator\Constraints as Assert; | |
use Vich\UploaderBundle\Mapping\Annotation as Vich; | |
use Gedmo\Mapping\Annotation as Gedmo; | |
use Doctrine\Common\Collections\ArrayCollection; | |
use JMS\Serializer\Annotation as Serializer; | |
/** | |
* NewsSlider | |
* | |
* @ORM\Table() | |
* @Vich\Uploadable | |
* @ORM\Entity(repositoryClass="Acme\CoreBundle\Entity\NewsSliderRepository") | |
*/ | |
class NewsSlider extends EntityWithImage | |
{ | |
protected $upload_dir = 'news'; | |
/** | |
* @var integer | |
* | |
* @ORM\Column(name="id", type="integer") | |
* @ORM\Id | |
* @ORM\GeneratedValue(strategy="AUTO") | |
*/ | |
private $id; | |
/** | |
* @Assert\File( | |
* maxSize="2M", | |
* mimeTypes={"image/png", "image/jpeg", "image/pjpeg"} | |
* ) | |
* @Vich\UploadableField(mapping="news_slider_image", fileNameProperty="imageName") | |
* | |
* @var File $image | |
*/ | |
private $image; | |
/** | |
* @ORM\Column(type="string", length=255, name="image_name", nullable=true) | |
* | |
* @var string $imageName | |
*/ | |
protected $imageName; | |
/** | |
* @var integer | |
* | |
* @ORM\Column(name="rank", type="integer", nullable=true) | |
*/ | |
private $rank; | |
/** | |
* @var string | |
* | |
* @ORM\Column(name="title", type="string", length=255, nullable=true) | |
*/ | |
private $title; | |
/** | |
* @var string | |
* | |
* @ORM\Column(name="description", type="string", length=255, nullable=true) | |
*/ | |
private $description; | |
/** | |
* @ORM\ManyToOne(targetEntity="News", inversedBy="slider") | |
* @ORM\JoinColumn(name="news_id", referencedColumnName="id", onDelete="CASCADE", nullable=true) | |
* @Serializer\Expose | |
* @Serializer\Groups({"list","details"}) | |
*/ | |
protected $news; | |
/** | |
* @var datetime $created | |
* | |
* @Gedmo\Timestampable(on="create") | |
* @ORM\Column(type="datetime") | |
*/ | |
private $created; | |
/** | |
* @var datetime $updated | |
* | |
* @Gedmo\Timestampable(on="update") | |
* @ORM\Column(type="datetime") | |
*/ | |
private $updated; | |
/** | |
* getters/setters | |
*/ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment