Browse Source

Add Embed Registry plugin - refs BT#15390

Add a course tool to get a registry of embed content and track the students access to it.
Angel Fernando Quiroz Campos 5 years ago
parent
commit
ec5893c15a

+ 291 - 0
plugin/embedregistry/EmbedRegistryPlugin.php

@@ -0,0 +1,291 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+use Chamilo\CoreBundle\Entity\Course;
+use Chamilo\CoreBundle\Entity\Session;
+use Chamilo\PluginBundle\Entity\EmbedRegistry\Embed;
+use Symfony\Component\Filesystem\Filesystem;
+
+/**
+ * Class EmbedRegistryPlugin
+ */
+class EmbedRegistryPlugin extends Plugin
+{
+    const SETTING_ENABLED = 'tool_enabled';
+    const SETTING_TITLE = 'tool_title';
+    const SETTING_EXTERNAL_URL = 'external_url';
+
+    const TBL_EMBED = 'plugin_embed_registry_embed';
+
+    /**
+     * EmbedRegistryPlugin constructor.
+     */
+    protected function __construct()
+    {
+        $authors = [
+            'Angel Fernando Quiroz Campos',
+        ];
+
+        parent::__construct(
+            '1.0',
+            implode(', ', $authors),
+            [
+                self::SETTING_ENABLED => 'boolean',
+                self::SETTING_TITLE => 'text',
+                self::SETTING_EXTERNAL_URL => 'text',
+            ]
+        );
+    }
+
+    /**
+     * @return string
+     */
+    public function get_title()
+    {
+        $title = $this->get(self::SETTING_TITLE);
+
+        if (!empty($title)) {
+            return $title;
+        }
+
+        return parent::get_title(); // TODO: Change the autogenerated stub
+    }
+
+    /**
+     * @return EmbedRegistryPlugin|null
+     */
+    public static function create()
+    {
+        static $result = null;
+
+        return $result ? $result : $result = new self();
+    }
+
+    public function install()
+    {
+        $entityPath = $this->getEntityPath();
+
+        if (!is_dir($entityPath)) {
+            if (!is_writable(dirname($entityPath))) {
+                Display::addFlash(
+                    Display::return_message(
+                        get_lang('ErrorCreatingDir').' '.$entityPath,
+                        'error'
+                    )
+                );
+
+                return false;
+            }
+
+            mkdir($entityPath, api_get_permissions_for_new_directories());
+        }
+
+        $fs = new Filesystem();
+        $fs->mirror(__DIR__.'/Entity/', $entityPath, null, ['override']);
+
+        $this->createPluginTables();
+    }
+
+    private function createPluginTables()
+    {
+        $connection = Database::getManager()->getConnection();
+
+        if ($connection->getSchemaManager()->tablesExist(self::TBL_EMBED)) {
+            return;
+        }
+
+        $queries = [
+            'CREATE TABLE plugin_embed_registry_embed (id INT AUTO_INCREMENT NOT NULL, c_id INT NOT NULL, session_id INT DEFAULT NULL, title LONGTEXT NOT NULL, display_start_date DATETIME NOT NULL, display_end_date DATETIME NOT NULL, html_code LONGTEXT NOT NULL, INDEX IDX_5236D25991D79BD3 (c_id), INDEX IDX_5236D259613FECDF (session_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB',
+            'ALTER TABLE plugin_embed_registry_embed ADD CONSTRAINT FK_5236D25991D79BD3 FOREIGN KEY (c_id) REFERENCES course (id)',
+            'ALTER TABLE plugin_embed_registry_embed ADD CONSTRAINT FK_5236D259613FECDF FOREIGN KEY (session_id) REFERENCES session (id)',
+        ];
+
+        foreach ($queries as $query) {
+            Database::query($query);
+        }
+    }
+
+    public function uninstall()
+    {
+        $entityPath = $this->getEntityPath();
+        $fs = new Filesystem();
+
+        if ($fs->exists($entityPath)) {
+            $fs->remove($entityPath);
+        }
+
+        Database::query('DROP TABLE IF EXISTS '.self::TBL_EMBED);
+    }
+
+    /**
+     * @return string
+     */
+    private function getEntityPath()
+    {
+        return api_get_path(SYS_PATH).'src/Chamilo/PluginBundle/Entity/'.$this->getCamelCaseName();
+    }
+
+    /**
+     * @return EmbedRegistryPlugin
+     */
+    public function performActionsAfterConfigure()
+    {
+        $em = Database::getManager();
+
+        $this->deleteCourseToolLinks();
+
+        if ('true' === $this->get(self::SETTING_ENABLED)) {
+            $courses = $em->createQuery('SELECT c.id FROM ChamiloCoreBundle:Course c')->getResult();
+
+            foreach ($courses as $course) {
+                $this->createLinkToCourseTool($this->get_title(), $course['id']);
+            }
+        }
+
+        return $this;
+    }
+
+    private function deleteCourseToolLinks()
+    {
+        Database::getManager()
+            ->createQuery('DELETE FROM ChamiloCourseBundle:CTool t WHERE t.category = :category AND t.link LIKE :link')
+            ->execute(['category' => 'plugin', 'link' => 'embedregistry/start.php%']);
+    }
+
+    /**
+     * @param int $courseId
+     */
+    public function doWhenDeletingCourse($courseId)
+    {
+        Database::getManager()
+            ->createQuery('DELETE FROM ChamiloPluginBundle:EmbedRegistry\Embed e WHERE e.course = :course')
+            ->execute(['course' => (int) $courseId]);
+    }
+
+    /**
+     * @param int $sessionId
+     */
+    public function doWhenDeletingSession($sessionId)
+    {
+        Database::getManager()
+            ->createQuery('DELETE FROM ChamiloPluginBundle:EmbedRegistry\Embed e WHERE e.session = :session')
+            ->execute(['session' => (int) $sessionId]);
+    }
+
+    /**
+     * @param Course       $course
+     * @param Session|null $session
+     *
+     * @throws \Doctrine\ORM\NonUniqueResultException
+     *
+     * @return Embed
+     */
+    public function getCurrentEmbed(Course $course, Session $session = null)
+    {
+        $embedRepo = Database::getManager()->getRepository('ChamiloPluginBundle:EmbedRegistry\Embed');
+        $qb = $embedRepo->createQueryBuilder('e');
+        $query = $qb
+            ->where('e.displayStartDate <= :now')
+            ->andWhere('e.displayEndDate >= :now')
+            ->andWhere(
+                $qb->expr()->eq('e.course', $course->getId())
+            );
+
+        $query->andWhere(
+            $session
+                ? $qb->expr()->eq('e.session', $session->getId())
+                : $qb->expr()->isNull('e.session')
+        );
+
+        $query = $query
+            ->orderBy('e.displayStartDate', 'DESC')
+            ->setMaxResults(1)
+            ->setParameters(['now' => api_get_utc_datetime(null, false, true)])
+            ->getQuery();
+
+        return $query->getOneOrNullResult();
+    }
+
+    /**
+     * @param Embed $embed
+     *
+     * @return string
+     */
+    public function formatDisplayDate(Embed $embed)
+    {
+        $startDate = sprintf(
+            '<time datetime="%s">%s</time>',
+            $embed->getDisplayStartDate()->format(DateTime::W3C),
+            api_convert_and_format_date($embed->getDisplayStartDate())
+        );
+        $endDate = sprintf(
+            '<time datetime="%s">%s</time>',
+            $embed->getDisplayEndDate()->format(DateTime::W3C),
+            api_convert_and_format_date($embed->getDisplayEndDate())
+        );
+
+        return sprintf(get_lang('FromDateXToDateY'), $startDate, $endDate);
+    }
+
+    /**
+     * @param Embed $embed
+     *
+     * @return string
+     */
+    public function getViewUrl(Embed $embed)
+    {
+        return api_get_path(WEB_PLUGIN_PATH).'embedregistry/view.php?id='.$embed->getId().'&'.api_get_cidreq();
+    }
+
+    /**
+     * @param Embed $embed
+     *
+     * @return mixed
+     * @throws \Doctrine\ORM\Query\QueryException
+     */
+    public function getMembersCount(Embed $embed)
+    {
+        $dql = 'SELECT COUNT(DISTINCT tea.accessUserId) FROM ChamiloCoreBundle:TrackEAccess tea
+                WHERE
+                    tea.accessTool = :tool AND
+                    (tea.accessDate >= :start_date AND tea.accessDate <= :end_date) AND
+                    tea.cId = :course';
+
+        $params = [
+            'tool' => 'plugin_'.$this->get_name(),
+            'start_date' => $embed->getDisplayStartDate(),
+            'end_date' => $embed->getDisplayEndDate(),
+            'course' => $embed->getCourse(),
+        ];
+
+        if ($embed->getSession()) {
+            $dql .= ' AND tea.accessSessionId = :session ';
+
+            $params['session'] = $embed->getSession();
+        }
+
+        $count = Database::getManager()
+            ->createQuery($dql)
+            ->setParameters($params)
+            ->getSingleScalarResult();
+
+        return $count;
+    }
+
+    public function saveEventAccessTool()
+    {
+        $tableAccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS);
+
+
+
+        $params = [
+            'access_user_id' => api_get_user_id(),
+            'c_id' => api_get_course_int_id(),
+            'access_tool' => 'plugin_'.$this->get_name(),
+            'access_date' => api_get_utc_datetime(),
+            'access_session_id' => api_get_session_id(),
+            'user_ip' => Database::escape_string(api_get_real_ip()),
+        ];
+        Database::insert($tableAccess, $params);
+    }
+}

+ 206 - 0
plugin/embedregistry/Entity/Embed.php

@@ -0,0 +1,206 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Chamilo\PluginBundle\Entity\EmbedRegistry;
+
+use Chamilo\CoreBundle\Entity\Course;
+use Chamilo\CoreBundle\Entity\Session;
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * Class EmbedRegistry.
+ *
+ * @package Chamilo\PluginBundle\Entity\EmbedRegistry
+ *
+ * @ORM\Entity()
+ * @ORM\Table(name="plugin_embed_registry_embed")
+ */
+class Embed
+{
+    /**
+     * @var integer
+     *
+     * @ORM\Column(name="id", type="integer")
+     * @ORM\Id
+     * @ORM\GeneratedValue
+     */
+    private $id;
+    /**
+     * @var string
+     *
+     * @ORM\Column(name="title", type="text")
+     */
+    private $title;
+    /**
+     * @var \DateTime
+     *
+     * @ORM\Column(name="display_start_date", type="datetime")
+     */
+    private $displayStartDate;
+    /**
+     * @var \DateTime
+     *
+     * @ORM\Column(name="display_end_date", type="datetime")
+     */
+    private $displayEndDate;
+    /**
+     * @var string
+     *
+     * @ORM\Column(name="html_code", type="text")
+     */
+    private $htmlCode;
+    /**
+     * @var Course
+     *
+     * @ORM\ManyToOne(targetEntity="Chamilo\CoreBundle\Entity\Course")
+     * @ORM\JoinColumn(name="c_id", referencedColumnName="id", nullable=false)
+     */
+    private $course;
+    /**
+     * @var Session|null
+     *
+     * @ORM\ManyToOne(targetEntity="Chamilo\CoreBundle\Entity\Session")
+     * @ORM\JoinColumn(name="session_id", referencedColumnName="id")
+     */
+    private $session;
+
+    /**
+     * @return int
+     */
+    public function getId()
+    {
+        return $this->id;
+    }
+
+    /**
+     * @param int $id
+     *
+     * @return Embed
+     */
+    public function setId($id)
+    {
+        $this->id = $id;
+
+        return $this;
+    }
+
+    /**
+     * @return string
+     */
+    public function getTitle()
+    {
+        return $this->title;
+    }
+
+    /**
+     * @param $title
+     *
+     * @return Embed
+     */
+    public function setTitle($title)
+    {
+        $this->title = $title;
+
+        return $this;
+    }
+
+    /**
+     * @return \DateTime
+     */
+    public function getDisplayStartDate()
+    {
+        return $this->displayStartDate;
+    }
+
+    /**
+     * @param \DateTime $displayStartDate
+     *
+     * @return Embed
+     */
+    public function setDisplayStartDate(\DateTime $displayStartDate)
+    {
+        $this->displayStartDate = $displayStartDate;
+
+        return $this;
+    }
+
+    /**
+     * @return \DateTime
+     */
+    public function getDisplayEndDate()
+    {
+        return $this->displayEndDate;
+    }
+
+    /**
+     * @param \DateTime $displayEndDate
+     *
+     * @return Embed
+     */
+    public function setDisplayEndDate(\DateTime $displayEndDate)
+    {
+        $this->displayEndDate = $displayEndDate;
+
+        return $this;
+    }
+
+    /**
+     * @return string
+     */
+    public function getHtmlCode()
+    {
+        return $this->htmlCode;
+    }
+
+    /**
+     * @param string $htmlCode
+     *
+     * @return Embed
+     */
+    public function setHtmlCode($htmlCode)
+    {
+        $this->htmlCode = $htmlCode;
+
+        return $this;
+    }
+
+    /**
+     * @return Course
+     */
+    public function getCourse()
+    {
+        return $this->course;
+    }
+
+    /**
+     * @param Course $course
+     *
+     * @return Embed
+     */
+    public function setCourse(Course $course)
+    {
+        $this->course = $course;
+
+        return $this;
+    }
+
+    /**
+     * @return Session|null
+     */
+    public function getSession()
+    {
+        return $this->session;
+    }
+
+    /**
+     * @param Session|null $session
+     *
+     * @return Embed
+     */
+    public function setSession(Session $session = null)
+    {
+        $this->session = $session;
+
+        return $this;
+    }
+}

+ 4 - 0
plugin/embedregistry/install.php

@@ -0,0 +1,4 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+EmbedRegistryPlugin::create()->install();

+ 17 - 0
plugin/embedregistry/lang/english.php

@@ -0,0 +1,17 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+$strings['plugin_title'] = 'Embed Registry';
+$strings['plugin_comment'] = 'Add a course tool to get a registry of embed content and track the students access to it.';
+
+$strings['tool_enabled'] = 'Tool enabled';
+$strings['tool_title'] = 'Tool Title';
+$strings['external_url'] = 'External tool';
+
+$strings['YouNeedCreateContent'] = 'First You need create the external content. Then you can add the Embeddable content to yours course.';
+$strings['CreateContent'] = 'Create external content';
+$strings['CreateEmbeddable'] = 'Add embeddable';
+$strings['EditEmbeddable'] = 'Edit embeddable';
+$strings['ContentNotFound'] = 'Content not found';
+$strings['HtmlCode'] = 'HTML code';
+$strings['LaunchContent'] = 'Launch content';

+ 17 - 0
plugin/embedregistry/lang/spanish.php

@@ -0,0 +1,17 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+$strings['plugin_title'] = 'Registro de contenido Embed';
+$strings['plugin_comment'] = 'Agrega una herramienta de curso para llevar un registro del contenido Embed y registrar el acceso de los estudiantes a este.';
+
+$strings['tool_enabled'] = 'Herramienta habilitada';
+$strings['tool_title'] = 'Título de la herramienta';
+$strings['external_url'] = 'URL externa';
+
+$strings['YouNeedCreateContent'] = 'Primero necesita crear el contenido externo. Luego, puede agregar el contenido Embed a su curso.';
+$strings['CreateContent'] = 'Crear contenido externo';
+$strings['CreateEmbeddable'] = 'Agregar Embed';
+$strings['EditEmbeddable'] = 'Editar Embed';
+$strings['ContentNotFound'] = 'Contenido no encontrado';
+$strings['HtmlCode'] = 'Código HTML';
+$strings['LaunchContent'] = 'Lanzar contenido';

+ 4 - 0
plugin/embedregistry/plugin.php

@@ -0,0 +1,4 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+$plugin_info = EmbedRegistryPlugin::create()->get_info();

+ 297 - 0
plugin/embedregistry/start.php

@@ -0,0 +1,297 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+use Chamilo\PluginBundle\Entity\EmbedRegistry\Embed;
+
+require_once __DIR__.'/../../main/inc/global.inc.php';
+
+api_block_anonymous_users();
+api_protect_course_script(true);
+
+$plugin = EmbedRegistryPlugin::create();
+
+if ('false' === $plugin->get(EmbedRegistryPlugin::SETTING_ENABLED)) {
+    api_not_allowed(true);
+}
+
+$isAllowedToEdit = api_is_allowed_to_edit(true);
+
+$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : null;
+
+$em = Database::getManager();
+$embedRepo = $em->getRepository('ChamiloPluginBundle:EmbedRegistry\Embed');
+
+$course = api_get_course_entity(api_get_course_int_id());
+$session = api_get_session_entity(api_get_session_id());
+
+$actions = [];
+
+$view = new Template($plugin->get_title());
+$view->assign('is_allowed_to_edit', $isAllowedToEdit);
+
+switch ($action) {
+    case 'add':
+        if (!$isAllowedToEdit) {
+            api_not_allowed(true);
+        }
+
+        $actions[] = Display::url(
+            Display::return_icon('back.png', get_lang('Back'), [], ICON_SIZE_MEDIUM),
+            api_get_self()
+        );
+
+        $form = new FormValidator('frm_edit');
+        $form->addText('title', get_lang('Title'), true);
+        $form->addDateRangePicker('range', get_lang('DateRange'));
+        $form->addTextarea('html_code', $plugin->get_lang('HtmlCode'), ['rows' => 5], true);
+        $form->addButtonUpdate(get_lang('Add'));
+        $form->addHidden('action', 'add');
+
+        if ($form->validate()) {
+            $values = $form->exportValues();
+
+            $startDate = api_get_utc_datetime($values['range_start'], false, true);
+            $endDate = api_get_utc_datetime($values['range_end'], false, true);
+
+            $embed = new Embed();
+            $embed
+                ->setTitle($values['title'])
+                ->setDisplayStartDate($startDate)
+                ->setDisplayEndDate($endDate)
+                ->setHtmlCode($values['html_code'])
+                ->setCourse($course)
+                ->setSession($session);
+
+            $em->persist($embed);
+            $em->flush();
+
+            Display::addFlash(
+                Display::return_message(get_lang('Added'), 'success')
+            );
+
+            header('Location: '.api_get_self());
+            exit;
+        }
+
+        $view->assign('header', $plugin->get_lang('CreateEmbeddable'));
+        $view->assign('form', $form->returnForm());
+
+        $externalUrl = $plugin->get(EmbedRegistryPlugin::SETTING_EXTERNAL_URL);
+
+        if (!empty($externalUrl)) {
+            $view->assign('external_url', $externalUrl);
+        }
+        break;
+    case 'edit':
+        if (!$isAllowedToEdit) {
+            api_not_allowed(true);
+        }
+
+        $actions[] = Display::url(
+            Display::return_icon('back.png', get_lang('Back'), [], ICON_SIZE_MEDIUM),
+            api_get_self()
+        );
+
+        $embedId = isset($_REQUEST['id']) ? (int) $_REQUEST['id'] : 0;
+
+        if (!$embedId) {
+            break;
+        }
+
+        /** @var Embed|null $embed */
+        $embed = $embedRepo->find($embedId);
+
+        if (!$embed) {
+            Display::addFlash(Display::return_message($plugin->get_lang('ContentNotFound'), 'danger'));
+
+            break;
+        }
+
+        $form = new FormValidator('frm_edit');
+        $form->addText('title', get_lang('Title'), true);
+        $form->addDateRangePicker('range', get_lang('DateRange'));
+        $form->addTextarea('html_code', $plugin->get_lang('HtmlCode'), ['rows' => 5], true);
+        $form->addButtonUpdate(get_lang('Edit'));
+        $form->addHidden('id', $embed->getId());
+        $form->addHidden('action', 'edit');
+
+        if ($form->validate()) {
+            $values = $form->exportValues();
+
+            $startDate = api_get_utc_datetime($values['range_start'], false, true);
+            $endDate = api_get_utc_datetime($values['range_end'], false, true);
+
+            $embed
+                ->setTitle($values['title'])
+                ->setDisplayStartDate($startDate)
+                ->setDisplayEndDate($endDate)
+                ->setHtmlCode($values['html_code']);
+
+            $em->persist($embed);
+            $em->flush();
+
+            Display::addFlash(
+                Display::return_message(get_lang('Updated'), 'success')
+            );
+
+            header('Location: '.api_get_self());
+            exit;
+        }
+
+        $form->setDefaults(
+            [
+                'title' => $embed->getTitle(),
+                'range' => api_get_local_time($embed->getDisplayStartDate())
+                    .' / '
+                    .api_get_local_time($embed->getDisplayEndDate()),
+                'html_code' => $embed->getHtmlCode(),
+            ]
+        );
+
+        $view->assign('header', $plugin->get_lang('EditEmbeddable'));
+        $view->assign('form', $form->returnForm());
+        break;
+    case 'delete':
+        $embedId = isset($_REQUEST['id']) ? (int) $_REQUEST['id'] : 0;
+
+        if (!$embedId) {
+            break;
+        }
+
+        /** @var Embed|null $embed */
+        $embed = $embedRepo->find($embedId);
+
+        if (!$embed) {
+            Display::addFlash(Display::return_message($plugin->get_lang('ContentNotFound'), 'danger'));
+
+            break;
+        }
+
+        $em->remove($embed);
+        $em->flush();
+
+        Display::addFlash(
+            Display::return_message(get_lang('Deleted'), 'success')
+        );
+
+        header('Location: '.api_get_self());
+        exit;
+    default:
+        $currentEmbed = $plugin->getCurrentEmbed($course, $session);
+
+        /** @var array|Embed[] $embeds */
+        $embeds = $embedRepo->findBy(['course' => $course, 'session' => $session]);
+
+        $tableData = [];
+
+        foreach ($embeds as $embed) {
+            $data = [
+                $embed->getTitle(),
+                api_convert_and_format_date($embed->getDisplayStartDate()),
+                api_convert_and_format_date($embed->getDisplayEndDate()),
+                $embed,
+            ];
+
+            if ($isAllowedToEdit) {
+                $data[] = $embed;
+            }
+
+            $tableData[] = $data;
+        }
+
+        if ($isAllowedToEdit) {
+            $btnAdd = Display::toolbarButton(
+                $plugin->get_lang('CreateEmbeddable'),
+                api_get_self().'?action=add',
+                'file-code-o',
+                'primary'
+            );
+
+            $view->assign(
+                'actions',
+                Display::toolbarAction($plugin->get_name(), [$btnAdd])
+            );
+
+            if (in_array($action, ['add', 'edit'])) {
+                $view->assign('form', $form->returnForm());
+            }
+        }
+
+        if ($currentEmbed) {
+            $view->assign('current_embed', $currentEmbed);
+            $view->assign(
+                'current_link',
+                Display::toolbarButton(
+                    $plugin->get_lang('LaunchContent'),
+                    $plugin->getViewUrl($embed),
+                    'rocket',
+                    'info'
+                )
+            );
+        }
+
+        $table = new SortableTableFromArray($tableData, 1);
+        $table->set_header(0, get_lang('Title'));
+        $table->set_header(1, get_lang('AvailableFrom'), true, 'th-header text-center', ['class' => 'text-center']);
+        $table->set_header(2, get_lang('AvailableTill'), true, 'th-header text-center', ['class' => 'text-center']);
+
+        if ($isAllowedToEdit) {
+            $table->set_header(3, get_lang('Members'), false, 'th-header text-right', ['class' => 'text-right']);
+            $table->set_column_filter(
+                3,
+                function (Embed $value) use ($plugin) {
+                    return $plugin->getMembersCount($value);
+                }
+            );
+        }
+
+        $table->set_header(
+            $isAllowedToEdit ? 4 : 3,
+            get_lang('Actions'),
+            false,
+            'th-header text-right',
+            ['class' => 'text-right']
+        );
+        $table->set_column_filter(
+            $isAllowedToEdit ? 4 : 3,
+            function (Embed $value) use ($isAllowedToEdit, $plugin) {
+                $actions = [];
+
+                $actions[] = Display::url(
+                    Display::return_icon('external_link.png', get_lang('View')),
+                    $plugin->getViewUrl($value)
+                );
+
+                if ($isAllowedToEdit) {
+                    $actions[] = Display::url(
+                        Display::return_icon('edit.png', get_lang('Edit')),
+                        api_get_self().'?action=edit&id='.$value->getId()
+                    );
+
+                    $actions[] = Display::url(
+                        Display::return_icon('delete.png', get_lang('Delete')),
+                        api_get_self().'?action=delete&id='.$value->getId()
+                    );
+                }
+
+                return implode(PHP_EOL, $actions);
+            }
+        );
+
+        $view->assign('embeds', $embeds);
+        $view->assign('table', $table->return_table());
+}
+
+$content = $view->fetch('embedregistry/view/start.tpl');
+
+if ($actions) {
+    $actions = implode(PHP_EOL, $actions);
+
+    $view->assign(
+        'actions',
+        Display::toolbarAction($plugin->get_name(), [$actions])
+    );
+}
+
+$view->assign('content', $content);
+$view->display_one_col_template();

+ 4 - 0
plugin/embedregistry/uninstall.php

@@ -0,0 +1,4 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+EmbedRegistryPlugin::create()->uninstall();

+ 72 - 0
plugin/embedregistry/view.php

@@ -0,0 +1,72 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+use Chamilo\PluginBundle\Entity\EmbedRegistry\Embed;
+
+require_once __DIR__.'/../../main/inc/global.inc.php';
+
+api_block_anonymous_users();
+api_protect_course_script(true);
+
+$plugin = EmbedRegistryPlugin::create();
+
+if ('false' === $plugin->get(EmbedRegistryPlugin::SETTING_ENABLED)) {
+    api_not_allowed(true);
+}
+
+$isAllowedToEdit = api_is_allowed_to_edit(true);
+
+$em = Database::getManager();
+$embedRepo = $em->getRepository('ChamiloPluginBundle:EmbedRegistry\Embed');
+
+$course = api_get_course_entity(api_get_course_int_id());
+$session = api_get_session_entity(api_get_session_id());
+
+$embedId = isset($_REQUEST['id']) ? (int) $_REQUEST['id'] : 0;
+
+if (!$embedId) {
+    api_not_allowed(true);
+}
+
+/** @var Embed|null $embed */
+$embed = $embedRepo->find($embedId);
+
+if (!$embed) {
+    api_not_allowed(
+        true,
+        Display::return_message($plugin->get_lang('ContentNotFound'), 'danger')
+    );
+}
+
+if ($course->getId() !== $embed->getCourse()->getId()) {
+    api_not_allowed(true);
+}
+
+if ($session && $embed->getSession()) {
+    if ($session->getId() !== $embed->getSession()->getId()) {
+        api_not_allowed(true);
+    }
+}
+
+$plugin->saveEventAccessTool();
+
+$interbreadcrumb[] = [
+    'name' => $plugin->get_title(),
+    'url' => api_get_path(WEB_PLUGIN_PATH).$plugin->get_name().'/start.php',
+];
+
+$actions = Display::url(
+    Display::return_icon('back.png', get_lang('Back'), [], ICON_SIZE_MEDIUM),
+    api_get_path(WEB_PLUGIN_PATH).$plugin->get_name().'/start.php?'.api_get_cidreq()
+);
+
+$view = new Template($embed->getTitle());
+$view->assign('header', $embed->getTitle());
+$view->assign('actions', Display::toolbarAction($plugin->get_name(), [$actions]));
+$view->assign(
+    'content',
+    '<p>'.$plugin->formatDisplayDate($embed).'</p>'
+        .PHP_EOL
+        .Security::remove_XSS($embed->getHtmlCode(), COURSEMANAGERLOWSECURITY)
+);
+$view->display_one_col_template();

+ 37 - 0
plugin/embedregistry/view/start.tpl

@@ -0,0 +1,37 @@
+{% if is_allowed_to_edit %}
+    {% if external_url is defined %}
+        <div class="alert alert-info">
+            <p>
+                {{ 'YouNeedCreateContent'|get_plugin_lang('EmbedRegistryPlugin') }}
+                <a href="{{ external_url }}" class="btn btn-info" target="_blank">{{ 'CreateContent'|get_plugin_lang('EmbedRegistryPlugin') }}</a>
+            </p>
+        </div>
+    {% endif %}
+
+    {% if form is defined %}
+        {{ form }}
+    {% endif %}
+{% endif %}
+
+{% if current_embed is defined %}
+    {% set start_date %}
+        <time datetime="{{ current_embed.displayStartDate.format(constant('\DateTime::W3C')) }}">
+            {{ current_embed.displayStartDate|api_convert_and_format_date }}
+        </time>
+    {% endset %}
+    {% set end_date %}
+        <time datetime="{{ current_embed.displayEndDate.format(constant('\DateTime::W3C')) }}">
+            {{ current_embed.displayEndDate|api_convert_and_format_date }}
+        </time>
+    {% endset %}
+
+    <div class="well well-sm text-center">
+        <p class="lead">{{ current_embed.title }}</p>
+        <p>
+            <small>{{ 'FromDateXToDateY'|get_lang|format(start_date, end_date) }}</small>
+        </p>
+        <p>{{ current_link }}</p>
+    </div>
+{% endif %}
+
+{{ table }}