From e445ceb9bb86a66a30187111185e86b0dada14ad Mon Sep 17 00:00:00 2001 From: tuj Date: Mon, 20 May 2019 13:25:05 +0200 Subject: [PATCH] Add support for screen-bundle (#10) --- CHANGELOG.md | 4 + DependencyInjection/Configuration.php | 5 + .../Os2DisplayCoreExtension.php | 8 + Entity/Screen.php | 6 +- Events/PrePushScreenSerializationEvent.php | 41 +++ Resources/config/services.yml | 10 + Services/MiddlewareService.php | 237 ++++++++++++++++++ 7 files changed, 308 insertions(+), 3 deletions(-) create mode 100644 Events/PrePushScreenSerializationEvent.php create mode 100644 Services/MiddlewareService.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 89f9114..344b9ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Os2Display/CoreBundle CHANGELOG +## 2.1.0 + +* Added support for screen-bundle. + ## 2.0.0 * Symfony 3.4 upgrade. diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index dc74403..5ee810b 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -24,6 +24,11 @@ public function getConfigTreeBuilder() // configure your bundle. See the documentation linked above for // more information on that topic. + $rootNode + ->children() + ->integerNode('cache_ttl')->end() + ->end(); + return $treeBuilder; } } diff --git a/DependencyInjection/Os2DisplayCoreExtension.php b/DependencyInjection/Os2DisplayCoreExtension.php index 7a4c8c0..8c91381 100644 --- a/DependencyInjection/Os2DisplayCoreExtension.php +++ b/DependencyInjection/Os2DisplayCoreExtension.php @@ -19,5 +19,13 @@ public function load(array $configs, ContainerBuilder $container) { $this->dir = __DIR__; parent::load($configs, $container); + + $configuration = new Configuration(); + $config = $this->processConfiguration($configuration, $configs); + $def = $container->getDefinition('os2display.middleware.service'); + + if (isset($config['cache_ttl'])) { + $def->replaceArgument(3, $config['cache_ttl']); + } } } diff --git a/Entity/Screen.php b/Entity/Screen.php index b391f6c..ceb6afe 100644 --- a/Entity/Screen.php +++ b/Entity/Screen.php @@ -27,13 +27,13 @@ class Screen extends ApiEntity implements GroupableEntity * @ORM\Column(type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") - * @Groups({"api", "api-bulk", "search", "screen", "timeline-screen", "campaign"}) + * @Groups({"api", "api-bulk", "search", "screen", "timeline-screen", "campaign", "middleware"}) */ private $id; /** * @ORM\Column(name="title", type="text", nullable=false) - * @Groups({"api", "api-bulk", "search", "screen", "timeline-screen", "campaign"}) + * @Groups({"api", "api-bulk", "search", "screen", "timeline-screen", "campaign", "middleware"}) */ private $title; @@ -76,7 +76,7 @@ class Screen extends ApiEntity implements GroupableEntity /** * @ORM\ManyToOne(targetEntity="ScreenTemplate", inversedBy="screens") - * @Groups({"api", "api-bulk", "screen"}) + * @Groups({"api", "api-bulk", "screen", "middleware"}) */ private $template; diff --git a/Events/PrePushScreenSerializationEvent.php b/Events/PrePushScreenSerializationEvent.php new file mode 100644 index 0000000..578e57b --- /dev/null +++ b/Events/PrePushScreenSerializationEvent.php @@ -0,0 +1,41 @@ +screenObject = $screenObject; + } + + public function getScreenObject() + { + return $this->screenObject; + } + + public function setScreenObject(\stdClass $screenObject) + { + $this->screenObject = $screenObject; + } +} diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 4e3e3c4..415454f 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -2,6 +2,11 @@ parameters: router.options.generator_base_class: Os2Display\CoreBundle\Routing\HashtagDecodedUrlGenerator services: + os2display.core.cache: + class: Doctrine\Common\Cache\FilesystemCache + arguments: ['%kernel.cache_dir%'] + public: true + os2display.listener: class: Os2Display\CoreBundle\EventListener\SearchIndexer arguments: ['@jms_serializer', '@service_container', '@os2display.utility_service'] @@ -135,3 +140,8 @@ services: arguments: ['sonata.media.provider.zencoder', '@sonata.media.filesystem.local', '@sonata.media.cdn.server', '@sonata.media.generator.default', '@sonata.media.thumbnail.format', '%absolute_path_to_server%', '%zencoder_api%', '@logger'] calls: - [setTemplates, [{ helper_thumbnail: 'SonataMediaBundle:Provider:thumbnail.html.twig', helper_view: 'SonataMediaBundle:Provider:view_video.html.twig' }]] + + os2display.middleware.service: + class: Os2Display\CoreBundle\Services\MiddlewareService + arguments: ['@doctrine.orm.entity_manager', '@jms_serializer', '@os2display.core.cache', 300, '@event_dispatcher'] + public: true diff --git a/Services/MiddlewareService.php b/Services/MiddlewareService.php new file mode 100644 index 0000000..bae2f55 --- /dev/null +++ b/Services/MiddlewareService.php @@ -0,0 +1,237 @@ +entityManager = $entityManager; + $this->serializer = $serializer; + $this->channelRepository = $entityManager->getRepository( + Channel::class + ); + $this->sharedChannelRepository = $entityManager->getRepository(SharedChannel::class); + $this->screenRepository = $entityManager->getRepository(Screen::class); + $this->cache = $cache; + $this->cacheTTL = $cacheTTL; + $this->dispatcher = $dispatcher; + } + + /** + * Get screen as an array. + * + * @param $screen + * @return mixed|string + */ + public function getScreenArray($screen) + { + $data = $this->serializer->serialize( + $screen, + 'json', + SerializationContext::create() + ->setGroups(array('middleware')) + ); + + $data = json_decode($data); + + return $data; + } + + /** + * Get channel as an array. + * + * @param $channel + * @return mixed|string + */ + public function getChannelArray($channel) + { + $data = $this->serializer->serialize( + $channel, + 'json', + SerializationContext::create() + ->setGroups(array('middleware')) + ); + + $data = json_decode($data); + + return $data; + } + + /** + * Get shared channel as an array. + * + * @param $channel + * @return mixed|string + */ + public function getSharedChannelArray($channel) + { + $data = $this->serializer->serialize( + $channel, + 'json', + SerializationContext::create() + ->setGroups(array('middleware')) + ); + + $data = json_decode($data); + + return $data; + } + + /** + * Get a fake screen array of 'full-screen' screen template, where + * channel is inserted in region 1. + * + * @param $channelId + * @return false|mixed|object + */ + public function getCurrentChannelArray($channelId) { + $cachedResult = $this->cache->fetch('os2display.core.channel.' . $channelId); + + if ($cachedResult != false) { + return $cachedResult; + } + + $channelRepository = $this->entityManager->getRepository(Channel::class); + + $channel = $channelRepository->findOneById($channelId); + $channelArray = $this->getChannelArray($channel); + + $channelArray->regions = [1]; + + // Use full-screen screen template. + $templateRepository = $this->entityManager->getRepository(ScreenTemplate::class); + $templateArray = json_decode($this->serializer->serialize( + $templateRepository->findOneById('full-screen'), + 'json', + SerializationContext::create() + ->setGroups(array('middleware')) + )); + + $result = (object)[ + 'channels' => [$channelArray], + 'screen' => [ + 'id' => 1, + 'title' => 'channel-public', + 'options' => [], + 'template' => $templateArray, + ], + ]; + + return $result; + } + + /** + * @param $screenId + * @return false|mixed|object + */ + public function getCurrentScreenArray($screenId) + { + $cachedResult = $this->cache->fetch('os2display.core.screen.' . $screenId); + + if ($cachedResult != false) { + return $cachedResult; + } + + $screenRepository = $this->entityManager->getRepository(Screen::class); + + $screen = $screenRepository->findOneById($screenId); + $screenArray = $this->getScreenArray($screen); + + $result = (object)[ + 'channels' => [], + 'screen' => $screenArray, + ]; + + // Build result object. + foreach ($screen->getChannelScreenRegions() as $channelScreenRegion) { + $channel = $channelScreenRegion->getChannel(); + $region = $channelScreenRegion->getRegion(); + $channelId = null; + $data = null; + $isSharedChannel = false; + + if (!is_null($channel)) { + $channelId = $channel->getId(); + } else { + // Handle shared channels. + $channel = $channelScreenRegion->getSharedChannel(); + $channelId = $channel->getUniqueId(); + $isSharedChannel = true; + } + + if (!isset($result->channels[$channelId])) { + $result->channels[$channelId] = (object)[ + 'regions' => [$region], + ]; + } else { + $result->channels[$channelId]->regions[] = $region; + } + + $result->channels[$channelId]->isSharedChannel = $isSharedChannel; + } + + // Send event to let other processes affect which channels are shown in + // the different regions of the screen. This is to allow e.g. campaigns + // to affect which channels are shown. + $event = new PrePushScreenSerializationEvent($result); + $this->dispatcher->dispatch(PrePushScreenSerializationEvent::NAME, $event); + $result = $event->getScreenObject(); + + // Serialize the channels in the region array. + foreach ($result->channels as $channelId => $channelObject) { + if (isset($channelObject->isSharedChannel) && $channelObject->isSharedChannel) { + $channel = $this->sharedChannelRepository->findOneByUniqueId($channelId); + $serializedChannel = $this->getSharedChannelArray($channel); + $serializedChannel->data->slides = json_decode($serializedChannel->data->slides); + } + else { + $channel = $this->channelRepository->findOneById($channelId); + $serializedChannel = $this->getChannelArray($channel); + } + + $channelObject->data = $serializedChannel->data; + + $channelObject->hash = sha1( + json_encode($result->channels[$channelId]) + ); + } + + // Cache and return results. + $this->cache->save('os2display.core.screen.' . $screenId, $result, $this->cacheTTL); + + return $result; + } +}