Browse Source

Adding Installer bundle, fixing index page

Julio Montoya 10 năm trước cách đây
mục cha
commit
4dc4cbe28a
43 tập tin đã thay đổi với 1654 bổ sung412 xóa
  1. 3 1
      app/config/sonata/sonata_page.yml
  2. 4 4
      composer.json
  3. 12 0
      main/inc/lib/chamilo_session.class.php
  4. 2 0
      main/inc/lib/internationalization.lib.php
  5. 62 1
      src/ChamiloLMS/CoreBundle/Admin/CourseAdmin.php
  6. 14 0
      src/ChamiloLMS/CoreBundle/ChamiloLMSCoreBundle.php
  7. 13 2
      src/ChamiloLMS/CoreBundle/Controller/BaseController.php
  8. 4 157
      src/ChamiloLMS/CoreBundle/Controller/IndexController.php
  9. 2 3
      src/ChamiloLMS/CoreBundle/Controller/LegacyController.php
  10. 70 74
      src/ChamiloLMS/CoreBundle/DataFixtures/ORM/LoadPageData.php
  11. 0 3
      src/ChamiloLMS/CoreBundle/DataFixtures/ORM/LoadPortalData.php
  12. 46 7
      src/ChamiloLMS/CoreBundle/Entity/Course.php
  13. 41 0
      src/ChamiloLMS/CoreBundle/Entity/Listener/CourseListener.php
  14. 194 0
      src/ChamiloLMS/CoreBundle/Entity/TrackAttemptJury.php
  15. 1 1
      src/ChamiloLMS/CoreBundle/Entity/UsergroupRelUser.php
  16. 14 8
      src/ChamiloLMS/CoreBundle/EventListener/MessageListener.php
  17. 10 4
      src/ChamiloLMS/CoreBundle/EventListener/ShowUserListener.php
  18. 2 2
      src/ChamiloLMS/CoreBundle/Menu/MainMenuBuilder.php
  19. 7 41
      src/ChamiloLMS/CoreBundle/Menu/SimpleMenuBuilder.php
  20. 1 0
      src/ChamiloLMS/CoreBundle/Resources/config/admin.yml
  21. 0 5
      src/ChamiloLMS/CoreBundle/Resources/config/routing.yml
  22. 22 0
      src/ChamiloLMS/CoreBundle/Resources/config/services.yml
  23. 544 0
      src/ChamiloLMS/CoreBundle/Resources/views/Calendar/month.html.twig
  24. 2 0
      src/ChamiloLMS/CoreBundle/Resources/views/Index/index.html.twig
  25. 0 1
      src/ChamiloLMS/CoreBundle/Resources/views/Index/userportal.html.twig
  26. 8 0
      src/ChamiloLMS/CourseBundle/ChamiloLMSCourseBundle.php
  27. 89 11
      src/ChamiloLMS/CourseBundle/Controller/Home/HomeController.php
  28. 33 0
      src/ChamiloLMS/CourseBundle/DependencyInjection/Compiler/ToolCompilerClass.php
  29. 4 1
      src/ChamiloLMS/CourseBundle/Entity/CTool.php
  30. 0 0
      src/ChamiloLMS/CourseBundle/Resources/config/routing.yml
  31. 19 0
      src/ChamiloLMS/CourseBundle/Resources/config/services.yml
  32. 0 0
      src/ChamiloLMS/CourseBundle/Resources/views/Home/add.tpl
  33. 0 0
      src/ChamiloLMS/CourseBundle/Resources/views/Home/edit.tpl
  34. 2 0
      src/ChamiloLMS/CourseBundle/Resources/views/Home/index.html.twig
  35. 0 0
      src/ChamiloLMS/CourseBundle/Resources/views/Home/list.tpl
  36. 35 0
      src/ChamiloLMS/CourseBundle/Tool/BaseTool.php
  37. 36 0
      src/ChamiloLMS/CourseBundle/Tool/Calendar.php
  38. 37 0
      src/ChamiloLMS/CourseBundle/Tool/Document.php
  39. 36 0
      src/ChamiloLMS/CourseBundle/Tool/ToolInterface.php
  40. 36 0
      src/ChamiloLMS/CourseBundle/ToolChain.php
  41. 46 0
      src/ChamiloLMS/InstallerBundle/ChamiloLMSInstallerBundle.php
  42. 186 0
      src/ChamiloLMS/InstallerBundle/Command/InstallCommand.php
  43. 17 86
      tests/doctrine_console/cli-config.php

+ 3 - 1
app/config/sonata/sonata_page.yml

@@ -22,6 +22,7 @@ sonata_page:
         - ^_(.*)            # ignore symfony routes
         - login
         - home
+        - homepage
         - (.*)fos_user_(.*)
 
     ignore_routes:
@@ -82,7 +83,8 @@ sonata_page:
                      F: footer
 
         2columns:
-            path: 'ApplicationSonataPageBundle::default_2columns_layout.html.twig'
+            #path: 'ApplicationSonataPageBundle::default_2columns_layout.html.twig'
+            path: 'ChamiloLMSCoreBundle::main_layout.html.twig'
             name: '2 columns layout'
             containers:
                  header:

+ 4 - 4
composer.json

@@ -48,22 +48,22 @@
         "twig/twig": "~1.12",
         "twig/extensions": "~1.0",
 
-        "symfony/symfony": "~2.4",
+        "symfony/symfony": "~2.5",
 
         "symfony/assetic-bundle": "~2.3",
         "symfony/swiftmailer-bundle": "~2.3",
         "symfony/monolog-bundle": "~2.3",
 
         "sensio/distribution-bundle": "~2.3",
-        "sensio/framework-extra-bundle": "~2.3",
+        "sensio/framework-extra-bundle": "~3.0.0",
         "sensio/generator-bundle": "~2.3",
 
         "jms/security-extra-bundle": "~1.5",
         "jms/di-extra-bundle": "~1.4",
         "jms/serializer-bundle": "~0.11",
 
-        "doctrine/orm": "~2.4",
-        "doctrine/doctrine-bundle": "~1.2",
+        "doctrine/orm": "2.4.2",
+        "doctrine/doctrine-bundle": "~1.3@dev",
         "doctrine/doctrine-migrations-bundle": "dev-master",
         "doctrine/migrations": "dev-master",
         "doctrine/doctrine-fixtures-bundle": "~2.2",

+ 12 - 0
main/inc/lib/chamilo_session.class.php

@@ -19,6 +19,7 @@ class ChamiloSession
     public static $configDir;
     public static $assets;
     public static $htmlEditor;
+    public static $twig;
 
     /**
      * @return string
@@ -28,6 +29,9 @@ class ChamiloSession
         return self::$configDir;
     }
 
+    /**
+     * @return string
+     */
     public static function getLogDir()
     {
         return self::$logDir;
@@ -65,6 +69,14 @@ class ChamiloSession
         return self::$courseDir;
     }
 
+    /**
+     * @return Twig_Environment
+     */
+    public static function getTwig()
+    {
+        return self::$twig;
+    }
+
     /**
      * @return ChamiloLMS\CoreBundle\Component\Editor\Editor
      */

+ 2 - 0
main/inc/lib/internationalization.lib.php

@@ -123,6 +123,8 @@ function api_purify_language_id($language)
  */
 function api_get_language_isocode($language = null, $default_code = 'en')
 {
+    return Session::getTranslator()->getLocale();
+
     static $iso_code = array();
     if (empty($language)) {
         $language = api_get_interface_language(false, true);

+ 62 - 1
src/ChamiloLMS/CoreBundle/Admin/CourseAdmin.php

@@ -2,11 +2,14 @@
 
 namespace ChamiloLMS\CoreBundle\Admin;
 
+use ChamiloLMS\CoreBundle\Entity\Listener\CourseListener;
+use ChamiloLMS\CourseBundle\Entity\CTool;
 use Sonata\AdminBundle\Admin\Admin;
 use Sonata\AdminBundle\Form\FormMapper;
 use Sonata\AdminBundle\Datagrid\DatagridMapper;
 use Sonata\AdminBundle\Datagrid\ListMapper;
 use Sonata\AdminBundle\Show\ShowMapper;
+use ChamiloLMS\CourseBundle\ToolChain;
 
 use Knp\Menu\ItemInterface as MenuItemInterface;
 
@@ -80,8 +83,8 @@ class CourseAdmin extends Admin
     {
         $listMapper
             ->addIdentifier('id')
-            ->addIdentifier('code')
             ->addIdentifier('title')
+            ->addIdentifier('code')
         ;
     }
 
@@ -94,5 +97,63 @@ class CourseAdmin extends Admin
     {
         $course->setUsers($course->getUsers());
         $course->setUrls($course->getUrls());
+        $this->updateTools($course);
+    }
+
+    /**
+     * @param Course $course
+     * @return mixed|void
+     */
+    public function prePersist($course)
+    {
+        $this->updateTools($course);
+    }
+
+    /***
+     * @param Course $course
+     */
+    public function updateTools($course)
+    {
+        $toolChain = $this->getToolChain();
+        $tools = $toolChain->getTools();
+
+        $currentTools = $course->getTools();
+        $addedTools = array();
+        if (!empty($currentTools)) {
+            foreach ($currentTools as $tool) {
+                $addedTools[] = $tool->getName();
+            }
+        }
+
+        foreach ($tools as $tool) {
+            $toolName = $tool->getName();
+            if (!in_array($toolName, $addedTools)) {
+
+                $toolEntity = new CTool();
+                $toolEntity->setCId($course->getId());
+                $toolEntity->setName($tool->getName());
+                $toolEntity->setLink($tool->getLink());
+                $toolEntity->setTarget($tool->getTarget());
+                $toolEntity->setCategory($tool->getCategory());
+
+                $course->addTools($toolEntity);
+            }
+        }
+    }
+
+    /**
+     * @param ToolChain $chainTool
+     */
+    public function setToolChain(ToolChain $chainTool)
+    {
+        $this->toolChain = $chainTool;
+    }
+
+    /**
+     * @return ToolChain
+     */
+    public function getToolChain()
+    {
+        return $this->toolChain;
     }
 }

+ 14 - 0
src/ChamiloLMS/CoreBundle/ChamiloLMSCoreBundle.php

@@ -2,8 +2,22 @@
 
 namespace ChamiloLMS\CoreBundle;
 
+use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\EntityListenerPass;
+use ChamiloLMS\CoreBundle\DependencyInjection\Compiler\DoctrineEntityListenerPass;
 use Symfony\Component\HttpKernel\Bundle\Bundle;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
 
 class ChamiloLMSCoreBundle extends Bundle
 {
+    public function boot()
+    {
+        // Add legacy calls.
+    }
+
+    public function build(ContainerBuilder $container)
+    {
+        parent::build($container);
+        //$container->addCompilerPass(new EntityListenerPass());
+        //$container->addCompilerPass(new DoctrineEntityListenerPass());
+    }
 }

+ 13 - 2
src/ChamiloLMS/CoreBundle/Controller/BaseController.php

@@ -34,7 +34,7 @@ abstract class BaseController extends Controller
     }
 
     /**
-     * @return Symfony\Component\HttpFoundation\Session\SessionInterface
+     * @return \Symfony\Component\HttpFoundation\Session\SessionInterface
      */
     public function getSessionHandler()
     {
@@ -57,6 +57,18 @@ abstract class BaseController extends Controller
         return new NotFoundHttpException();
     }
 
+    /**
+     * @param string $message
+     * @param string $class
+     */
+    public function addMessage($message, $class)
+    {
+        $this->get('session')->getFlashBag()->add(
+            $class,
+            $message
+        );
+    }
+
     /**
      * Converts string 'ChamiloLMS\CoreBundle\Controller\Admin\QuestionManager' into
      * 'admin/question_manager'
@@ -232,7 +244,6 @@ abstract class BaseController extends Controller
      */
     public function getCourse()
     {
-        var_dump($this->getSessionHandler()->get('course'));
         return $this->getSessionHandler()->get('course');
     }
 

+ 4 - 157
src/ChamiloLMS/CoreBundle/Controller/IndexController.php

@@ -11,12 +11,10 @@ use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpKernel\HttpKernelInterface;
 use Symfony\Component\Finder\Finder;
-
 use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
 use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
 use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
-//use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
-use JMS\SecurityExtraBundle\Annotation\Secure;
+use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
 
 /**
  * Class IndexController
@@ -25,11 +23,6 @@ use JMS\SecurityExtraBundle\Annotation\Secure;
  */
 class IndexController extends BaseController
 {
-    /**
-     * @Route("/home", name="homepage")
-     * @Method({"GET"})
-     * @return Response
-     */
     public function indexAction()
     {
         /** @var \PageController $pageController */
@@ -77,7 +70,7 @@ class IndexController extends BaseController
         return $this->render(
             'ChamiloLMSCoreBundle:Index:index.html.twig',
             array(
-                'content' => null,
+                'content' => 'hello',
                 'hot_courses' => $hotCourses,
                 'announcements_block' => $announcementsBlock,
                 //'home_page_block' => $pageController->returnHomePage()
@@ -85,98 +78,6 @@ class IndexController extends BaseController
         );
     }
 
-    /**
-     * @param Application $app
-     * @return Response
-     */
-    public function loginAction(Application $app)
-    {
-        $request = $this->getRequest();
-        $app['template']->assign('error', $app['security.last_error']($request));
-        $extra = array();
-        if (api_get_setting('use_virtual_keyboard') == 'true') {
-            $extra[] = api_get_css(api_get_path(WEB_LIBRARY_JS_PATH).'keyboard/keyboard.css');
-            $extra[] = api_get_js('keyboard/jquery.keyboard.js');
-        }
-        $app['template']->addResource($extra, 'string');
-        $response = $app['template']->render_template('auth/login.tpl');
-        return new Response($response, 200, array('Cache-Control' => 's-maxage=3600, public'));
-    }
-
-    /**
-     * @param
-     *
-     * @return string
-     */
-    public function displayLoginForm()
-    {
-        /* {{ form_widget(form) }}
-          $form = $app['form.factory']->createBuilder('form')
-          ->add('name')
-          ->add('email')
-          ->add('gender', 'choice', array(
-          'choices' => array(1 => 'male', 2 => 'female'),
-          'expanded' => true,
-          ))
-          ->getForm();
-          return $app['template']->assign('form', $form->createView());
-         */
-        $form = new \FormValidator(
-            'formLogin',
-            'POST',
-            $this->get('url_generator')->generate('secured_login_check'),
-            null,
-            array('class'=> 'form-signin-block')
-        );
-
-        $form->addElement(
-            'text',
-            'username',
-            null,
-            array(
-                'class' => 'input-medium autocapitalize_off virtualkey',
-                'placeholder' => get_lang('UserName'),
-                'autofocus' => 'autofocus',
-                'icon' => 'fa fa-user fa-fw'
-            )
-        );
-
-        $form->addElement(
-            'password',
-            'password',
-            null,
-            array(
-                'placeholder' => get_lang('Pass'),
-                'class' => 'input-medium virtualkey',
-                'icon' => 'fa fa-key fa-fw'
-            )
-        );
-
-        $form->addElement('style_submit_button', 'submitAuth', get_lang('LoginEnter'), array('class' => 'btn btn-primary btn-block'));
-        $html = $form->return_form();
-
-        /** Verify if settings is active to set keyboard. Included extra class in form input elements */
-
-        if (api_get_setting('use_virtual_keyboard') == 'true') {
-            $html .= "<script>
-                $(function(){
-                    $('.virtualkey').keyboard({
-                        layout:'custom',
-                        customLayout: {
-                        'default': [
-                            '1 2 3 4 5 6 7 8 9 0 {bksp}',
-                            'q w e r t y u i o p',
-                            'a s d f g h j k l',
-                            'z x c v b n m',
-                            '{cancel} {accept}'
-                        ]
-                        }
-                    });
-                });
-            </script>";
-        }
-        return $html;
-    }
 
     /**
      * @todo move all this getDocument* actions into another controller
@@ -311,63 +212,10 @@ class IndexController extends BaseController
         }
     }
 
-    /**
-     * Reacts on a failed login.
-     * Displays an explanation with a link to the registration form.
-     *
-     * @todo use twig template to prompt errors + move this into a helper
-     */
-    private function handleLoginFailed($error)
-    {
-        $message = get_lang('InvalidId');
-
-        if (!isset($error)) {
-            if (api_is_self_registration_allowed()) {
-                $message = get_lang('InvalidForSelfRegistration');
-            }
-        } else {
-            switch ($error) {
-                case '':
-                    if (api_is_self_registration_allowed()) {
-                        $message = get_lang('InvalidForSelfRegistration');
-                    }
-                    break;
-                case 'account_expired':
-                    $message = get_lang('AccountExpired');
-                    break;
-                case 'account_inactive':
-                    $message = get_lang('AccountInactive');
-                    break;
-                case 'user_password_incorrect':
-                    $message = get_lang('InvalidId');
-                    break;
-                case 'access_url_inactive':
-                    $message = get_lang('AccountURLInactive');
-                    break;
-                case 'unrecognize_sso_origin':
-                    //$message = get_lang('SSOError');
-                    break;
-            }
-        }
-        return \Display::return_message($message, 'error');
-    }
-
-    public function dashboardAction()
-    {
-        /*$template = $this->getTemplate();
-
-        $template->assign('content', 'welcome!');
-        $response = $template->renderLayout('layout_2_col.tpl');
-
-        //return new Response($response, 200, array('Cache-Control' => 's-maxage=3600, public'));
-        return new Response($response, 200, array());*/
-    }
-
     /**
      * @Route("/userportal", name="userportal")
      * @Method({"GET"})
-     * Security("has_role('ROLE_USER')")
-     * @Secure(roles="ROLE_STUDENT")
+     * @Security("has_role('ROLE_USER')")
      *
      * @param string $type courses|sessions|mycoursecategories
      * @param string $filter for the userportal courses page. Only works when setting 'history'
@@ -377,9 +225,7 @@ class IndexController extends BaseController
     public function userPortalAction($type = 'courses', $filter = 'current', $page = 1)
     {
         $user = $this->getUser();
-
         $pageController = new \ChamiloLMS\CoreBundle\Framework\PageController();
-
         $items = null;
 
         if (!empty($user)) {
@@ -449,6 +295,7 @@ class IndexController extends BaseController
      * Toggle the student view action
      *
      * @Route("/toggle_student_view")
+     * @Security("has_role('ROLE_TEACHER')")
      * @Method({"GET"})
      *
      * @return Response

+ 2 - 3
src/ChamiloLMS/CoreBundle/Controller/LegacyController.php

@@ -48,16 +48,15 @@ class LegacyController extends BaseController
         Session::$urlGenerator = $this->container->get('router');
         Session::$security = $this->container->get('security.context');
         Session::$translator = $this->container->get('translator');
-
         Session::$assets = $this->container->get('templating.helper.assets');
-
         Session::$rootDir = $this->container->get('kernel')->getRealRootDir();
         Session::$logDir = $this->container->get('kernel')->getLogDir();
         Session::$dataDir = $this->container->get('kernel')->getDataDir();
         Session::$tempDir = $this->container->get('kernel')->getCacheDir();
         Session::$courseDir = $this->container->get('kernel')->getDataDir();
-        Session::$configDir = $this->container->get('kernel')->getConfigDir();
+        //Session::$configDir = $this->container->get('kernel')->getConfigDir();
         Session::$htmlEditor = $this->container->get('html_editor');
+        Session::$twig = $this->container->get('twig');
 
         if (is_file($fileToLoad) &&
             \Security::check_abs_path($fileToLoad, $mainPath)

+ 70 - 74
src/ChamiloLMS/CoreBundle/DataFixtures/ORM/LoadPageData.php

@@ -76,7 +76,6 @@ class LoadPageData extends AbstractFixture implements ContainerAwareInterface, O
         $site->setEnabledTo(new \DateTime('+20 years'));
         $site->setRelativePath("");
         $site->setIsDefault(true);
-
         $this->getSiteManager()->save($site);
 
         return $site;
@@ -229,11 +228,11 @@ CONTENT
      */
     public function createHomePage(SiteInterface $site)
     {
-        return;
         $pageManager = $this->getPageManager();
         $blockManager = $this->getBlockManager();
         $blockInteractor = $this->getBlockInteractor();
 
+        /** @var \Sonata\PageBundle\Model\Page $homepage */
         $this->addReference('page-homepage', $homepage = $pageManager->create());
         $homepage->setSlug('/');
         $homepage->setUrl('/');
@@ -243,43 +242,28 @@ CONTENT
         $homepage->setDecorate(0);
         $homepage->setRequestMethod('GET|POST|HEAD|DELETE|PUT');
         $homepage->setTemplateCode('2columns');
-        $homepage->setRouteName('homepage');
+        $homepage->setRouteName(PageInterface::PAGE_ROUTE_CMS_NAME);
         $homepage->setSite($site);
-
         $pageManager->save($homepage);
 
-        // CREATE A HEADER BLOCK
+        // Header
         $homepage->addBlocks($contentTop = $blockInteractor->createNewContainer(array(
             'enabled' => true,
             'page' => $homepage,
             'code' => 'content_top',
         )));
-
         $contentTop->setName('The container top container');
-
         $blockManager->save($contentTop);
 
-        // add a block text
+        // Add a block text for the header
         $contentTop->addChildren($text = $blockManager->create());
         $text->setType('sonata.block.service.text');
-        $text->setSetting('content', <<<CONTENT
-<div class="col-md-3 welcome"><h2>Welcome</h2></div>
-<div class="col-md-9">
-    <p>
-        This page is a demo.
-    </p>
-
-    <p>
-        Pages.
-    </p>
-</div>
-CONTENT
-        );
+        $text->setSetting('content', 'Welcome to Chamilo (header)');
         $text->setPosition(1);
         $text->setEnabled(true);
         $text->setPage($homepage);
 
-
+        // Create content block
         $homepage->addBlocks($content = $blockInteractor->createNewContainer(array(
             'enabled' => true,
             'page' => $homepage,
@@ -288,7 +272,17 @@ CONTENT
         $content->setName('The content container');
         $blockManager->save($content);
 
-        /*
+        // Add a block text for the content
+        $contentTop->addChildren($text = $blockManager->create());
+        $text->setType('sonata.block.service.text');
+        $text->setSetting('content', 'Welcome to chamilo (content)');
+        $text->setPosition(1);
+        $text->setEnabled(true);
+        $text->setPage($homepage);
+
+        return;
+
+
         // Add media gallery block
         $content->addChildren($gallery = $blockManager->create());
         $gallery->setType('sonata.media.block.gallery');
@@ -299,58 +293,60 @@ CONTENT
         $gallery->setEnabled(true);
         $gallery->setPage($homepage);
 
-        // Add recent products block
-        $content->addChildren($newProductsBlock = $blockManager->create());
-        $newProductsBlock->setType('sonata.product.block.recent_products');
-        $newProductsBlock->setSetting('number', 4);
-        $newProductsBlock->setSetting('title', 'New products');
-        $newProductsBlock->setPosition(2);
-        $newProductsBlock->setEnabled(true);
-        $newProductsBlock->setPage($homepage);
-
-        // Add homepage bottom container
-        $homepage->addBlocks($bottom = $blockInteractor->createNewContainer(array(
-            'enabled' => true,
-            'page'    => $homepage,
-            'code'    => 'content_bottom',
-        ), function ($container) {
-            $container->setSetting('layout', '{{ CONTENT }}');
-        }));
-        $bottom->setName('The bottom content container');
+        /*
 
-        // Add homepage newsletter container
-        $bottom->addChildren($bottomNewsletter = $blockInteractor->createNewContainer(array(
-            'enabled' => true,
-            'page'    => $homepage,
-            'code'    => 'bottom_newsletter',
-        ), function ($container) {
-            $container->setSetting('layout', '<div class="block-newsletter col-sm-6 well">{{ CONTENT }}</div>');
-        }));
-        $bottomNewsletter->setName('The bottom newsetter container');
-        $bottomNewsletter->addChildren($newsletter = $blockManager->create());
-        $newsletter->setType('sonata.demo.block.newsletter');
-        $newsletter->setPosition(1);
-        $newsletter->setEnabled(true);
-        $newsletter->setPage($homepage);
-
-        // Add homepage embed tweet container
-        $bottom->addChildren($bottomEmbed = $blockInteractor->createNewContainer(array(
-            'enabled' => true,
-            'page'    => $homepage,
-            'code'    => 'bottom_embed',
-        ), function ($container) {
-            $container->setSetting('layout', '<div class="col-sm-6">{{ CONTENT }}</div>');
-        }));
-        $bottomEmbed->setName('The bottom embedded tweet container');
-        $bottomEmbed->addChildren($embedded = $blockManager->create());
-        $embedded->setType('sonata.seo.block.twitter.embed');
-        $embedded->setPosition(1);
-        $embedded->setEnabled(true);
-        $embedded->setSetting('tweet', "https://twitter.com/dunglas/statuses/438337742565826560");
-        $embedded->setSetting('lang', "en");
-        $embedded->setPage($homepage);
-
-        $pageManager->save($homepage);*/
+       // Add recent products block
+       $content->addChildren($newProductsBlock = $blockManager->create());
+       $newProductsBlock->setType('sonata.product.block.recent_products');
+       $newProductsBlock->setSetting('number', 4);
+       $newProductsBlock->setSetting('title', 'New products');
+       $newProductsBlock->setPosition(2);
+       $newProductsBlock->setEnabled(true);
+       $newProductsBlock->setPage($homepage);
+
+       // Add homepage bottom container
+       $homepage->addBlocks($bottom = $blockInteractor->createNewContainer(array(
+           'enabled' => true,
+           'page'    => $homepage,
+           'code'    => 'content_bottom',
+       ), function ($container) {
+           $container->setSetting('layout', '{{ CONTENT }}');
+       }));
+       $bottom->setName('The bottom content container');
+
+       // Add homepage newsletter container
+       $bottom->addChildren($bottomNewsletter = $blockInteractor->createNewContainer(array(
+           'enabled' => true,
+           'page'    => $homepage,
+           'code'    => 'bottom_newsletter',
+       ), function ($container) {
+           $container->setSetting('layout', '<div class="block-newsletter col-sm-6 well">{{ CONTENT }}</div>');
+       }));
+       $bottomNewsletter->setName('The bottom newsetter container');
+       $bottomNewsletter->addChildren($newsletter = $blockManager->create());
+       $newsletter->setType('sonata.demo.block.newsletter');
+       $newsletter->setPosition(1);
+       $newsletter->setEnabled(true);
+       $newsletter->setPage($homepage);
+
+       // Add homepage embed tweet container
+       $bottom->addChildren($bottomEmbed = $blockInteractor->createNewContainer(array(
+           'enabled' => true,
+           'page'    => $homepage,
+           'code'    => 'bottom_embed',
+       ), function ($container) {
+           $container->setSetting('layout', '<div class="col-sm-6">{{ CONTENT }}</div>');
+       }));
+       $bottomEmbed->setName('The bottom embedded tweet container');
+       $bottomEmbed->addChildren($embedded = $blockManager->create());
+       $embedded->setType('sonata.seo.block.twitter.embed');
+       $embedded->setPosition(1);
+       $embedded->setEnabled(true);
+       $embedded->setSetting('tweet', "https://twitter.com/dunglas/statuses/438337742565826560");
+       $embedded->setSetting('lang', "en");
+       $embedded->setPage($homepage);
+
+       $pageManager->save($homepage);*/
     }
 
     /**

+ 0 - 3
src/ChamiloLMS/CoreBundle/DataFixtures/ORM/LoadPortalData.php

@@ -258,9 +258,6 @@ class LoadPortalData extends AbstractFixture implements ContainerAwareInterface,
         $manager->persist($tool);
 
         $manager->flush();
-
-
-
     }
 
     /**

+ 46 - 7
src/ChamiloLMS/CoreBundle/Entity/Course.php

@@ -2,13 +2,14 @@
 
 namespace ChamiloLMS\CoreBundle\Entity;
 
+use ChamiloLMS\CourseBundle\Entity\CTool;
 use Doctrine\ORM\Mapping as ORM;
 use Doctrine\Common\Collections\ArrayCollection;
 use Gedmo\Mapping\Annotation as Gedmo;
 
 /**
  * Course
- *
+ * @ORM\HasLifecycleCallbacks
  * @ORM\Table(name="course")
  * @ORM\Entity(repositoryClass="ChamiloLMS\CoreBundle\Entity\Repository\CourseRepository")
  */
@@ -221,21 +222,30 @@ class Course
      **/
     private $items;
 
+    /**
+     * @ORM\OneToMany(targetEntity="ChamiloLMS\CourseBundle\Entity\CTool", mappedBy="course", cascade={"persist"})
+     **/
+    private $tools;
+
     /**
      * ORM\OneToMany(targetEntity="CurriculumCategory", mappedBy="course")
      **/
     //private $curriculumCategories;
 
-    public function __toString()
+    /**
+     *
+     */
+    public function __construct()
     {
-        return strval($this->getTitle());
     }
 
-    /*public function __construct()
+    /**
+     * @return string
+     */
+    public function __toString()
     {
-        $this->users = new ArrayCollection();
-        $this->items = new ArrayCollection();
-    }*/
+        return strval($this->getTitle());
+    }
 
     /**
      * @return mixed
@@ -253,6 +263,35 @@ class Course
         return $this->items;
     }
 
+    /**
+     * @return ArrayCollection
+     */
+    public function getTools()
+    {
+        return $this->tools;
+    }
+
+    /**
+     * @param $tools
+     */
+    public function setTools($tools)
+    {
+        $this->tools = new ArrayCollection();
+
+        foreach ($tools as $tool) {
+            $this->addTool($tool);
+        }
+    }
+
+    /**
+     * @param CTool $tool
+     */
+    public function addTools(CTool $tool)
+    {
+        $tool->setCourse($this);
+        $this->tools[] = $tool;
+    }
+
     /**
      * @return ArrayCollection
      */

+ 41 - 0
src/ChamiloLMS/CoreBundle/Entity/Listener/CourseListener.php

@@ -0,0 +1,41 @@
+<?php
+
+namespace ChamiloLMS\CoreBundle\Entity\Listener;
+
+use Doctrine\ORM\Event\LifecycleEventArgs;
+use ChamiloLMS\CoreBundle\Entity\Course;
+
+/**
+ * Class CourseListener
+ * @package ChamiloLMS\CoreBundle\EventListener
+ */
+class CourseListener
+{
+    private $toolChain;
+
+    /**
+     * @param $toolChain
+     */
+    public function __construct($toolChain)
+    {
+        $this->toolChain = $toolChain;
+    }
+
+    /**
+     * new object : prePersist
+     * edited object: preUpdate
+     * @param LifecycleEventArgs $args
+     */
+    public function prePersist(Course $course, LifecycleEventArgs $args)
+    {
+
+        foreach ($this->toolChain as $tool) {
+            $tool->getName();
+        }
+        $course->setDescription( ' dq sdqs dqs dqs ');
+        $args->getEntityManager()->persist($course);
+        $args->getEntityManager()->flush();
+        var_dump($this->toolChain);
+
+    }
+}

+ 194 - 0
src/ChamiloLMS/CoreBundle/Entity/TrackAttemptJury.php

@@ -0,0 +1,194 @@
+<?php
+
+namespace ChamiloLMS\CoreBundle\Entity;
+
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * TrackAttemptJury
+ *
+ * @ORM\Table(name="track_attempt_jury")
+ * @ORM\Entity
+ */
+class TrackAttemptJury
+{
+    /**
+     * @var integer
+     *
+     * @ORM\Column(name="id", type="integer", precision=0, scale=0, nullable=false, unique=false)
+     * @ORM\Id
+     * @ORM\GeneratedValue(strategy="AUTO")
+     */
+    private $id;
+
+    /**
+     * @var integer
+     *
+     * @ORM\Column(name="exe_id", type="integer", precision=0, scale=0, nullable=true, unique=false)
+     */
+    private $exeId;
+
+    /**
+     * @var integer
+     *
+     * @ORM\Column(name="question_id", type="integer", precision=0, scale=0, nullable=true, unique=false)
+     */
+    private $questionId;
+
+    /**
+     * @var float
+     *
+     * @ORM\Column(name="score", type="float", precision=0, scale=0, nullable=true, unique=false)
+     */
+    private $score;
+
+    /**
+     * @var integer
+     *
+     * @ORM\Column(name="jury_member_id", type="integer", precision=0, scale=0, nullable=true, unique=false)
+     */
+    private $juryMemberId;
+
+    /**
+     * @var integer
+     *
+     * @ORM\Column(name="question_score_name_id", type="integer", precision=0, scale=0, nullable=true, unique=false)
+     */
+    private $questionScoreNameId;
+
+    /**
+     * @ORM\ManyToOne(targetEntity="TrackEExercices", inversedBy="juryAttempts")
+     * @ORM\JoinColumn(name="exe_id", referencedColumnName="exe_id")
+     */
+    private $attempt;
+
+    public function getAttempt()
+    {
+        return $this->attempt;
+    }
+
+    /**
+     * Get id
+     *
+     * @return integer
+     */
+    public function getId()
+    {
+        return $this->id;
+    }
+
+    /**
+     * Set exeId
+     *
+     * @param integer $exeId
+     * @return TrackAttemptJury
+     */
+    public function setExeId($exeId)
+    {
+        $this->exeId = $exeId;
+
+        return $this;
+    }
+
+    /**
+     * Get exeId
+     *
+     * @return integer
+     */
+    public function getExeId()
+    {
+        return $this->exeId;
+    }
+
+    /**
+     * Set questionId
+     *
+     * @param integer $questionId
+     * @return TrackAttemptJury
+     */
+    public function setQuestionId($questionId)
+    {
+        $this->questionId = $questionId;
+
+        return $this;
+    }
+
+    /**
+     * Get questionId
+     *
+     * @return integer
+     */
+    public function getQuestionId()
+    {
+        return $this->questionId;
+    }
+
+    /**
+     * Set score
+     *
+     * @param float $score
+     * @return TrackAttemptJury
+     */
+    public function setScore($score)
+    {
+        $this->score = $score;
+
+        return $this;
+    }
+
+    /**
+     * Get score
+     *
+     * @return float
+     */
+    public function getScore()
+    {
+        return $this->score;
+    }
+
+    /**
+     * Set juryMemberId
+     *
+     * @param integer $juryMemberId
+     * @return TrackAttemptJury
+     */
+    public function setJuryMemberId($juryMemberId)
+    {
+        $this->juryMemberId = $juryMemberId;
+
+        return $this;
+    }
+
+    /**
+     * Get juryMemberId
+     *
+     * @return integer
+     */
+    public function getJuryMemberId()
+    {
+        return $this->juryMemberId;
+    }
+
+    /**
+     * Set questionScoreNameId
+     *
+     * @param integer $questionScoreNameId
+     * @return TrackAttemptJury
+     */
+    public function setQuestionScoreNameId($questionScoreNameId)
+    {
+        $this->questionScoreNameId = $questionScoreNameId;
+
+        return $this;
+    }
+
+    /**
+     * Get questionScoreNameId
+     *
+     * @return integer
+     */
+    public function getQuestionScoreNameId()
+    {
+        return $this->questionScoreNameId;
+    }
+}

+ 1 - 1
src/ChamiloLMS/CoreBundle/Entity/UsergroupRelUser.php

@@ -25,7 +25,7 @@ class UsergroupRelUser
     /**
      * @var \User
      *
-     * @ORM\ManyToOne(targetEntity="Application\Sonata\UserBundle\Entity\User")
+     * @ORM\ManyToOne(targetEntity="Application\Sonata\UserBundle\Entity\User", inversedBy="classes")
      * @ORM\JoinColumns({
      *   @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=true)
      * })

+ 14 - 8
src/ChamiloLMS/CoreBundle/EventListener/MessageListener.php

@@ -24,21 +24,27 @@ class MessageListener
 
     protected function getMessages()
     {
+        return array();
+
         $threads = $this->container->get('fos_message.provider')->getInboxThreads();
         $security = $this->container->get('security.context');
         $token = $security->getToken();
-        $user = $token->getUser();
-        $messages = array();
 
-        /** @var \ChamiloLMS\CoreBundle\Entity\Thread $thread*/
-        foreach ($threads as $thread) {
-            if ($thread->isReadByParticipant($user)) {
-                foreach($thread->getMessages() as $message) {
-                    $messages[] = $message;
+        $user = $token->getUser();
+        if (!empty($user)) {
+            $messages = array();
+
+            /** @var \ChamiloLMS\CoreBundle\Entity\Thread $thread */
+            foreach ($threads as $thread) {
+                if ($thread->isReadByParticipant($user)) {
+                    foreach ($thread->getMessages() as $message) {
+                        $messages[] = $message;
+                    }
                 }
             }
+
+            return $messages;
         }
 
-        return $messages;
     }
 }

+ 10 - 4
src/ChamiloLMS/CoreBundle/EventListener/ShowUserListener.php

@@ -19,16 +19,22 @@ class ShowUserListener
     public function onShowUser(ShowUserEvent $event)
     {
         $user = $this->getUser();
-        $event->setUser($user);
+        if (!empty($user)) {
+            $event->setUser($user);
+        }
     }
 
     public function getUser()
     {
+        /** @var  $security */
         $security = $this->container->get('security.context');
         $token = $security->getToken();
 
-
-        // $user = $this->getUser();
-        return $token->getUser();
+        if ($token) {
+            $user = $token->getUser();
+            if ($user) {
+                return $user;
+            }
+        }
     }
 }

+ 2 - 2
src/ChamiloLMS/CoreBundle/Menu/MainMenuBuilder.php

@@ -22,8 +22,8 @@ class MainMenuBuilder extends ContainerAware
     /**
      * Constructor
      *
-     * @param MenuFactory                     $factory
-     * @param RouterInterface                 $router
+     * @param MenuFactory $factory
+     * @param RouterInterface $router
      */
     public function __construct(FactoryInterface $factory, RouterInterface $router)
     {

+ 7 - 41
src/ChamiloLMS/CoreBundle/Menu/SimpleMenuBuilder.php

@@ -4,7 +4,6 @@ namespace ChamiloLMS\CoreBundle\Menu;
 
 use Knp\Menu\FactoryInterface;
 use Symfony\Component\DependencyInjection\ContainerAware;
-use Avanzu\AdminThemeBundle\Model\MenuItemInterface as ThemeMenuItem;
 
 /**
  * Class Builder
@@ -27,50 +26,16 @@ class SimpleMenuBuilder extends ContainerAware
     {
         $isFooter = array_key_exists('is_footer', $options) ? $options['is_footer'] : false;
 
-        $shopCategories = $this->container->get('sonata.classification.manager.category')->findBy(array('enabled' => true, 'parent' => null));
-
         $menuOptions = array_merge($options, array(
             'childrenAttributes' => array('class' => 'nav nav-pills'),
         ));
 
         $menu = $factory->createItem('main', $menuOptions);
+        $child = $menu->addChild('News', array('route' => 'sonata_news_home', array("attributes" => array("id" => 'nav'))));
 
-        //$shopMenuParams = array('route' => 'sonata_catalog_index');
-        $shopMenuParams = array('route' => 'home');
-
-        if (count($shopCategories) > 0 && !$isFooter) {
-            $shopMenuParams = array_merge($shopMenuParams, array(
-                'attributes' => array('class' => 'dropdown'),
-                'childrenAttributes' => array('class' => 'dropdown-menu'),
-                'linkAttributes' => array('class' => 'dropdown-toggle', 'data-toggle' => 'dropdown', 'data-target' => '#'),
-                'label' => 'Products <b class="caret caret-menu"></b>',
-                'extras' => array(
-                    'safe_label' => true,
-                )
-            ));
-        }
-
-        if ($isFooter) {
-            $shopMenuParams = array_merge($shopMenuParams, array(
-                'attributes' => array('class' => 'span2'),
-                "childrenAttributes" => array('class' => 'nav')
-            ));
-        }
 
-        $shop = $menu->addChild('Shops', $shopMenuParams);
-
-        $menu->addChild('News', array('route' => 'sonata_news_home'));
-
-        foreach ($shopCategories as $category) {
-            $shop->addChild($category->getName(), array(
-                'route' => 'sonata_catalog_category',
-                'routeParameters' => array(
-                    'category_id'   => $category->getId(),
-                    'category_slug' => $category->getSlug()),
-                )
-            );
-        }
 
+        /*
         $dropdownExtrasOptions = $isFooter ? array(
             'uri' => "#",
             'attributes' => array('class' => 'span2'),
@@ -91,15 +56,16 @@ class SimpleMenuBuilder extends ContainerAware
         $extras->addChild('Api', array('route' => 'page_slug', 'routeParameters' => array('path' => '/api-landing')));
         $extras->addChild('Gallery', array('route' => 'sonata_media_gallery_index'));
         $extras->addChild('Media & SEO', array('route' => 'home'));
-        //$extras->addChild('Media & SEO', array('route' => 'sonata_demo_media'));
 
         $menu->addChild($extras);
+        */
 
         $menu->addChild('Admin', array(
             'route' => 'page_slug',
             'routeParameters' => array(
                 'path' => '/user'
-            )
+            ),
+            'id' => 'admin'
         ));
 
         if ($isFooter) {
@@ -107,10 +73,10 @@ class SimpleMenuBuilder extends ContainerAware
                 'route' => 'page_slug',
                 'routeParameters' => array(
                     'path' => '/legal-notes',
-                )
+                ),
+                'id' => 'legal'
             ));
         }
-
         return $menu;
     }
 

+ 1 - 0
src/ChamiloLMS/CoreBundle/Resources/config/admin.yml

@@ -9,6 +9,7 @@ services:
             - ~
         calls:
             - [ setTranslationDomain, [ChamiloLMSCoreBundle]]
+            - [ setToolChain, [@chamilolms.tool_chain]]
 
     sonata.admin.session:
         class: ChamiloLMS\CoreBundle\Admin\SessionAdmin

+ 0 - 5
src/ChamiloLMS/CoreBundle/Resources/config/routing.yml

@@ -3,11 +3,6 @@ index:
     type:     annotation
     prefix:   /
 
-front:
-    resource: "@ChamiloLMSCoreBundle/Controller/FrontController.php"
-    type:     annotation
-    prefix:   /front
-
 # legacy routes
 main:
     path:     /main/{name}

+ 22 - 0
src/ChamiloLMS/CoreBundle/Resources/config/services.yml

@@ -1,4 +1,16 @@
 services:
+#    chamilolms.doctrine.entity_listener_resolver:
+#        class: ChamiloLMS\CoreBundle\Doctrine\EntityListenerResolver
+#        arguments: [ "@service_container" ]
+
+    chamilolms.entity_listener.course:
+        class: ChamiloLMS\CoreBundle\Entity\Listener\CourseListener
+        arguments: [ @chamilolms.tool_chain ]
+        tags:
+            - { name: doctrine.orm.entity_listener }
+
+#            - { name: doctrine.event_listener, event: prePersist }
+
     html_editor:
         class: ChamiloLMS\CoreBundle\Component\Editor\CkEditor\CkEditor
         arguments: [@translator, @router]
@@ -22,6 +34,12 @@ services:
         tags:
             - { name: kernel.event_subscriber }
 
+    listener.navbar_menu_listener:
+        class: ChamiloLMS\CoreBundle\EventListener\MenuListener
+        arguments: [@service_container]
+        tags:
+            - { name: kernel.event_listener, event: theme.sidebar_setup_menu_knp, method: onSetupMenu }
+
     listener.navbar_user_listener:
         class: ChamiloLMS\CoreBundle\EventListener\ShowUserListener
         arguments: [@service_container]
@@ -64,6 +82,10 @@ services:
 
     # Menus
 
+    chamilolms.menu.simple_menu:
+        class: ChamiloLMS\CoreBundle\Menu\SimpleMenuBuilder
+        arguments: [@service_container]
+
     chamilolms.corebundle.menu.main_menu_builder:
         class: ChamiloLMS\CoreBundle\Menu\MainMenuBuilder
         arguments: [@knp_menu.factory, @router]

+ 544 - 0
src/ChamiloLMS/CoreBundle/Resources/views/Calendar/month.html.twig

@@ -0,0 +1,544 @@
+<script>
+function checkLength( o, n, min, max ) {
+    if ( o.val().length > max || o.val().length < min ) {
+        o.addClass( "ui-state-error" );
+        /*updateTips( "Length of " + n + " must be between " +
+         min + " and " + max + "." );*/
+        return false;
+    } else {
+        return true;
+    }
+}
+function clean_user_select() {
+    //Cleans the selected attr
+    $("#users_to_send_id").val('').trigger("chosen:updated");
+    /*$('#users_to_send_id')
+     .find('option')
+     .removeAttr('selected')
+     .end();*/
+}
+
+var region_value = '{{ region_value }}';
+$(document).ready(function() {
+    var date = new Date();
+    var d = date.getDate();
+    var m = date.getMonth()+1;
+    var y = date.getFullYear();
+
+    $("#dialog-form").dialog({
+        autoOpen: false,
+        modal	: false,
+        width	: 580,
+        height	: 480,
+        zIndex: 20000 // added because of qtip2
+    });
+
+    $("#simple-dialog-form").dialog({
+        autoOpen: false,
+        modal	: false,
+        width	: 580,
+        height	: 480,
+        zIndex: 20000 // added because of qtip2
+    });
+
+    var title = $( "#title" ),
+            content = $( "#content" ),
+            allFields = $( [] ).add( title ).add( content ), tips = $(".validateTips");
+
+    $('#users_to_send_id').bind('change', function() {
+
+        var selected_counts = $("#users_to_send_id option:selected").size();
+
+        //alert(selected_counts);
+        /* if (selected_counts >= 1 && $("#users_to_send_id option[value='everyone']").attr('selected') == 'selected') {
+         clean_user_select();
+
+         $('#users_to_send_id option').eq(0).attr('selected', 'selected');
+         //deleting the everyone
+         $("#users_to_send_id").trigger("liszt:updated");
+         deleted_items = true;
+
+         }*/
+        //$("#users_to_send_id").trigger("chosen:updated");
+        /*
+         if (selected_counts >= 1) {
+         $('#users_to_send_id option').eq(0).removeAttr('selected');
+
+
+         }
+
+         */
+        //clean_user_select();
+        //$("#users_to_send_id").trigger("liszt:updated");
+        //alert($("#users_to_send_id option[value='everyone']").attr('selected'));
+        if ($("#users_to_send_id option[value='everyone']").attr('selected') == 'selected') {
+            //clean_user_select();
+            //$('#users_to_send_id option').eq(0).attr('selected', 'selected');
+            //$("#users_to_send_id").trigger("liszt:updated");
+        }
+    });
+
+    $.datepicker.setDefaults( $.datepicker.regional[region_value] );
+
+    var calendar = $('#calendar').fullCalendar({
+        header: {
+            left: 'today prev,next',
+            center: 'title',
+            right: 'month,agendaWeek,agendaDay, test'
+        },
+        {% if use_google_calendar == 1 %}
+        eventSources: [
+            // if you want to add more just add URL in this array
+            '{{ google_calendar_url }}',
+            {
+                className: 'gcal-event' // an option!
+            }
+        ],
+        {% endif %}
+
+        defaultView:    '{{ default_view }}',
+        buttonText: 	{{ button_text }},
+        monthNames: 	{{ month_names }},
+        monthNamesShort:{{ month_names_short }},
+        dayNames: 		{{ day_names }},
+        dayNamesShort: 	{{ day_names_short }},
+        firstHour: 8,
+        firstDay: 1,
+        selectable	: true,
+        selectHelper: true,
+
+        viewDisplay: function(view) {
+            /* When changing the view update the qtips */
+            var api = $('.qtip').qtip('api'); // Access the API of the first tooltip on the page
+            if (api) {
+                api.destroy();
+                //api.render();
+            }
+        },
+        // Add event
+        select: function(start, end, allDay, jsEvent, view) {
+            //Removing UTC stuff
+            var start_date = $.datepicker.formatDate("yy-mm-dd", start) + " " + start.toTimeString().substr(0, 8);
+            var end_date  = $.datepicker.formatDate("yy-mm-dd", end) + " " + end.toTimeString().substr(0, 8);
+
+            $('#visible_to_input').show();
+            $('#add_as_announcement_div').show();
+            $('#visible_to_read_only').hide();
+
+            // Cleans the selected attr
+            clean_user_select();
+
+            //Sets the 1st item selected by default
+            //$('#users_to_send_id option').eq(0).attr('selected', 'selected');
+
+            // Update chz-select
+            //$("#users_to_send_id").trigger("chosen:updated");
+
+            if ({{ can_add_events }} == 1) {
+                var url = '{{ web_agenda_ajax_url }}&a=add_event&start='+start_date+'&end='+end_date+'&all_day='+allDay+'&view='+view.name;
+                var start_date_value = $.datepicker.formatDate('{{ js_format_date }}', start);
+                var end_date_value  = $.datepicker.formatDate('{{ js_format_date }}', end);
+
+                $('#start_date').html(start_date_value + " " +  start.toTimeString().substr(0, 8));
+
+                if (view.name != 'month') {
+                    $('#start_date').html(start_date_value + " " +  start.toTimeString().substr(0, 8));
+                    if (start.toDateString() == end.toDateString()) {
+                        $('#end_date').html(' - '+end.toTimeString().substr(0, 8));
+                    } else {
+                        $('#end_date').html(' - '+start_date_value+" " + end.toTimeString().substr(0, 8));
+                    }
+                } else {
+                    $('#start_date').html(start_date_value);
+                    $('#end_date').html(' ');
+                }
+                $('#color_calendar').html('{{ type_label }}');
+                $('#color_calendar').removeClass('group_event');
+                $('#color_calendar').addClass('label_tag');
+                $('#color_calendar').addClass('{{ type_event_class }}');
+
+                allFields.removeClass("ui-state-error");
+                $("#dialog-form").dialog("open");
+                $("#dialog-form").dialog({
+                    buttons: {
+                        '{{ "Add" | trans }}' : function() {
+                            var bValid = true;
+                            bValid = bValid && checkLength(title, "title", 1, 255);
+                            //bValid = bValid && checkLength( content, "content", 1, 255 );
+
+                            var params = $("#add_event_form").serialize();
+                            $.ajax({
+                                url: url+'&'+params,
+                                success:function(data) {
+                                    var user = $('#users_to_send_id').val();
+                                    if (user) {
+                                        if (user.length > 1) {
+                                            user = 0;
+                                        } else {
+                                            user = user[0];
+                                        }
+                                        var user_length = String(user).length;
+                                        if (String(user).substring(0,1) == 'G') {
+                                            var user_id = String(user).substring(6,user_length);
+                                            var user_id = "G:"+user_id;
+                                        } else {
+                                            var user_id = String(user).substring(5,user_length);
+                                        }
+                                        var temp = "&user_id="+user_id;
+                                        var position =String(window.location).indexOf("&user");
+                                        var url_length = String(window.location).length;
+                                        var url = String(window.location).substring(0, position)+temp;
+
+                                        /*if (position > 0) {
+                                         window.location.replace(url);
+                                         } else {
+                                         url = String(window.location)+temp;
+                                         window.location.replace(url);
+                                         }*/
+                                    } else {
+                                        /* calendar.fullCalendar("refetchEvents");
+                                         calendar.fullCalendar("rerenderEvents");*/
+                                    }
+
+                                    calendar.fullCalendar("refetchEvents");
+                                    calendar.fullCalendar("rerenderEvents");
+
+                                    $("#dialog-form").dialog("close");
+                                }
+                            });
+                        }
+                    },
+                    close: function() {
+                        $("#title").attr('value', '');
+                        $("#content").attr('value', '');
+                    }
+                });
+
+                // Don't follow the link.
+                return false;
+
+                calendar.fullCalendar('unselect');
+                //Reload events
+                calendar.fullCalendar("refetchEvents");
+                calendar.fullCalendar("rerenderEvents");
+            }
+        },
+        eventRender: function(event, element) {
+            if (event.attachment) {
+                element.qtip({
+                    hide: {
+                        delay: 2000
+                    },
+                    content: event.attachment,
+                    position: { at:'top right' , my:'bottom right'},
+                }).removeData('qtip'); // this is an special hack to add multiple qtip in the same target
+            }
+            if (event.description) {
+                element.qtip({
+                    hide: {
+                        delay: 2000
+                    },
+                    content: event.description,
+                    position: { at:'top left' , my:'bottom left'}
+                });
+            }
+        },
+        eventClick: function(calEvent, jsEvent, view) {
+            //var start_date 	= Math.round(calEvent.start.getTime() / 1000);
+            var start_date = $.datepicker.formatDate("yy-mm-dd", calEvent.start) + " " + calEvent.start.toTimeString().substr(0, 8);
+
+            if (calEvent.allDay == 1) {
+                var end_date 	= '';
+            } else {
+                var end_date 	= '';
+                if (calEvent.end && calEvent.end != '') {
+                    //var end_date 	= Math.round(calEvent.end.getTime() / 1000);
+                    var end_date  = $.datepicker.formatDate("yy-mm-dd", calEvent.end) + " " + calEvent.end.toTimeString().substr(0, 8);
+                }
+            }
+
+            // Edit event.
+            if (calEvent.editable) {
+
+                $('#visible_to_input').hide();
+                $('#add_as_announcement_div').hide();
+
+                {% if type != 'admin' %}
+                $('#visible_to_read_only').show();
+                console.log(calEvent.sent_to);
+                $("#visible_to_read_only_users").html(calEvent.sent_to);
+                {% endif %}
+
+                $('#color_calendar').html('{{type_label}}');
+                $('#color_calendar').addClass('label_tag');
+                $('#color_calendar').removeClass('course_event');
+                $('#color_calendar').removeClass('personal_event');
+                $('#color_calendar').removeClass('group_event');
+                $('#color_calendar').addClass(calEvent.type+'_event');
+
+                my_start_month = calEvent.start.getMonth() +1;
+
+                $('#start_date').html(calEvent.start.getDate() +"/"+ my_start_month +"/"+calEvent.start.getFullYear());
+
+                if (end_date != '') {
+                    my_end_month = calEvent.end.getMonth() +1;
+                    $('#end_date').html(' '+calEvent.end.getDate() +"/"+ my_end_month +"/"+calEvent.end.getFullYear());
+                }
+
+                if ($("#title").parent().find('#title_edit').length == 0) {
+                    $("#title").parent().append('<div id="title_edit"></div>');
+                }
+
+                $("#title_edit").html(calEvent.title);
+
+                if ($("#content").parent().find('#content_edit').length == 0) {
+                    $("#content").parent().append('<div id="content_edit"></div>');
+                }
+
+                $("#content_edit").html(calEvent.description);
+
+                $("#title_edit").show();
+                $("#content_edit").show();
+
+                $("#title").hide();
+                $("#content").hide();
+
+                allFields.removeClass( "ui-state-error" );
+
+                $("#dialog-form").dialog("open");
+
+                var url = '{{ web_agenda_ajax_url }}&a=edit_event&id='+calEvent.id+'&start='+start_date+'&end='+end_date+'&all_day='+calEvent.allDay+'&view='+view.name;
+                var delete_url = '{{ web_agenda_ajax_url }}&a=delete_event&id='+calEvent.id;
+
+                $("#dialog-form").dialog({
+                    buttons: {
+                        '{{ "ExportiCalConfidential"|trans }}' : function() {
+                            url =  "{{ _p.web_main }}calendar/ical_export.php?id=" + calEvent.id+'&course_id='+calEvent.course_id+"&class=confidential";
+                            window.location.href = url;
+                        },
+                        '{{ "ExportiCalPrivate"|trans }}': function() {
+                            url =  "{{ _p.web_main }}calendar/ical_export.php?id=" + calEvent.id+'&course_id='+calEvent.course_id+"&class=private";
+                            window.location.href = url;
+                        },
+                        '{{ "ExportiCalPublic"|trans }}': function() {
+                            url =  "{{ _p.web_main }}calendar/ical_export.php?id=" + calEvent.id+'&course_id='+calEvent.course_id+"&class=public";
+                            window.location.href = url;
+                        },
+                        {% if type == 'not_available' %}
+                        '{{ "Edit" | trans }}' : function() {
+                            var bValid = true;
+                            bValid = bValid && checkLength( title, "title", 1, 255 );
+
+                            var params = $("#add_event_form").serialize();
+                            $.ajax({
+                                url: url+'&'+params,
+                                success:function() {
+                                    calEvent.title 			= $("#title").val();
+                                    calEvent.start 			= calEvent.start;
+                                    calEvent.end 			= calEvent.end;
+                                    calEvent.allDay         = calEvent.allDay;
+                                    calEvent.description 	= $("#content").val();
+
+                                    calendar.fullCalendar('updateEvent',
+                                            calEvent,
+                                            true // make the event "stick"
+                                    );
+                                    $("#dialog-form").dialog("close");
+                                }
+                            });
+                        },
+                        {% endif %}
+
+                        '{{ "Edit"|trans }}' : function() {
+                            url =  "{{ _p.web_main }}calendar/agenda.php?action=edit&type=fromjs&id=" + calEvent.id+'&course_id='+calEvent.course_id+"";
+                            window.location.href = url;
+                            $("#dialog-form").dialog( "close" );
+                        },
+
+                        '{{ "Delete"|trans }}': function() {
+
+                            if (calEvent.parent_event_id || calEvent.has_children != '' ) {
+                                var newDiv = $(document.createElement('div'));
+                                //newDiv.html('{{ "" |trans }}');
+
+                                newDiv.dialog({
+                                    modal: true,
+                                    title: "{{ 'Confirmation' | trans }}"
+                                });
+
+                                var buttons = newDiv.dialog("option", "buttons");
+
+                                if (calEvent.has_children == '0') {
+                                    $.extend(buttons, {
+                                        '{{ "DeleteThisItem" | trans }}' : function() {
+                                            $.ajax({
+                                                url: delete_url,
+                                                success:function() {
+                                                    calendar.fullCalendar('removeEvents',
+                                                            calEvent
+                                                    );
+                                                    calendar.fullCalendar("refetchEvents");
+                                                    calendar.fullCalendar("rerenderEvents");
+                                                    $("#dialog-form").dialog( "close" );
+                                                    newDiv.dialog( "close" );
+                                                }
+                                            });
+                                        }
+                                    });
+                                    newDiv.dialog("option", "buttons", buttons);
+                                }
+
+                                var buttons = newDiv.dialog("option", "buttons");
+
+                                $.extend(buttons, {
+                                    '{{ "DeleteAllItems" | trans }}' : function() {
+                                        $.ajax({
+                                            url: delete_url+'&delete_all_events=1',
+                                            success:function() {
+                                                calendar.fullCalendar('removeEvents',
+                                                        calEvent
+                                                );
+                                                calendar.fullCalendar("refetchEvents");
+                                                calendar.fullCalendar("rerenderEvents");
+                                                $("#dialog-form").dialog( "close" );
+                                                newDiv.dialog( "close" );
+                                            }
+                                        });
+                                    }
+                                });
+                                newDiv.dialog("option", "buttons", buttons);
+
+                                return true;
+                            }
+
+                            $.ajax({
+                                url: delete_url,
+                                success:function() {
+                                    calendar.fullCalendar('removeEvents',
+                                            calEvent
+                                    );
+                                    calendar.fullCalendar("refetchEvents");
+                                    calendar.fullCalendar("rerenderEvents");
+                                    $("#dialog-form").dialog( "close" );
+                                }
+                            });
+                        }
+                    },
+                    close: function() {
+                        $("#title_edit").hide();
+                        $("#content_edit").hide();
+
+                        $("#title").show();
+                        $("#content").show();
+
+                        $("#title_edit").html('');
+                        $("#content_edit").html('');
+
+                        $("#title").attr('value', '');
+                        $("#content").attr('value', '');
+                    }
+                });
+            } else {
+                //Simple form
+                my_start_month = calEvent.start.getMonth() +1;
+                $('#simple_start_date').html(calEvent.start.getDate() +"/"+ my_start_month +"/"+calEvent.start.getFullYear());
+
+                if (end_date != '') {
+                    my_end_month = calEvent.end.getMonth() +1;
+                    $('#simple_start_date').html(calEvent.start.getDate() +"/"+ my_start_month +"/"+calEvent.start.getFullYear() +" - "+calEvent.start.toLocaleTimeString());
+                    $('#simple_end_date').html(' '+calEvent.end.getDate() +"/"+ my_end_month +"/"+calEvent.end.getFullYear() +" - "+calEvent.end.toLocaleTimeString());
+                }
+
+                $("#simple_title").html(calEvent.title);
+                $("#simple_content").html(calEvent.description);
+                $("#simple-dialog-form").dialog("open");
+                $("#simple-dialog-form").dialog({
+                    buttons: {
+                        '{{"ExportiCalConfidential"|trans}}' : function() {
+                            url =  "ical_export.php?id=" + calEvent.id+'&course_id='+calEvent.course_id+"&class=confidential";
+                            window.location.href = url;
+
+                        },
+                        '{{"ExportiCalPrivate"|trans}}': function() {
+                            url =  "ical_export.php?id=" + calEvent.id+'&course_id='+calEvent.course_id+"&class=private";
+                            window.location.href = url;
+                        },
+                        '{{"ExportiCalPublic"|trans}}': function() {
+                            url =  "ical_export.php?id=" + calEvent.id+'&course_id='+calEvent.course_id+"&class=public";
+                            window.location.href = url;
+                        }
+                    }
+                });
+            }
+        },
+        editable: true,
+        events: "{{web_agenda_ajax_url}}&a=get_events",
+        eventDrop: function(event, day_delta, minute_delta, all_day, revert_func) {
+            $.ajax({
+                url: '{{ web_agenda_ajax_url }}',
+                data: {
+                    a:'move_event', id: event.id, day_delta: day_delta, minute_delta: minute_delta
+                }
+            });
+        },
+        eventResize: function(event, day_delta, minute_delta, revert_func) {
+            $.ajax({
+                url: '{{ web_agenda_ajax_url }}',
+                data: {
+                    a:'resize_event', id: event.id, day_delta: day_delta, minute_delta: minute_delta
+                }
+            });
+        },
+        axisFormat: 'HH(:mm)',
+        timeFormat: 'HH:mm{ - HH:mm}',
+        loading: function(bool) {
+            if (bool) $('#loading').show();
+            else $('#loading').hide();
+        }
+    });
+});
+</script>
+{{ actions_div }}
+
+<div id="simple-dialog-form" style="display:none;">
+    <div style="width:500px">
+        <form name="form-simple" class="form-vertical">
+            <div class="control-group">
+                <label class="control-label">
+                    <b>{{ "Date" |trans}}</b>
+                </label>
+                <div class="controls">
+                    <span id="simple_start_date"></span>
+                    <span id="simple_end_date"></span>
+                </div>
+            </div>
+            <div class="control-group">
+                <label class="control-label">
+                    <b>{{ "Title" |trans}}</b>
+                </label>
+                <div class="controls">
+                    <div id="simple_title"></div>
+                </div>
+            </div>
+
+            <div class="control-group">
+                <label class="control-label">
+                    <b>{{ "Description" |trans}}</b>
+                </label>
+                <div class="controls">
+                    <div id="simple_content"></div>
+                </div>
+            </div>
+        </form>
+    </div>
+</div>
+
+<div id="dialog-form" style="display:none;">
+    <div style="width:500px">
+        {{ form_add }}
+    </div>
+</div>
+<div id="loading" style="margin-left:150px;position:absolute;display:none">
+    {{ "Loading"|trans }}...
+</div>
+<div id="calendar"></div>

+ 2 - 0
src/ChamiloLMS/CoreBundle/Resources/views/Index/index.html.twig

@@ -1,6 +1,8 @@
+{% extends "ChamiloLMSCoreBundle::main_layout.html.twig" %}
 {% block page_content %}
     {% autoescape false %}
     {{ content }}
+    {% include "@template_style/layout/hot_courses.tpl" %}
     {% endautoescape %}
 {% endblock %}
 

+ 0 - 1
src/ChamiloLMS/CoreBundle/Resources/views/Index/userportal.html.twig

@@ -1,4 +1,3 @@
-{#{% extends "ChamiloLMSCoreBundle::main_layout.html.twig" %}#}
 {%  block page_content  %}
     {% autoescape false %}
     {{ content }}

+ 8 - 0
src/ChamiloLMS/CourseBundle/ChamiloLMSCourseBundle.php

@@ -3,7 +3,15 @@
 namespace ChamiloLMS\CourseBundle;
 
 use Symfony\Component\HttpKernel\Bundle\Bundle;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
 
+use ChamiloLMS\CourseBundle\DependencyInjection\Compiler\ToolCompilerClass;
 class ChamiloLMSCourseBundle extends Bundle
 {
+    public function build(ContainerBuilder $container)
+    {
+        parent::build($container);
+
+        $container->addCompilerPass(new ToolCompilerClass());
+    }
 }

+ 89 - 11
src/ChamiloLMS/CourseBundle/Controller/Home/HomeController.php

@@ -13,12 +13,13 @@ use ChamiloLMS\CoreBundle\Entity\CTool;
 use ChamiloLMS\CoreBundle\Form\CourseHomeToolType;
 use Doctrine\Common\Collections\Criteria;
 use Display;
+use CourseHome;
 use ChamiloLMS\CoreBundle\Entity\Course;
 use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
 
 /**
  * Class HomeController
- * @package ChamiloLMS\CourseBundle\Controller\CourseHome
+ * @package ChamiloLMS\CourseBundle\Controller\Home
  * @author Julio Montoya <gugli100@gmail.com>
  * @Route("/")
  */
@@ -58,7 +59,7 @@ class HomeController extends ToolBaseController
             $editIcons = Display::url(
                 Display::return_icon('edit.png'),
                 $this->generateUrl(
-                    'chamilolms_course_home_coursehome_iconlist',
+                    'chamilolms_course_home_home_iconlist',
                     array(
                         'course' => api_get_course_id(),
                     )
@@ -92,18 +93,16 @@ class HomeController extends ToolBaseController
             }
         }
 
-        $script =  'activity.php';
         if (api_get_setting('homepage_view') == 'activity' || api_get_setting('homepage_view') == 'activity_big') {
-            $script =  'activity.php';
+            $result = $this->renderActivityView();
         } elseif (api_get_setting('homepage_view') == '2column') {
-            $script = '2column.php';
+            $result = $this->render2ColumnView();
         } elseif (api_get_setting('homepage_view') == '3column') {
-            $script = '3column.php';
+            $result = $this->render3ColumnView();
         } elseif (api_get_setting('homepage_view') == 'vertical_activity') {
-            $script = 'vertical_activity.php';
+            $result = $this->renderVerticalActivityView();
         }
 
-        $result = require_once api_get_path(SYS_CODE_PATH).'course_home/'.$script;
         $toolList = $result['tool_list'];
 
         $introduction = Display::return_introduction_section(
@@ -113,11 +112,11 @@ class HomeController extends ToolBaseController
         );
         $sessionInfo = null;
         if (api_get_setting('show_session_data') == 'true' && $sessionId) {
-            $sessionInfo = \CourseHome::show_session_data($sessionId);
+            $sessionInfo = CourseHome::show_session_data($sessionId);
         }
 
         /*$response = $this->render(
-            'ChamiloLMSCoreBundle:Tool:CourseHome/index.html.twig',
+            'ChamiloLMSCoreBundle:Tool:Home/index.html.twig',
             array(
                 'session_info' => $sessionInfo,
                 'icons' => $result['content'],
@@ -131,7 +130,7 @@ class HomeController extends ToolBaseController
         return new Response($response, 200, array());*/
 
         return $this->render(
-            'ChamiloLMSCourseBundle:CourseHome:index.html.twig',
+            'ChamiloLMSCourseBundle:Home:index.html.twig',
             array(
                 'session_info' => $sessionInfo,
                 'icons' => $result['content'],
@@ -143,6 +142,85 @@ class HomeController extends ToolBaseController
         );
     }
 
+    function return_block($title, $content)
+    {
+        $html = '<div class="page-header">
+                <h3>'.$title.'</h3>
+            </div>
+            '.$content.'</div>';
+        return $html;
+    }
+
+    private function renderActivityView()
+    {
+        $session_id = api_get_session_id();
+        $urlGenerator = $this->get('router');
+
+        $content = null;
+
+        // Start of tools for CourseAdmins (teachers/tutors)
+        $totalList = array();
+
+        if ($session_id == 0 && api_is_course_admin() && api_is_allowed_to_edit(null, true)) {
+            $list = CourseHome::get_tools_category(TOOL_AUTHORING);
+            $result = CourseHome::show_tools_category($urlGenerator, $list);
+            $content .= $this->return_block(get_lang('Authoring'), $result['content']);
+
+            $totalList = $result['tool_list'];
+
+            $list = CourseHome::get_tools_category(TOOL_INTERACTION);
+            $list2 = CourseHome::get_tools_category(TOOL_COURSE_PLUGIN);
+            $list = array_merge($list, $list2);
+            $result =  CourseHome::show_tools_category($urlGenerator, $list);
+            $totalList = array_merge($totalList, $result['tool_list']);
+
+            $content .= $this->return_block(get_lang('Interaction'), $result['content']);
+
+            $list = CourseHome::get_tools_category(TOOL_ADMIN_PLATFORM);
+            $totalList = array_merge($totalList, $list);
+            $result = CourseHome::show_tools_category($urlGenerator, $list);
+            $totalList = array_merge($totalList, $result['tool_list']);
+            $content .= $this->return_block(get_lang('Administration'), $result['content']);
+
+        } elseif (api_is_coach()) {
+
+            $content .=  '<div class="row">';
+            $list = CourseHome::get_tools_category(TOOL_STUDENT_VIEW);
+            $content .= CourseHome::show_tools_category($urlGenerator, $result['content']);
+            $totalList = array_merge($totalList, $result['tool_list']);
+            $content .= '</div>';
+        } else {
+            $list = CourseHome::get_tools_category(TOOL_STUDENT_VIEW);
+            if (count($list) > 0) {
+                $content .= '<div class="row">';
+                $result = CourseHome::show_tools_category($urlGenerator, $list);
+                $content .= $result['content'];
+                $totalList = array_merge($totalList, $result['tool_list']);
+                $content .= '</div>';
+            }
+        }
+
+        return array(
+            'content' => $content,
+            'tool_list' => $totalList
+        );
+    }
+
+    private function render2ColumnView()
+    {
+
+    }
+
+    private function render3ColumnView()
+    {
+
+    }
+
+    private function renderVerticalActivityView()
+    {
+
+    }
+
     /**
      * @return array
      */

+ 33 - 0
src/ChamiloLMS/CourseBundle/DependencyInjection/Compiler/ToolCompilerClass.php

@@ -0,0 +1,33 @@
+<?php
+
+namespace ChamiloLMS\CourseBundle\DependencyInjection\Compiler;;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Class ToolCompilerClass
+ * @package ChamiloLMS\CourseBundle\DependencyInjection\Compiler
+ */
+class ToolCompilerClass implements CompilerPassInterface
+{
+    public function process(ContainerBuilder $container)
+    {
+        if (!$container->hasDefinition('chamilolms.tool_chain')) {
+            return;
+        }
+
+        $definition = $container->getDefinition(
+            'chamilolms.tool_chain'
+        );
+
+        $taggedServices = $container->findTaggedServiceIds(
+            'chamilolm.course.tool'
+        );
+
+        foreach ($taggedServices as $id => $attributes) {
+            $definition->addMethodCall('addTool', array(new Reference($id)));
+        }
+    }
+}

+ 4 - 1
src/ChamiloLMS/CourseBundle/Entity/CTool.php

@@ -121,7 +121,7 @@ class CTool
     private $description;
 
     /**
-     * @ORM\ManyToOne(targetEntity="ChamiloLMS\CoreBundle\Entity\Course")
+     * @ORM\ManyToOne(targetEntity="ChamiloLMS\CoreBundle\Entity\Course", inversedBy="tools")
      * @ORM\JoinColumn(name="c_id", referencedColumnName="id")
      */
     private $course;
@@ -132,6 +132,9 @@ class CTool
      */
     public function __construct()
     {
+        // Default values
+        $this->id = 0;
+        $this->sessionId = 0;
     }
 
     /**

+ 0 - 0
src/ChamiloLMS/CourseBundle/Resources/config/routing.yml


+ 19 - 0
src/ChamiloLMS/CourseBundle/Resources/config/services.yml

@@ -0,0 +1,19 @@
+parameters:
+    tool_chain.class: ChamiloLMS\CourseBundle\ToolChain
+services:
+    chamilolms.tool_chain:
+        class: %tool_chain.class%
+
+    chamilolms.coursebundle.tool.calendar.class:
+        class: ChamiloLMS\CourseBundle\Tool\Calendar
+        arguments:
+            - calendar
+        tags:
+            - { name: chamilolm.course.tool }
+
+    chamilolms.coursebundle.tool.document.class:
+        class: ChamiloLMS\CourseBundle\Tool\Document
+        arguments:
+            - document
+        tags:
+            - { name: chamilolm.course.tool }

+ 0 - 0
src/ChamiloLMS/CourseBundle/Resources/views/CourseHome/add.tpl → src/ChamiloLMS/CourseBundle/Resources/views/Home/add.tpl


+ 0 - 0
src/ChamiloLMS/CourseBundle/Resources/views/CourseHome/edit.tpl → src/ChamiloLMS/CourseBundle/Resources/views/Home/edit.tpl


+ 2 - 0
src/ChamiloLMS/CourseBundle/Resources/views/CourseHome/index.html.twig → src/ChamiloLMS/CourseBundle/Resources/views/Home/index.html.twig

@@ -1,3 +1,5 @@
+{% extends "ChamiloLMSCoreBundle::main_layout.html.twig" %}
+
 {% block page_content %}
 
 {% autoescape false %}

+ 0 - 0
src/ChamiloLMS/CourseBundle/Resources/views/CourseHome/list.tpl → src/ChamiloLMS/CourseBundle/Resources/views/Home/list.tpl


+ 35 - 0
src/ChamiloLMS/CourseBundle/Tool/BaseTool.php

@@ -0,0 +1,35 @@
+<?php
+
+namespace ChamiloLMS\CourseBundle\Tool;
+use Symfony\Component\OptionsResolver\OptionsResolverInterface;
+
+
+abstract class BaseTool implements ToolInterface
+{
+    protected $name;
+    protected $link;
+
+    /**
+     * @param string $name
+     */
+    public function __construct($name)
+    {
+        $this->name = $name;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setDefaultSettings(OptionsResolverInterface $resolver)
+    {
+
+    }
+}

+ 36 - 0
src/ChamiloLMS/CourseBundle/Tool/Calendar.php

@@ -0,0 +1,36 @@
+<?php
+
+namespace ChamiloLMS\CourseBundle\Tool;
+
+/**
+ * Class Calendar
+ * @package ChamiloLMS\CourseBundle\Tool
+ */
+class Calendar extends BaseTool
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function getName()
+    {
+        return 'Calendar';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getLink()
+    {
+        return 'calendar/agenda.php';
+    }
+
+    public function getTarget()
+    {
+        return '_self';
+    }
+
+    public function getCategory()
+    {
+        return 'authoring';
+    }
+}

+ 37 - 0
src/ChamiloLMS/CourseBundle/Tool/Document.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace ChamiloLMS\CourseBundle\Tool;
+
+/**
+ * Class Calendar
+ * @package ChamiloLMS\CourseBundle\Tool
+ */
+class Document extends BaseTool
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function getName()
+    {
+        return 'Document';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getLink()
+    {
+        return 'document/document.php';
+    }
+
+    public function getTarget()
+    {
+        return '_self';
+    }
+
+    public function getCategory()
+    {
+        return 'authoring';
+    }
+
+}

+ 36 - 0
src/ChamiloLMS/CourseBundle/Tool/ToolInterface.php

@@ -0,0 +1,36 @@
+<?php
+
+namespace ChamiloLMS\CourseBundle\Tool;
+
+/**
+ * Interface ToolInterface
+ * @package ChamiloLMS\CourseBundle\Tool
+ */
+interface ToolInterface
+{
+    /**
+     * @return string
+     */
+    public function getName();
+
+    /**
+     * @return string
+     */
+    public function getLink();
+
+    /**
+     * @return string
+     */
+    public function getTarget();
+
+    /**
+     * @return string
+     */
+    public function getCategory();
+
+    /**
+     * @return string
+     */
+    //public function getName();
+
+}

+ 36 - 0
src/ChamiloLMS/CourseBundle/ToolChain.php

@@ -0,0 +1,36 @@
+<?php
+
+namespace ChamiloLMS\CourseBundle;
+
+/**
+ * Class ToolChain
+ * @package ChamiloLMS\CourseBundle
+ */
+class ToolChain
+{
+    protected $tools;
+
+    /**
+     *
+     */
+    public function __construct()
+    {
+        $this->tools = array();
+    }
+
+    /**
+     * @param $tool
+     */
+    public function addTool($tool)
+    {
+        $this->tools[] = $tool;
+    }
+
+    /**
+     * @return array
+     */
+    public function getTools()
+    {
+        return $this->tools;
+    }
+}

+ 46 - 0
src/ChamiloLMS/InstallerBundle/ChamiloLMSInstallerBundle.php

@@ -0,0 +1,46 @@
+<?php
+
+namespace ChamiloLMS\InstallerBundle;
+
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+use Symfony\Component\Console\Application;
+use ChamiloLMS\InstallerBundle\Command\InstallCommand;
+
+/**
+ * Class ChamiloLMSInstallerBundle
+ * @package ChamiloLMS\InstallerBundle
+ */
+class ChamiloLMSInstallerBundle extends Bundle
+{
+    /**
+     * @param Application $application
+     */
+    public function registerCommands(Application $application)
+    {
+        $application->addCommands(array(
+            // DBAL Commands.
+            new \Doctrine\DBAL\Tools\Console\Command\RunSqlCommand(),
+            new \Doctrine\DBAL\Tools\Console\Command\ImportCommand(),
+
+            // Migrations Commands.
+            new \Doctrine\DBAL\Migrations\Tools\Console\Command\DiffCommand(),
+            new \Doctrine\DBAL\Migrations\Tools\Console\Command\ExecuteCommand(),
+            new \Doctrine\DBAL\Migrations\Tools\Console\Command\GenerateCommand(),
+            new \Doctrine\DBAL\Migrations\Tools\Console\Command\MigrateCommand(),
+            new \Doctrine\DBAL\Migrations\Tools\Console\Command\StatusCommand(),
+            new \Doctrine\DBAL\Migrations\Tools\Console\Command\VersionCommand(),
+
+            // Chash commands.
+            //new UpgradeCommand(),
+            new InstallCommand(),
+            new \Chash\Command\Installation\InstallCommand(),
+
+            new \Chash\Command\Files\CleanCoursesFilesCommand(),
+            new \Chash\Command\Files\CleanTempFolderCommand(),
+            new \Chash\Command\Files\CleanConfigFilesCommand(),
+            new \Chash\Command\Files\MailConfCommand(),
+            new \Chash\Command\Files\SetPermissionsAfterInstallCommand(),
+            new \Chash\Command\Files\GenerateTempFileStructureCommand()
+        ));
+    }
+}

+ 186 - 0
src/ChamiloLMS/InstallerBundle/Command/InstallCommand.php

@@ -0,0 +1,186 @@
+<?php
+
+namespace ChamiloLMS\InstallerBundle\Command;
+
+use RuntimeException;
+use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Input\ArrayInput;
+
+/**
+ * Class InstallCommand
+ * @package ChamiloLMS\InstallerBundle\Command
+ */
+class InstallCommand extends ContainerAwareCommand
+{
+    protected function configure()
+    {
+        $this
+            ->setName('chamilo:install')
+            ->setDescription('Chamilo installer.')
+        ;
+    }
+
+    /**
+     * @param InputInterface $input
+     * @param OutputInterface $output
+     * @return int|null|void
+     */
+    protected function execute(InputInterface $input, OutputInterface $output)
+    {
+        $output->writeln('<info>Installing Chamilo.</info>');
+        $output->writeln('');
+
+        $this
+            ->checkStep($input, $output)
+            ->setupStep($input, $output)
+        ;
+
+        $output->writeln('<info>Chamilo has been successfully installed.</info>');
+    }
+
+    /**
+     * @param string $command
+     * @param OutputInterface $output
+     * @param array $arguments
+     * @return $this
+     * @throws \Exception
+     */
+    protected function runCommand($command, OutputInterface $output, $arguments = array())
+    {
+        $arguments['command'] = $command;
+        $input = new ArrayInput($arguments);
+
+        $this
+            ->getApplication()
+            ->find($command)
+            ->run($input, $output)
+        ;
+
+        return $this;
+    }
+
+    /**
+     * @param InputInterface $input
+     * @param OutputInterface $output
+     * @return $this
+     */
+    protected function checkStep(InputInterface $input, OutputInterface $output)
+    {
+        $output->writeln('<info>Checking system requirements.</info>');
+
+        $fulfilled = true;
+
+        // $rootDir = $this->getContainer()->get('kernel')->getRealRootDir();
+
+        $this->runCommand('doctrine:database:drop', $output, array('--force' => true));
+
+        // Make sure we close the original connection because it lost the reference to the database
+        $connection = $this->getApplication()->getKernel()->getContainer()->get('doctrine')->getConnection();
+
+        if ($connection->isConnected()) {
+            $connection->close();
+        }
+
+        $this->runCommand('cache:warmup', $output, array('--env' => 'prod', '--no-debug' => true));
+
+        $this
+            ->runCommand('doctrine:database:create', $output)
+            ->runCommand('doctrine:schema:create', $output)
+            //->runCommand('doctrine:phpcr:repository:init', $input, $output)
+            //->runCommand('chash:chamilo_install', $inputToInstall, $output)
+            ->runCommand('assets:install', $output)
+
+            //->runCommand('assetic:dump', $input, $output)
+        ;
+
+        if (!$fulfilled) {
+            throw new RuntimeException('Some system requirements are not fulfilled. Please check output messages and fix them.');
+        }
+
+        $output->writeln('');
+
+        return $this;
+    }
+
+    protected function setupStep(InputInterface $input, OutputInterface $output)
+    {
+        $output->writeln('<info>Setting up database.</info>');
+
+        //$this->setupDatabase($input, $output);
+
+        //if ($this->getHelperSet()->get('dialog')->askConfirmation($output, '<question>Load fixtures (Y/N)?</question>', false)) {
+        $this->setupFixtures($input, $output);
+        //}
+
+        $output->writeln('');
+        $output->writeln('<info>Administration setup.</info>');
+
+        $this->setupAdmin($output);
+
+        $this->runCommand('sonata:page:update-core-routes', $output, array('--site' => 'all'));
+        $this->runCommand('sonata:page:create-snapshots', $output, array('--site' => 'all'));
+
+        $output->writeln('');
+
+        return $this;
+    }
+
+    /**
+     * @param InputInterface $input
+     * @param OutputInterface $output
+     */
+    protected function setupDatabase(InputInterface $input, OutputInterface $output)
+    {
+        $this
+            ->runCommand('doctrine:database:create', $input, $output)
+            ->runCommand('doctrine:schema:create', $input, $output)
+            //->runCommand('doctrine:phpcr:repository:init', $input, $output)
+            ->runCommand('assets:install', $input, $output)
+            //->runCommand('assetic:dump', $input, $output)
+        ;
+    }
+
+    /**
+     * @param InputInterface $input
+     * @param OutputInterface $output
+     */
+    protected function setupFixtures(InputInterface $input, OutputInterface $output)
+    {
+        $this
+            ->runCommand(
+                'doctrine:fixtures:load',
+                $output,
+                array('--no-interaction' => true)
+            )
+            //->runCommand('doctrine:phpcr:fixtures:load', $input, $output)
+        ;
+    }
+
+    /**
+     * @param OutputInterface $output
+     */
+    protected function setupAdmin(OutputInterface $output)
+    {
+        $dialog = $this->getHelperSet()->get('dialog');
+        //$user = new \Application\Sonata\UserBundle\Entity\User();
+        $em = $this->getApplication()->getKernel()->getContainer()->get('doctrine')->getManager();
+        /** @var \Application\Sonata\UserBundle\Entity\User $user */
+        $user = $em->getRepository('ApplicationSonataUserBundle:User')->findOneById(1);
+
+        $user->setUsername($dialog->ask($output, '<question>Username</question>(admin):', 'admin'));
+        $user->setPlainPassword($dialog->ask($output, '<question>Password</question>(admin):', 'admin'));
+
+        $user->setFirstname($dialog->ask($output, '<question>Firstname</question>(Jane):', 'Jane'));
+        $user->setLastname($dialog->ask($output, '<question>Lastname</question>(Doe):', 'Doe'));
+        $user->setEmail($dialog->ask($output, '<question>Email</question>(admin@example.org):', 'admin@example.org'));
+        $user->setEnabled(true);
+        $user->addRole('ROLE_SUPER_ADMIN');
+
+        $em = $this->getContainer()->get('doctrine.orm.entity_manager');
+        $em->persist($user);
+        $em->flush();
+    }
+
+}

+ 17 - 86
tests/doctrine_console/cli-config.php

@@ -8,114 +8,45 @@ use Doctrine\Common\Annotations\AnnotationReader;
 use Doctrine\Common\Annotations\AnnotationRegistry;
 use Symfony\Component\Yaml\Parser;
 
-AnnotationRegistry::registerFile(api_get_path(SYS_PATH)."vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php");
+$sysPath = __DIR__."/../../";
+AnnotationRegistry::registerFile($sysPath."vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php");
 $reader = new AnnotationReader();
 
-$driverImpl = new \Doctrine\ORM\Mapping\Driver\AnnotationDriver($reader, array(api_get_path(SYS_PATH)."tests/doctrine_console/mapping"));
+$driverImpl = new \Doctrine\ORM\Mapping\Driver\AnnotationDriver(
+    $reader,
+    array($sysPath."tests/doctrine_console/mapping")
+);
 
 $config->setMetadataDriverImpl($driverImpl);
 $config->setProxyDir(__DIR__ . '/Proxies');
 $config->setProxyNamespace('Proxies');
 
-$courseList = CourseManager::get_real_course_list();
-//$courseList = array();
-
-$configurationPath = api_get_path(SYS_PATH).'main/inc/conf/';
-$newConfigurationFile = $configurationPath.'configuration.yml';
-
-if (is_file($newConfigurationFile) && file_exists($newConfigurationFile)) {
-    $yaml = new Parser();
-    $_configuration = $yaml->parse(file_get_contents($newConfigurationFile));
-}
-
-$connectionOptions = array();
-
-if (!empty($courseList)) {
-
-    $dbPrefix = isset($_configuration['db_prefix']) && !empty($_configuration['db_prefix']) ? $_configuration['db_prefix'].Database::get_database_glue() : null;
-    foreach ($courseList as $course) {
-        $connectionOptions['_chamilo_course_'.$course['db_name']] = array(
-            'driver'    => 'pdo_mysql',
-            'dbname'    => $dbPrefix.$course['db_name'],
-            'user'      => $_configuration['db_user'],
-            'password'  => $_configuration['db_password'],
-            'host'      => $_configuration['db_host'],
-        );
-    }
-}
-
-if (isset($_configuration['main_database'])) {
-    $connectionOptions['main_database'] = array(
-        'driver'    => 'pdo_mysql',
-        'dbname'    => $_configuration['main_database'],
-        'user'      => $_configuration['db_user'],
-        'password'  => $_configuration['db_password'],
-        'host'      => $_configuration['db_host'],
-    );
-}
-
-if (isset($_configuration['statistics_database'])) {
-    $connectionOptions['statistics_database'] = array(
-        'driver'    => 'pdo_mysql',
-        'dbname'    => $_configuration['statistics_database'],
-        'user'      => $_configuration['db_user'],
-        'password'  => $_configuration['db_password'],
-        'host'      => $_configuration['db_host'],
-    );
-} else {
-    if (isset($_configuration['main_database'])) {
-        $connectionOptions['statistics_database'] = $connectionOptions['main_database'];
-    }
-}
-
-if (isset($_configuration['user_personal_database'])) {
-    $connectionOptions['user_personal_database'] = array(
-        'driver'    => 'pdo_mysql',
-        'dbname'    => $_configuration['user_personal_database'],
-        'user'      => $_configuration['db_user'],
-        'password'  => $_configuration['db_password'],
-        'host'      => $_configuration['db_host'],
-    );
-} else {
-    if (isset($_configuration['main_database'])) {
-        $connectionOptions['user_personal_database'] = $connectionOptions['main_database'];
-    }
-}
-
 $defaultConnection = array(
-    'driver' => 'pdo_mysql'
+    'driver'    => 'pdo_mysql',
+    'dbname'    => 'chamilo',
+    'user'      => 'root',
+    'password'  => 'root',
+    'host'      => 'localhost',
 );
 
-if (isset($_configuration['main_database'])) {
-    $defaultConnection = array(
-        'driver'    => 'pdo_mysql',
-        'dbname'    => $_configuration['main_database'],
-        'user'      => $_configuration['db_user'],
-        'password'  => $_configuration['db_password'],
-        'host'      => $_configuration['db_host'],
-    );
-}
-
 $em = \Doctrine\ORM\EntityManager::create($defaultConnection, $config);
 
 //Fixes some errors
 $platform = $em->getConnection()->getDatabasePlatform();
 $platform->registerDoctrineTypeMapping('enum', 'string');
 $platform->registerDoctrineTypeMapping('set', 'string');
-
+ \Doctrine\DBAL\Types\Type::addType('json', 'Sonata\Doctrine\Types\JsonType');
 $helpers = array(
     'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()),
     'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em),
     'configuration' => new \Chash\Helpers\ConfigurationHelper()
 );
 
-use Doctrine\DBAL\DriverManager;
-$multipleEM = array();
-foreach ($connectionOptions as $name => $connection) {
-    $em = \Doctrine\ORM\EntityManager::create($connection, $config);
-    //$helpers[$name] = new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em);
-    $helpers[$name] = new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection());
-}
+$em = \Doctrine\ORM\EntityManager::create($defaultConnection, $config);
+
+use Doctrine\ORM\Tools\Console\ConsoleRunner;
+return ConsoleRunner::createHelperSet($em);
+
 
 /*
 To generate doctrine2 entities you must: