Browse Source

Merge pull request #764 from AngelFQC/BT9893

Validate session subscription with sequences - refs BT#9893 #TMI
Angel Fernando Quiroz Campos 9 years ago
parent
commit
539d662e41

+ 9 - 1
app/Resources/public/css/base.css

@@ -5848,7 +5848,7 @@ div#chat-remote-video video {
 }
 #parents .parent {
   display: inline-block;
-  width: 15%;
+  width: 125px;
   padding: 5px;
   /* background: url("../../main/img/icons/48/sequence-arrow.png") no-repeat center bottom; */
 }
@@ -6177,6 +6177,14 @@ div#chat-remote-video video {
   margin-left: 5%;
   text-align: center;
 }
+
+p.bg-primary,
+p.bg-success,
+p.bg-info,
+p.bg-warning,
+p.bg-danger {
+    padding: 10px;
+}
 /* CSS NEW TOP ******************************************************************************/
 /* CSS Responsive */
 @media (min-width: 1025px) and (max-width: 1200px) {

+ 24 - 0
main/auth/courses.php

@@ -1,5 +1,6 @@
 <?php
 /* For licensing terms, see /license.txt */
+use \Chamilo\CoreBundle\Entity\SequenceResource;
 
 /**
 * Template (front controller in MVC pattern) used for distpaching
@@ -211,6 +212,29 @@ switch ($action) {
     case 'subscribe_to_session':
         $registrationAllowed = api_get_setting('catalog_allow_session_auto_subscription');
         if ($registrationAllowed === 'true') {
+            $entityManager = Database::getManager();
+            $repository = $entityManager->getRepository('ChamiloCoreBundle:SequenceResource');
+
+            $sequences = $repository->getRequirements(
+                $_GET['session_id'],
+                SequenceResource::SESSION_TYPE
+            );
+
+            if (count($sequences) > 0) {
+                $requirementsData = SecuenceResourceManager::checkRequirementsForUser(
+                    $sequences,
+                    api_get_user_id(),
+                    SequenceResource::SESSION_TYPE
+                );
+
+                $continueWithSubscription = SecuenceResourceManager::checkSequenceAreCompleted($requirementsData);
+
+                if (!$continueWithSubscription) {
+                    header('Location: ' .  api_get_path(WEB_CODE_PATH) . 'auth/courses.php');
+                    exit;
+                }
+            }
+
             SessionManager::suscribe_users_to_session(
                 $_GET['session_id'],
                 array($_GET['user_id'])

+ 74 - 29
main/auth/courses_controller.php

@@ -489,26 +489,74 @@ class CoursesController
 
     /**
      * Get a HTML button for subscribe to session
-     * @param string    The session data
-     * @param boolean   Session autosubscription set. False by default.
-     * @return string   The button
+     * @param int $sessionId The session ID
+     * @param string $sessionName The session name
+     * @param boolean $checkRequirements Optional.
+     *        Whether the session has requirement. Default is false
+     * @return string The button HTML
      */
-    public function getRegisteredInSessionButton($sessionData, $catalogSessionAutoSubscriptionAllowed = false)
+    public function getRegisteredInSessionButton(
+        $sessionId,
+        $sessionName,
+        $checkRequirements = false
+    )
     {
-        $url = $catalogSessionAutoSubscriptionAllowed ?
-            api_get_path(WEB_CODE_PATH)."auth/courses.php?action=subscribe_to_session&session_id=".
-            intval($sessionData)."&user_id=".api_get_user_id() :
-            api_get_path(WEB_CODE_PATH)."inc/email_editor.php?action=subscribe_me_to_session&session=".
-            Security::remove_XSS($sessionData);
+        if ($checkRequirements) {
+            $url = api_get_path(WEB_AJAX_PATH);
+            $url .= 'sequence.ajax.php?';
+            $url .= http_build_query([
+                'a' => 'get_requirements',
+                'id' => intval($sessionId),
+                'type' => SequenceResource::SESSION_TYPE,
+                'modal_size' => 'md'
+            ]);
+
+            return Display::toolbarButton(
+                get_lang('CheckRequirements'),
+                $url,
+                'check-circle',
+                'primary',
+                ['class' => 'btn-lg btn-block ajax']
+            );
+        }
+
+        $catalogSessionAutoSubscriptionAllowed = false;
+
+        if (
+            api_get_setting('catalog_allow_session_auto_subscription') === 'true'
+        ) {
+            $catalogSessionAutoSubscriptionAllowed = true;
+        }
+
+        $url = api_get_path(WEB_CODE_PATH);
 
-        $result = Display::url('<i class="fa fa-check-circle"></i> '.get_lang('Subscribe'), $url, array(
-            'class' => 'btn btn-large btn-primary',
-        ));
+        if ($catalogSessionAutoSubscriptionAllowed) {
+            $url .= 'auth/courses.php?';
+            $url .= http_build_query([
+                'action' => 'subscribe_to_session',
+                'session_id' => intval($sessionId),
+                'user_id' => api_get_user_id()
+            ]);
+        } else {
+            $url .= 'inc/email_editor.php?';
+            $url .= http_build_query([
+                'action' => 'subscribe_me_to_session',
+                'session' => Security::remove_XSS($sessionName)
+            ]);
+        }
+
+        $result = Display::toolbarButton(
+            get_lang('Subscribe'),
+            $url,
+            'check-circle',
+            'primary',
+            ['class' => 'btn-lg btn-block']
+        );
 
         $hook = HookResubscribe::create();
         if (!empty($hook)) {
             $hook->setEventData(array(
-                'session_id' => intval($sessionData)
+                'session_id' => intval($sessionId)
             ));
             try {
                 $hook->notifyResubscribe(HOOK_EVENT_TYPE_PRE);
@@ -528,7 +576,10 @@ class CoursesController
     {
         $icon = '<i class="fa fa-smile-o"></i>';
 
-        return Display::div($icon . ' ' . get_lang("AlreadyRegisteredToSession"),array('class'=>'info-catalog'));
+        return Display::div(
+            $icon . ' ' . get_lang("AlreadyRegisteredToSession"),
+            array('class' => 'info-catalog')
+        );
     }
 
     /**
@@ -633,8 +684,6 @@ class CoursesController
      */
     private function getFormatedSessionsBlock(array $sessions)
     {
-        $key = 'name';
-        $catalogSessionAutoSubscriptionAllowed = false;
         $extraFieldValue = new ExtraFieldValue('session');
         $userId = api_get_user_id();
         $sessionsBlocks = [];
@@ -649,11 +698,6 @@ class CoursesController
             'variable' => 'tags'
         ]);
 
-        if (api_get_setting('catalog_allow_session_auto_subscription') === 'true') {
-            $key = 'id';
-            $catalogSessionAutoSubscriptionAllowed = true;
-        }
-
         foreach ($sessions as $session) {
             $sessionDates = SessionManager::parseSessionDates([
                 'display_start_date' => $session->getDisplayStartDate(),
@@ -689,6 +733,12 @@ class CoursesController
                 $sessionCourseTags = array_unique($sessionCourseTags);
             }
 
+            $repo = $entityManager->getRepository('ChamiloCoreBundle:SequenceResource');
+            $requirementAndDependencies = $repo->getRequirementAndDependencies(
+                $session->getId(),
+                SequenceResource::SESSION_TYPE
+            );
+
             $sessionsBlock = array(
                 'id' => $session->getId(),
                 'name' => $session->getName(),
@@ -700,19 +750,14 @@ class CoursesController
                 'icon' => $this->getSessionIcon($session->getName()),
                 'date' => $sessionDates['display'],
                 'subscribe_button' => $this->getRegisteredInSessionButton(
-                    $key === 'id' ? $session->getId() : $session->getName(),
-                    $catalogSessionAutoSubscriptionAllowed
+                    $session->getId(),
+                    $session->getName(),
+                    !empty($requirementAndDependencies['requirements'])
                 ),
                 'show_description' => $session->getShowDescription(),
                 'tags' => $sessionCourseTags
             );
 
-            $repo = $entityManager->getRepository('ChamiloCoreBundle:SequenceResource');
-            $requirementAndDependencies = $repo->getRequirementAndDependencies(
-                $session->getId(),
-                SequenceResource::SESSION_TYPE
-            );
-
             $sessionsBlock = array_merge($sessionsBlock, $requirementAndDependencies);
             $sessionsBlocks[] = $sessionsBlock;
         }

+ 17 - 2
main/gradebook/gradebook_add_cat.php

@@ -118,12 +118,27 @@ if ($form->validate()) {
     $cat->set_session_id(api_get_session_id());
     //Always add the gradebook to the course
     $cat->set_course_code(api_get_course_id());
-    $cat->set_skills($values['skills']);
+
+    if (isset($values['skills'])) {
+        $cat->set_skills($values['skills']);
+    }
+
     $cat->set_description($values['description']);
     $cat->set_user_id($values['hid_user_id']);
     $cat->set_parent_id($values['hid_parent_id']);
     $cat->set_weight($values['weight']);
-    $cat->setGenerateCertificates($values['generate_certificates']);
+
+    if (isset($values['generate_certificates'])) {
+        $cat->setGenerateCertificates(true);
+    } else {
+        $cat->setGenerateCertificates(false);
+    }
+
+    if (isset($values['is_requirement'])) {
+        $cat->setIsRequirement(true);
+    } else {
+        $cat->setIsRequirement(false);
+    }
 
     if (empty ($values['visible'])) {
         $visible = 0;

+ 20 - 3
main/gradebook/gradebook_edit_cat.php

@@ -100,13 +100,23 @@ if ($form->validate()) {
         $cat->set_course_code($values['course_code']);
     }
 
-    $cat->set_grade_model_id($values['grade_model_id']);
+    if (isset($values['grade_model_id'])) {
+        $cat->set_grade_model_id($values['grade_model_id']);
+    }
+
     $cat->set_description($values['description']);
-    $cat->set_skills($values['skills']);
+
+    if (isset($values['skills'])) {
+        $cat->set_skills($values['skills']);
+    }
+
     $cat->set_user_id($values['hid_user_id']);
     $cat->set_parent_id($values['hid_parent_id']);
     $cat->set_weight($values['weight']);
-    $cat->setGenerateCertificates($values['generate_certificates']);
+
+    if (isset($values['generate_certificates'])) {
+        $cat->setGenerateCertificates($values['generate_certificates']);
+    }
 
     if ($values['hid_parent_id'] == 0 ) {
         $cat->set_certificate_min_score($values['certif_min_score']);
@@ -119,6 +129,13 @@ if ($form->validate()) {
     }
 
     $cat->set_visible($visible);
+
+    if (isset($values['is_requirement'])) {
+        $cat->setIsRequirement(true);
+    } else {
+        $cat->setIsRequirement(false);
+    }
+
     $cat->save();
     header('Location: '.Security::remove_XSS($_SESSION['gradebook_dest']).'?editcat=&selectcat=' . $cat->get_parent_id().'&'.api_get_cidreq());
     exit;

+ 110 - 99
main/gradebook/lib/be/category.class.php

@@ -21,12 +21,26 @@ class Category implements GradebookItem
     private $skills = array();
     private $grade_model_id;
     private $generateCertificates;
+    private $isRequirement;
 
     /**
      * Consctructor
      */
     public function __construct()
     {
+        $this->id = 0;
+        $this->name = null;
+        $this->description = null;
+        $this->user_id = 0;
+        $this->course_code = null;
+        $this->parent = 0;
+        $this->weight = 0;
+        $this->visible = false;
+        $this->certificate_min_score = 0;
+        $this->session_id = 0;
+        $this->grade_model_id = 0;
+        $this->generateCertificates = false;
+        $this->isRequirement = false;
     }
 
     /**
@@ -113,6 +127,15 @@ class Category implements GradebookItem
         return $this->visible;
     }
 
+    /**
+     * Get $isRequirement
+     * @return int
+     */
+    public function getIsRequirement()
+    {
+        return $this->isRequirement;
+    }
+
     /**
      * @param int $id
      */
@@ -210,6 +233,15 @@ class Category implements GradebookItem
         $this->locked = $locked;
     }
 
+    /**
+     * Set $isRequirement
+     * @param int $isRequirement
+     */
+    public function setIsRequirement($isRequirement)
+    {
+        $this->isRequirement = $isRequirement;
+    }
+
     /**
      * @return int
      */
@@ -440,6 +472,7 @@ class Category implements GradebookItem
         $cat->set_weight(0);
         $cat->set_visible(1);
         $cat->setGenerateCertificates(0);
+        $cat->setIsRequirement(false);
 
         return $cat;
     }
@@ -467,12 +500,46 @@ class Category implements GradebookItem
             $cat->set_grade_model_id($data['grade_model_id']);
             $cat->set_locked($data['locked']);
             $cat->setGenerateCertificates($data['generate_certificates']);
+            $cat->setIsRequirement($data['is_requirement']);
             $categories[] = $cat;
         }
 
         return $categories;
     }
 
+    /**
+     * Create a category object from a GradebookCategory entity
+     * @param Chamilo\CoreBundle\Entity\GradebookCategory $gradebookCategory
+     *         The entity
+     * @return \Category
+     */
+    public static function createCategoryObjectFromEntity(
+        Chamilo\CoreBundle\Entity\GradebookCategory $gradebookCategory
+    )
+    {
+        $category = new Category();
+        $category->set_id($gradebookCategory->getId());
+        $category->set_name($gradebookCategory->getName());
+        $category->set_description($gradebookCategory->getDescription());
+        $category->set_user_id($gradebookCategory->getUserId());
+        $category->set_course_code($gradebookCategory->getCourseCode());
+        $category->set_parent_id($gradebookCategory->getParentId());
+        $category->set_weight($gradebookCategory->getWeight());
+        $category->set_visible($gradebookCategory->getVisible());
+        $category->set_session_id($gradebookCategory->getSessionId());
+        $category->set_certificate_min_score(
+            $gradebookCategory->getCertifMinScore()
+        );
+        $category->set_grade_model_id($gradebookCategory->getGradeModelId());
+        $category->set_locked($gradebookCategory->getLocked());
+        $category->setGenerateCertificates(
+            $gradebookCategory->getGenerateCertificates()
+        );
+        $category->setIsRequirement($gradebookCategory->getIsRequirement());
+
+        return $category;
+    }
+
     /**
      * Insert this category into the database
      */
@@ -483,70 +550,26 @@ class Category implements GradebookItem
         }
 
         if (isset($this->name) && isset($this->user_id)) {
-            $tbl_grade_categories = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
-            $sql = 'INSERT INTO '.$tbl_grade_categories.' (name,user_id,weight,visible';
-            if (isset($this->description)) {
-                $sql .= ',description';
-            }
-            if (isset($this->course_code)) {
-                $sql .= ',course_code';
-            }
-            if (isset($this->parent)) {
-                $sql .= ',parent_id';
-            }
-            if (!empty($this->session_id)) {
-                $sql .= ', session_id';
-            }
-
-            if (isset($this->grade_model_id)) {
-                $sql .= ', grade_model_id ';
-            }
-            if (isset($this->certificate_min_score) && !empty($this->certificate_min_score)) {
-                $sql .= ', certif_min_score ';
-            }
-
-            if (isset($this->generateCertificates)) {
-                $sql .= ', generate_certificates ';
-            }
-
-            /*
-            $setting = api_get_setting('tool_visible_by_default_at_creation');
-            $visible = 1;
-            if (isset($setting['gradebook'])) {
-                if ($setting['gradebook'] == 'false') {
-                    $visible = 0;
-                }
-            }*/
+            $em = Database::getManager();
+
+            $category = new \Chamilo\CoreBundle\Entity\GradebookCategory();
+            $category->setName($this->name);
+            $category->setDescription($this->description);
+            $category->setUserId($this->user_id);
+            $category->setCourseCode($this->course_code);
+            $category->setParentId($this->parent);
+            $category->setWeight($this->weight);
+            $category->setVisible($this->visible);
+            $category->setCertifMinScore($this->certificate_min_score);
+            $category->setSessionId($this->session_id);
+            $category->setGenerateCertificates($this->generateCertificates);
+            $category->setGradeModelId($this->grade_model_id);
+            $category->setIsRequirement($this->isRequirement);
+            $category->setLocked(false);
+
+            $em->persist($category);
+            $em->flush();
 
-            $visible = intval($this->is_visible());
-
-            $sql .= ") VALUES ('".Database::escape_string($this->get_name())."'"
-                .','.intval($this->get_user_id())
-                .','.Database::escape_string($this->get_weight())
-                .','.$visible;
-            if (isset($this->description)) {
-                $sql .= ",'".Database::escape_string($this->get_description())."'";
-            }
-            if (isset($this->course_code)) {
-                $sql .= ",'".Database::escape_string($this->get_course_code())."'";
-            }
-            if (isset($this->parent)) {
-                $sql .= ','.intval($this->get_parent_id());
-            }
-            if (!empty($this->session_id)) {
-                $sql .= ', '.intval($this->get_session_id());
-            }
-            if (isset($this->grade_model_id)) {
-                $sql .= ', '.intval($this->get_grade_model_id());
-            }
-            if (isset($this->certificate_min_score) && !empty($this->certificate_min_score)) {
-                $sql .= ', '.intval($this->get_certificate_min_score());
-            }
-            if (isset($this->generateCertificates)) {
-                $sql .= ', ' . intval($this->generateCertificates);
-            }
-            $sql .= ')';
-            Database::query($sql);
             $id = Database::insert_id();
             $this->set_id($id);
 
@@ -595,44 +618,32 @@ class Category implements GradebookItem
      */
     public function save()
     {
-        $tbl_grade_categories = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
+        $em = Database::getManager();
 
-        $sql = 'UPDATE '.$tbl_grade_categories." SET
-                name = '".Database::escape_string($this->get_name())."'".',
-                description = ';
-        if (isset($this->description)) {
-            $sql .= "'".Database::escape_string($this->get_description())."'";
-        } else {
-            $sql .= 'null';
-        }
-        $sql .= ', user_id = '.intval($this->get_user_id())
-            .', course_code = ';
-        if (isset($this->course_code)) {
-            $sql .= "'".Database::escape_string($this->get_course_code())."'";
-        } else {
-            $sql .= 'null';
-        }
-        $sql .=    ', parent_id = ';
-        if (isset($this->parent)) {
-            $sql .= intval($this->get_parent_id());
-        } else {
-            $sql .= 'null';
-        }
-        $sql .= ', certif_min_score = ';
-        if (isset($this->certificate_min_score) && !empty($this->certificate_min_score)) {
-            $sql .= intval($this->get_certificate_min_score());
-        } else {
-            $sql .= 'null';
-        }
-        if (isset($this->grade_model_id)) {
-            $sql .= ', grade_model_id = '.intval($this->get_grade_model_id());
+        $gradebookCategory = $em
+            ->getRepository('ChamiloCoreBundle:GradebookCategory')
+            ->find($this->id);
+
+        if (empty($gradebookCategory)) {
+            return false;
         }
-        $sql .= ', weight = "'.Database::escape_string($this->get_weight())
-            .'", visible = '.intval($this->is_visible())
-            . ', generate_certificates = ' . intval($this->generateCertificates)
-            .' WHERE id = '.intval($this->id);
 
-        Database::query($sql);
+        $gradebookCategory->setName($this->name);
+        $gradebookCategory->setDescription($this->description);
+        $gradebookCategory->setUserId($this->user_id);
+        $gradebookCategory->setCourseCode($this->course_code);
+        $gradebookCategory->setParentId($this->parent);
+        $gradebookCategory->setWeight($this->weight);
+        $gradebookCategory->setVisible($this->visible);
+        $gradebookCategory->setCertifMinScore($this->certificate_min_score);
+        $gradebookCategory->setGenerateCertificates(
+            $this->generateCertificates
+        );
+        $gradebookCategory->setGradeModelId($this->grade_model_id);
+        $gradebookCategory->setIsRequirement($this->isRequirement);
+
+        $em->persist($gradebookCategory);
+        $em->flush();
 
         if (!empty($this->id)) {
             $parent_id = $this->get_parent_id();
@@ -746,7 +757,7 @@ class Category implements GradebookItem
             return null;
         } else {
             $tbl_category = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
-            $sql = 'SELECT name,description,user_id,course_code,parent_id,weight,visible,certif_min_score,session_id, generate_certificates
+            $sql = 'SELECT name,description,user_id,course_code,parent_id,weight,visible,certif_min_score,session_id, generate_certificates, is_requirement
                     FROM '.$tbl_category.' c
                     WHERE c.id='.intval($selectcat);
             $result = Database::query($sql);

+ 17 - 1
main/gradebook/lib/fe/catform.class.php

@@ -176,7 +176,8 @@ class CatForm extends FormValidator
                 'weight' 			=> $this->category_object->get_weight(),
                 'visible' 			=> $this->category_object->is_visible(),
                 'certif_min_score'  => $this->category_object->get_certificate_min_score(),
-                'generate_certificates' => $this->category_object->getGenerateCertificates()
+                'generate_certificates' => $this->category_object->getGenerateCertificates(),
+                'is_requirement' => $this->category_object->getIsRequirement()
             )
         );
         $this->addElement('hidden', 'hid_id', $this->category_object->get_id());
@@ -370,6 +371,21 @@ class CatForm extends FormValidator
             );
         }
 
+        if (!empty(api_get_session_id())) {
+            $isRequirementCheckbox = $this->addCheckBox(
+                'is_requirement',
+                [
+                    null,
+                    get_lang('ConsiderThisGradebookAsRequirementForASessionSequence')
+                ],
+                get_lang('IsRequirement')
+            );
+        }
+
+        if ($this->category_object->getIsRequirement()) {
+            $isRequirementCheckbox->setChecked(true);
+        }
+
         if ($this->form_type == self :: TYPE_ADD) {
             $this->addButtonCreate(get_lang('AddCategory'));
         } else {

+ 44 - 0
main/inc/ajax/sequence.ajax.php

@@ -283,4 +283,48 @@ switch ($action) {
                 break;
         }
         break;
+    case 'get_requirements':
+        $userId = api_get_user_id();
+
+        switch ($type) {
+            case SequenceResource::SESSION_TYPE:
+                $session = api_get_session_info($id);
+
+                $sequences = $repository->getRequirements(
+                    $session['id'],
+                    $type
+                );
+
+                if (count($sequences) === 0) {
+                    break;
+                }
+
+                $sequenceList = SecuenceResourceManager::checkRequirementsForUser($sequences, $userId, $type);
+                $allowSubscription = SecuenceResourceManager::checkSequenceAreCompleted($sequenceList);
+
+                $courseController = new CoursesController();
+
+                $view = new Template(null, false, false, false, false, false);
+                $view->assign('sequences', $sequenceList);
+                $view->assign('allow_subscription', $allowSubscription);
+
+                if ($allowSubscription) {
+                    $view->assign(
+                        'subscribe_button',
+                        $courseController->getRegisteredInSessionButton(
+                            $session['id'],
+                            $session['name'],
+                            false
+                        )
+                    );
+                }
+
+                $template = $view->get_template(
+                    'sequence_resource/session_requirements.tpl'
+                );
+
+                $view->display($template);
+                break;
+        }
+        break;
 }

+ 117 - 0
main/inc/lib/SecuenceResourceManager.php

@@ -0,0 +1,117 @@
+<?php
+/* For licensing terms, see /license.txt */
+use \Chamilo\CoreBundle\Entity\SequenceResource;
+
+/**
+ * SecuenceResourceManager class
+ * Helper for SequenceResource
+ *
+ * @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
+ */
+class SecuenceResourceManager
+{
+
+    /**
+     * Check if the ser has completed the requirements for the sequences
+     * @param array $sequences The sequences
+     * @param int $userId The user ID
+     * @param int $type The type of sequence resource
+     * @return array
+     */
+    public static function checkRequirementsForUser(array $sequences, $userId, $type)
+    {
+        $sequenceList = [];
+
+        switch ($type) {
+            case SequenceResource::SESSION_TYPE:
+                $sequenceList = self::checkSessionRequirementsForUser($sequences, $userId);
+                break;
+        }
+
+        return $sequenceList;
+    }
+
+    /**
+     * Check if the ser has completed the requirements for the session sequences
+     * @param array $sequences The sequences
+     * @param int $userId The user ID
+     * @return array
+     */
+    private static function checkSessionRequirementsForUser(array $sequences, $userId)
+    {
+        $sequenceList = [];
+
+        $entityManager = Database::getManager();
+
+        $gradebookCategoryRepo = $entityManager->getRepository(
+            'ChamiloCoreBundle:GradebookCategory'
+        );
+
+        foreach ($sequences as $sequenceId => $sequence) {
+            $item = [
+                'name' => $sequence['name'],
+                'requirements' => []
+            ];
+
+            foreach ($sequence['requirements'] as $sessionRequired) {
+                $itemSession = [
+                    'name' => $sessionRequired->getName(),
+                    'status' => true
+                ];
+
+                $sessionsCourses = $sessionRequired->getCourses();
+
+                foreach ($sessionsCourses as $sessionCourse) {
+                    $course = $sessionCourse->getCourse();
+
+                    $gradebooks = $gradebookCategoryRepo->findBy([
+                        'courseCode' => $course->getCode(),
+                        'sessionId' => $sessionRequired->getId(),
+                        'isRequirement' => true
+                    ]);
+
+                    foreach ($gradebooks as $gradebook) {
+                        $category = Category::createCategoryObjectFromEntity(
+                            $gradebook
+                        );
+
+                        $itemSession['status'] = $itemSession['status'] && Category::userFinishedCourse(
+                            $userId,
+                            $category
+                        );
+                    }
+                }
+
+                $item['requirements'][$sessionRequired->getId()] = $itemSession;
+            }
+
+            $sequenceList[$sequenceId] = $item;
+        }
+
+        return $sequenceList;
+    }
+
+    /**
+     * Check if at least one sequence are completed
+     * @param array $sequences The sequences
+     * @param int $type The type of sequence resource
+     * @return boolean
+     */
+    public static function checkSequenceAreCompleted(array $sequences)
+    {
+        foreach ($sequences as $secuence) {
+            $status = true;
+
+            foreach ($secuence['requirements'] as $item) {
+                $status = $status && $item['status'];
+            }
+
+            if ($status) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+}

+ 18 - 0
main/session/about.php

@@ -32,6 +32,9 @@ $entityManager = Database::getManager();
 $fieldsRepo = $entityManager->getRepository('ChamiloCoreBundle:ExtraField');
 $fieldTagsRepo = $entityManager->getRepository('ChamiloCoreBundle:ExtraFieldRelTag');
 $userRepo = $entityManager->getRepository('ChamiloUserBundle:User');
+$sequenceResourceRepo = $entityManager->getRepository(
+    'ChamiloCoreBundle:SequenceResource'
+);
 
 $tagField = $fieldsRepo->findOneBy([
     'extraFieldType' => ExtraField::COURSE_FIELD_TYPE,
@@ -110,6 +113,13 @@ $sessionDates = SessionManager::parseSessionDates([
     'coach_access_end_date' => $session->getCoachAccessEndDate()
 ]);
 
+$sessionRequirements = $sequenceResourceRepo->getRequirements(
+    $session->getId(),
+    \Chamilo\CoreBundle\Entity\SequenceResource::SESSION_TYPE
+);
+
+$courseController = new CoursesController();
+
 /* View */
 $template = new Template($session->getName(), true, true, false, true, false);
 $template->assign('show_tutor', (api_get_setting('show_session_coach')==='true' ? true : false));
@@ -123,6 +133,14 @@ $template->assign(
         api_get_user_id()
     )
 );
+$template->assign(
+    'subscribe_button',
+    $courseController->getRegisteredInSessionButton(
+        $session->getId(),
+        $session->getName(),
+        !empty($sessionRequirements)
+    )
+);
 
 $template->assign('courses', $courses);
 $template->assign('essence', \Essence\Essence::instance());

+ 32 - 0
main/template/default/sequence_resource/session_requirements.tpl

@@ -0,0 +1,32 @@
+<h2 class="page-header">{{ 'SessionRequirements'|get_lang }}</h2>
+
+{% for item in sequences %}
+    <h4>{{ item.name }}</h4>
+
+    <div id="parents">
+        {% for session in item.requirements %}
+            <div class="parent">
+                <div class="big-icon">
+                    <img src="{{ 'item-sequence.png'|icon(48) }}">
+                    <p class="sequence-course">{{ session.name }}</p>
+                    <span class="label {{ session.status ? 'label-success' : 'label-danger' }}">
+                        {% if session.status %}
+                            <i class="fa fa-check"></i> {{ 'Complete'|get_lang }}
+                        {% else %}
+                            <i class="fa fa-exclamation-triangle"></i> {{ 'Incomplete'|get_lang }}
+                        {% endif %}
+                    </span>
+                </div>
+            </div>
+
+            {% if loop.index != item.requirements|length %}
+                <i class="fa fa-plus fa-3x sequence-plus-icon"></i>
+            {% endif %}
+        {% endfor %}
+    </div>
+{% endfor %}
+
+{% if allow_subscription %}
+    <hr>
+    <p>{{ subscribe_button }}</p>
+{% endif %}

+ 17 - 4
main/template/default/session/about.tpl

@@ -56,9 +56,9 @@
                     </div>
                 {% endif %}
 
-                {% if not is_subscribed %}
+                {% if courses|length == 1 and not is_subscribed %}
                     <div class="subscribe">
-                        <a href="#" class="btn btn-success btn-lg btn-block"><i class="fa fa-book"></i> {{ "Subscribe"|get_lang }}</a>
+                        {{ subscribe_button }}
                     </div>
                 {% endif %}
             </div>
@@ -142,12 +142,25 @@
                 </div>
             </div>
         </div>
+
+        {% if courses|length == 1 and not is_subscribed %}
+            <div class="row">
+                <div class="col-md-4 col-md-offset-4">
+                    <div class="text-center">
+                        {{ subscribe_button }}
+                    </div>
+                </div>
+            </div>
+        {% endif %}
+    {% endfor %}
+
+    {% if courses|length > 1 and not is_subscribed %}
         <div class="row">
             <div class="col-md-4 col-md-offset-4">
                 <div class="text-center">
-                    <a href="#" class="btn btn-success btn-lg btn-block"><i class="fa fa-book"></i> {{ "Subscribe"|get_lang }}</a>
+                    {{ subscribe_button }}
                 </div>
             </div>
         </div>
-    {% endfor %}
+    {% endif %}
 </div>

+ 34 - 0
src/Chamilo/CoreBundle/Entity/GradebookCategory.php

@@ -12,6 +12,7 @@ use Doctrine\ORM\Mapping as ORM;
  */
 class GradebookCategory
 {
+
     /**
      * @var string
      *
@@ -110,6 +111,18 @@ class GradebookCategory
      */
     private $gradeModelId;
 
+    /**
+     * @var boolean
+     *
+     * @ORM\Column(
+     *      name="is_requirement",
+     *      type="boolean",
+     *      nullable=false,
+     *      options={"default": 0 }
+     * )
+     */
+    private $isRequirement;
+
     /**
      * @var integer
      *
@@ -443,6 +456,27 @@ class GradebookCategory
         return $this->gradeModelId;
     }
 
+    /**
+     * Set isRequirement
+     * @param boolean $isRequirement
+     * @return \Chamilo\CoreBundle\Entity\GradebookCategory
+     */
+    public function setIsRequirement($isRequirement)
+    {
+        $this->isRequirement = $isRequirement;
+
+        return $this;
+    }
+
+    /**
+     * Get isRequirement
+     * @return boolean
+     */
+    public function getIsRequirement()
+    {
+        return $this->isRequirement;
+    }
+
     /**
      * Get id
      *

+ 54 - 0
src/Chamilo/CoreBundle/Entity/Repository/SequenceRepository.php

@@ -103,4 +103,58 @@ class SequenceRepository extends EntityRepository
         }
     }
 
+    /**
+     * Get the requirements for a resource only
+     * @param int $resourceId The resource ID
+     * @param int $type The type of sequence resource
+     * @return array
+     */
+    public function getRequirements($resourceId, $type)
+    {
+        $sequencesResource = $this->findBy([
+            'resourceId' => $resourceId,
+            'type' => $type
+        ]);
+
+        $result = [];
+
+        foreach ($sequencesResource as $sequenceResource) {
+            if (!$sequenceResource->hasGraph()) {
+                continue;
+            }
+
+            $sequence = $sequenceResource->getSequence();
+            $graph = $sequence->getUnSerializeGraph();
+            $vertex = $graph->getVertex($resourceId);
+            $from = $vertex->getVerticesEdgeFrom();
+
+            $sequenceInfo = [
+                'name' => $sequence->getName(),
+                'requirements' => []
+            ];
+
+            foreach ($from as $subVertex) {
+                $vertexId = $subVertex->getId();
+
+                switch ($type) {
+                    case SequenceResource::SESSION_TYPE:
+                        $session = $this->getEntityManager()->getReference(
+                            'ChamiloCoreBundle:Session',
+                            $vertexId
+                        );
+
+                        if (empty($session)) {
+                            break;
+                        }
+
+                        $sequenceInfo['requirements'][$vertexId] = $session;
+                        break;
+                }
+            }
+
+            $result[$sequence->getId()] = $sequenceInfo;
+        }
+
+        return $result;
+    }
 }

+ 36 - 0
src/Chamilo/CoreBundle/Migrations/Schema/V110/Version20150706135000.php

@@ -0,0 +1,36 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Chamilo\CoreBundle\Migrations\Schema\V110;
+
+use Chamilo\CoreBundle\Migrations\AbstractMigrationChamilo;
+use Doctrine\DBAL\Schema\Schema;
+
+/**
+ * GradebookCategory changes
+ */
+class Version20150706135000 extends AbstractMigrationChamilo
+{
+    /**
+     * @param Schema $schema
+     */
+    public function up(Schema $schema)
+    {
+        $gradebookCategory = $schema->getTable('gradebook_category');
+
+        $isRequirement = $gradebookCategory->addColumn(
+            'is_requirement',
+            \Doctrine\DBAL\Types\Type::BOOLEAN
+        );
+        $isRequirement->setNotnull(true)->setDefault(false);
+    }
+
+    /**
+     * @param Schema $schema
+     */
+    public function down(Schema $schema)
+    {
+        $gradebookCategory = $schema->getTable('gradebook_category');
+        $gradebookCategory->dropColumn('is_requirement');
+    }
+}