upgrade
This commit is contained in:
@@ -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%']);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user