This commit is contained in:
Xes
2025-08-14 22:39:38 +02:00
parent 3641e93527
commit 5403f346e3
3370 changed files with 327179 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
# Top Links
As an administrator (from the administration page in the plugin block) you will be able to create new links, that will appear in all courses as a new tool.
Those new links/tools will appear first in the list of tools for learners.
## Configuration
1. Install the plugin
2. Assign the `pre_footer` and `menu_administrator` regions to the plugin.

259
plugin/toplinks/admin.php Normal file
View File

@@ -0,0 +1,259 @@
<?php
/* For license terms, see /license.txt */
use Chamilo\CoreBundle\Entity\Course as CourseEntity;
use Chamilo\PluginBundle\Entity\TopLinks\TopLink;
use Chamilo\PluginBundle\Entity\TopLinks\TopLinkRelTool;
use Chamilo\PluginBundle\TopLinks\Form\LinkForm as TopLinkForm;
use Symfony\Component\Filesystem\Filesystem;
$cidReset = true;
require_once __DIR__.'/../../main/inc/global.inc.php';
api_protect_admin_script();
$plugin = TopLinksPlugin::create();
$httpRequest = \Symfony\Component\HttpFoundation\Request::createFromGlobals();
$pageBaseUrl = api_get_self();
$em = Database::getManager();
$linkRepo = $em->getRepository(TopLink::class);
$pageTitle = $plugin->get_title();
$pageActions = Display::url(
Display::return_icon('back.png', get_lang('Back'), [], ICON_SIZE_MEDIUM),
$pageBaseUrl
);
$pageContent = '';
$interbreadcrumb[] = [
'name' => get_lang('Administration'),
'url' => api_get_path(WEB_CODE_PATH).'admin/index.php',
];
$interbreadcrumb[] = ['name' => $plugin->get_title(), 'url' => $pageBaseUrl];
switch ($httpRequest->query->getAlpha('action', 'list')) {
case 'list':
default:
array_pop($interbreadcrumb); // Only show link to administration in breadcrumb
$pageActions = Display::url(
Display::return_icon('add.png', get_lang('AddLink'), [], ICON_SIZE_MEDIUM),
"$pageBaseUrl?".http_build_query(['action' => 'add'])
);
$table = new SortableTable(
'toplinks',
function () use ($linkRepo) {
return $linkRepo->count([]);
},
function ($offset, $limit, $column, $direction) use ($linkRepo) {
$links = $linkRepo->all($offset, $limit, $column, $direction);
return array_map(
function (TopLink $link) {
return [
[$link->getTitle(), $link->getUrl()],
$link->getId(),
];
},
$links
);
},
0
);
$table->set_header(0, get_lang('LinkName'));
$table->set_header(1, get_lang('Actions'), false, ['class' => 'th-head text-right'], ['class' => 'text-right']);
$table->set_column_filter(
0,
function (array $params) {
[$title, $url] = $params;
return "$title<br>".Display::url($url, $url);
}
);
$table->set_column_filter(
1,
function (int $id) use ($pageBaseUrl, $em, $plugin) {
$missingCourses = $em->getRepository(TopLinkRelTool::class)->getMissingCoursesForTool($id);
$countMissingCourses = count($missingCourses);
$actions = [];
$actions[] = Display::url(
Display::return_icon('edit.png', get_lang('Edit')),
"$pageBaseUrl?".http_build_query(['action' => 'edit', 'link' => $id])
);
if (count($missingCourses) > 0) {
$actions[] = Display::url(
Display::return_icon(
'view_tree.png',
sprintf($plugin->get_lang('ReplicateInXMissingCourses'), $countMissingCourses)
),
"$pageBaseUrl?".http_build_query(['action' => 'replicate', 'link' => $id])
);
} else {
$actions[] = Display::return_icon(
'view_tree_na.png',
$plugin->get_lang('AlreadyReplicatedInAllCourses')
);
}
$actions[] = Display::url(
Display::return_icon('delete.png', get_lang('Delete')),
"$pageBaseUrl?".http_build_query(['action' => 'delete', 'link' => $id])
);
return implode(PHP_EOL, $actions);
}
);
if ($table->total_number_of_items) {
$pageContent = $table->return_table();
} else {
$pageContent = Display::return_message(
get_lang('NoData'),
'info'
);
}
break;
case 'add':
$pageTitle = get_lang('LinkAdd');
$form = new TopLinkForm();
$form->createElements();
if ($form->validate()) {
$values = $form->exportValues();
$link = new TopLink();
$link
->setTitle($values['title'])
->setUrl($values['url'])
->setTarget($values['target']);
$em->persist($link);
$em->flush();
$iconPath = $form
->setLink($link)
->saveImage();
$link->setIcon($iconPath);
$em->flush();
Display::addFlash(
Display::return_message(get_lang('LinkAdded'), 'success')
);
header("Location: $pageBaseUrl");
exit;
}
$pageContent = $form->returnForm();
break;
case 'edit':
$pageTitle = get_lang('LinkMod');
$link = $em->find(TopLink::class, $httpRequest->query->getInt('link'));
if (null === $link) {
Display::addFlash(
Display::return_message(get_lang('NotFound'), 'error')
);
header("Location: $pageBaseUrl");
exit;
}
$form = new TopLinkForm($link);
$form->createElements();
if ($form->validate()) {
$values = $form->exportValues();
$iconPath = $form->saveImage();
$link
->setTitle($values['title'])
->setUrl($values['url'])
->setIcon($iconPath)
->setTarget($values['target']);
$em->flush();
$em->getRepository(TopLinkRelTool::class)->updateTools($link);
Display::addFlash(
Display::return_message(get_lang('LinkModded'), 'success')
);
header("Location: $pageBaseUrl");
exit;
}
$pageContent = $form->returnForm();
break;
case 'delete':
$link = $em->find(TopLink::class, $httpRequest->query->getInt('link'));
if (null === $link) {
Display::addFlash(
Display::return_message(get_lang('NotFound'), 'error')
);
header("Location: $pageBaseUrl");
exit;
}
if ($link->getIcon()) {
$fullIconPath = api_get_path(SYS_UPLOAD_PATH).'plugins/toplinks/'.$link->getIcon();
$fs = new Filesystem();
$fs->remove($fullIconPath);
}
$em->remove($link);
$em->flush();
Display::addFlash(
Display::return_message(get_lang('LinkDeleted'), 'success')
);
header("Location: $pageBaseUrl");
exit;
case 'replicate':
$link = $em->find(TopLink::class, $httpRequest->query->getInt('link'));
if (null === $link) {
Display::addFlash(
Display::return_message(get_lang('NotFound'), 'error')
);
header("Location: $pageBaseUrl");
exit;
}
$missingCourses = $em->getRepository(TopLinkRelTool::class)->getMissingCoursesForTool($link->getId());
/** @var CourseEntity $missingCourse */
foreach ($missingCourses as $missingCourse) {
$plugin->addToolInCourse($missingCourse->getId(), $link);
}
Display::addFlash(
Display::return_message($plugin->get_lang('LinkReplicated'), 'success')
);
header("Location: $pageBaseUrl");
exit;
}
$view = new Template($plugin->get_title());
$view->assign('header', $pageTitle);
$view->assign('actions', Display::toolbarAction('xapi_actions', [$pageActions]));
$view->assign('content', $pageContent);
$view->display_one_col_template();

47
plugin/toplinks/index.php Normal file
View File

@@ -0,0 +1,47 @@
<?php
/* For license terms, see /license.txt */
use Chamilo\PluginBundle\Entity\TopLinks\TopLinkRelTool;
$httpRequest = \Symfony\Component\HttpFoundation\Request::createFromGlobals();
if ('/main/course_home/course_home.php' === $httpRequest->getScriptName()) {
$course = api_get_course_entity();
$em = Database::getManager();
$linkToolRepo = $em->getRepository(TopLinkRelTool::class);
$linkTools = $linkToolRepo->findInCourse($course);
$toolIds = [];
/** @var TopLinkRelTool $linkTool */
foreach ($linkTools as $linkTool) {
$toolIds[] = [
'id' => $linkTool->getTool()->getIid(),
'img' => $linkTool->getLink()->getIcon()
? api_get_path(WEB_UPLOAD_PATH).'plugins/toplinks/'.$linkTool->getLink()->getIcon()
: null,
];
} ?>
<script>
$(function () {
var ids = JSON.parse('<?php echo json_encode($toolIds); ?>');
$(ids).each(function (index, iconTool) {
var $toolA = $('#tooldesc_' + iconTool.id);
var $toolImg = $toolA.find('img#toolimage_' + iconTool.id);
if (iconTool.img) {
$toolImg.prop('src', iconTool.img).data('forced-src', iconTool.img);
}
var $block = $toolA.parents('.course-tool').parent();
$block.prependTo($block.parent());
});
});
</script>
<?php
}

View File

@@ -0,0 +1,5 @@
<?php
/* For license terms, see /license.txt */
$plugin = TopLinksPlugin::create()->install();

View File

@@ -0,0 +1,9 @@
<?php
/* For license terms, see /license.txt */
$strings['plugin_title'] = 'Top Links';
$strings['plugin_comment'] = 'Create links in all courses and position them on the top of the course tools';
$strings['ReplicateInXMissingCourses'] = 'Replicate in %d missing courses';
$strings['AlreadyReplicatedInAllCourses'] = 'Already replicated in all courses';
$strings['LinkReplicated'] = 'Link replicated in courses';

View File

@@ -0,0 +1,9 @@
<?php
/* For license terms, see /license.txt */
$strings['plugin_title'] = 'Top Links';
$strings['plugin_comment'] = 'Crea enlaces en todos los cursos y los posiciona al inicio de la lista de herramientas del curso.';
$strings['ReplicateInXMissingCourses'] = 'Replicar en %d cursos faltantes';
$strings['AlreadyReplicatedInAllCourses'] = 'Replicado en todos los cursos';
$strings['LinkReplicated'] = 'Enlace replicado en los cursos';

View File

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

View File

@@ -0,0 +1,78 @@
<?php
/* For license terms, see /license.txt */
namespace Chamilo\PluginBundle\Entity\TopLinks\Repository;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CourseBundle\Entity\CTool;
use Chamilo\PluginBundle\Entity\TopLinks\TopLink;
use Chamilo\PluginBundle\Entity\TopLinks\TopLinkRelTool;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query\Expr\Join;
/**
* Class TopLinkRelToolRepository.
*
* @package Chamilo\PluginBundle\Entity\TopLinks\Repository
*/
class TopLinkRelToolRepository extends EntityRepository
{
public function findInCourse(Course $course)
{
$qb = $this->createQueryBuilder('tlrt');
return $qb
->innerJoin('tlrt.tool', 'tool', Join::WITH)
->where($qb->expr()->eq('tool.cId', ':course'))
->setParameter('course', $course)
->getQuery()
->getResult();
}
public function updateTools(TopLink $link)
{
$subQb = $this->createQueryBuilder('tlrt');
$subQb
->select('tool.iid')
->innerJoin('tlrt.tool', 'tool', Join::WITH)
->where($subQb->expr()->eq('tlrt.link', ':link'))
->setParameter('link', $link);
$linkTools = $subQb->getQuery()->getArrayResult();
$qb = $this->_em->createQueryBuilder();
$qb
->update(CTool::class, 'tool')
->set('tool.name', ':link_name')
->set('tool.target', ':link_target')
->where(
$qb->expr()->in('tool.iid', ':tools')
)
->setParameter('link_name', $link->getTitle())
->setParameter('link_target', $link->getTarget())
->setParameter('tools', array_column($linkTools, 'iid'))
->getQuery()
->execute();
}
public function getMissingCoursesForTool(int $linkId)
{
$qb = $this->_em->createQueryBuilder();
$subQb = $this->_em->createQueryBuilder();
$subQb
->select('t.cId')
->from(CTool::class, 't')
->innerJoin(TopLinkRelTool::class, 'tlrt', Join::WITH, $subQb->expr()->eq('t.iid', 'tlrt.tool'))
->where($subQb->expr()->eq('tlrt.link', ':link_id'));
return $qb
->select('c')
->from(Course::class, 'c')
->where($qb->expr()->notIn('c.id', $subQb->getDQL()))
->setParameter('link_id', $linkId)
->getQuery()
->getResult();
}
}

View File

@@ -0,0 +1,26 @@
<?php
/* For license terms, see /license.txt */
namespace Chamilo\PluginBundle\Entity\TopLinks\Repository;
use Doctrine\ORM\EntityRepository;
/**
* Class TopLinkRepository.
*
* @package Chamilo\PluginBundle\Entity\TopLinks
*/
class TopLinkRepository extends EntityRepository
{
public function all($offset, $limit, $column, $direction): array
{
$orderBy = ['title' => $direction];
if (1 == $column) {
$orderBy = ['url' => $direction];
}
return parent::findBy([], $orderBy, $limit, $offset);
}
}

View File

@@ -0,0 +1,137 @@
<?php
/* For license terms, see /license.txt */
namespace Chamilo\PluginBundle\Entity\TopLinks;
use Chamilo\CourseBundle\Entity\CTool;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* Class TopLink.
*
* @package Chamilo\PluginBundle\Entity\TopLinks
*
* @ORM\Table(name="toplinks_link")
* @ORM\Entity(repositoryClass="Chamilo\PluginBundle\Entity\TopLinks\Repository\TopLinkRepository")
*/
class TopLink
{
/**
* @var int
*
* @ORM\Column(type="integer", name="id")
* @ORM\Id()
* @ORM\GeneratedValue()
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="title", type="string")
*/
private $title;
/**
* @var string
*
* @ORM\Column(name="url", type="text")
*/
private $url;
/**
* @var string
*
* @ORM\Column(name="target", type="string", length=10, options={"default":"_blank"})
*/
private $target;
/**
* @var string|null
*
* @ORM\Column(name="icon", type="string", nullable=true)
*/
private $icon;
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\OneToMany(targetEntity="Chamilo\PluginBundle\Entity\TopLinks\TopLinkRelTool", mappedBy="link", orphanRemoval=true, cascade={"persist", "remove"})
*/
private $tools;
public function __construct()
{
$this->target = '_blank';
$this->icon = null;
$this->tools = new ArrayCollection();
}
public function getId(): int
{
return $this->id;
}
public function getTitle(): string
{
return $this->title;
}
public function setTitle(string $title): TopLink
{
$this->title = $title;
return $this;
}
public function getUrl(): string
{
return $this->url;
}
public function setUrl(string $url): TopLink
{
$this->url = $url;
return $this;
}
public function getTarget(): string
{
return $this->target;
}
public function setTarget(string $target): TopLink
{
$this->target = $target;
return $this;
}
public function getIcon(): ?string
{
return $this->icon;
}
public function setIcon(string $icon = null): TopLink
{
$this->icon = $icon;
return $this;
}
/**
* @return \Doctrine\Common\Collections\Collection
*/
public function getTools()
{
return $this->tools;
}
public function addTool(CTool $tool)
{
$linkTool = new TopLinkRelTool();
$linkTool
->setTool($tool)
->setLink($this);
$this->tools->add($linkTool);
}
}

View File

@@ -0,0 +1,84 @@
<?php
/* For license terms, see /license.txt */
namespace Chamilo\PluginBundle\Entity\TopLinks;
use Chamilo\CourseBundle\Entity\CTool;
use Doctrine\ORM\Mapping as ORM;
/**
* Class TopLinkRelTool.
*
* @package Chamilo\PluginBundle\Entity\TopLinks
*
* @ORM\Table(name="toplinks_link_rel_tool")
* @ORM\Entity(repositoryClass="Chamilo\PluginBundle\Entity\TopLinks\Repository\TopLinkRelToolRepository")
*/
class TopLinkRelTool
{
/**
* @var int
*
* @ORM\Column(type="integer", name="id")
* @ORM\Id()
* @ORM\GeneratedValue()
*/
private $id;
/**
* @var \Chamilo\PluginBundle\Entity\TopLinks\TopLink
*
* @ORM\ManyToOne(targetEntity="Chamilo\PluginBundle\Entity\TopLinks\TopLink", inversedBy="tools")
* @ORM\JoinColumn(name="link_id", referencedColumnName="id")
*/
private $link;
/**
* @var \Chamilo\CourseBundle\Entity\CTool
*
* @ORM\OneToOne(targetEntity="Chamilo\CourseBundle\Entity\CTool", cascade={"persist", "remove"})
* @ORM\JoinColumn(name="tool_id", referencedColumnName="iid", nullable=true, onDelete="CASCADE")
*/
private $tool;
public function getId(): int
{
return $this->id;
}
public function setId(int $id): TopLinkRelTool
{
$this->id = $id;
return $this;
}
/**
* @return \Chamilo\PluginBundle\Entity\TopLinks\TopLink
*/
public function getLink(): TopLink
{
return $this->link;
}
/**
* @param \Chamilo\PluginBundle\Entity\TopLinks\TopLink $link
*/
public function setLink(TopLink $link): TopLinkRelTool
{
$this->link = $link;
return $this;
}
public function getTool(): CTool
{
return $this->tool;
}
public function setTool(CTool $tool): TopLinkRelTool
{
$this->tool = $tool;
return $this;
}
}

View File

@@ -0,0 +1,40 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\PluginBundle\Entity\TopLinks\TopLink;
/**
* Class TopLinksCreateCourseHookObserver.
*/
class TopLinksCreateCourseHookObserver extends HookObserver implements HookCreateCourseObserverInterface
{
/**
* XApiCreateCourseHookObserver constructor.
*/
protected function __construct()
{
parent::__construct('plugin/toplinks/src/TopLinksPlugin.php', 'toplinks');
}
public function hookCreateCourse(HookCreateCourseEventInterface $hook): int
{
$data = $hook->getEventData();
$type = $data['type'];
$courseInfo = $data['course_info'];
$plugin = TopLinksPlugin::create();
$em = Database::getManager();
$linkRepo = $em->getRepository(TopLink::class);
if (HOOK_EVENT_TYPE_POST == $type) {
foreach ($linkRepo->findAll() as $link) {
$plugin->addToolInCourse($courseInfo['real_id'], $link);
}
}
return (int) $courseInfo['real_id'];
}
}

View File

@@ -0,0 +1,148 @@
<?php
/* For license terms, see /license.txt */
namespace Chamilo\PluginBundle\TopLinks\Form;
use Chamilo\PluginBundle\Entity\TopLinks\TopLink;
use FormValidator;
use Image;
use Security;
use Symfony\Component\Filesystem\Filesystem;
/**
* Class LinkForm.
*
* @package Chamilo\PluginBundle\TopLinks\Form
*/
class LinkForm extends FormValidator
{
/**
* @var TopLink
*/
private $link;
/**
* LinkForm constructor.
*/
public function __construct(TopLink $link = null)
{
$this->link = $link;
$actionParams = [
'action' => 'add',
'sec_token' => Security::get_existing_token(),
];
if ($this->link) {
$actionParams['action'] = 'edit';
$actionParams['link'] = $this->link->getId();
}
$action = api_get_self().'?'.http_build_query($actionParams);
parent::__construct('frm_link', 'post', $action, '');
}
public function validate(): bool
{
return parent::validate() && Security::check_token('get');
}
public function exportValues($elementList = null)
{
Security::clear_token();
return parent::exportValues($elementList);
}
public function createElements()
{
global $htmlHeadXtra;
$htmlHeadXtra[] = api_get_css_asset('cropper/dist/cropper.min.css');
$htmlHeadXtra[] = api_get_asset('cropper/dist/cropper.min.js');
$this->addText('title', get_lang('LinkName'));
$this->addUrl('url', 'URL');
$this->addRule('url', get_lang('GiveURL'), 'url');
$this->addSelect(
'target',
[
get_lang('LinkTarget'),
get_lang('AddTargetOfLinkOnHomepage'),
],
[
'_blank' => get_lang('LinkOpenBlank'),
'_self' => get_lang('LinkOpenSelf'),
]
);
$this->addFile(
'picture',
[
$this->link ? get_lang('UpdateImage') : get_lang('AddImage'),
get_lang('OnlyImagesAllowed'),
],
[
'id' => 'picture',
'class' => 'picture-form',
'crop_image' => true,
'crop_ratio' => '1 / 1',
'accept' => 'image/*',
]
);
$allowedPictureTypes = api_get_supported_image_extensions(false);
$this->addRule(
'picture',
get_lang('OnlyImagesAllowed').' ('.implode(', ', $allowedPictureTypes).')',
'filetype',
$allowedPictureTypes
);
$this->addButtonSave(get_lang('SaveLink'), 'submitLink');
}
public function returnForm()
{
$defaults = [];
if ($this->link) {
$defaults['title'] = $this->link->getTitle();
$defaults['url'] = $this->link->getUrl();
$defaults['target'] = $this->link->getTarget();
}
$this->setDefaults($defaults);
return parent::returnForm(); // TODO: Change the autogenerated stub
}
public function setLink(TopLink $link): LinkForm
{
$this->link = $link;
return $this;
}
public function saveImage(): ?string
{
$pictureCropResult = $this->exportValue('picture_crop_result');
if (empty($pictureCropResult)) {
return null;
}
$extension = pathinfo($_FILES['picture']['name'], PATHINFO_EXTENSION);
$newFilename = md5($this->link->getId()).".$extension";
$directoryName = api_get_path(SYS_UPLOAD_PATH).'plugins/toplinks';
$fs = new Filesystem();
$fs->mkdir($directoryName, api_get_permissions_for_new_directories());
$image = new Image($_FILES['picture']['tmp_name']);
$image->crop($pictureCropResult);
$image->resize(ICON_SIZE_BIG);
$image->send_image("$directoryName/$newFilename");
return $newFilename;
}
}

View File

@@ -0,0 +1,136 @@
<?php
/* For license terms, see /license.txt */
use Chamilo\PluginBundle\Entity\TopLinks\TopLink;
use Chamilo\PluginBundle\Entity\TopLinks\TopLinkRelTool;
use Doctrine\ORM\Tools\SchemaTool;
/**
* Class TopLinksPlugin.
*/
class TopLinksPlugin extends Plugin implements HookPluginInterface
{
/**
* TopLinksPlugin constructor.
*/
protected function __construct()
{
$settings = [
];
parent::__construct(
'0.1',
'Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>',
$settings
);
}
/**
* @return \TopLinksPlugin
*/
public static function create(): TopLinksPlugin
{
static $result = null;
return $result ? $result : $result = new self();
}
/**
* {@inheritdoc}
*/
public function getAdminUrl()
{
$webPath = api_get_path(WEB_PLUGIN_PATH).$this->get_name();
return "$webPath/admin.php";
}
public function addToolInCourse(int $courseId, TopLink $link)
{
// The $link param is set to "../plugin" as a hack to link correctly to the plugin URL in course tool.
// Otherwise, the link en the course tool will link to "/main/" URL.
$tool = $this->createLinkToCourseTool(
$link->getTitle(),
$courseId,
'external_link.png',
'../plugin/toplinks/start.php?'.http_build_query(['link' => $link->getId()]),
0,
'authoring'
);
if (null === $tool) {
return;
}
$tool->setTarget($link->getTarget());
$link->addTool($tool);
$em = Database::getManager();
$em->persist($link);
$em->flush();
}
public function install()
{
$em = Database::getManager();
$schemaManager = $em->getConnection()->getSchemaManager();
$tableReferences = [
'toplinks_link' => $em->getClassMetadata(TopLink::class),
'toplinks_link_rel_tool' => $em->getClassMetadata(TopLinkRelTool::class),
];
$tablesExists = $schemaManager->tablesExist(array_keys($tableReferences));
if ($tablesExists) {
return;
}
$schemaTool = new SchemaTool($em);
$schemaTool->createSchema(array_values($tableReferences));
$this->installHook();
}
public function installHook(): int
{
$createCourseObserver = TopLinksCreateCourseHookObserver::create();
HookCreateCourse::create()->attach($createCourseObserver);
return 1;
}
public function uninstall()
{
$em = Database::getManager();
$tableReferences = [
'toplinks_link' => $em->getClassMetadata(TopLink::class),
'toplinks_link_rel_tool' => $em->getClassMetadata(TopLinkRelTool::class),
];
$schemaTool = new SchemaTool($em);
$schemaTool->dropSchema(array_values($tableReferences));
$this->uninstallHook();
$this->deleteCourseTools();
}
public function uninstallHook(): int
{
$createCourseObserver = TopLinksCreateCourseHookObserver::create();
HookCreateCourse::create()->detach($createCourseObserver);
return 1;
}
private function deleteCourseTools()
{
Database::getManager()
->createQuery('DELETE FROM ChamiloCourseBundle:CTool t WHERE t.category = :category AND t.link LIKE :link')
->execute(['category' => 'authoring', 'link' => '../plugin/toplinks/start.php%']);
}
}

29
plugin/toplinks/start.php Normal file
View File

@@ -0,0 +1,29 @@
<?php
/* For license terms, see /license.txt */
use Chamilo\PluginBundle\Entity\TopLinks\TopLink;
use Symfony\Component\HttpFoundation\RedirectResponse;
require_once __DIR__.'/../../main/inc/global.inc.php';
api_protect_course_script(true);
api_block_anonymous_users();
$plugin = TopLinksPlugin::create();
$httpRequest = \Symfony\Component\HttpFoundation\Request::createFromGlobals();
$em = Database::getManager();
$link = $em->find(TopLink::class, $httpRequest->query->getInt('link'));
if (null === $link) {
Display::addFlash(
Display::return_message(get_lang('NotFound'), 'error')
);
RedirectResponse::create(api_get_course_url())->send();
exit;
}
RedirectResponse::create($link->getUrl())->send();

View File

@@ -0,0 +1,5 @@
<?php
/* For license terms, see /license.txt */
$plugin = TopLinksPlugin::create()->uninstall();