<?php
namespace Cms\Modules\GalleryBundle\Form\Type\Gallery;
use Cms\ContainerBundle\Entity\Container;
use Cms\ContainerBundle\Entity\Containers\GenericContainer;
use Cms\ContainerBundle\Entity\Containers\IntranetContainer;
use Cms\ContainerBundle\Entity\Containers\PersonalContainer;
use Cms\ContainerBundle\Service\ContainerService;
use Cms\CoreBundle\Form\Type\DateTimeType;
use Cms\CoreBundle\Form\Type\HtmlType;
use Cms\CoreBundle\Form\Type\SlugType;
use Cms\CoreBundle\Model\Url;
use Cms\CoreBundle\Service\Transcoding\Transcoder;
use Cms\CoreBundle\Util\Doctrine\EntityManager;
use Cms\DomainBundle\Entity\Domain;
use Cms\FileBundle\Entity\Nodes\File;
use Cms\FileBundle\Entity\Nodes\Folder;
use Cms\FileBundle\Form\Type\FileModalType;
use Cms\ModuleBundle\Form\StandardMetadataType;
use Cms\ModuleBundle\Form\Type\AbstractModuleDataType;
use Cms\ModuleBundle\Validator\Constraints\ModuleReservedSlugs;
use Cms\ModuleBundle\Validator\Constraints\ModuleSlug;
use Cms\Modules\GalleryBundle\Form\Type\GalleryEditorType;
use Cms\Modules\GalleryBundle\Model\Gallery\GalleryData;
use Cms\Modules\GalleryBundle\Model\GalleryEntry;
use Cms\TagBundle\Form\Type\TaggableType;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Validator\Constraints\NotBlank;
/**
* Class GalleryDataType
* @package Cms\Modules\GalleryBundle\Form\Type\Gallery
*/
final class GalleryDataType extends AbstractModuleDataType
{
/**
* @var ParameterBagInterface
*/
private ParameterBagInterface $params;
/**
* @var EntityManager
*/
private EntityManager $em;
/**
* @var ContainerService
*/
private ContainerService $containerService;
/**
* @param ParameterBagInterface $params
* @param EntityManager $em
* @param ContainerService $containerService
*/
public function __construct(
ParameterBagInterface $params,
EntityManager $em,
ContainerService $containerService
)
{
$this->params = $params;
$this->em = $em;
$this->containerService = $containerService;
}
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options): void
{
/** @var Container $container */
$container = $options['container'];
$builder
->add('title', TextType::class, array(
'constraints' => array(
new NotBlank(),
),
))
->add('slug', SlugType::class, array(
'dependency' => array('title'),
'helpText' => 'Attention! Changing the URL can cause broken links across your site. Proceed with caution.',
'constraints' => array(
new ModuleSlug(),
new ModuleReservedSlugs(),
),
'slugPrefix' => sprintf(
'%s/gallery/{id}/',
rtrim($this->containerService->getFrontPath($container), '/')
),
))
->add('timestamp', DateTimeType::class, array(
'constraints' => array(
new NotBlank(),
),
))
// not showing image field as this is set via featured setting in gallery items
->add('abstract', TextareaType::class, array(
'label' => 'Teaser',
))
->add('description', HtmlType::class, array(
'baseHref' => $this->containerService->getFrontLink($container),
))
->add('tags', TaggableType::class, [])
->add('entries', GalleryEditorType::class, array(
'modalParams' => array(
'containerId' => $container->getId()
),
'wscCustomerId' => $this->params->get('wsc.customer_id'),
'baseHref' => $this->containerService->getFrontLink($container),
))
->add('standardMetadata', StandardMetadataType::class, [])
->add('socialImage', FileModalType::class, array(
'container' => $container->getId(),
))
->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($container, $options) {
/** @var GalleryData $data */
$data = $event->getForm()->getData();
$entries = Transcoder::fromStorage($data->getEntries());
$featured = null;
/** @var GalleryEntry $entry */
foreach ($entries as $entry) {
if ($entry->getFeatured() === true) {
$featured = $entry;
break;
}
}
if ( ! $featured && count($entries) > 0) {
$featured = $entries[0];
}
$file = null;
if ( ! empty($featured) && ! empty($featured->getMedia())) {
try {
$file = $this->fileUrlToEntity($featured, $container, $options);
} catch (\Exception $e) {
// NOOP
}
}
$data->setImage($file);
}
)
;
}
private function fileUrlToEntity(GalleryEntry $entry, Container $rootContainer)
{
// TODO: SYMFONY: fix this?
$url = Url::factory($entry->getMedia());
$value = $url->getPath();
$hostname = $url->getHost();
if (preg_match('/^(.*?)\\/files\\/(.+)/', $value, $matches) !== 1) {
throw new \RuntimeException();
}
$containers = array_values(array_filter(explode('/', $matches[1])));
// handle intranet requests
switch (true) {
case (count($containers) > 0 && strpos($containers[0], '~') === 0):
$site = $this->em->getRepository(IntranetContainer::class)->findOneBy(array(
'parent' => null,
'slug' => ltrim($containers[0], '~'),
));
$containers = array_slice($containers, 1);
break;
case empty($hostname):
$cntr = null;
switch (true) {
case $rootContainer instanceof GenericContainer:
case $rootContainer instanceof IntranetContainer:
$cntr = $rootContainer;
break;
case $rootContainer instanceof PersonalContainer:
$cntr = $rootContainer->getContainer();
break;
default:
throw new \RuntimeException();
}
while ($cntr->getParent()) {
$cntr = $cntr->getParent();
}
$site = $cntr;
break;
default:
$fixedhost = preg_replace('/^https?:\\/\\/([^\\/]+).*$/', '$1', $hostname);
if (preg_match('/^([-a-zA-Z0-9]+)\\.([-a-zA-Z0-9]+)\\.campussuite\\.site$/', $fixedhost, $hostmatches) === 1) {
$site = $this->em->getRepository(GenericContainer::class)->findOneBy(array(
'parent' => null,
'slug' => $hostmatches[1],
));
} else {
$domain = $this->em->getRepository(Domain::class)->findOneByHost(
$fixedhost
);
$site = $this->em->getRepository(GenericContainer::class)->findOneByDomain(
$domain
);
}
}
$container = $site;
foreach ($containers as $slug) {
$container = $this->em->getRepository(Container::class)->findOneBy(array(
'parent' => $container,
'slug' => urldecode($slug),
));
if (empty($container)) {
throw new \RuntimeException();
}
}
$folders = array_values(array_filter(explode('/', $matches[2])));
$fileparts = [];
if (preg_match('/(.*)\\.([a-zA-Z0-9]+)(?:[?].*)?$/', array_pop($folders), $fileparts) !== 1) {
throw new \RuntimeException();
}
$folder = null;
foreach ($folders as $name) {
$folder = $this->em->getRepository(Folder::class)->findOneBy(array(
'container' => $container,
'parent' => $folder,
'name' => urldecode($name),
));
if (empty($folder)) {
throw new \RuntimeException();
}
}
$file = $this->em->getRepository(File::class)->findOneBy(array(
'parent' => $folder,
'name' => urldecode($fileparts[1]),
'extension' => urldecode($fileparts[2]),
));
if (empty($file)) {
throw new \RuntimeException();
}
return $file;
}
}