Actualización
This commit is contained in:
9
plugin/toplinks/README.md
Normal file
9
plugin/toplinks/README.md
Normal 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
259
plugin/toplinks/admin.php
Normal 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
47
plugin/toplinks/index.php
Normal 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
|
||||
}
|
||||
5
plugin/toplinks/install.php
Normal file
5
plugin/toplinks/install.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
/* For license terms, see /license.txt */
|
||||
|
||||
$plugin = TopLinksPlugin::create()->install();
|
||||
9
plugin/toplinks/lang/english.php
Normal file
9
plugin/toplinks/lang/english.php
Normal 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';
|
||||
9
plugin/toplinks/lang/spanish.php
Normal file
9
plugin/toplinks/lang/spanish.php
Normal 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';
|
||||
5
plugin/toplinks/plugin.php
Normal file
5
plugin/toplinks/plugin.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
/* For license terms, see /license.txt */
|
||||
|
||||
$plugin_info = TopLinksPlugin::create()->get_info();
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
26
plugin/toplinks/src/Entity/Repository/TopLinkRepository.php
Normal file
26
plugin/toplinks/src/Entity/Repository/TopLinkRepository.php
Normal 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);
|
||||
}
|
||||
}
|
||||
137
plugin/toplinks/src/Entity/TopLink.php
Normal file
137
plugin/toplinks/src/Entity/TopLink.php
Normal 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);
|
||||
}
|
||||
}
|
||||
84
plugin/toplinks/src/Entity/TopLinkRelTool.php
Normal file
84
plugin/toplinks/src/Entity/TopLinkRelTool.php
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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'];
|
||||
}
|
||||
}
|
||||
148
plugin/toplinks/src/LinkForm.php
Normal file
148
plugin/toplinks/src/LinkForm.php
Normal 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;
|
||||
}
|
||||
}
|
||||
136
plugin/toplinks/src/TopLinksPlugin.php
Normal file
136
plugin/toplinks/src/TopLinksPlugin.php
Normal 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
29
plugin/toplinks/start.php
Normal 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();
|
||||
5
plugin/toplinks/uninstall.php
Normal file
5
plugin/toplinks/uninstall.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
/* For license terms, see /license.txt */
|
||||
|
||||
$plugin = TopLinksPlugin::create()->uninstall();
|
||||
Reference in New Issue
Block a user