src/Pumukit/NewAdminBundle/Twig/PumukitAdminExtension.php line 183

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Pumukit\NewAdminBundle\Twig;
  4. use Doctrine\ODM\MongoDB\DocumentManager;
  5. use MongoDB\BSON\ObjectId;
  6. use Pumukit\EncoderBundle\Services\ProfileService;
  7. use Pumukit\EncoderBundle\Services\Repository\JobRepository;
  8. use Pumukit\NewAdminBundle\Form\Type\Base\CustomLanguageType;
  9. use Pumukit\SchemaBundle\Document\EmbeddedBroadcast;
  10. use Pumukit\SchemaBundle\Document\MultimediaObject;
  11. use Pumukit\SchemaBundle\Document\Role;
  12. use Pumukit\SchemaBundle\Document\Series;
  13. use Pumukit\SchemaBundle\Document\User;
  14. use Pumukit\SchemaBundle\Document\ValueObject\Tags;
  15. use Pumukit\SchemaBundle\Services\EmbeddedEventSessionService;
  16. use Pumukit\SchemaBundle\Services\MultimediaObjectService;
  17. use Pumukit\SchemaBundle\Services\SpecialTranslationService;
  18. use Pumukit\WebTVBundle\PumukitWebTVBundle;
  19. use Symfony\Component\Intl\Languages;
  20. use Symfony\Component\Routing\RouterInterface;
  21. use Symfony\Contracts\Translation\TranslatorInterface;
  22. use Twig\Environment;
  23. use Twig\Extension\AbstractExtension;
  24. use Twig\TwigFilter;
  25. use Twig\TwigFunction;
  26. class PumukitAdminExtension extends AbstractExtension
  27. {
  28.     private $dm;
  29.     private $languages;
  30.     private $profileService;
  31.     private $translator;
  32.     private $router;
  33.     private $countMmobjsByStatus;
  34.     private $countMmobjsWithTag;
  35.     private $mmobjService;
  36.     private $specialTranslationService;
  37.     private $eventService;
  38.     private $enablePlaylist;
  39.     private JobRepository $jobRepository;
  40.     public function __construct(ProfileService $profileServiceDocumentManager $documentManagerTranslatorInterface $translatorRouterInterface $routerMultimediaObjectService $mmobjServiceSpecialTranslationService $specialTranslationServiceEmbeddedEventSessionService $eventServiceJobRepository $jobRepository$enablePlaylist)
  41.     {
  42.         $this->dm $documentManager;
  43.         $this->languages Languages::getNames();
  44.         $this->profileService $profileService;
  45.         $this->translator $translator;
  46.         $this->router $router;
  47.         $this->mmobjService $mmobjService;
  48.         $this->specialTranslationService $specialTranslationService;
  49.         $this->eventService $eventService;
  50.         $this->jobRepository $jobRepository;
  51.         $this->enablePlaylist $enablePlaylist;
  52.     }
  53.     public function getFilters(): array
  54.     {
  55.         return [
  56.             new TwigFilter('basename', [$this'getBasename']),
  57.             new TwigFilter('profile', [$this'getProfile']),
  58.             new TwigFilter('display', [$this'getDisplay']),
  59.             new TwigFilter('duration_string', [$this'getDurationString']),
  60.             new TwigFilter('language_name_custom', [$this'getLanguageName']),
  61.             new TwigFilter('status_icon', [$this'getStatusIcon']),
  62.             new TwigFilter('status_text', [$this'getStatusText']),
  63.             new TwigFilter('series_icon', [$this'getSeriesIcon']),
  64.             new TwigFilter('series_text', [$this'getSeriesText']),
  65.             new TwigFilter('profile_width', [$this'getProfileWidth']),
  66.             new TwigFilter('profile_height', [$this'getProfileHeight']),
  67.             new TwigFilter('series_announce_icon', [$this'getSeriesAnnounceIcon']),
  68.             new TwigFilter('series_announce_text', [$this'getSeriesAnnounceText']),
  69.             new TwigFilter('mms_announce_icon', [$this'getMmsAnnounceIcon']),
  70.             new TwigFilter('mms_announce_text', [$this'getMmsAnnounceText']),
  71.             new TwigFilter('filter_profiles', [$this'filterProfiles']),
  72.             new TwigFilter('count_multimedia_objects', [$this'countMultimediaObjects']),
  73.             new TwigFilter('count_events', [$this'countEvents']),
  74.             new TwigFilter('next_session_event', [$this'getNextEventSession']),
  75.             new TwigFilter('unescape', [$this'unescapeLabel']),
  76.         ];
  77.     }
  78.     public function getFunctions(): array
  79.     {
  80.         return [
  81.             new TwigFunction('php_upload_max_filesize', [$this'getPhpUploadMaxFileSize']),
  82.             new TwigFunction('path_exists', [$this'existsRoute']),
  83.             new TwigFunction('is_playable_on_playlist', [$this'isPlayableOnPlaylist']),
  84.             new TwigFunction('predefined_languages', [$this'getPredefinedLanguages']),
  85.             new TwigFunction('is_mmobj_owner', [$this'isUserOwner']),
  86.             new TwigFunction('broadcast_description', [$this'getBroadcastDescription']),
  87.             new TwigFunction('is_naked', [$this'isNaked'], ['needs_environment' => true]),
  88.             new TwigFunction('is_playlist_enabled', [$this'isPlaylistEnabled']),
  89.             new TwigFunction('trans_i18n_broadcast', [$this'getI18nEmbeddedBroadcast']),
  90.             new TwigFunction('date_from_mongo_id', [$this'getDateFromMongoId']),
  91.             new TwigFunction('default_poster', [$this'getDefaultPoster']),
  92.             new TwigFunction('sort_roles', [$this'getSortRoles']),
  93.             new TwigFunction('status_string_text_by_value', [$this'getStatusTextByValue']),
  94.             new TwigFunction('role_string_text_by_value', [$this'getRoleTextByValue']),
  95.             new TwigFunction('is_immutable', [$this'isImmutable']),
  96.             new TwigFunction('is_addon_language', [$this'isAddonLanguage']),
  97.             new TwigFunction('has_pending_jobs', [$this'hasPendingJobs']),
  98.         ];
  99.     }
  100.     public function getBasename(?string $path): string
  101.     {
  102.         if (!$path) {
  103.             return '';
  104.         }
  105.         return basename($path);
  106.     }
  107.     public function getProfile(Tags $tags): string
  108.     {
  109.         $profile '';
  110.         foreach ($tags->toArray() as $tag) {
  111.             if (str_contains($tag'profile:')) {
  112.                 return substr($tagstrlen('profile:'), strlen($tag) - 1);
  113.             }
  114.         }
  115.         return $profile;
  116.     }
  117.     public function existsRoute(string $name): bool
  118.     {
  119.         return null !== $this->router->getRouteCollection()->get($name);
  120.     }
  121.     public function getDisplay(string $profileName)
  122.     {
  123.         $display false;
  124.         $profile $this->profileService->getProfile($profileName);
  125.         if (null !== $profile) {
  126.             $display $profile['display'];
  127.         }
  128.         return $display;
  129.     }
  130.     public function getDurationString(int $duration): string
  131.     {
  132.         return gmdate('H:i:s'$duration);
  133.     }
  134.     public function getLanguageName(string $codebool $translate true): string
  135.     {
  136.         $addonLanguages CustomLanguageType::$addonLanguages;
  137.         if ('zh-CN' === $code) {
  138.             return '简体中文';
  139.         }
  140.         if ('zh-TW' === $code) {
  141.             return '繁體中文';
  142.         }
  143.         if (isset($this->languages[$code])) {
  144.             $name $translate ?
  145.                   $this->languages[$code] :
  146.                   Languages::getName($code);
  147.             return ucfirst($name);
  148.         }
  149.         if (isset($addonLanguages[$code])) {
  150.             $name $addonLanguages[$code];
  151.             if ($translate) {
  152.                 $name $this->translator->trans($name);
  153.             }
  154.             return ucfirst($name);
  155.         }
  156.         return $code;
  157.     }
  158.     public function isAddonLanguage(string $code): bool
  159.     {
  160.         $addonLanguages CustomLanguageType::$addonLanguages;
  161.         if (isset($addonLanguages[$code])) {
  162.             return true;
  163.         }
  164.         return false;
  165.     }
  166.     public function getPredefinedLanguages(): array
  167.     {
  168.         return array_merge($this->languagesCustomLanguageType::$addonLanguages);
  169.     }
  170.     public function getStatusIcon(int $status): string
  171.     {
  172.         $iconClass 'mdi-alert-warning';
  173.         switch ($status) {
  174.             case MultimediaObject::STATUS_PUBLISHED:
  175.                 $iconClass 'fa fa-check-circle';
  176.                 //                $iconClass = 'mdi-device-signal-wifi-4-bar';
  177.                 break;
  178.             case MultimediaObject::STATUS_HIDDEN:
  179.                 $iconClass 'fa fa-eye-slash';
  180.                 //                $iconClass = 'mdi-device-signal-wifi-0-bar';
  181.                 break;
  182.             case MultimediaObject::STATUS_BLOCKED:
  183.                 //                $iconClass = 'mdi-device-wifi-lock';
  184.                 $iconClass 'fa fa-ban';
  185.                 break;
  186.         }
  187.         return $iconClass;
  188.     }
  189.     public function getStatusText($param): string
  190.     {
  191.         $iconText 'New';
  192.         $status $param instanceof MultimediaObject $param->getStatus() : $param;
  193.         switch ($status) {
  194.             case MultimediaObject::STATUS_PUBLISHED:
  195.                 if ($param instanceof MultimediaObject && $param->containsTagWithCod(PumukitWebTVBundle::WEB_TV_TAG)) {
  196.                     $iconText $this->translator->trans('Published: is listed in the Series and can be played with published URL');
  197.                 } else {
  198.                     $iconText $this->translator->trans('Published');
  199.                 }
  200.                 break;
  201.             case MultimediaObject::STATUS_HIDDEN:
  202.                 $iconText $this->translator->trans('Hidden: is not listed in the Series but can be played with magic URL');
  203.                 break;
  204.             case MultimediaObject::STATUS_BLOCKED:
  205.                 $iconText $this->translator->trans('Blocked: cannot be accessed outside the back-end');
  206.                 break;
  207.         }
  208.         return $iconText;
  209.     }
  210.     public function getStatusTextByValue(int $status): string
  211.     {
  212.         return MultimediaObject::$statusTexts[$status];
  213.     }
  214.     public function getRoleTextByValue(string $roleCode): string
  215.     {
  216.         $role $this->dm->getRepository(Role::class)->findOneBy(['cod' => $roleCode]);
  217.         if (!$role) {
  218.             throw new \Exception('Role not found');
  219.         }
  220.         return $role->getName();
  221.     }
  222.     public function getSeriesIcon(Series $series)
  223.     {
  224.         [$mmobjsPublished$mmobjsHidden$mmobjsBlocked] = $this->countMmobjsByStatus($series);
  225.         $iconClass 'mdi-alert-warning';
  226.         if ((=== $mmobjsPublished) && (=== $mmobjsHidden) && (=== $mmobjsBlocked)) {
  227.             $iconClass 'mdi-device-signal-wifi-off pumukit-none';
  228.         } elseif (($mmobjsPublished $mmobjsHidden) && ($mmobjsPublished $mmobjsBlocked)) {
  229.             $iconClass 'mdi-device-signal-wifi-4-bar pumukit-published';
  230.         } elseif (($mmobjsPublished === $mmobjsHidden) && ($mmobjsPublished $mmobjsBlocked)) {
  231.             $iconClass 'mdi-device-signal-wifi-0-bar pumukit-hidden-published';
  232.         } elseif (($mmobjsHidden $mmobjsPublished) && ($mmobjsHidden $mmobjsBlocked)) {
  233.             $iconClass 'mdi-device-signal-wifi-0-bar pumukit-hidden';
  234.         } elseif (($mmobjsPublished === $mmobjsBlocked) && ($mmobjsPublished $mmobjsHidden)) {
  235.             $iconClass 'mdi-device-wifi-lock pumukit-blocked-published';
  236.         } elseif (($mmobjsBlocked === $mmobjsHidden) && ($mmobjsBlocked $mmobjsPublished)) {
  237.             $iconClass 'mdi-device-wifi-lock pumukit-blocked-hidden';
  238.         } elseif (($mmobjsPublished === $mmobjsBlocked) && ($mmobjsPublished === $mmobjsHidden)) {
  239.             $iconClass 'mdi-device-wifi-lock pumukit-blocked-hidden-published';
  240.         } elseif (($mmobjsBlocked $mmobjsPublished) && ($mmobjsBlocked $mmobjsHidden)) {
  241.             $iconClass 'mdi-device-wifi-lock pumukit-blocked';
  242.         }
  243.         if ($series->isHide()) {
  244.             $iconClass .= ' pumukit-series-hidden';
  245.         }
  246.         return $iconClass;
  247.     }
  248.     public function getSeriesText(Series $series): string
  249.     {
  250.         [$mmobjsPublished$mmobjsHidden$mmobjsBlocked] = $this->countMmobjsByStatus($series);
  251.         return sprintf(
  252.             "%s: \n %s: %d,\n%s: %d,\n%s: %d\n",
  253.             $this->translator->trans('Multimedia Objects'),
  254.             $this->translator->trans('i18n.multiple.Published'),
  255.             $mmobjsPublished,
  256.             $this->translator->trans('i18n.multiple.Hidden'),
  257.             $mmobjsHidden,
  258.             $this->translator->trans('i18n.multiple.Blocked'),
  259.             $mmobjsBlocked
  260.         );
  261.     }
  262.     public function getProfileWidth(array $tags): string
  263.     {
  264.         $profileName $this->getProfileFromTags($tags);
  265.         $profile $this->profileService->getProfile($profileName);
  266.         if (null !== $profile) {
  267.             return $profile['resolution_hor'];
  268.         }
  269.         return '0';
  270.     }
  271.     public function getProfileHeight(array $tags): string
  272.     {
  273.         $profileName $this->getProfileFromTags($tags);
  274.         $profile $this->profileService->getProfile($profileName);
  275.         if (null !== $profile) {
  276.             return $profile['resolution_ver'];
  277.         }
  278.         return '0';
  279.     }
  280.     public function getSeriesAnnounceIcon(Series $series): string
  281.     {
  282.         $icon 'mdi-action-done pumukit-transparent';
  283.         if ($series->getAnnounce()) {
  284.             return 'mdi-action-spellcheck pumukit-series-announce';
  285.         }
  286.         return $icon;
  287.     }
  288.     public function getSeriesAnnounceText(Series $series): string
  289.     {
  290.         $text '';
  291.         if ($series->getAnnounce()) {
  292.             return $this->translator->trans('This Series is announced');
  293.         }
  294.         return $text;
  295.     }
  296.     public function getMmsAnnounceIcon(Series $series): string
  297.     {
  298.         $icon 'mdi-action-done pumukit-transparent';
  299.         $count $this->countMmobjsWithTag($series'PUDENEW');
  300.         if ($count 0) {
  301.             return 'mdi-action-spellcheck pumukit-mm-announce';
  302.         }
  303.         return $icon;
  304.     }
  305.     public function getMmsAnnounceText(Series $series): string
  306.     {
  307.         $text '';
  308.         $count $this->countMmobjsWithTag($series'PUDENEW');
  309.         if ($count 0) {
  310.             return 'This Series has '.$count.' announced Multimedia Object(s)';
  311.         }
  312.         return $text;
  313.     }
  314.     public function getPhpUploadMaxFileSize(): string
  315.     {
  316.         return ini_get('upload_max_filesize').'B';
  317.     }
  318.     public function filterProfiles(MultimediaObject $multimediaObject): array
  319.     {
  320.         return $this->profileService->filterProfilesByType($multimediaObject);
  321.     }
  322.     public function countMultimediaObjects(Series $series): int
  323.     {
  324.         return $this->dm->getRepository(MultimediaObject::class)->countInSeries($series);
  325.     }
  326.     public function countEvents(Series $series): int
  327.     {
  328.         return $this->dm->getRepository(MultimediaObject::class)->countEventsInSeries($series);
  329.     }
  330.     public function getBroadcastDescription($broadcastType$templatebool $isLive false): string
  331.     {
  332.         $description '';
  333.         $changeWord 'multimedia object';
  334.         if ($isLive) {
  335.             $changeWord 'live event';
  336.         }
  337.         if ((EmbeddedBroadcast::TYPE_PUBLIC === $broadcastType) && $template) {
  338.             $description $this->translator->trans('Any Internet user can play the new multimedia objects created from this video template');
  339.         } elseif (EmbeddedBroadcast::TYPE_PUBLIC === $broadcastType) {
  340.             $description $this->translator->trans("Any Internet user can play this {$changeWord}");
  341.         } elseif ((EmbeddedBroadcast::TYPE_PASSWORD === $broadcastType) && $template) {
  342.             $description $this->translator->trans('Only users with the defined password can play the new multimedia objects created from this video template');
  343.         } elseif (EmbeddedBroadcast::TYPE_PASSWORD === $broadcastType) {
  344.             $description $this->translator->trans("Only users with the defined password can play this {$changeWord}");
  345.         } elseif ((EmbeddedBroadcast::TYPE_LOGIN === $broadcastType) && $template) {
  346.             $description $this->translator->trans('Only logged in users in the system can play the new multimedia objects created from this video template');
  347.         } elseif (EmbeddedBroadcast::TYPE_LOGIN === $broadcastType) {
  348.             $description $this->translator->trans("Only logged in users in the system can play this {$changeWord}");
  349.         } elseif ((EmbeddedBroadcast::TYPE_GROUPS === $broadcastType) && $template) {
  350.             $description $this->translator->trans('Only users in the selected Groups can play the new multimedia objects created from this video template');
  351.         } elseif (EmbeddedBroadcast::TYPE_GROUPS === $broadcastType) {
  352.             $description $this->translator->trans("Only users in the selected Groups can play this {$changeWord}");
  353.         }
  354.         return $description;
  355.     }
  356.     public function isPlayableOnPlaylist(MultimediaObject $multimediaObject): bool
  357.     {
  358.         return $this->mmobjService->isPlayableOnPlaylist($multimediaObject);
  359.     }
  360.     public function isUserOwner(User $userMultimediaObject $multimediaObject): bool
  361.     {
  362.         return $this->mmobjService->isUserOwner($user$multimediaObject);
  363.     }
  364.     public function isNaked(Environment $env)
  365.     {
  366.         if (isset($env->getGlobals()['app'])) {
  367.             return $env->getGlobals()['app']->getRequest()->attributes->get('nakedbackoffice'false);
  368.         }
  369.         return false;
  370.     }
  371.     public function isPlaylistEnabled()
  372.     {
  373.         return $this->enablePlaylist;
  374.     }
  375.     public function getI18nEmbeddedBroadcast(EmbeddedBroadcast $embeddedBroadcast, ?string $locale 'en'): string
  376.     {
  377.         return $this->specialTranslationService->getI18nEmbeddedBroadcast($embeddedBroadcast$locale);
  378.     }
  379.     public function getDateFromMongoId(MultimediaObject $multimediaObject)
  380.     {
  381.         $id = new ObjectId($multimediaObject->getId());
  382.         return $id->getTimestamp();
  383.     }
  384.     public function getNextEventSession(MultimediaObject $multimediaObject)
  385.     {
  386.         $now = new \DateTime();
  387.         $now $now->getTimestamp();
  388.         $aSessions = [];
  389.         $event $multimediaObject->getEmbeddedEvent();
  390.         foreach ($event->getEmbeddedEventSession() as $session) {
  391.             $sessionStart = clone $session->getStart();
  392.             $sessionEnds $sessionStart->add(new \DateInterval('PT'.$session->getDuration().'S'));
  393.             if ($session->getStart()->getTimestamp() > $now) {
  394.                 $aSessions[$session->getStart()->getTimestamp()][] = $session;
  395.             } elseif (($session->getStart()->getTimestamp() < $now) && ($sessionEnds->getTimestamp() > $now)) {
  396.                 $aSessions[$session->getStart()->getTimestamp()][] = $session;
  397.             }
  398.         }
  399.         if (!empty($aSessions)) {
  400.             ksort($aSessions);
  401.             return array_shift($aSessions);
  402.         }
  403.         return false;
  404.     }
  405.     public function getDefaultPoster(): string
  406.     {
  407.         return $this->eventService->getDefaultPoster();
  408.     }
  409.     public function getSortRoles(MultimediaObject $multimediaObjectbool $display true): array
  410.     {
  411.         static $rolesCached = [];
  412.         if (isset($rolesCached[$display])) {
  413.             $roles $rolesCached[$display];
  414.         } else {
  415.             $roles $this->dm->getRepository(Role::class)->findBy(['display' => $display], ['rank' => 1]);
  416.             $rolesCached[$display] = $roles;
  417.         }
  418.         $aRoles = [];
  419.         foreach ($roles as $role) {
  420.             $embeddedRole $multimediaObject->getEmbeddedRole($role);
  421.             if ($embeddedRole && !== (is_countable($embeddedRole->getPeople()) ? count($embeddedRole->getPeople()) : 0)) {
  422.                 $aRoles[] = $embeddedRole;
  423.             }
  424.         }
  425.         return $aRoles;
  426.     }
  427.     public function isImmutable(MultimediaObject $multimediaObject): bool
  428.     {
  429.         return $multimediaObject->getImmutable() && $multimediaObject->getImmutable()->value();
  430.     }
  431.     public function unescapeLabel($value)
  432.     {
  433.         return html_entity_decode($value);
  434.     }
  435.     public function hasPendingJobs(MultimediaObject $multimediaObject): bool
  436.     {
  437.         $jobs $this->jobRepository->getNotFinishedJobsByMultimediaObjectId($multimediaObject->getId());
  438.         return !== (is_countable($jobs) ? count($jobs) : 0);
  439.     }
  440.     private function getProfileFromTags(array $tags): string
  441.     {
  442.         $profile '';
  443.         foreach ($tags as $tag) {
  444.             if (false !== strpos($tag'profile:')) {
  445.                 return substr($tagstrlen('profile:'), strlen($tag) - 1);
  446.             }
  447.         }
  448.         return $profile;
  449.     }
  450.     private function countMmobjsByStatus(Series $series)
  451.     {
  452.         if (isset($this->countMmobjsByStatus[$series->getId()])) {
  453.             return $this->countMmobjsByStatus[$series->getId()];
  454.         }
  455.         $mmobjsPublished 0;
  456.         $mmobjsHidden 0;
  457.         $mmobjsBlocked 0;
  458.         $seriesColl $this->dm->getDocumentCollection(MultimediaObject::class);
  459.         $aggrPipe = [
  460.             ['$match' => ['series' => new ObjectId($series->getId())]],
  461.             ['$group' => ['_id' => '$status',
  462.                 'count' => ['$sum' => 1], ]],
  463.         ];
  464.         $mmobjCounts iterator_to_array($seriesColl->aggregate($aggrPipe, ['cursor' => []]));
  465.         foreach ($mmobjCounts as $mmobjCount) {
  466.             switch ($mmobjCount['_id']) {
  467.                 case MultimediaObject::STATUS_PUBLISHED:
  468.                     $mmobjsPublished $mmobjCount['count'];
  469.                     break;
  470.                 case MultimediaObject::STATUS_HIDDEN:
  471.                     $mmobjsHidden $mmobjCount['count'];
  472.                     break;
  473.                 case MultimediaObject::STATUS_BLOCKED:
  474.                     $mmobjsBlocked $mmobjCount['count'];
  475.                     break;
  476.             }
  477.         }
  478.         $result = [$mmobjsPublished$mmobjsHidden$mmobjsBlocked];
  479.         return $this->countMmobjsByStatus[$series->getId()] = $result;
  480.     }
  481.     private function countMmobjsWithTag(Series $seriesstring $tagCod)
  482.     {
  483.         if (isset($this->countMmobjsWithTag[$series->getId()][$tagCod])) {
  484.             return $this->countMmobjsWithTag[$series->getId()][$tagCod];
  485.         }
  486.         $repoSeries $this->dm->getRepository(MultimediaObject::class);
  487.         $qb $repoSeries->createStandardQueryBuilder()->field('series')->equals(new ObjectId($series->getId()))->field('tags.cod')->equals('PUDENEW');
  488.         $count $qb->count()->getQuery()->execute();
  489.         $this->countMmobjsWithTag[$series->getId()][$tagCod] = $count;
  490.         return $count;
  491.     }
  492. }