diff --git a/plugin/ims_lti/Entity/ImsLtiTool.php b/plugin/ims_lti/Entity/ImsLtiTool.php index 48503fc424..9f31de9d38 100644 --- a/plugin/ims_lti/Entity/ImsLtiTool.php +++ b/plugin/ims_lti/Entity/ImsLtiTool.php @@ -5,6 +5,7 @@ namespace Chamilo\PluginBundle\Entity\ImsLti; use Chamilo\CoreBundle\Entity\Course; use Chamilo\CoreBundle\Entity\GradebookEvaluation; +use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; /** @@ -59,12 +60,6 @@ class ImsLtiTool * @ORM\Column(name="custom_params", type="text", nullable=true) */ private $customParams = null; - /** - * @var bool - * - * @ORM\Column(name="is_global", type="boolean") - */ - private $isGlobal = false; /** * @var bool * @@ -95,6 +90,21 @@ class ImsLtiTool */ private $gradebookEval = null; + /** + * @var ImsLtiTool|null + * + * @ORM\ManyToOne(targetEntity="Chamilo\PluginBundle\Entity\ImsLti\ImsLtiTool", inversedBy="children") + * @ORM\JoinColumn(name="parent_id", referencedColumnName="id") + */ + private $parent; + + /** + * @var ArrayCollection + * + * @ORM\OneToMany(targetEntity="Chamilo\PluginBundle\Entity\ImsLti\ImsLtiTool", mappedBy="parent") + */ + private $children; + /** * ImsLtiTool constructor. */ @@ -102,11 +112,11 @@ class ImsLtiTool { $this->description = null; $this->customParams = null; - $this->isGlobal = true; $this->activeDeepLinking = false; $this->course = null; $this->gradebookEval =null; $this->privacy = null; + $this->children = new ArrayCollection(); } /** @@ -239,17 +249,6 @@ class ImsLtiTool return $this->course === null; } - /** - * @param bool $isGlobal - * @return ImsLtiTool - */ - public function setIsGlobal($isGlobal) - { - $this->isGlobal = $isGlobal; - - return $this; - } - /** * @return array */ @@ -299,7 +298,7 @@ class ImsLtiTool } /** - * Set course. And set isGlobal according to the course or not. + * Set course. * * @param Course|null $course * @@ -308,7 +307,6 @@ class ImsLtiTool public function setCourse(Course $course = null) { $this->course = $course; - $this->isGlobal = $course === null; return $this; } @@ -406,4 +404,28 @@ class ImsLtiTool { return unserialize($this->privacy); } + + /** + * @return ImsLtiTool|null + */ + public function getParent() + { + return $this->parent; + } + + /** + * @param ImsLtiTool $parent + * + * @return ImsLtiTool + */ + public function setParent(ImsLtiTool $parent) + { + $this->parent = $parent; + + $this->sharedSecret = $parent->getSharedSecret(); + $this->consumerKey = $parent->getConsumerKey(); + $this->privacy = $parent->getPrivacy(); + + return $this; + } } diff --git a/plugin/ims_lti/ImsLtiPlugin.php b/plugin/ims_lti/ImsLtiPlugin.php index bfce57f562..b036a520cb 100644 --- a/plugin/ims_lti/ImsLtiPlugin.php +++ b/plugin/ims_lti/ImsLtiPlugin.php @@ -126,11 +126,11 @@ class ImsLtiPlugin extends Plugin $toolTable->addColumn('consumer_key', Type::STRING); $toolTable->addColumn('shared_secret', Type::STRING); $toolTable->addColumn('custom_params', Type::TEXT)->setNotnull(false); - $toolTable->addColumn('is_global', Type::BOOLEAN); $toolTable->addColumn('active_deep_linking', Type::BOOLEAN)->setDefault(false); $toolTable->addColumn('c_id', Type::INTEGER)->setNotnull(false); $toolTable->addColumn('gradebook_eval_id', Type::INTEGER)->setNotnull(false); $toolTable->addColumn('privacy', Type::TEXT)->setNotnull(false)->setDefault(null); + $toolTable->addColumn('parent_id', Type::INTEGER)->setNotnull(false); $toolTable->addForeignKeyConstraint( 'course', ['c_id'], @@ -145,9 +145,11 @@ class ImsLtiPlugin extends Plugin ['onDelete' => 'SET NULL'], 'FK_C5E47F7C82F80D8B' ); + $toolTable->addForeignKeyConstraint($toolTable, ['parent_id'], ['id'], [], 'FK_C5E47F7C727ACA70'); $toolTable->setPrimaryKey(['id']); $toolTable->addIndex(['c_id'], 'IDX_C5E47F7C91D79BD3'); $toolTable->addIndex(['gradebook_eval_id'], 'IDX_C5E47F7C82F80D8B'); + $toolTable->addIndex(['parent_id'], 'IDX_C5E47F7C727ACA70'); $queries = $pluginSchema->toSql($platform); @@ -378,18 +380,21 @@ class ImsLtiPlugin extends Plugin $url = empty($contentItem['url']) ? $baseLtiTool->getLaunchUrl() : $contentItem['url']; /** @var ImsLtiTool $newLtiTool */ - $newLtiTool = $ltiToolRepo->findOneBy(['launchUrl' => $url, 'isGlobal' => false, 'course' => $course]); + $newLtiTool = $ltiToolRepo->findOneBy(['launchUrl' => $url, 'parent' => $baseLtiTool, 'course' => $course]); - if (empty($newLtiTool)) { + if (null === $newLtiTool) { $newLtiTool = new ImsLtiTool(); $newLtiTool ->setLaunchUrl($url) - ->setConsumerKey( - $baseLtiTool->getConsumerKey() + ->setParent( + $baseLtiTool ) - ->setSharedSecret( - $baseLtiTool->getSharedSecret() - ); + ->setPrivacy( + $baseLtiTool->isSharingName(), + $baseLtiTool->isSharingEmail(), + $baseLtiTool->isSharingEmail() + ) + ->setCourse($course); } $newLtiTool @@ -398,8 +403,7 @@ class ImsLtiPlugin extends Plugin ) ->setDescription( !empty($contentItem['text']) ? $contentItem['text'] : null - ) - ->setCourse($course); + ); $em->persist($newLtiTool); $em->flush(); @@ -460,7 +464,7 @@ class ImsLtiPlugin extends Plugin $toolRepo = $em->getRepository('ChamiloPluginBundle:ImsLti\ImsLtiTool'); /** @var ImsLtiTool $tool */ - $tool = $toolRepo->findOneBy(['id' => $toolId, 'isGlobal' => false, 'course' => $course]); + $tool = $toolRepo->findOneBy(['id' => $toolId, 'course' => $course]); return !empty($tool); } diff --git a/plugin/ims_lti/README.md b/plugin/ims_lti/README.md index 82a106321b..6cff6fd95f 100644 --- a/plugin/ims_lti/README.md +++ b/plugin/ims_lti/README.md @@ -53,8 +53,13 @@ CREATE INDEX IDX_C5E47F7C91D79BD3 ON plugin_ims_lti_tool (c_id); ALTER TABLE plugin_ims_lti_tool ADD gradebook_eval_id INT DEFAULT NULL; ALTER TABLE plugin_ims_lti_tool ADD CONSTRAINT FK_C5E47F7C82F80D8B - FOREIGN KEY (gradebook_eval_id) REFERENCES gradebook_evaluation (id) ON DELETE SET NULL; + FOREIGN KEY (gradebook_eval_id) REFERENCES gradebook_evaluation (id) + ON DELETE SET NULL; CREATE INDEX IDX_C5E47F7C82F80D8B ON plugin_ims_lti_tool (gradebook_eval_id); ALTER TABLE plugin_ims_lti_tool ADD privacy LONGTEXT DEFAULT NULL; +ALTER TABLE plugin_ims_lti_tool ADD parent_id INT DEFAULT NULL, DROP is_global; +ALTER TABLE plugin_ims_lti_tool ADD CONSTRAINT FK_C5E47F7C727ACA70 + FOREIGN KEY (parent_id) REFERENCES plugin_ims_lti_tool (id); +CREATE INDEX IDX_C5E47F7C727ACA70 ON plugin_ims_lti_tool (parent_id); ``` diff --git a/plugin/ims_lti/configure.php b/plugin/ims_lti/configure.php index 87c38b69c9..932566468d 100644 --- a/plugin/ims_lti/configure.php +++ b/plugin/ims_lti/configure.php @@ -20,7 +20,7 @@ $action = !empty($_REQUEST['action']) ? $_REQUEST['action'] : 'add'; /** @var Course $course */ $course = $em->find('ChamiloCoreBundle:Course', api_get_course_int_id()); $addedTools = $toolsRepo->findBy(['course' => $course]); -$globalTools = $toolsRepo->findBy(['isGlobal' => true]); +$globalTools = $toolsRepo->findBy(['parent' => null, 'course' => null]); if ($baseTool && !$baseTool->isGlobal()) { Display::addFlash( @@ -78,6 +78,10 @@ switch ($action) { ); } + if ($baseTool) { + $tool->setParent($baseTool); + } + $em->persist($tool); $em->flush(); @@ -90,11 +94,10 @@ switch ($action) { header('Location: '.api_get_self().'?'.api_get_cidreq()); exit; } + + $form->setDefaultValues(); break; case 'edit': - $form = new FormValidator('ims_lti_edit_tool'); - $form->addHeader($plugin->get_lang('ToolSettings')); - /** @var ImsLtiTool|null $tool */ $tool = null; @@ -102,35 +105,19 @@ switch ($action) { $tool = $em->find('ChamiloPluginBundle:ImsLti\ImsLtiTool', (int) $_REQUEST['id']); } - if (empty($tool)) { - Display::addFlash( - Display::return_message($plugin->get_lang('ToolNotAvailable'), 'warning') - ); - - break; - } - - if (!ImsLtiPlugin::existsToolInCourse($tool->getId(), $course)) { - Display::addFlash( - Display::return_message($plugin->get_lang('ToolNotAvailable'), 'warning') + if (empty($tool) || + !ImsLtiPlugin::existsToolInCourse($tool->getId(), $course) + ) { + api_not_allowed( + true, + Display::return_message($plugin->get_lang('ToolNotAvailable'), 'error') ); break; } - $form->addText('name', get_lang('Title')); - $form->addButtonAdvancedSettings('lti_adv'); - $form->addHtml(''); - $form->addButtonUpdate($plugin->get_lang('EditExternalTool')); - $form->addHidden('id', $tool->getId()); - $form->addHidden('action', 'edit'); - $form->applyFilter('__ALL__', 'Security::remove_XSS'); + $form = new FrmEdit('ims_lti_edit_tool', [], $tool); + $form->build(false); if ($form->validate()) { $formValues = $form->getSubmitValues(); @@ -138,10 +125,25 @@ switch ($action) { $tool ->setName($formValues['name']) ->setDescription($formValues['description']) + ->setActiveDeepLinking( + !empty($formValues['deep_linking']) + ) ->setCustomParams( empty($formValues['custom_params']) ? null : $formValues['custom_params'] + ) + ->setPrivacy( + !empty($formValues['share_name']), + !empty($formValues['share_email']), + !empty($formValues['share_picture']) ); + if (null === $tool->getParent()) { + $tool + ->setLaunchUrl($formValues['launch_url']) + ->setConsumerKey($formValues['consumer_key']) + ->setSharedSecret($formValues['shared_secret']); + } + $em->persist($tool); $em->flush(); @@ -159,11 +161,7 @@ switch ($action) { exit; } - $form->setDefaults([ - 'name' => $tool->getName(), - 'description' => $tool->getDescription(), - 'custom_params' => $tool->getCustomParams(), - ]); + $form->setDefaultValues(); break; } diff --git a/plugin/ims_lti/edit.php b/plugin/ims_lti/edit.php index ff2e442d8d..7d562cc5dd 100644 --- a/plugin/ims_lti/edit.php +++ b/plugin/ims_lti/edit.php @@ -29,28 +29,8 @@ if (!$tool) { exit; } -$form = new FormValidator('ims_lti_edit_tool'); -$form->addText('name', get_lang('Name')); -$form->addText('url', $plugin->get_lang('LaunchUrl')); -$form->addText('consumer_key', $plugin->get_lang('ConsumerKey')); -$form->addText('shared_secret', $plugin->get_lang('SharedSecret')); -$form->addButtonAdvancedSettings('lti_adv'); -$form->addHtml(''); -$form->addButtonSave(get_lang('Save')); -$form->addHidden('id', $tool->getId()); -$form->setDefaults([ - 'name' => $tool->getName(), - 'description' => $tool->getDescription(), - 'url' => $tool->getLaunchUrl(), - 'consumer_key' => $tool->getConsumerKey(), - 'shared_secret' => $tool->getSharedSecret(), - 'custom_params' => $tool->getCustomParams(), - 'deep_linking' => $tool->isActiveDeepLinking(), -]); +$form = new FrmEdit('ims_lti_edit_tool', [], $tool); +$form->build(); if ($form->validate()) { $formValues = $form->exportValues(); @@ -58,10 +38,25 @@ if ($form->validate()) { $tool ->setName($formValues['name']) ->setDescription($formValues['description']) - ->setLaunchUrl($formValues['url']) - ->setConsumerKey($formValues['consumer_key']) - ->setSharedSecret($formValues['shared_secret']) - ->setCustomParams($formValues['custom_params']); + ->setCustomParams($formValues['custom_params']) + ->setPrivacy( + !empty($formValues['share_name']), + !empty($formValues['share_email']), + !empty($formValues['share_picture']) + ); + + if (null === $tool->getParent()) { + $tool + ->setLaunchUrl($formValues['launch_url']) + ->setConsumerKey($formValues['consumer_key']) + ->setSharedSecret($formValues['shared_secret']); + } + + if (null === $tool->getParent() || + (null !== $tool->getParent() && !$tool->getParent()->isActiveDeepLinking()) + ) { + $tool->setActiveDeepLinking(!empty($formValues['deep_linking'])); + } $em->persist($tool); $em->flush(); @@ -74,6 +69,11 @@ if ($form->validate()) { exit; } +$form->setDefaultValues(); + +$interbreadcrumb[] = ['url' => api_get_path(WEB_CODE_PATH).'admin/index.php', 'name' => get_lang('PlatformAdmin')]; +$interbreadcrumb[] = ['url' => api_get_path(WEB_PLUGIN_PATH).'ims_lti/admin.php', 'name' => $plugin->get_title()]; + $template = new Template($plugin->get_lang('EditExternalTool')); $template->assign('form', $form->returnForm()); diff --git a/plugin/ims_lti/lang/english.php b/plugin/ims_lti/lang/english.php index 0fd32312f5..2cc639f2ec 100644 --- a/plugin/ims_lti/lang/english.php +++ b/plugin/ims_lti/lang/english.php @@ -33,3 +33,5 @@ $strings['ToolEdited'] = 'Tool edited'; $strings['ShareLauncherName'] = 'Share launcher\'s name'; $strings['ShareLauncherEmail'] = 'Share launcher\'s email'; $strings['ShareLauncherPicture'] = 'Share launcher\'s picture'; +$strings['NoTool'] = 'Tool not exists'; +$strings['ToolAddedOnCourseX'] = 'Tool addeed on course %s.'; diff --git a/plugin/ims_lti/src/Form/FrmAdd.php b/plugin/ims_lti/src/Form/FrmAdd.php index a5b0207950..a1ea6466b3 100644 --- a/plugin/ims_lti/src/Form/FrmAdd.php +++ b/plugin/ims_lti/src/Form/FrmAdd.php @@ -70,7 +70,10 @@ class FrmAdd extends FormValidator $this->addHtml(''); $this->addButtonCreate($plugin->get_lang('AddExternalTool')); $this->applyFilter('__ALL__', 'Security::remove_XSS'); + } + public function setDefaultValues() + { if (null !== $this->baseTool) { $this->setDefaults( [ diff --git a/plugin/ims_lti/src/Form/FrmEdit.php b/plugin/ims_lti/src/Form/FrmEdit.php new file mode 100644 index 0000000000..5dbfe92b5c --- /dev/null +++ b/plugin/ims_lti/src/Form/FrmEdit.php @@ -0,0 +1,111 @@ +tool = $tool; + } + + /** + * Build the form. + * + * @param bool $globalMode + * + * @throws Exception + */ + public function build($globalMode = true) + { + $plugin = ImsLtiPlugin::create(); + $course = $this->tool->getCourse(); + $parent = $this->tool->getParent(); + + $this->addHeader($plugin->get_lang('ToolSettings')); + + if (null !== $course && $globalMode) { + $this->addHtml( + Display::return_message( + sprintf($plugin->get_lang('ToolAddedOnCourseX'), $course->getTitle()), + 'normal', + false + ) + ); + } + + $this->addText('name', get_lang('Name')); + $this->addTextarea('description', get_lang('Description')); + + if (null === $parent) { + $this->addElement('url', 'launch_url', $plugin->get_lang('LaunchUrl')); + $this->addRule('launch_url', get_lang('Required'), 'required'); + $this->addText('consumer_key', $plugin->get_lang('ConsumerKey')); + $this->addText('shared_secret', $plugin->get_lang('SharedSecret')); + } + + $this->addButtonAdvancedSettings('lti_adv'); + $this->addHtml(''); + $this->addButtonAdvancedSettings('lti_privacy', get_lang('Privacy')); + $this->addHtml(''); + $this->addButtonCreate($plugin->get_lang('EditExternalTool')); + $this->addHidden('id', $this->tool->getId()); + $this->addHidden('action', 'edit'); + $this->applyFilter('__ALL__', 'Security::remove_XSS'); + } + + public function setDefaultValues() + { + $this->setDefaults( + [ + 'name' => $this->tool->getName(), + 'description' => $this->tool->getDescription(), + 'launch_url' => $this->tool->getLaunchUrl(), + 'consumer_key' => $this->tool->getConsumerKey(), + 'shared_secret' => $this->tool->getSharedSecret(), + 'custom_params' => $this->tool->getCustomParams(), + 'deep_linking' => $this->tool->isActiveDeepLinking(), + 'share_name' => $this->tool->isSharingName(), + 'share_email' => $this->tool->isSharingEmail(), + 'share_picture' => $this->tool->isSharingPicture(), + ] + ); + } +}