diff --git a/main/inc/lib/extra_field.lib.php b/main/inc/lib/extra_field.lib.php
index 311140143f..59fbc6f131 100755
--- a/main/inc/lib/extra_field.lib.php
+++ b/main/inc/lib/extra_field.lib.php
@@ -735,9 +735,14 @@ class ExtraField extends Model
$addOptions = array();
+ $optionsExists = false;
global $app;
- $optionsExists = $app['orm.em']->getRepository('ChamiloLMS\Entity\ExtraFieldOptionRelFieldOption')->
- findOneBy(array('fieldId' => $field_details['id']));
+ // Check if exist $app['orm.em'] object
+ if (isset($app['orm.em']) && is_object($app['orm.em'])) {
+ $optionsExists = $app['orm.em']
+ ->getRepository('ChamiloLMS\Entity\ExtraFieldOptionRelFieldOption')
+ ->findOneBy(array('fieldId' => $field_details['id']));
+ }
if ($optionsExists) {
if (isset($userInfo['status']) && !empty($userInfo['status'])) {
diff --git a/main/inc/lib/hook/HookWSRegistration.php b/main/inc/lib/hook/HookWSRegistration.php
index 25e7d7d7a7..c2b51b14a3 100644
--- a/main/inc/lib/hook/HookWSRegistration.php
+++ b/main/inc/lib/hook/HookWSRegistration.php
@@ -34,7 +34,7 @@ class HookWSRegistration extends HookEvent implements HookWSRegistrationEventInt
{
/** @var \HookWSRegistrationObserverInterface $observer */
// check if already have server data
- if (!isset($this->eventData['server'])) {
+ if (isset($this->eventData['server'])) {
// Save Hook event type data
$this->eventData['type'] = $type;
foreach ($this->observers as $observer) {
diff --git a/main/inc/lib/internationalization.lib.php b/main/inc/lib/internationalization.lib.php
index 8025b630b5..f483e04c50 100755
--- a/main/inc/lib/internationalization.lib.php
+++ b/main/inc/lib/internationalization.lib.php
@@ -3348,12 +3348,12 @@ function get_datepicker_langage_code() {
/**
* Returns the variable translated
- * @param $variable the string to translate
- * @param $pluginName the Plugin name
+ * @param string $variable the string to translate
+ * @param string $pluginName the Plugin name
* @return string the variable translated
*/
function get_plugin_lang($variable, $pluginName) {
- eval("\$plugin = {$pluginName}::create();");
+ $plugin = $pluginName::create();
return $plugin->get_lang($variable);
}
/**
diff --git a/main/inc/lib/sessionmanager.lib.php b/main/inc/lib/sessionmanager.lib.php
index 91d6506438..fa2f2ca83f 100755
--- a/main/inc/lib/sessionmanager.lib.php
+++ b/main/inc/lib/sessionmanager.lib.php
@@ -5224,8 +5224,8 @@ class SessionManager
$sessionId = intval($sessionId);
$userId = intval($userId);
- $sql = "SELECT COUNT(1) AS qty FROM $sessionRelUserTable
- WHERE id_session = $sessionId AND id_user = $userId AND relation_type = 0";
+ $sql = "SELECT COUNT(1) AS qty FROM $sessionRelUserTable "
+ . "WHERE id_session = $sessionId AND id_user = $userId AND relation_type = 0";
$result = Database::fetch_assoc(Database::query($sql));
@@ -5305,7 +5305,6 @@ class SessionManager
* Check if the course belongs to the session
* @param int $sessionId The session id
* @param string $courseCode The course code
- *
* @return bool
*/
public static function sessionHasCourse($sessionId, $courseCode)
@@ -5429,4 +5428,266 @@ class SessionManager
));
}
+ /**
+ * Returns the list of session (name, short description, start date, end date) from category.
+ * The short description is an extra field value
+ * @param int $categoryId
+ * @param string $target
+ * @return mixed
+ */
+ public static function getSessionBriefListByCategory($categoryId, $target) {
+ // Init variables
+ $categoryId = (int) $categoryId;
+ $sessionList = array();
+ // Check if categoryId is valid
+ if ($categoryId > 0) {
+ $target = Database::escape_string($target);
+ $sTable = Database::get_main_table(TABLE_MAIN_SESSION);
+ $sfTable = Database::get_main_table(TABLE_MAIN_SESSION_FIELD);
+ $sfvTable = Database::get_main_table(TABLE_MAIN_SESSION_FIELD_VALUES);
+ // Join session field and session field values tables
+ $joinTable = $sfTable . ' sf INNER JOIN ' . $sfvTable . ' sfv ON sf.id = sfv.field_id';
+ $fieldsArray = array(
+ 'short_description', 'mode', 'duration', 'vacancies', 'brochure', 'target', 'schedule'
+ );
+ // Get the session list from session category and target
+ $sessionList = Database::select(
+ 'id, name, date_start, date_end',
+ $sTable,
+ array(
+ 'where' => array(
+ "session_category_id = ? AND id IN (
+ SELECT sfv.session_id FROM $joinTable WHERE
+ sfv.session_id = session.id
+ AND sf.field_variable = 'target'
+ AND sfv.field_value = ?
+ );" => array($categoryId, $target)
+ )
+ )
+ );
+
+ // Get session fields
+ $extraField = new ExtraField('session');
+ $fieldList = $extraField->get_all(array(
+ 'field_variable IN ( ?, ?, ?, ?, ?, ?, ? )' => $fieldsArray
+ ));
+ // Index session fields
+ foreach ($fieldList as $field) {
+ $fields[$field['id']] = $field['field_variable'];
+ }
+ // Get session field values
+ $extra = new ExtraFieldValue('session');
+ $sessionFieldValueList = $extra->get_all(array('field_id IN ( ?, ?, ?, ?, ?, ?, ? )' => array_keys($fields)));
+ // Add session fields values to session list
+ foreach ($sessionList as $id => &$session) {
+ foreach ($sessionFieldValueList as $sessionFieldValue) {
+ // Match session field values to session
+ if ($sessionFieldValue['session_id'] == $id) {
+ // Check if session field value is set in session field list
+ if (isset($fields[$sessionFieldValue['field_id']])) {
+ $var = $fields[$sessionFieldValue['field_id']];
+ $val = $sessionFieldValue['field_value'];
+ // Assign session field value to session
+ $session[$var] = $val;
+ }
+ }
+ }
+ }
+ }
+
+ return $sessionList;
+ }
+
+ /**
+ * Return the Session Category id searched by name
+ * @param string $categoryName Name attribute of session category used for search query
+ * @param bool $force boolean used to get even if something is wrong (e.g not unique name)
+ * @return int|array If success, return category id (int), else it will return an array
+ * with the next structure:
+ * array('error' => true, 'errorMessage' => ERROR_MESSAGE)
+ */
+ public static function getSessionCategoryIdByName($categoryName, $force = false)
+ {
+ // Start error result
+ $errorResult = array('error' => true, 'errorMessage' => get_lang('ThereWasAnError'));
+ $categoryName = Database::escape_string($categoryName);
+ // Check if is not empty category name
+ if (!empty($categoryName)) {
+ $sessionCategoryTable = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
+ // Get all session category with same name
+ $result = Database::select(
+ 'id',
+ $sessionCategoryTable,
+ array(
+ 'where' => array(
+ 'name = ?' => $categoryName,
+ )
+ )
+ );
+ // Check the result
+ if ($result < 1) {
+ // If not found any result, update error message
+ $errorResult['errorMessage'] = 'Not found any session category name ' . $categoryName;
+ } elseif (count($result) > 1 && !$force) {
+ // If found more than one result and force is disabled, update error message
+ $errorResult['errorMessage'] = 'Found many session categories';
+ } elseif (count($result) == 1 || $force) {
+ // If found just one session category or force option is enabled
+
+ return key($result);
+ }
+ } else {
+ // category name is empty, update error message
+ $errorResult['errorMessage'] = 'Not valid category name';
+ }
+
+ return $errorResult;
+ }
+
+ /**
+ * Return all data from sessions (plus extra field, course and coach data) by category id
+ * @param int $sessionCategoryId session category id used to search sessions
+ * @return array If success, return session list and more session related data, else it will return an array
+ * with the next structure:
+ * array('error' => true, 'errorMessage' => ERROR_MESSAGE)
+ */
+ public static function getSessionListAndExtraByCategoryId($sessionCategoryId)
+ {
+ // Start error result
+ $errorResult = array('error' => true, 'errorMessage' => get_lang('ThereWasAnError'));
+ $sessionCategoryId = intval($sessionCategoryId);
+ // Check if sesssion category id is valid
+ if ($sessionCategoryId > 0) {
+ // Get table names
+ $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION);
+ $sessionFieldTable = Database::get_main_table(TABLE_MAIN_SESSION_FIELD);
+ $sessionFieldValueTable = Database::get_main_table(TABLE_MAIN_SESSION_FIELD_VALUES);
+ $sessionCourseUserTable = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
+ $userTable = Database::get_main_table(TABLE_MAIN_USER);
+ $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
+
+ // Get all data from all sessions whit the session category specified
+ $sessionList = Database::select(
+ '*',
+ $sessionTable,
+ array(
+ 'where' => array(
+ 'session_category_id = ?' => $sessionCategoryId
+ )
+ )
+ );
+ // Check if session list query had result
+ if (!empty($sessionList)) {
+ // implode all session id
+ $sessionIdsString = '(' . implode(', ', array_keys($sessionList)) . ')';
+ // Get all field variables
+ $sessionFieldList = Database::select('id, field_variable', $sessionFieldTable);
+ // Get all field values
+ $sessionFieldValueList = Database::select(
+ 'session_id, field_id, field_value',
+ $sessionFieldValueTable,
+ array('where' => array('session_id IN ?' => $sessionIdsString))
+ );
+ // Check if session field values had result
+ if (!empty($sessionFieldValueList)) {
+ $sessionFieldValueListBySession = array();
+ foreach ($sessionFieldValueList as $key => $sessionFieldValue) {
+ // Create an array to index ids to session id
+ $sessionFieldValueListBySession[$sessionFieldValue['session_id']][] = $key;
+ }
+ }
+ // Query used to find course-coaches from sessions
+ $sql = "SELECT scu.id_session AS session_id, c.id AS course_id, c.code AS course_code," .
+ " c.title AS course_title, u.username AS coach_username, u.firstname AS coach_firstname, " .
+ " u.lastname AS coach_lastname " .
+ "FROM $courseTable c " .
+ "INNER JOIN $sessionCourseUserTable scu ON c.code = scu.course_code " .
+ "INNER JOIN $userTable u ON scu.id_user = u.user_id " .
+ "WHERE scu.status = 2 AND scu.id_session IN $sessionIdsString " .
+ "ORDER BY scu.id_session ASC ";
+ $res = Database::query($sql);
+ $sessionCourseList = Database::store_result($res, 'ASSOC');
+ // Check if course list had result
+ if (!empty($sessionCourseList)) {
+ foreach ($sessionCourseList as $key => $sessionCourse) {
+ // Create an array to index ids to session_id
+ $sessionCourseListBySession[$sessionCourse['session_id']][] = $key;
+ }
+ }
+ // Join lists
+ if (is_array($sessionList)) {
+ foreach ($sessionList as $id => &$row) {
+ if (
+ !empty($sessionFieldValueListBySession) &&
+ is_array($sessionFieldValueListBySession[$id])
+ ) {
+ // If have an index array for session extra fields, use it to join arrays
+ foreach ($sessionFieldValueListBySession[$id] as $key) {
+ $row['extra'][$key] = array(
+ 'field_name' => $sessionFieldList[$sessionFieldValueList[$key]['field_id']]['field_variable'],
+ 'field_value' => $sessionFieldValueList[$key]['field_value'],
+ );
+ }
+ }
+ if (
+ !empty($sessionCourseListBySession) &&
+ is_array($sessionCourseListBySession[$id])
+ ) {
+ // If have an index array for session course coach, use it to join arrays
+ foreach ($sessionCourseListBySession[$id] as $key) {
+ $row['course'][$key] = array(
+ 'course_id' => $sessionCourseList[$key]['course_id'],
+ 'course_code' => $sessionCourseList[$key]['course_code'],
+ 'course_title' => $sessionCourseList[$key]['course_title'],
+ 'coach_username' => $sessionCourseList[$key]['coach_username'],
+ 'coach_firstname' => $sessionCourseList[$key]['coach_firstname'],
+ 'coach_lastname' => $sessionCourseList[$key]['coach_lastname'],
+ );
+ }
+ }
+ }
+ }
+
+ return $sessionList;
+ } else {
+ // Not found result, update error message
+ $errorResult['errorMessage'] = 'Not found any session for session category id ' . $sessionCategoryId;
+ }
+
+ return $errorResult;
+ }
+ }
+
+ /**
+ * Return session description from
+ * @param int $sessionId
+ * @return string
+ */
+ public static function getDescriptionFromSessionId($sessionId)
+ {
+ // Init variables
+ $sessionId = intval($sessionId);
+ $description = '';
+ // Check if session id is valid
+ if ($sessionId !== 0) {
+ // Select query from session id
+ $rows = Database::select(
+ 'description',
+ Database::get_main_table(TABLE_MAIN_SESSION),
+ array(
+ 'where' => array(
+ 'id = ?' => $sessionId
+ )
+ )
+ );
+
+ // Check if select query result is not empty
+ if (!empty($rows)) {
+ // Get session description
+ $description = $rows[0]['description'];
+ }
+ }
+
+ return $description;
+ }
}
diff --git a/main/inc/lib/usermanager.lib.php b/main/inc/lib/usermanager.lib.php
index 1dfdbbb764..b80ce7ee4e 100755
--- a/main/inc/lib/usermanager.lib.php
+++ b/main/inc/lib/usermanager.lib.php
@@ -5112,4 +5112,34 @@ EOF;
return 0;
}
+ /**
+ * Get the boss user ID from a followed user id
+ * @param $userId
+ * @return bool
+ */
+ public static function getStudentBoss($userId)
+ {
+ $userId = intval($userId);
+ if ($userId !== 0) {
+ $userRelTable = Database::get_main_table(TABLE_MAIN_USER_REL_USER);
+ $row = Database::select(
+ 'DISTINCT friend_user_id AS boss_id',
+ $userRelTable,
+ array(
+ 'where' => array(
+ 'user_id = ? AND relation_type = ? LIMIT 1' => array(
+ $userId,
+ USER_RELATION_TYPE_BOSS,
+ )
+ )
+ )
+ );
+ if (!empty($row)) {
+
+ return $row[0]['boss_id'];
+ }
+ }
+
+ return false;
+ }
}
diff --git a/main/webservices/registration.soap.php b/main/webservices/registration.soap.php
index 72585740a0..9fc2bad13d 100755
--- a/main/webservices/registration.soap.php
+++ b/main/webservices/registration.soap.php
@@ -10,13 +10,26 @@ require_once $libpath.'add_course.lib.inc.php';
$debug = false;
define('WS_ERROR_SECRET_KEY', 1);
+define('WS_ERROR_NOT_FOUND_RESULT', 2);
+define('WS_ERROR_INVALID_INPUT', 3);
+define('WS_ERROR_SETTING', 4);
+
function return_error($code) {
$fault = null;
switch ($code) {
case WS_ERROR_SECRET_KEY:
$fault = new soap_fault('Server', '', 'Secret key is not correct or params are not correctly set');
- break;
+ break;
+ case WS_ERROR_NOT_FOUND_RESULT:
+ $fault = new soap_fault('Server', '', 'Not found any result from the query');
+ break;
+ case WS_ERROR_INVALID_INPUT:
+ $fault = new soap_fault('Server', '', 'The input variables are invalid o are not correctly set');
+ break;
+ case WS_ERROR_SETTING:
+ $fault = new soap_fault('Server', '', 'Please check the configuration and installation for this webservice');
+ break;
}
return $fault;
}
@@ -5434,7 +5447,7 @@ $server->wsdl->addComplexType(
'SOAP-ENC:Array',
array(),
array(
- array('ref'=>'SOAP:ENC:arrayType',
+ array('ref'=>'SOAP-ENC:arrayType',
'wsdl:arrayType'=>'tns:session[]')
),
'tns:session'
diff --git a/plugin/advancedsubscription/README.md b/plugin/advancedsubscription/README.md
new file mode 100644
index 0000000000..5e08c22523
--- /dev/null
+++ b/plugin/advancedsubscription/README.md
@@ -0,0 +1,4 @@
+Advanced subscription plugin for Chamilo LMS
+=======================================
+@TODO:Edit README.md
+
diff --git a/plugin/advancedsubscription/ajax/advsub.ajax.php b/plugin/advancedsubscription/ajax/advsub.ajax.php
new file mode 100644
index 0000000000..5d31325934
--- /dev/null
+++ b/plugin/advancedsubscription/ajax/advsub.ajax.php
@@ -0,0 +1,248 @@
+
+ * @package chamilo.plugin.advancedsubscription
+ */
+
+/**
+ * Init
+ */
+require_once __DIR__ . '/../config.php';
+
+$plugin = AdvancedSubscriptionPlugin::create();
+// Get validation hash
+$hash = Security::remove_XSS($_REQUEST['v']);
+// Get data from request (GET or POST)
+$data['a'] = Security::remove_XSS($_REQUEST['a']);
+$data['s'] = intval($_REQUEST['s']);
+$data['current_user_id'] = intval($_REQUEST['current_user_id']);
+$data['u'] = intval($_REQUEST['u']);
+$data['q'] = intval($_REQUEST['q']);
+$data['e'] = intval($_REQUEST['e']);
+$data['is_connected'] = isset($_REQUEST['is_connected']) ? boolval($_REQUEST['is_connected']) : false;
+$data['profile_completed'] = isset($_REQUEST['profile_completed']) ? floatval($_REQUEST['profile_completed']) : 0;
+// Init result array
+$result = array('error' => true, 'errorMessage' => get_lang('ThereWasAnError'));
+// Check if data is valid or is for start subscription
+$verified = $plugin->checkHash($data, $hash) || $data['a'] == 'subscribe';
+if ($verified) {
+ switch($data['a']) {
+ case 'check': // Check minimum requirements
+ try {
+ $res = AdvancedSubscriptionPlugin::create()->isAbleToRequest($data['u'], $data);
+ if ($res) {
+ $result['error'] = false;
+ $result['errorMessage'] = 'No error';
+ $result['pass'] = true;
+ } else {
+ $result['errorMessage'] = 'User can not be subscribed';
+ $result['pass'] = false;
+ }
+ } catch (\Exception $e) {
+ $result['errorMessage'] = $e->getMessage();
+ }
+ break;
+ case 'subscribe': // Subscription
+ // Start subscription to queue
+ $res = AdvancedSubscriptionPlugin::create()->startSubscription($data['u'], $data['s'], $data);
+ // Check if queue subscription was successful
+ if ($res === true) {
+ // Prepare data
+ // Get session data
+ $sessionArray = api_get_session_info($data['s']);
+ $extraSession = new ExtraFieldValue('session');
+ $var = $extraSession->get_values_by_handler_and_field_variable($data['s'], 'description');
+ $sessionArray['description'] = $var['field_valiue'];
+ $var = $extraSession->get_values_by_handler_and_field_variable($data['s'], 'target');
+ $sessionArray['target'] = $var['field_valiue'];
+ $var = $extraSession->get_values_by_handler_and_field_variable($data['s'], 'mode');
+ $sessionArray['mode'] = $var['field_valiue'];
+ $var = $extraSession->get_values_by_handler_and_field_variable($data['s'], 'publication_end_date');
+ $sessionArray['publication_end_date'] = $var['field_value'];
+ $var = $extraSession->get_values_by_handler_and_field_variable($data['s'], 'recommended_number_of_participants');
+ $sessionArray['recommended_number_of_participants'] = $var['field_valiue'];
+ // Get student data
+ $studentArray = api_get_user_info($data['u']);
+ $studentArray['picture'] = UserManager::get_user_picture_path_by_id($studentArray['user_id'], 'web', false, true);
+ $studentArray['picture'] = UserManager::get_picture_user($studentArray['user_id'], $studentArray['picture']['file'], 22, USER_IMAGE_SIZE_MEDIUM);
+ // Get superior data if exist
+ $superiorId = UserManager::getStudentBoss($data['u']);
+ if (!empty($superiorId)) {
+ $superiorArray = api_get_user_info($superiorId);
+ } else {
+ $superiorArray = null;
+ }
+ // Get admin data
+ $adminsArray = UserManager::get_all_administrators();
+ foreach ($adminsArray as &$admin) {
+ $admin['complete_name'] = $admin['lastname'] . ', ' . $admin['firstname'];
+ }
+ unset($admin);
+ // Set data
+ $data['a'] = 'confirm';
+ $data['student'] = $studentArray;
+ $data['superior'] = $superiorArray;
+ $data['admins'] = $adminsArray;
+ $data['session'] = $sessionArray;
+ $data['signature'] = api_get_setting('Institution');
+
+ // Check if student boss exists
+ if (empty($superiorId)) {
+ // Student boss does not exist
+ // Update status to accepted by boss
+ $res = $plugin->updateQueueStatus($data, ADV_SUB_QUEUE_STATUS_BOSS_APPROVED);
+ if (!empty($res)) {
+ // Prepare admin url
+ $data['admin_view_url'] = api_get_path(WEB_PLUGIN_PATH) .
+ 'advancedsubscription/src/admin_view.php?s=' . $data['s'];
+ // Send mails
+ $result['mailIds'] = $plugin->sendMail($data, ADV_SUB_ACTION_STUDENT_REQUEST_NO_BOSS);
+ // Check if mails were sent
+ if (!empty($result['mailIds'])) {
+ $result['error'] = false;
+ $result['errorMessage'] = 'No error';
+ $result['pass'] = true;
+ // Check if exist an email to render
+ if (isset($result['mailIds']['render'])) {
+ // Render mail
+ $message = MessageManager::get_message_by_id($result['mailIds']['render']);
+ $message = str_replace(array('
', '
', '
'), '', $message['content']);
+ echo $message;
+ exit;
+ }
+ }
+ }
+ } else {
+ // Student boss does exist
+ // Get url to be accepted by boss
+ $data['e'] = ADV_SUB_QUEUE_STATUS_BOSS_APPROVED;
+ $data['student']['acceptUrl'] = $plugin->getQueueUrl($data);
+ // Get url to be rejected by boss
+ $data['e'] = ADV_SUB_QUEUE_STATUS_BOSS_DISAPPROVED;
+ $data['student']['rejectUrl'] = $plugin->getQueueUrl($data);
+ // Send mails
+ $result['mailIds'] = $plugin->sendMail($data, ADV_SUB_ACTION_STUDENT_REQUEST);
+ // Check if mails were sent
+ if (!empty($result['mailIds'])) {
+ $result['error'] = false;
+ $result['errorMessage'] = 'No error';
+ $result['pass'] = true;
+ // Check if exist an email to render
+ if (isset($result['mailIds']['render'])) {
+ // Render mail
+ $message = MessageManager::get_message_by_id($result['mailIds']['render']);
+ $message = str_replace(array('
', '
', '
'), '', $message['content']);
+ echo $message;
+ exit;
+ }
+ }
+ }
+ } else {
+ if (is_string($res)) {
+ $result['errorMessage'] = $res;
+ } else {
+ $result['errorMessage'] = 'User can not be subscribed';
+ }
+ $result['pass'] = false;
+ }
+
+ break;
+ case 'confirm':
+ // Check if is set new status
+ if (isset($data['e'])) {
+ // Update queue status
+ $res = $plugin->updateQueueStatus($data, $data['e']);
+ if ($res === true) {
+ // Prepare data
+ // Prepare session data
+ $sessionArray = api_get_session_info($data['s']);
+ $extraSession = new ExtraFieldValue('session');
+ $var = $extraSession->get_values_by_handler_and_field_variable($data['s'], 'description');
+ $sessionArray['description'] = $var['field_valiue'];
+ $var = $extraSession->get_values_by_handler_and_field_variable($data['s'], 'target');
+ $sessionArray['target'] = $var['field_valiue'];
+ $var = $extraSession->get_values_by_handler_and_field_variable($data['s'], 'mode');
+ $sessionArray['mode'] = $var['field_valiue'];
+ $var = $extraSession->get_values_by_handler_and_field_variable($data['s'], 'publication_end_date');
+ $sessionArray['publication_end_date'] = $var['field_value'];
+ $var = $extraSession->get_values_by_handler_and_field_variable($data['s'], 'recommended_number_of_participants');
+ $sessionArray['recommended_number_of_participants'] = $var['field_valiue'];
+ // Prepare student data
+ $studentArray = api_get_user_info($data['u']);
+ $studentArray['picture'] = UserManager::get_user_picture_path_by_id($studentArray['user_id'], 'web', false, true);
+ $studentArray['picture'] = UserManager::get_picture_user($studentArray['user_id'], $studentArray['picture']['file'], 22, USER_IMAGE_SIZE_MEDIUM);
+ // Prepare superior data
+ $superiorId = UserManager::getStudentBoss($data['u']);
+ if (!empty($superiorId)) {
+ $superiorArray = api_get_user_info($superiorId);
+ } else {
+ $superiorArray = null;
+ }
+ // Prepare admin data
+ $adminsArray = UserManager::get_all_administrators();
+ foreach ($adminsArray as &$admin) {
+ $admin['complete_name'] = $admin['lastname'] . ', ' . $admin['firstname'];
+ }
+ unset($admin);
+ // Set data
+ $data['student'] = $studentArray;
+ $data['superior'] = $superiorArray;
+ $data['admins'] = $adminsArray;
+ $data['session'] = $sessionArray;
+ $data['signature'] = api_get_setting('Institution');
+ $data['admin_view_url'] = api_get_path(WEB_PLUGIN_PATH) . 'advancedsubscription/src/admin_view.php?s=' . $data['s'];
+ // Check if exist and action in data
+ if (empty($data['action'])) {
+ // set action in data by new status
+ switch ($data['e']) {
+ case ADV_SUB_QUEUE_STATUS_BOSS_APPROVED:
+ $data['action'] = ADV_SUB_ACTION_SUPERIOR_APPROVE;
+ break;
+ case ADV_SUB_QUEUE_STATUS_BOSS_DISAPPROVED:
+ $data['action'] = ADV_SUB_ACTION_SUPERIOR_DISAPPROVE;
+ break;
+ case ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED:
+ $data['action'] = ADV_SUB_ACTION_ADMIN_APPROVE;
+ break;
+ case ADV_SUB_QUEUE_STATUS_ADMIN_DISAPPROVED:
+ $data['action'] = ADV_SUB_ACTION_ADMIN_DISAPPROVE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Student Session inscription
+ if ($data['e'] == ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED) {
+ SessionManager::suscribe_users_to_session($data['s'], array($data['u']), null, false);
+ }
+
+ // Send mails
+ $result['mailIds'] = $plugin->sendMail($data, $data['action']);
+ // Check if mails were sent
+ if (!empty($result['mailIds'])) {
+ $result['error'] = false;
+ $result['errorMessage'] = 'User has been processed';
+ // Check if exist mail to render
+ if (isset($result['mailIds']['render'])) {
+ // Render mail
+ $message = MessageManager::get_message_by_id($result['mailIds']['render']);
+ $message = str_replace(array('
', '
', '
'), '', $message['content']);
+ echo $message;
+ exit;
+ }
+ }
+ } else {
+ $result['errorMessage'] = 'User queue can not be updated';
+ }
+ }
+ break;
+ default:
+ $result['errorMessage'] = 'Action do not exist!';
+ }
+}
+
+// Echo result as json
+echo json_encode($result);
diff --git a/plugin/advancedsubscription/config.php b/plugin/advancedsubscription/config.php
new file mode 100644
index 0000000000..21711c9c44
--- /dev/null
+++ b/plugin/advancedsubscription/config.php
@@ -0,0 +1,29 @@
+
+ * @package chamilo.plugin.advancedsubscription
+ */
+
+define('TABLE_ADV_SUB_QUEUE', 'plugin_advsub_queue');
+
+define('ADV_SUB_ACTION_STUDENT_REQUEST', 0);
+define('ADV_SUB_ACTION_SUPERIOR_APPROVE', 1);
+define('ADV_SUB_ACTION_SUPERIOR_DISAPPROVE', 2);
+define('ADV_SUB_ACTION_SUPERIOR_SELECT', 3);
+define('ADV_SUB_ACTION_ADMIN_APPROVE', 4);
+define('ADV_SUB_ACTION_ADMIN_DISAPPROVE', 5);
+define('ADV_SUB_ACTION_STUDENT_REQUEST_NO_BOSS', 6);
+
+define('ADV_SUB_QUEUE_STATUS_NO_QUEUE', -1);
+define('ADV_SUB_QUEUE_STATUS_START', 0);
+define('ADV_SUB_QUEUE_STATUS_BOSS_DISAPPROVED', 1);
+define('ADV_SUB_QUEUE_STATUS_BOSS_APPROVED', 2);
+define('ADV_SUB_QUEUE_STATUS_ADMIN_DISAPPROVED', 3);
+define('ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED', 10);
+
+require_once __DIR__ . '/../../main/inc/global.inc.php';
+require_once api_get_path(LIBRARY_PATH) . 'plugin.class.php';
+require_once api_get_path(PLUGIN_PATH) . 'advancedsubscription/src/AdvancedSubscriptionPlugin.php';
+require_once api_get_path(PLUGIN_PATH) . 'advancedsubscription/src/HookAdvancedSubscription.php';
diff --git a/plugin/advancedsubscription/index.html b/plugin/advancedsubscription/index.html
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/plugin/advancedsubscription/index.html
@@ -0,0 +1 @@
+
diff --git a/plugin/advancedsubscription/install.php b/plugin/advancedsubscription/install.php
new file mode 100644
index 0000000000..a194fc807e
--- /dev/null
+++ b/plugin/advancedsubscription/install.php
@@ -0,0 +1,17 @@
+install();
diff --git a/plugin/advancedsubscription/lang/english.php b/plugin/advancedsubscription/lang/english.php
new file mode 100644
index 0000000000..ab4c8bc9a4
--- /dev/null
+++ b/plugin/advancedsubscription/lang/english.php
@@ -0,0 +1,56 @@
+no sean el curso de inducción";
+$strings['course_session_credit_year_start_date'] = 'Fecha de inicio';
+$strings['course_session_credit_year_start_date_help'] = "Fecha de inicio del año (día/mes)";
+$strings['min_profile_percentage'] = 'Porcentage de perfil completado mínimo requerido';
+$strings['min_profile_percentage_help'] = 'Número porcentage ( > 0.00 y < 100.00)';
+
+
+/* String for error message about requirements */
+$strings['AdvancedSubscriptionNotConnected'] = "Usted no está conectado en la plataforma. Por favor ingrese su usuario / constraseña para poder inscribirse";
+$strings['AdvancedSubscriptionProfileIncomplete'] = "Su perfil no es lo suficientemente completo para poder inscribirse al curso. Por favor complete su perfil";
+$strings['AdvancedSubscriptionIncompleteInduction'] = "Usted aún no ha completado el curso de inducción. Por favor complete el curso inducción";
+$strings['AdvancedSubscriptionCostXLimitReached'] = "Lo sentimos, usted ya ha alcanzado el límite anual de %s UIT para los cursos que ha seguido este año";
+$strings['AdvancedSubscriptionTimeXLimitReached'] = "Lo sentimos, usted ya ha alcanzado el límite anual de %s horas para los cursos que ha seguido este año";
+$strings['AdvancedSubscriptionCourseXLimitReached'] = "Lo sentimos, usted ya ha alcanzado el límite anual de %s cursos que ha seguido este año";
+$strings['AdvancedSubscriptionNotMoreAble'] = "Lo sentimos, usted ya no cumple con las condiciones iniciales para poder inscribirse al curso";
+$strings['AdvancedSubscriptionIncompleteParams'] = "Los parámetros enviados no están completos o no son los correctos.";
+
+$strings['AdvancedSubscriptionIsNotEnabled'] = "La inscripción avanzada no está activada";
+
+//Needed in order to show the plugin title
+
+// Mail translations
+$strings['MailStudentRequest'] = 'Solicitud de registro de estudiante';
+$strings['MailBossAccept'] = 'Solicitud de registro aceptada por superior';
+$strings['MailBossReject'] = 'Solicitud de registro rechazada por superior';
+$strings['MailStudentRequestSelect'] = 'Selección de solicitudes de registro de estudiante';
+$strings['MailAdminAccept'] = 'Solicitud de registro aceptada por administrador';
+$strings['MailAdminReject'] = 'Solicitud de registro rechazada por administrador';
+$strings['MailStudentRequestNoBoss'] = 'Solicitud de registro de estudiante sin superior';
+
+// TPL translations
+// Admin view
+$strings['SelectASession'] = 'Elija una sesión';
+$strings['SessionName'] = 'Nombre de la sesión';
+$strings['Target'] = 'Publico objetivo';
+$strings['Vacancies'] = 'Vacantes';
+$strings['RecommendedNumberOfParticipants'] = 'Número recomendado de participantes';
+$strings['PublicationEndDate'] = 'Fecha fin de publicación';
+$strings['Mode'] = 'Modalidad';
+$strings['Postulant'] = 'Postulante';
+$strings['InscriptionDate'] = 'Fecha de inscripción';
+$strings['BossValidation'] = 'Validación del superior';
+$strings['Decision'] = 'Decisión';
+$strings['AdvancedSubscriptionAdminViewTitle'] = 'Resultado de confirmación de solicitud de inscripción';
\ No newline at end of file
diff --git a/plugin/advancedsubscription/license.txt b/plugin/advancedsubscription/license.txt
new file mode 100644
index 0000000000..a7619191f8
--- /dev/null
+++ b/plugin/advancedsubscription/license.txt
@@ -0,0 +1 @@
+This plugin, as the rest of Chamilo, is released under the GNU/GPLv3 license.
diff --git a/plugin/advancedsubscription/plugin.php b/plugin/advancedsubscription/plugin.php
new file mode 100644
index 0000000000..a6640a7ba4
--- /dev/null
+++ b/plugin/advancedsubscription/plugin.php
@@ -0,0 +1,12 @@
+Plugins)
+ * @package chamilo.plugin.advancedsubscription
+ */
+/**
+ * Plugin details (must be present)
+ */
+require_once __DIR__ . '/config.php';
+$plugin_info = AdvancedSubscriptionPlugin::create()->get_info();
diff --git a/plugin/advancedsubscription/readme.txt b/plugin/advancedsubscription/readme.txt
new file mode 100644
index 0000000000..dd46052900
--- /dev/null
+++ b/plugin/advancedsubscription/readme.txt
@@ -0,0 +1,3 @@
+Advanced subscription plugin
+@TODO: Complete readme.txt
+This plugin enables Chamilo to extend its subscribe parameters.
diff --git a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.php b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.php
new file mode 100644
index 0000000000..d8f4626f55
--- /dev/null
+++ b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.php
@@ -0,0 +1,872 @@
+ 'boolean',
+ 'yearly_cost_limit' => 'text',
+ 'yearly_hours_limit' => 'text',
+ 'yearly_cost_unit_converter' => 'text',
+ 'courses_count_limit' => 'text',
+ 'course_session_credit_year_start_date' => 'text',
+ 'ws_url' => 'text',
+ 'min_profile_percentage' => 'text',
+ 'check_induction' => 'boolean',
+ 'confirmation_message' => 'wysiwyg',
+ 'secret_key' => 'text',
+ );
+
+ parent::__construct('1.0', 'Imanol Losada, Daniel Barreto', $parameters);
+ }
+
+ /**
+ * Instance the plugin
+ * @staticvar null $result
+ * @return AdvancedSubscriptionPlugin
+ */
+ static function create()
+ {
+ static $result = null;
+
+ return $result ? $result : $result = new self();
+ }
+
+ /**
+ * Install the plugin
+ * @return void
+ */
+ public function install()
+ {
+ $this->installDatabase();
+ $this->installHook();
+ }
+
+ /**
+ * Uninstall the plugin
+ * @return void
+ */
+ public function uninstall()
+ {
+ $this->uninstallHook();
+ $this->uninstallDatabase();
+ }
+
+ /**
+ * Create the database tables for the plugin
+ * @return void
+ */
+ private function installDatabase()
+ {
+ $pAdvSubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE);
+
+ $sql = "CREATE TABLE IF NOT EXISTS $pAdvSubQueueTable (" .
+ "id int UNSIGNED NOT NULL AUTO_INCREMENT, " .
+ "session_id int UNSIGNED NOT NULL, " .
+ "user_id int UNSIGNED NOT NULL, " .
+ "status int UNSIGNED NOT NULL, " .
+ "last_message_id int UNSIGNED NOT NULL, " .
+ "created_at datetime NOT NULL, " .
+ "updated_at datetime NULL, " .
+ "PRIMARY KEY PK_advsub_queue (id), " .
+ "UNIQUE KEY UK_advsub_queue (user_id, session_id)); ";
+ Database::query($sql);
+ }
+
+ /**
+ * Drop the database tables for the plugin
+ * @return void
+ */
+ private function uninstallDatabase()
+ {
+ /* Drop plugin tables */
+ $pAdvSubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE);
+
+ $sql = "DROP TABLE IF EXISTS $pAdvSubQueueTable; ";
+ Database::query($sql);
+
+ /* Delete settings */
+ $tSettings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
+ Database::query("DELETE FROM $tSettings WHERE subkey = 'advancedsubscription'");
+ }
+
+ /**
+ * Return true if user is able to be added to queue for session subscription
+ * @param int $userId
+ * @param array $params MUST have keys:
+ * "is_connected" Indicate if the user is online on external web
+ * "profile_completed" Percentage of completed profile, given by WS
+ * @throws Exception
+ * @return bool
+ */
+ public function isAbleToRequest($userId, $params = array())
+ {
+ if (isset($params['is_connected']) && isset($params['profile_completed'])) {
+ $isAble = false;
+ $advSubPlugin = self::create();
+ $wsUrl = $advSubPlugin->get('ws_url');
+ // @TODO: Get connection status from user by WS
+ $isConnected = $params['is_connected'];
+ if ($isConnected) {
+ $profileCompletedMin = (float) $advSubPlugin->get('min_profile_percentage');
+ // @TODO: Get completed profile percentage by WS
+ $profileCompleted = (float) $params['profile_completed'];
+ if ($profileCompleted > $profileCompletedMin) {
+ $checkInduction = $advSubPlugin->get('check_induction');
+ // @TODO: check if user have completed at least one induction session
+ $completedInduction = true;
+ if (!$checkInduction || $completedInduction) {
+ $uitMax = $advSubPlugin->get('yearly_cost_unit_converter');
+ $uitMax *= $advSubPlugin->get('yearly_cost_limit');
+ // @TODO: Get UIT completed by user this year by WS
+ $uitUser = 0;
+ $extra = new ExtraFieldValue('session');
+ $var = $extra->get_values_by_handler_and_field_variable($params['session_id'], 'cost');
+ $uitUser += $var['field_value'];
+ if ($uitMax >= $uitUser) {
+ $expendedTimeMax = $advSubPlugin->get('yearly_hours_limit');
+ // @TODO: Get Expended time from user data
+ $expendedTime = 0;
+ $var = $extra->get_values_by_handler_and_field_variable($params['session_id'], 'duration');
+ $expendedTime += $var['field_value'];
+ if ($expendedTimeMax >= $expendedTime) {
+ $expendedNumMax = $advSubPlugin->get('courses_count_limit');
+ // @TODO: Get Expended num from user
+ $expendedNum = 0;
+ if ($expendedNumMax >= $expendedNum) {
+ $isAble = true;
+ } else {
+ throw new \Exception($this->get_lang('AdvancedSubscriptionCourseXLimitReached'));
+ }
+ } else {
+ throw new \Exception($this->get_lang('AdvancedSubscriptionTimeXLimitReached'));
+ }
+ } else {
+ throw new \Exception($this->get_lang('AdvancedSubscriptionCostXLimitReached'));
+ }
+ } else {
+ throw new \Exception($this->get_lang('AdvancedSubscriptionIncompleteInduction'));
+ }
+ } else {
+ throw new \Exception($this->get_lang('AdvancedSubscriptionProfileIncomplete'));
+ }
+ } else {
+ throw new \Exception($this->get_lang('AdvancedSubscriptionNotConnected'));
+ }
+
+ return $isAble;
+ } else {
+ throw new \Exception($this->get_lang('AdvancedSubscriptionIncompleteParams'));
+ }
+
+ }
+
+ /**
+ * Register a user into a queue for a session
+ * @param $userId
+ * @param $sessionId
+ * @return bool|int
+ */
+ public function addToQueue($userId, $sessionId)
+ {
+ $now = api_get_utc_datetime();
+ $pAdvSubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE);
+ $attributes = array(
+ 'session_id' => $sessionId,
+ 'user_id' => $userId,
+ 'status' => 0,
+ 'created_at' => $now,
+ 'updated_at' => null,
+ );
+
+ $id = Database::insert($pAdvSubQueueTable, $attributes);
+
+ return $id;
+ }
+
+ /**
+ * Register message with type and status
+ * @param $mailId
+ * @param $userId
+ * @param $sessionId
+ * @return bool|int
+ */
+ public function saveLastMessage($mailId, $userId, $sessionId)
+ {
+ $queueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE);
+ $attributes = array(
+ 'last_message_id' => $mailId,
+ );
+
+ $num = Database::update(
+ $queueTable,
+ $attributes,
+ array('user_id = ? AND session_id = ?' => array($userId, $sessionId))
+ );
+
+ return $num;
+ }
+
+ /**
+ * Check for requirements and register user into queue
+ * @param $userId
+ * @param $sessionId
+ * @param $params
+ * @return bool|string
+ */
+ public function startSubscription($userId, $sessionId, $params)
+ {
+ $result = false;
+ if (!empty($sessionId) && !empty($userId)) {
+ $advSub = self::create();
+ try {
+ if ($advSub->isAbleToRequest($userId, $params)) {
+ $result = (bool) $advSub->addToQueue($userId, $sessionId);
+ } else {
+ throw new \Exception($this->get_lang('AdvancedSubscriptionNotMoreAble'));
+ }
+ } catch (Exception $e) {
+ $result = $e->getMessage();
+ }
+ } else {
+ $result = 'Params not found';
+ }
+
+ return $result;
+ }
+
+ /**
+ * Send message for the student subscription approval to a specific session
+ * @param int $studentId
+ * @param int $receiverId
+ * @param string $subject
+ * @param string $content
+ * @param int $sessionId
+ * @param bool $save
+ * @return bool|int
+ */
+ public function sendMailMessage($studentId, $receiverId, $subject, $content, $sessionId, $save = false)
+ {
+ global $_configuration; // @TODO: Add $_configuration['no_reply_user_id'] to configuration file
+
+ $mailId = MessageManager::send_message(
+ $receiverId,
+ $subject,
+ $content,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ $_configuration['no_reply_user_id']
+ );
+
+ if ($save && !empty($mailId)) {
+ // Save as sent message
+ $this->saveLastMessage($mailId, $studentId, $sessionId);
+ }
+ return $mailId;
+ }
+
+ /**
+ * Check if session is open for subscription
+ * @param $sessionId
+ * @param string $fieldVariable
+ * @return bool
+ */
+ public function isSessionOpen($sessionId, $fieldVariable = 'es_abierta')
+ {
+ $sessionId = (int) $sessionId;
+ $fieldVariable = Database::escape_string($fieldVariable);
+ $isOpen = false;
+ if ($sessionId > 0 && !empty($fieldVariable)) {
+ $sfTable = Database::get_main_table(TABLE_MAIN_SESSION_FIELD);
+ $sfvTable = Database::get_main_table(TABLE_MAIN_SESSION_FIELD_VALUES);
+ $joinTable = $sfvTable . ' sfv INNER JOIN ' . $sfTable . ' sf ON sfv.field_id = sf.id ';
+ $row = Database::select(
+ 'sfv.field_value as field_value',
+ $joinTable,
+ array(
+ 'where' => array(
+ 'sfv.session_id = ? AND sf.field_variable = ?' => array($sessionId, $fieldVariable),
+ )
+ )
+ );
+ if (isset($row[0]) && is_array($row[0])) {
+ $isOpen = (bool) $row[0]['field_value'];
+ }
+ }
+
+ return $isOpen;
+ }
+
+ /**
+ * Update the queue status for subscription approval rejected or accepted
+ * @param $params
+ * @param $newStatus
+ * @return bool
+ */
+ public function updateQueueStatus($params, $newStatus)
+ {
+ if (isset($params['queue']['id'])) {
+ $where = array(
+ 'id = ?' => $params['queue']['id'],
+ );
+ } elseif(isset($params['u']) && isset($params['s'])) {
+ $where = array(
+ 'user_id = ? AND session_id = ? AND status <> ? AND status <> ?' => array(
+ $params['u'],
+ $params['s'],
+ $newStatus,
+ ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED,
+ ),
+ );
+ }
+ if (isset($where)) {
+ $res = (bool) Database::update(
+ Database::get_main_table(TABLE_ADV_SUB_QUEUE),
+ array(
+ 'status' => $newStatus,
+ 'updated_at' => api_get_utc_datetime(),
+ ),
+ $where
+ );
+ } else {
+ $res = false;
+ }
+
+ return $res;
+ }
+
+ /**
+ * Render and send mail by defined advanced subscription action
+ * @param $data
+ * @param $actionType
+ * @return array
+ */
+ public function sendMail($data, $actionType)
+ {
+ $tpl = new Template($this->get_lang('plugin_title'));
+ $tpl->assign('data', $data);
+ $tplParams = array(
+ 'user',
+ 'student',
+ 'students',
+ 'superior',
+ 'admins',
+ 'session',
+ 'signature',
+ 'admin_view_url',
+ 'acceptUrl',
+ 'rejectUrl'
+ );
+ foreach ($tplParams as $tplParam) {
+ $tpl->assign($tplParam, $data[$tplParam]);
+ }
+ $mailIds = array();
+ switch ($actionType) {
+ case ADV_SUB_ACTION_STUDENT_REQUEST:
+ // Mail to student
+ $mailIds['render'] = $this->sendMailMessage(
+ $data['u'],
+ $data['student']['user_id'],
+ $this->get_lang('MailStudentRequest'),
+ $tpl->fetch('/advancedsubscription/views/advsub_request_received.tpl'),
+ $data['s']
+ );
+ // Mail to superior
+ $mailIds[] = $this->sendMailMessage(
+ $data['u'],
+ $data['superior']['user_id'],
+ $this->get_lang('MailStudentRequest'),
+ $tpl->fetch('/advancedsubscription/views/advsub_request_superior.tpl'),
+ $data['s'],
+ true
+ );
+ break;
+ case ADV_SUB_ACTION_SUPERIOR_APPROVE:
+ // Mail to student
+ $mailIds[] = $this->sendMailMessage(
+ $data['u'],
+ $data['student']['user_id'],
+ $this->get_lang('MailBossAccept'),
+ $tpl->fetch('/advancedsubscription/views/advsub_request_superior_approved.tpl'),
+ $data['s']
+ );
+ // Mail to superior
+ $mailIds['render'] = $this->sendMailMessage(
+ $data['u'],
+ $data['superior']['user_id'],
+ $this->get_lang('MailBossAccept'),
+ $tpl->fetch('/advancedsubscription/views/advsub_request_approve_confirmed.tpl'),
+ $data['s']
+ );
+ // Mail to admin
+ foreach ($data['admins'] as $adminId => $admin) {
+ $tpl->assign('admin', $admin);
+ $mailIds[] = $this->sendMailMessage(
+ $data['u'],
+ $adminId,
+ $this->get_lang('MailBossAccept'),
+ $tpl->fetch('/advancedsubscription/views/advsub_request_approved_info_admin.tpl'),
+ $data['s'],
+ true
+ );
+ }
+ break;
+ case ADV_SUB_ACTION_SUPERIOR_DISAPPROVE:
+ // Mail to student
+ $mailIds[] = $this->sendMailMessage(
+ $data['u'],
+ $data['student']['user_id'],
+ $this->get_lang('MailBossReject'),
+ $tpl->fetch('/advancedsubscription/views/advsub_request_superior_disapproved.tpl'),
+ $data['s'],
+ true
+ );
+ // Mail to superior
+ $mailIds['render'] = $this->sendMailMessage(
+ $data['u'],
+ $data['superior']['user_id'],
+ $this->get_lang('MailBossReject'),
+ $tpl->fetch('/advancedsubscription/views/advsub_request_disapprove_confirmed.tpl'),
+ $data['s']
+ );
+ break;
+ case ADV_SUB_ACTION_SUPERIOR_SELECT:
+ // Mail to student
+ $mailIds[] = $this->sendMailMessage(
+ $data['u'],
+ $data['student']['user_id'],
+ $this->get_lang('MailStudentRequestSelect'),
+ $tpl->fetch('/advancedsubscription/views/advsub_request_received.tpl'),
+ $data['s']
+ );
+ // Mail to superior
+ $mailIds['render'] = $this->sendMailMessage(
+ $data['u'],
+ $data['superior']['user_id'],
+ $this->get_lang('MailStudentRequestSelect'),
+ $tpl->fetch('/advancedsubscription/views/advsub_request_superior.tpl'),
+ $data['s'],
+ true
+ );
+ break;
+ case ADV_SUB_ACTION_ADMIN_APPROVE:
+ // Mail to student
+ $mailIds[] = $this->sendMailMessage(
+ $data['u'],
+ $data['student']['user_id'],
+ $this->get_lang('MailAdminAccept'),
+ $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_accepted_notice_student.tpl'),
+ $data['s']
+ );
+ // Mail to superior
+ $mailIds[] = $this->sendMailMessage(
+ $data['u'],
+ $data['superior']['user_id'],
+ $this->get_lang('MailAdminAccept'),
+ $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_accepted_notice_superior.tpl'),
+ $data['s']
+ );
+ // Mail to admin
+ $adminId = $data['current_user_id'];
+ $tpl->assign('admin', $data['admins'][$adminId]);
+ $mailIds['render'] = $this->sendMailMessage(
+ $data['u'],
+ $adminId,
+ $this->get_lang('MailAdminAccept'),
+ $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_accepted_notice_admin.tpl'),
+ $data['s'],
+ true
+ );
+ break;
+ case ADV_SUB_ACTION_ADMIN_DISAPPROVE:
+ // Mail to student
+ $mailIds[] = $this->sendMailMessage(
+ $data['u'],
+ $data['student']['user_id'],
+ $this->get_lang('MailAdminReject'),
+ $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_rejected_notice_student.tpl'),
+ $data['s'],
+ true
+ );
+ // Mail to superior
+ $mailIds[] = $this->sendMailMessage(
+ $data['u'],
+ $data['superior']['user_id'],
+ $this->get_lang('MailAdminReject'),
+ $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_rejected_notice_superior.tpl'),
+ $data['s']
+ );
+ // Mail to admin
+ $adminId = $data['current_user_id'];
+ $tpl->assign('admin', $data['admins'][$adminId]);
+ $mailIds['render'] = $this->sendMailMessage(
+ $data['u'],
+ $adminId,
+ $this->get_lang('MailAdminReject'),
+ $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_rejected_notice_admin.tpl'),
+ $data['s']
+ );
+ break;
+ case ADV_SUB_ACTION_STUDENT_REQUEST_NO_BOSS:
+ // Mail to student
+ $mailIds['render'] = $this->sendMailMessage(
+ $data['u'],
+ $data['student']['user_id'],
+ $this->get_lang('MailStudentRequestNoBoss'),
+ $tpl->fetch('/advancedsubscription/views/advsub_request_received_no_boss.tpl'),
+ $data['s']
+ );
+ // Mail to admin
+ foreach ($data['admins'] as $adminId => $admin) {
+ $tpl->assign('admin', $admin);
+ $mailIds[] = $this->sendMailMessage(
+ $data['u'],
+ $adminId,
+ $this->get_lang('MailStudentRequestNoBoss'),
+ $tpl->fetch('/advancedsubscription/views/advsub_request_approved_info_admin.tpl'),
+ $data['s'],
+ true
+ );
+ }
+ break;
+ default:
+ break;
+ }
+
+ return $mailIds;
+ }
+
+ /**
+ * Count the users in queue filtered by params (sessions, status)
+ * @param array $params Input array containing the set of
+ * session and status to count from queue
+ * e.g:
+ * array('sessions' => array(215, 218, 345, 502),
+ * 'status' => array(0, 1, 2))
+ * @return int
+ */
+ public function countQueueByParams($params)
+ {
+ $count = 0;
+ if (!empty($params) && is_array($params)) {
+ $advsubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE);
+ $where['1 = ? '] = 1;
+ if (isset($params['sessions']) && is_array($params['sessions'])) {
+ $where['AND session_id IN ( ? ) '] = implode($params['sessions']);
+ }
+ if (isset($params['status']) && is_array($params['status'])) {
+ $where['AND status IN ( ? ) '] = implode($params['status']);
+ }
+ $where['where'] = $where;
+ $count = Database::select('COUNT(*)', $advsubQueueTable, $where);
+ $count = $count[0]['COUNT(*)'];
+ }
+ return $count;
+ }
+
+ /**
+ * This method will call the Hook management insertHook to add Hook observer from this plugin
+ * @return int
+ */
+ public function installHook()
+ {
+ $hookObserver = HookAdvancedSubscription::create();
+ HookAdminBlock::create()->attach($hookObserver);
+ HookWSRegistration::create()->attach($hookObserver);
+ HookNotificationContent::create()->attach($hookObserver);
+ HookNotificationTitle::create()->attach($hookObserver);
+ }
+
+ /**
+ * This method will call the Hook management deleteHook to disable Hook observer from this plugin
+ * @return int
+ */
+ public function uninstallHook()
+ {
+ $hookObserver = HookAdvancedSubscription::create();
+ HookAdminBlock::create()->detach($hookObserver);
+ HookWSRegistration::create()->detach($hookObserver);
+ HookNotificationContent::create()->detach($hookObserver);
+ HookNotificationTitle::create()->detach($hookObserver);
+ }
+
+ /**
+ * Return the status from user in queue to session subscription
+ * @param int $userId
+ * @param int $sessionId
+ * @return bool|int
+ */
+ public function getQueueStatus($userId, $sessionId)
+ {
+ if (!empty($userId) && !empty($sessionId)) {
+ $queueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE);
+ $row = Database::select(
+ 'status',
+ $queueTable,
+ array(
+ 'where' => array(
+ 'user_id = ? AND session_id = ?' => array($userId, $sessionId),
+ )
+ )
+ );
+
+ if (count($row) == 1) {
+
+ return $row[0]['status'];
+ } else {
+
+ return ADV_SUB_QUEUE_STATUS_NO_QUEUE;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Return the remaining vacancy
+ * @param $sessionId
+ * @return bool|int
+ */
+ public function getVacancy($sessionId)
+ {
+ if (!empty($sessionId)) {
+ $extra = new ExtraFieldValue('session');
+ $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'vacancies');
+ $vacancy = intval($var['field_value']);
+ if (!empty($vacancy)) {
+ $vacancy -= $this->countQueueByParams(array('sessions' => $sessionId, 'status' => ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED));
+
+ if ($vacancy >= 0) {
+
+ return $vacancy;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Return the session details data from session extra field value
+ * @param $sessionId
+ * @return bool|mixed
+ */
+ public function getSessionDetails($sessionId)
+ {
+ if (!empty($sessionId)) {
+ $extra = new ExtraFieldValue('session');
+ $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'id');
+ $data['id'] = $var['field_value'];
+ $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'cost');
+ $data['cost'] = $var['field_value'];
+ $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'place');
+ $data['place'] = $var['field_value'];
+ $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'allow_visitors');
+ $data['allow_visitors'] = $var['field_value'];
+ $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'horas_lectivas');
+ $data['duration'] = $var['field_value'];
+ // Get brochure URL
+ $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'brochure');
+ $data['brochure'] = api_get_path(WEB_CODE_PATH) . $var['field_value'];
+ // Get banner URL
+ $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'banner');
+ $data['banner'] = api_get_path(WEB_CODE_PATH) . $var['field_value'];
+ $data['description'] = SessionManager::getDescriptionFromSessionId($sessionId);
+
+ return $data;
+ }
+
+ return false;
+ }
+
+ /**
+ * Get status message
+ * @param int $status
+ * @param bool $isAble
+ * @return string
+ */
+ public function getStatusMessage($status, $isAble = true)
+ {
+ $message = '';
+ switch ($status)
+ {
+ case ADV_SUB_QUEUE_STATUS_NO_QUEUE:
+ if ($isAble) {
+ $message = $this->get_lang('AdvancedSubscriptionNoQueueIsAble');
+ } else {
+ $message = $this->get_lang('AdvancedSubscriptionNoQueue');
+ }
+ break;
+ case ADV_SUB_QUEUE_STATUS_START:
+ $message = $this->get_lang('AdvancedSubscriptionQueueStart');
+ break;
+ case ADV_SUB_QUEUE_STATUS_BOSS_DISAPPROVED:
+ $message = $this->get_lang('AdvancedSubscriptionQueueBossDisapproved');
+ break;
+ case ADV_SUB_QUEUE_STATUS_BOSS_APPROVED:
+ $message = $this->get_lang('AdvancedSubscriptionQueueBossApproved');
+ break;
+ case ADV_SUB_QUEUE_STATUS_ADMIN_DISAPPROVED:
+ $message = $this->get_lang('AdvancedSubscriptionQueueAdminDisapproved');
+ break;
+ case ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED:
+ $message = $this->get_lang('AdvancedSubscriptionQueueAdminApproved');
+ break;
+ default:
+ $message = sprintf($this->get_lang('AdvancedSubscriptionQueueDefault'), $status);
+
+ }
+
+ return $message;
+ }
+
+ /**
+ * Return the url to go to session
+ * @param $sessionId
+ * @return string
+ */
+ public function getSessionUrl($sessionId)
+ {
+ $url = api_get_path(WEB_CODE_PATH) . 'session/?session_id=' . $sessionId;
+ return $url;
+ }
+
+ /**
+ * Return the url to enter to subscription queue to session
+ * @param $params
+ * @return string
+ */
+ public function getQueueUrl($params)
+ {
+ $url = api_get_path(WEB_PLUGIN_PATH) . 'advancedsubscription/ajax/advsub.ajax.php?' .
+ 'a=' . $params['a'] . '&' .
+ 's=' . $params['s'] . '&' .
+ 'current_user_id=' . $params['current_user_id'] . '&' .
+ 'e=' . $params['e'] . '&' .
+ 'u=' . $params['u'] . '&' .
+ 'q=' . $params['q'] . '&' .
+ 'is_connected=' . $params['is_connected'] . '&' .
+ 'profile_completed=' . $params['profile_completed'] . '&' .
+ 'v=' . $this->generateHash($params);
+ return $url;
+ }
+
+ /**
+ * Return the list of student, in queue used by admin view
+ * @param int $sessionId
+ * @return array
+ */
+ public function listAllStudentsInQueueBySession($sessionId)
+ {
+ $extraSession = new ExtraFieldValue('session');
+ $session = api_get_session_info($sessionId);
+ $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'target');
+ $session['target'] = $var['field_value'];
+ $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'publication_end_date');
+ $session['publication_end_date'] = $var['field_value'];
+ $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'mode');
+ $session['mode'] = $var['field_value'];
+ $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'recommended_number_of_participants');
+ $session['recommended_number_of_participants'] = $var['field_value'];
+ $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'vacancies');
+ $session['vacancies'] = $var['field_value'];
+ $queueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE);
+ $userTable = Database::get_main_table(TABLE_MAIN_USER);
+ $userJoinTable = $queueTable . ' q INNER JOIN ' . $userTable . ' u ON q.user_id = u.user_id';
+ $where = array(
+ 'where' =>
+ array(
+ 'q.session_id = ? AND q.status <> ? AND q.status <> ?' => array(
+ $sessionId,
+ ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED,
+ ADV_SUB_QUEUE_STATUS_ADMIN_DISAPPROVED,
+ )
+ )
+ );
+ $select = 'u.user_id, u.firstname, u.lastname, q.created_at, q.updated_at, q.status, q.id as queue_id';
+ $students = Database::select($select, $userJoinTable, $where);
+ foreach ($students as &$student) {
+ $status = intval($student['status']);
+ switch($status) {
+ case ADV_SUB_QUEUE_STATUS_NO_QUEUE:
+ case ADV_SUB_QUEUE_STATUS_START:
+ $student['validation'] = '';
+ break;
+ case ADV_SUB_QUEUE_STATUS_BOSS_DISAPPROVED:
+ case ADV_SUB_QUEUE_STATUS_ADMIN_DISAPPROVED:
+ $student['validation'] = get_lang('No');
+ break;
+ case ADV_SUB_QUEUE_STATUS_BOSS_APPROVED:
+ case ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED:
+ $student['validation'] = get_lang('Yes');
+ break;
+ default:
+ error_log(__FILE__ . ' ' . __FUNCTION__ . ' Student status no detected');
+ }
+ }
+ $return = array(
+ 'session' => $session,
+ 'students' => $students,
+ );
+
+ return $return;
+
+ }
+
+ /**
+ * List all session (id, name) for select input
+ * @return array
+ */
+ public function listAllSessions()
+ {
+ $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION);
+ $columns = 'id, name';
+ return Database::select($columns, $sessionTable);
+ }
+
+ /**
+ * Generate security hash to check data send by url params
+ * @param string $data
+ * @return string
+ */
+ public function generateHash($data)
+ {
+ $key = sha1($this->get('secret_key'));
+ // Prepare array to have specific type variables
+ $dataPrepared['a'] = strval($data['a']);
+ $dataPrepared['s'] = intval($data['s']);
+ $dataPrepared['current_user_id'] = intval($data['current_user_id']);
+ $dataPrepared['u'] = intval($data['u']);
+ $dataPrepared['q'] = intval($data['q']);
+ $dataPrepared['e'] = intval($data['e']);
+ $dataPrepared = serialize($dataPrepared);
+ return sha1($dataPrepared . $key);
+ }
+
+ /**
+ * Verify hash from data
+ * @param string $data
+ * @param string $hash
+ * @return bool
+ */
+ public function checkHash($data, $hash)
+ {
+ return $this->generateHash($data) == $hash;
+ }
+}
diff --git a/plugin/advancedsubscription/src/HookAdvancedSubscription.php b/plugin/advancedsubscription/src/HookAdvancedSubscription.php
new file mode 100644
index 0000000000..2a3c8f53c8
--- /dev/null
+++ b/plugin/advancedsubscription/src/HookAdvancedSubscription.php
@@ -0,0 +1,608 @@
+
+ * @package chamilo.plugin.advancedsubscription
+ */
+
+require_once __DIR__ . '/../config.php';
+
+class HookAdvancedSubscription extends HookObserver implements
+ HookAdminBlockObserverInterface,
+ HookWSRegistrationObserverInterface,
+ HookNotificationContentObserverInterface
+{
+
+ protected function __construct()
+ {
+ parent::__construct(
+ 'plugin/advancedsubscription/src/HookAdvancedSubscription.class.php',
+ 'advancedsubscription'
+ );
+ }
+
+ /**
+ * @param HookAdminBlockEventInterface $hook
+ * @return int
+ */
+ public function hookAdminBlock(HookAdminBlockEventInterface $hook)
+ {
+ $data = $hook->getEventData();
+ if ($data['type'] === HOOK_EVENT_TYPE_PRE) {
+ // Nothing to do
+ } elseif ($data['type'] === HOOK_EVENT_TYPE_POST) {
+
+ if (isset($data['blocks'])) {
+ $data['blocks']['sessions']['items'][] = array(
+ 'url' => '../../plugin/advancedsubscription/src/admin_view.php',
+ 'label' => get_plugin_lang('plugin_title', 'AdvancedSubscriptionPlugin'),
+ );
+ }
+ } else {
+ // Hook type is not valid
+ // Nothing to do
+ }
+
+ return $data;
+ }
+
+ /**
+ * Add Webservices to registration.soap.php
+ * @param HookWSRegistrationEventInterface $hook
+ * @return int
+ */
+ public function hookWSRegistration(HookWSRegistrationEventInterface $hook)
+ {
+ $data = $hook->getEventData();
+ if ($data['type'] === HOOK_EVENT_TYPE_PRE) {
+
+ } elseif ($data['type'] === HOOK_EVENT_TYPE_POST) {
+ /** @var \nusoap_server $server */
+ $server = &$data['server'];
+
+ /** WSSessionListInCategory */
+
+ // Output params for sessionBriefList WSSessionListInCategory
+ $server->wsdl->addComplexType(
+ 'sessionBrief',
+ 'complexType',
+ 'struct',
+ 'all',
+ '',
+ array(
+ 'id' => array('name' => 'id', 'type' => 'xsd:int'), // session.id
+ 'name' => array('name' => 'name', 'type' => 'xsd:string'), // session.name
+ 'short_description' => array('name' => 'short_description', 'type' => 'xsd:string'), // session.short_description
+ 'mode' => array('name' => 'mode', 'type' => 'xsd:string'), // session.mode
+ 'date_start' => array('name' => 'date_start', 'type' => 'xsd:string'), // session.date_start
+ 'date_end' => array('name' => 'date_end', 'type' => 'xsd:string'), // session.date_end
+ 'duration' => array('name' => 'duration', 'type' => 'xsd:string'), // session.duration
+ 'vacancies' => array('name' => 'vacancies', 'type' => 'xsd:string'), // session.vacancies
+ 'schedule' => array('name' => 'schedule', 'type' => 'xsd:string'), // session.schedule
+ )
+ );
+
+ //Output params for WSSessionListInCategory
+ $server->wsdl->addComplexType(
+ 'sessionBriefList',
+ 'complexType',
+ 'array',
+ '',
+ 'SOAP-ENC:Array',
+ array(),
+ array(
+ array('ref'=>'SOAP-ENC:arrayType',
+ 'wsdl:arrayType'=>'tns:sessionBrief[]')
+ ),
+ 'tns:sessionBrief'
+ );
+
+ // Input params for WSSessionListInCategory
+ $server->wsdl->addComplexType(
+ 'sessionCategoryInput',
+ 'complexType',
+ 'struct',
+ 'all',
+ '',
+ array(
+ 'id' => array('name' => 'id', 'type' => 'xsd:string'), // session_category.id
+ 'name' => array('name' => 'name', 'type' => 'xsd:string'), // session_category.name
+ 'target' => array('name' => 'target', 'type' => 'xsd:string'), // session.target
+ 'secret_key' => array('name' => 'secret_key', 'type' => 'xsd:string')
+ )
+ );
+
+ // Input params for WSSessionGetDetailsByUser
+ $server->wsdl->addComplexType(
+ 'advsubSessionDetailInput',
+ 'complexType',
+ 'struct',
+ 'all',
+ '',
+ array(
+ 'user_id' => array('name' => 'user_id', 'type' => 'xsd:int'), // user.user_id
+ 'session_id' => array('name' => 'session_id', 'type' => 'xsd:int'), // session.id
+ 'profile_completed' => array('name' => 'profile_completed', 'type' => 'xsd:float'), // user.profile_completes
+ 'is_connected' => array('name' => 'is_connected', 'type' => 'xsd:boolean'), // user.is_connected
+ 'secret_key' => array('name' => 'secret_key', 'type' => 'xsd:string'),
+ )
+ );
+
+ // Output params for WSSessionGetDetailsByUser
+ $server->wsdl->addComplexType(
+ 'advsubSessionDetail',
+ 'complexType',
+ 'struct',
+ 'all',
+ '',
+ array(
+ 'id' => array('name' => 'id', 'type' => 'xsd:string'), // session.id
+ 'cost' => array('name' => 'cost', 'type' => 'xsd:float'), // session.cost
+ 'place' => array('name' => 'place', 'type' => 'xsd:string'), // session.place
+ 'allow_visitors' => array('name' => 'allow_visitors', 'type' => 'xsd:string'), // session.allow_visitors
+ 'duration' => array('name' => 'duration', 'type' => 'xsd:int'), // session.duration
+ 'brochure' => array('name' => 'brochure', 'type' => 'xsd:string'), // session.brochure
+ 'banner' => array('name' => 'banner', 'type' => 'xsd:string'), // session.banner
+ 'description' => array('name' => 'description', 'type' => 'xsd:string'), // session.description
+ 'status' => array('name' => 'status', 'type' => 'xsd:string'), // status
+ 'action_url' => array('name' => 'action_url', 'type' => 'xsd:string'), // action_url
+ 'message' => array('name' => 'error_message', 'type' => 'xsd:string'), // message
+ )
+ );
+
+ /** WSListSessionsDetailsByCategory **/
+
+ // Input params for WSListSessionsDetailsByCategory
+ $server->wsdl->addComplexType(
+ 'listSessionsDetailsByCategory',
+ 'complexType',
+ 'struct',
+ 'all',
+ '',
+ array(
+ 'id' => array('name' => 'id', 'type' => 'xsd:string'), // session_category.id
+ 'category_name' => array('name' => 'category_name', 'type' => 'xsd:string'), // session_category.name
+ 'access_url_id' => array('name' => 'access_url_id', 'type' => 'xsd:int'), // session_category.access_url_id
+ 'secret_key' => array('name' => 'secret_key', 'type' => 'xsd:string') // secret key
+ ),
+ array(),
+ 'tns:listSessionsDetailsByCategory'
+ );
+
+ // Output params for sessionDetailsCourseList WSListSessionsDetailsByCategory
+ $server->wsdl->addComplexType(
+ 'sessionDetailsCourse',
+ 'complexType',
+ 'struct',
+ 'all',
+ '',
+ array(
+ 'course_id' => array('name' => 'course_id', 'type' => 'xsd:int'), // course.id
+ 'course_code' => array('name' => 'course_code', 'type' => 'xsd:string'), // course.code
+ 'course_title' => array('name' => 'course_title', 'type' => 'xsd:string'), // course.title
+ 'coach_username' => array('name' => 'coach_username', 'type' => 'xsd:string'), // user.username
+ 'coach_firstname' => array('name' => 'coach_firstname', 'type' => 'xsd:string'), // user.firstname
+ 'coach_lastname' => array('name' => 'coach_lastname', 'type' => 'xsd:string'), // user.lastname
+ )
+ );
+
+
+ // Output array for sessionDetails WSListSessionsDetailsByCategory
+ $server->wsdl->addComplexType(
+ 'sessionDetailsCourseList',
+ 'complexType',
+ 'array',
+ '',
+ 'SOAP-ENC:Array',
+ array(),
+ array(
+ array(
+ 'ref' => 'SOAP-ENC:arrayType',
+ 'wsdl:arrayType' => 'tns:sessionDetailsCourse[]',
+ )
+ ),
+ 'tns:sessionDetailsCourse'
+ );
+
+ // Output params for sessionDetailsList WSListSessionsDetailsByCategory
+ $server->wsdl->addComplexType(
+ 'sessionDetails',
+ 'complexType',
+ 'struct',
+ 'all',
+ '',
+ array(
+ // session.id
+ 'id' => array(
+ 'name' => 'id',
+ 'type' => 'xsd:int'
+ ),
+ // session.id_coach
+ 'coach_id' => array(
+ 'name' => 'coach_id',
+ 'type' => 'xsd:int'
+ ),
+ // session.name
+ 'name' => array(
+ 'name' => 'name',
+ 'type' => 'xsd:string'
+ ),
+ // session.nbr_courses
+ 'courses_num' => array(
+ 'name' => 'courses_num',
+ 'type' => 'xsd:int'
+ ),
+ // session.nbr_users
+ 'users_num' => array(
+ 'name' => 'users_num',
+ 'type' => 'xsd:int'
+ ),
+ // session.nbr_classes
+ 'classes_num' => array(
+ 'name' => 'classes_num',
+ 'type' => 'xsd:int'
+ ),
+ // session.date_start
+ 'date_start' => array(
+ 'name' => 'date_start',
+ 'type' => 'xsd:string'
+ ),
+ // session.date_end
+ 'date_end' => array(
+ 'name' => 'date_end',
+ 'type' => 'xsd:string'
+ ),
+ // session.nb_days_access_before_beginning
+ 'access_days_before_num' => array(
+ 'name' => 'access_days_before_num',
+ 'type' => 'xsd:int'
+ ),
+ // session.nb_days_access_after_end
+ 'access_days_after_num' => array(
+ 'name' => 'access_days_after_num',
+ 'type' => 'xsd:int'
+ ),
+ // session.session_admin_id
+ 'session_admin_id' => array(
+ 'name' => 'session_admin_id',
+ 'type' => 'xsd:int'
+ ),
+ // session.visibility
+ 'visibility' => array(
+ 'name' => 'visibility',
+ 'type' => 'xsd:int'
+ ),
+ // session.session_category_id
+ 'session_category_id' => array(
+ 'name' => 'session_category_id',
+ 'type' => 'xsd:int'
+ ),
+ // session.promotion_id
+ 'promotion_id' => array(
+ 'name' => 'promotion_id',
+ 'type' => 'xsd:int'
+ ),
+ // session.number of registered users validated
+ 'validated_user_num' => array(
+ 'name' => 'validated_user_num',
+ 'type' => 'xsd:int'
+ ),
+ // session.number of registered users from waiting queue
+ 'waiting_user_num' => array(
+ 'name' => 'waiting_user_num',
+ 'type' => 'xsd:int'
+ ),
+ // extra fields
+ // Array(field_name, field_value)
+ 'extra' => array(
+ 'name' => 'extra',
+ 'type' => 'tns:extrasList'
+ ),
+ // course and coaches data
+ // Array(course_id, course_code, course_title, coach_username, coach_firstname, coach_lastname)
+ 'course' => array(
+ 'name' => 'courses',
+ 'type' => 'tns:sessionDetailsCourseList'
+ ),
+ )
+ );
+
+ // Output params for WSListSessionsDetailsByCategory
+ $server->wsdl->addComplexType(
+ 'sessionDetailsList',
+ 'complexType',
+ 'array',
+ '',
+ 'SOAP-ENC:Array',
+ array(),
+ array(
+ array(
+ 'ref' => 'SOAP-ENC:arrayType',
+ 'wsdl:arrayType' => 'tns:sessionDetails[]',
+ )
+ ),
+ 'tns:sessionDetails'
+ );
+
+ // Register the method for WSSessionListInCategory
+ $server->register(
+ 'HookAdvancedSubscription..WSSessionListInCategory', // method name
+ array('sessionCategoryInput' => 'tns:sessionCategoryInput'), // input parameters
+ array('return' => 'tns:sessionBriefList'), // output parameters
+ 'urn:WSRegistration', // namespace
+ 'urn:WSRegistration#WSSessionListInCategory', // soapaction
+ 'rpc', // style
+ 'encoded', // use
+ 'This service checks if user assigned to course' // documentation
+ );
+
+ // Register the method for WSSessionGetDetailsByUser
+ $server->register(
+ 'HookAdvancedSubscription..WSSessionGetDetailsByUser', // method name
+ array('advsubSessionDetailInput' => 'tns:advsubSessionDetailInput'), // input parameters
+ array('return' => 'tns:advsubSessionDetail'), // output parameters
+ 'urn:WSRegistration', // namespace
+ 'urn:WSRegistration#WSSessionGetDetailsByUser', // soapaction
+ 'rpc', // style
+ 'encoded', // use
+ 'This service return session details to specific user' // documentation
+ );
+
+ // Register the method for WSListSessionsDetailsByCategory
+ $server->register(
+ 'HookAdvancedSubscription..WSListSessionsDetailsByCategory', // method name
+ array('name' => 'tns:listSessionsDetailsByCategory'), // input parameters
+ array('return' => 'tns:sessionDetailsList'), // output parameters
+ 'urn:WSRegistration', // namespace
+ 'urn:WSRegistration#WSListSessionsDetailsByCategory', // soapaction
+ 'rpc', // style
+ 'encoded', // use
+ 'This service returns a list of detailed sessions by a category' // documentation
+ );
+
+ return $data;
+ } else {
+ // Nothing to do
+ }
+ }
+
+ /**
+ * @param $params
+ * @return null|soap_fault
+ */
+ public static function WSSessionListInCategory($params)
+ {
+ global $debug;
+
+ if ($debug) error_log('WSUserSubscribedInCourse');
+ if ($debug) error_log('Params '. print_r($params, 1));
+ if (!WSHelperVerifyKey($params)) {
+
+ //return return_error(WS_ERROR_SECRET_KEY);
+ }
+ // Check if category ID is set
+ if (!empty($params['id']) && empty($params['name'])) {
+ $sessionCategoryId = $params['id'];
+ } elseif (!empty($params['name'])) {
+ // Check if category name is set
+ $sessionCategoryId = SessionManager::getSessionCategoryIdByName($params['name']);
+ if (is_array($sessionCategoryId)) {
+ $sessionCategoryId = current($sessionCategoryId);
+ }
+ } else {
+ // Return soap fault Not valid input params
+
+ return return_error(WS_ERROR_INVALID_INPUT);
+ }
+
+ // Get the session brief List by category
+ $sessionList = SessionManager::getSessionBriefListByCategory($sessionCategoryId, $params['target']);
+
+ return $sessionList;
+ }
+
+ /**
+ * @param $params
+ * @return null|soap_fault
+ */
+ public function WSSessionGetDetailsByUser($params)
+ {
+ global $debug;
+
+ if ($debug) error_log('WSUserSubscribedInCourse');
+ if ($debug) error_log('Params '. print_r($params, 1));
+ if (!WSHelperVerifyKey($params)) {
+
+ return return_error(WS_ERROR_SECRET_KEY);
+ }
+ $result = return_error(WS_ERROR_NOT_FOUND_RESULT);
+ // Check params
+ if (is_array($params) && !empty($params['session_id']) && !empty($params['user_id'])) {
+ $userId = (int) $params['user_id'];
+ $sessionId = (int) $params['session_id'];
+ // Check if student is already subscribed
+
+ $advsubPlugin = AdvancedSubscriptionPlugin::create();
+ $isOpen = $advsubPlugin->isSessionOpen($sessionId);
+ $status = $advsubPlugin->getQueueStatus($userId, $sessionId);
+ $vacancy = $advsubPlugin->getVacancy($sessionId);
+ $data = $advsubPlugin->getSessionDetails($sessionId);
+ if (!empty($data) && is_array($data)) {
+ $data['status'] = $status;
+ // 5 Cases:
+ if ($isOpen) {
+ // Go to Course session
+ $data['action_url'] = $advsubPlugin->getSessionUrl($sessionId);
+ } else {
+ try {
+ $isAble = $advsubPlugin->isAbleToRequest($userId, $params);
+ $data['message'] = $advsubPlugin->getStatusMessage($status, $isAble);
+ } catch (\Exception $e) {
+ $data['message'] = $e->getMessage();
+ }
+ $params['a'] = 'subscribe';
+ $params['s'] = intval($sessionId);
+ $params['current_user_id'] = 0; // No needed
+ $params['u'] = intval($userId);
+ $params['q'] = 0; // No needed
+ $params['e'] = ADV_SUB_QUEUE_STATUS_START;
+ if ($vacancy > 0) {
+ // Check conditions
+ if ($status === ADV_SUB_QUEUE_STATUS_NO_QUEUE) {
+ // No in Queue, require queue subscription url action
+ $data['action_url'] = $advsubPlugin->getQueueUrl($params);
+ } elseif ($status === ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED) {
+ // send url action
+ $data['action_url'] = $advsubPlugin->getSessionUrl($sessionId);
+ } else {
+ // In queue, output status message, no more info.
+ }
+ } else {
+ if ($status === ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED) {
+ $data['action_url'] = $advsubPlugin->getSessionUrl($sessionId);
+ } else {
+ // in Queue or not, cannot be subscribed to session
+ $data['action_url'] = $advsubPlugin->getQueueUrl($params);
+ }
+ }
+ }
+ $result = $data;
+ }
+ } else {
+ // Return soap fault Not valid input params
+ $result = return_error(WS_ERROR_INVALID_INPUT);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Get a list of sessions (id, coach_id, name, courses_num, users_num, classes_num,
+ * date_start, date_end, access_days_before_num, session_admin_id, visibility,
+ * session_category_id, promotion_id,
+ * validated_user_num, waiting_user_num,
+ * extra, course) the validated_usernum and waiting_user_num are
+ * used when have the plugin for advance incsription enables.
+ * The extra data (field_name, field_value)
+ * The course data (course_id, course_code, course_title,
+ * coach_username, coach_firstname, coach_lastname)
+ * @param array List of parameters (id, category_name, access_url_id, secret_key)
+ * @return array|soap_fault Sessions list (id=>[title=>'title',url='http://...',date_start=>'...',date_end=>''])
+ */
+ function WSListSessionsDetailsByCategory($params)
+ {
+ global $debug;
+
+ if ($debug) error_log('WSListSessionsDetailsByCategory');
+ if ($debug) error_log('Params '. print_r($params, 1));
+ $secretKey = $params['secret_key'];
+
+ // Check if secret key is valid
+ if(!WSHelperVerifyKey($secretKey)) {
+
+ return return_error(WS_ERROR_SECRET_KEY);
+ }
+
+ // Check if category ID is set
+ if (!empty($params['id']) && empty($params['category_name'])) {
+ $sessionCategoryId = $params['id'];
+ } elseif (!empty($params['category_name'])) {
+ // Check if category name is set
+ $sessionCategoryId = SessionManager::getSessionCategoryIdByName($params['category_name']);
+ if (is_array($sessionCategoryId)) {
+ $sessionCategoryId = current($sessionCategoryId);
+ }
+ } else {
+ // Return soap fault Not valid input params
+
+ return return_error(WS_ERROR_INVALID_INPUT);
+ }
+
+ // Get the session List by category
+ $sessionList = SessionManager::getSessionListAndExtraByCategoryId($sessionCategoryId);
+
+ if (empty($sessionList)) {
+ // If not found any session, return error
+
+ return return_error(WS_ERROR_NOT_FOUND_RESULT);
+ }
+ //@TODO: Not implemented yet, see BT#9092
+ // Check if advanced inscription plugin is enabled
+ $isAdvancedInscriptionEnabled = false;
+ if ($isAdvancedInscriptionEnabled) {
+ // Get validated and waiting queue users count for each session
+ foreach ($sessionList as &$session) {
+ // Add validated and queue users count
+ $session['validated_user_num'] = 0;
+ $session['waiting_user_num'] = 0;
+ }
+ } else {
+ // Set -1 to validated and waiting queue users count
+ }
+
+ return $sessionList;
+ }
+
+ /**
+ * @param HookNotificationContentEventInterface $hook
+ * @return int
+ */
+ public function hookNotificationContent(HookNotificationContentEventInterface $hook)
+ {
+ $data = $hook->getEventData();
+ if ($data['type'] === HOOK_EVENT_TYPE_PRE) {
+ $data['advsub_pre_content'] = $data['content'];
+
+ return $data;
+ } elseif ($data['type'] === HOOK_EVENT_TYPE_POST) {
+ if (
+ isset($data['content']) &&
+ !empty($data['content']) &&
+ isset($data['advsub_pre_content']) &&
+ !empty($data['advsub_pre_content'])
+ ) {
+ $data['content'] = str_replace(
+ array(
+ '
',
+ '
',
+ '
',
+ ),
+ '',
+ $data['advsub_pre_content']
+ );
+ }
+
+ return $data;
+ } else {
+ // Hook type is not valid
+ // Nothing to do
+ }
+ }
+
+ /**
+ * @param HookNotificationTitleEventInterface $hook
+ * @return int
+ */
+ public function hookNotificationTitle(HookNotificationTitleEventInterface $hook)
+ {
+ $data = $hook->getEventData();
+ if ($data['type'] === HOOK_EVENT_TYPE_PRE) {
+ $data['advsub_pre_title'] = $data['title'];
+
+ return $data;
+ } elseif ($data['type'] === HOOK_EVENT_TYPE_POST) {
+ if (
+ isset($data['advsub_pre_title']) &&
+ !empty($data['advsub_pre_title'])
+ ) {
+ $data['title'] = $data['advsub_pre_title'];
+ }
+
+ return $data;
+ } else {
+ // Hook type is not valid
+ // Nothing to do
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugin/advancedsubscription/src/admin_view.php b/plugin/advancedsubscription/src/admin_view.php
new file mode 100644
index 0000000000..02829eb552
--- /dev/null
+++ b/plugin/advancedsubscription/src/admin_view.php
@@ -0,0 +1,74 @@
+listAllSessions();
+
+if (!empty($s)) {
+ // Get student list in queue
+ $studentList = $plugin->listAllStudentsInQueueBySession($s);
+ // Set selected to current session
+ $sessionList[$s]['selected'] = 'selected="selected"';
+ $studentList['session']['id'] = $s;
+ // Assign variables
+
+ // send mail to superior
+ $sessionArray = api_get_session_info($s);
+ $extraSession = new ExtraFieldValue('session');
+ $var = $extraSession->get_values_by_handler_and_field_variable($s, 'description');
+ $sessionArray['description'] = $var['field_valiue'];
+ $var = $extraSession->get_values_by_handler_and_field_variable($s, 'target');
+ $sessionArray['target'] = $var['field_valiue'];
+ $var = $extraSession->get_values_by_handler_and_field_variable($s, 'mode');
+ $sessionArray['mode'] = $var['field_valiue'];
+ $var = $extraSession->get_values_by_handler_and_field_variable($s, 'publication_end_date');
+ $sessionArray['publication_end_date'] = $var['field_value'];
+ $var = $extraSession->get_values_by_handler_and_field_variable($s, 'recommended_number_of_participants');
+ $sessionArray['recommended_number_of_participants'] = $var['field_valiue'];
+ $adminsArray = UserManager::get_all_administrators();
+
+ $data['a'] = 'confirm';
+ $data['s'] = $s;
+ $data['current_user_id'] = api_get_user_id();
+
+ foreach ($studentList['students'] as &$student) {
+ $data['u'] = intval($student['user_id']);
+ $data['q'] = intval($student['queue_id']);
+ $data['e'] = ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED;
+ $student['acceptUrl'] = $plugin->getQueueUrl($data);
+ $data['e'] = ADV_SUB_QUEUE_STATUS_ADMIN_DISAPPROVED;
+ $student['rejectUrl'] = $plugin->getQueueUrl($data);
+ $student['complete_name'] = $student['lastname'] . ', ' . $student['firstname'];
+ $student['picture'] = UserManager::get_user_picture_path_by_id($student['user_id'], 'web', false, true);
+ $student['picture'] = UserManager::get_picture_user($student['user_id'], $student['picture']['file'], 22, USER_IMAGE_SIZE_MEDIUM);
+ }
+ $tpl->assign('session', $studentList['session']);
+ $tpl->assign('students', $studentList['students']);
+}
+
+// Assign variables
+$tpl->assign('sessionItems', $sessionList);
+$tpl->assign('approveAdmin', ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED);
+$tpl->assign('disapproveAdmin', ADV_SUB_QUEUE_STATUS_ADMIN_DISAPPROVED);
+// Get rendered template
+$content = $tpl->fetch('/advancedsubscription/views/admin_view.tpl');
+// Assign into content
+$tpl->assign('content', $content);
+// Display
+$tpl->display_one_col_template();
diff --git a/plugin/advancedsubscription/src/img/avatar.png b/plugin/advancedsubscription/src/img/avatar.png
new file mode 100644
index 0000000000..070ec64d66
Binary files /dev/null and b/plugin/advancedsubscription/src/img/avatar.png differ
diff --git a/plugin/advancedsubscription/src/img/icon-avatar.png b/plugin/advancedsubscription/src/img/icon-avatar.png
new file mode 100644
index 0000000000..86477a92ce
Binary files /dev/null and b/plugin/advancedsubscription/src/img/icon-avatar.png differ
diff --git a/plugin/advancedsubscription/uninstall.php b/plugin/advancedsubscription/uninstall.php
new file mode 100644
index 0000000000..4ee930e3c5
--- /dev/null
+++ b/plugin/advancedsubscription/uninstall.php
@@ -0,0 +1,17 @@
+uninstall();
diff --git a/plugin/advancedsubscription/views/admin_view.tpl b/plugin/advancedsubscription/views/admin_view.tpl
new file mode 100644
index 0000000000..05b21ac347
--- /dev/null
+++ b/plugin/advancedsubscription/views/admin_view.tpl
@@ -0,0 +1,204 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_admin.tpl b/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_admin.tpl
new file mode 100644
index 0000000000..478840590d
--- /dev/null
+++ b/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_admin.tpl
@@ -0,0 +1,86 @@
+
+
+
+
+ Solicitud recibida para el curso {{ session.name }}
+
+
+
+
+
+
+
diff --git a/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_student.tpl b/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_student.tpl
new file mode 100644
index 0000000000..e92528a69c
--- /dev/null
+++ b/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_student.tpl
@@ -0,0 +1,86 @@
+
+
+
+
+ Solicitud recibida para el curso {{ session.name }}
+
+
+
+
+
+
+
diff --git a/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_superior.tpl b/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_superior.tpl
new file mode 100644
index 0000000000..ff7d5a0b7f
--- /dev/null
+++ b/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_superior.tpl
@@ -0,0 +1,86 @@
+
+
+
+
+ Solicitud recibida para el curso {{ session.name }}
+
+
+
+
+
+
+
diff --git a/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_admin.tpl b/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_admin.tpl
new file mode 100644
index 0000000000..dbe5f476ce
--- /dev/null
+++ b/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_admin.tpl
@@ -0,0 +1,86 @@
+
+
+
+
+ Solicitud recibida para el curso {{ session.name }}
+
+
+
+
+
+
+
diff --git a/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_student.tpl b/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_student.tpl
new file mode 100644
index 0000000000..64727b26ba
--- /dev/null
+++ b/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_student.tpl
@@ -0,0 +1,86 @@
+
+
+
+
+ Solicitud recibida para el curso {{ session.name }}
+
+
+
+
+
+
+
diff --git a/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_superior.tpl b/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_superior.tpl
new file mode 100644
index 0000000000..da2b8fbfa9
--- /dev/null
+++ b/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_superior.tpl
@@ -0,0 +1,86 @@
+
+
+
+
+ Solicitud recibida para el curso {{ session.name }}
+
+
+
+
+
+
+
diff --git a/plugin/advancedsubscription/views/advsub_request_approve_confirmed.tpl b/plugin/advancedsubscription/views/advsub_request_approve_confirmed.tpl
new file mode 100644
index 0000000000..db9323e154
--- /dev/null
+++ b/plugin/advancedsubscription/views/advsub_request_approve_confirmed.tpl
@@ -0,0 +1,87 @@
+
+
+
+
+ Solicitud recibida para el curso {{ session.name }}
+
+
+
+
+
+
+  |
+
+
+  |
+
+
+
+
+ | |
+  |
+ |
+
+
+ | |
+ |
+ |
+
+
+ | |
+ |
+ |
+
+
+ | |
+ Confirmación: Aprobación recibida para {{ student.complete_name }} |
+ |
+
+
+ | |
+ |
+ |
+
+
+ | |
+ |
+ |
+
+
+ | |
+ Estimado:
+ {{ superior.complete_name }}
+ Hemos recibido y registrado su decisión de aprobar el curso {{ session.name }} para su colaborador {{ student.complete_name }}
+ Ahora la inscripción al curso está pendiente de la disponibilidad de cupos. Le mantendremos informado sobre el resultado de esta etapa
+ Gracias por su colaboración.
+ {{ signature }} |
+ |
+
+
+ | |
+ |
+ |
+
+ |
+
+
+  |
+
+
+  |
+
+
+ | |
+
+
+
+
diff --git a/plugin/advancedsubscription/views/advsub_request_approved_info_admin.tpl b/plugin/advancedsubscription/views/advsub_request_approved_info_admin.tpl
new file mode 100644
index 0000000000..b3affda159
--- /dev/null
+++ b/plugin/advancedsubscription/views/advsub_request_approved_info_admin.tpl
@@ -0,0 +1,95 @@
+
+
+
+
+ Solicitud recibida para el curso {{ session.name }}
+
+
+
+
+
+
+
diff --git a/plugin/advancedsubscription/views/advsub_request_approved_reminder.tpl b/plugin/advancedsubscription/views/advsub_request_approved_reminder.tpl
new file mode 100644
index 0000000000..3dd17c438a
--- /dev/null
+++ b/plugin/advancedsubscription/views/advsub_request_approved_reminder.tpl
@@ -0,0 +1,86 @@
+
+
+
+
+ Solicitud recibida para el curso {{ session.name }}
+
+
+
+
+
+
+
diff --git a/plugin/advancedsubscription/views/advsub_request_disapprove_confirmed.tpl b/plugin/advancedsubscription/views/advsub_request_disapprove_confirmed.tpl
new file mode 100644
index 0000000000..f41cbf82ea
--- /dev/null
+++ b/plugin/advancedsubscription/views/advsub_request_disapprove_confirmed.tpl
@@ -0,0 +1,86 @@
+
+
+
+
+ Solicitud recibida para el curso {{ session.name }}
+
+
+
+
+
+
+
diff --git a/plugin/advancedsubscription/views/advsub_request_received.tpl b/plugin/advancedsubscription/views/advsub_request_received.tpl
new file mode 100644
index 0000000000..0d1fd0b85d
--- /dev/null
+++ b/plugin/advancedsubscription/views/advsub_request_received.tpl
@@ -0,0 +1,87 @@
+
+
+
+
+ Solicitud recibida para el curso {{ session.name }}
+
+
+
+
+
+
+  |
+
+
+  |
+
+
+
+
+ | |
+  |
+ |
+
+
+ | |
+ |
+ |
+
+
+ | |
+ |
+ |
+
+
+ | |
+ Solicitud recibida para el curso {{ session.name }} |
+ |
+
+
+ | |
+ |
+ |
+
+
+ | |
+ |
+ |
+
+
+ | |
+ Estimado:
+ {{ student.complete_name }}
+ Hemos recibido y registrado su solicitud de inscripción al curso {{ session.name }} para iniciarse el {{ session.date_start }}.
+ Su inscripción es pendiente primero de la aprobación de su superior, y luego de la disponibilidad de cupos. Un correo ha sido enviado a su superior para revisión y aprobación de su solicitud.
+ Gracias.
+ Equipo Forge |
+ |
+
+
+ | |
+ |
+ |
+
+ |
+
+
+  |
+
+
+  |
+
+
+ | |
+
+
+
+
diff --git a/plugin/advancedsubscription/views/advsub_request_received_no_boss.tpl b/plugin/advancedsubscription/views/advsub_request_received_no_boss.tpl
new file mode 100644
index 0000000000..b4263e3db3
--- /dev/null
+++ b/plugin/advancedsubscription/views/advsub_request_received_no_boss.tpl
@@ -0,0 +1,87 @@
+
+
+
+
+ Solicitud recibida para el curso {{ session.name }}
+
+
+
+
+
+
+  |
+
+
+  |
+
+
+
+
+ | |
+  |
+ |
+
+
+ | |
+ |
+ |
+
+
+ | |
+ |
+ |
+
+
+ | |
+ Solicitud recibida para el curso {{ session.name }} |
+ |
+
+
+ | |
+ |
+ |
+
+
+ | |
+ |
+ |
+
+
+ | |
+ Estimado:
+ {{ student.complete_name }}
+ Hemos recibido y registrado su solicitud de inscripción al curso {{ session.name }} para iniciarse el {{ session.date_start }}.
+ Su inscripción es pendiente de la disponibilidad de cupos. Pronto recibirá los resultados de su aprobación de su solicitud.
+ Gracias.
+ Equipo Forge |
+ |
+
+
+ | |
+ |
+ |
+
+ |
+
+
+  |
+
+
+  |
+
+
+ | |
+
+
+
+
diff --git a/plugin/advancedsubscription/views/advsub_request_received_reminder.tpl b/plugin/advancedsubscription/views/advsub_request_received_reminder.tpl
new file mode 100644
index 0000000000..eb23a66ff5
--- /dev/null
+++ b/plugin/advancedsubscription/views/advsub_request_received_reminder.tpl
@@ -0,0 +1,87 @@
+
+
+
+
+ Solicitud recibida para el curso {{ session.name }}
+
+
+
+
+
+
+  |
+
+
+  |
+
+
+
+
+ | |
+  |
+ |
+
+
+ | |
+ |
+ |
+
+
+ | |
+ |
+ |
+
+
+ | |
+ Información: Solicitud pendiente de aprobación para el curso {{ session.name }} |
+ |
+
+
+ | |
+ |
+ |
+
+
+ | |
+ |
+ |
+
+
+ | |
+ Estimado:
+ {{ student.complete_name }}
+ Este correo es para confirmar que hemos recibido y registrado su solicitud de inscripción al curso {{ session.name }}, por iniciarse el {{ session.date_start }}.
+ Su inscripción todavía no ha sido aprobada por su superior, por lo que hemos vuelto a enviarle un correo electrónico de recordatorio.
+ Gracias por su paciencia.
+ Equipo Forge |
+ |
+
+
+ | |
+ |
+ |
+
+ |
+
+
+  |
+
+
+  |
+
+
+ | |
+
+
+
+
diff --git a/plugin/advancedsubscription/views/advsub_request_superior.tpl b/plugin/advancedsubscription/views/advsub_request_superior.tpl
new file mode 100644
index 0000000000..1424ae8c4a
--- /dev/null
+++ b/plugin/advancedsubscription/views/advsub_request_superior.tpl
@@ -0,0 +1,95 @@
+
+
+
+
+ Solicitud recibida para el curso {{ session.name }}
+
+
+
+
+
+
+
diff --git a/plugin/advancedsubscription/views/advsub_request_superior_approved.tpl b/plugin/advancedsubscription/views/advsub_request_superior_approved.tpl
new file mode 100644
index 0000000000..7bceecae5d
--- /dev/null
+++ b/plugin/advancedsubscription/views/advsub_request_superior_approved.tpl
@@ -0,0 +1,86 @@
+
+
+
+
+ Solicitud recibida para el curso {{ session.name }}
+
+
+
+
+
+
+
diff --git a/plugin/advancedsubscription/views/advsub_request_superior_disapproved.tpl b/plugin/advancedsubscription/views/advsub_request_superior_disapproved.tpl
new file mode 100644
index 0000000000..57853e98b5
--- /dev/null
+++ b/plugin/advancedsubscription/views/advsub_request_superior_disapproved.tpl
@@ -0,0 +1,86 @@
+
+
+
+
+ Solicitud recibida para el curso {{ session.name }}
+
+
+
+
+
+
+
diff --git a/plugin/advancedsubscription/views/advsub_request_superior_reminder.tpl b/plugin/advancedsubscription/views/advsub_request_superior_reminder.tpl
new file mode 100644
index 0000000000..b5811fa73e
--- /dev/null
+++ b/plugin/advancedsubscription/views/advsub_request_superior_reminder.tpl
@@ -0,0 +1,97 @@
+
+
+
+
+ Solicitud recibida para el curso {{ session.name }}
+
+
+
+
+
+
+
diff --git a/plugin/advancedsubscription/views/advsub_request_superior_reminder_max.tpl b/plugin/advancedsubscription/views/advsub_request_superior_reminder_max.tpl
new file mode 100644
index 0000000000..93a4f466f7
--- /dev/null
+++ b/plugin/advancedsubscription/views/advsub_request_superior_reminder_max.tpl
@@ -0,0 +1,97 @@
+
+
+
+
+Solicitud recibida para el curso {{ session.name }}
+
+
+
+
+
+
+
diff --git a/plugin/advancedsubscription/views/img/aprobar.png b/plugin/advancedsubscription/views/img/aprobar.png
new file mode 100644
index 0000000000..90250ca752
Binary files /dev/null and b/plugin/advancedsubscription/views/img/aprobar.png differ
diff --git a/plugin/advancedsubscription/views/img/avatar.png b/plugin/advancedsubscription/views/img/avatar.png
new file mode 100644
index 0000000000..35ec23c3f7
Binary files /dev/null and b/plugin/advancedsubscription/views/img/avatar.png differ
diff --git a/plugin/advancedsubscription/views/img/desaprobar.png b/plugin/advancedsubscription/views/img/desaprobar.png
new file mode 100644
index 0000000000..1d73cd739e
Binary files /dev/null and b/plugin/advancedsubscription/views/img/desaprobar.png differ
diff --git a/plugin/advancedsubscription/views/img/footer.png b/plugin/advancedsubscription/views/img/footer.png
new file mode 100644
index 0000000000..8a7603e6a7
Binary files /dev/null and b/plugin/advancedsubscription/views/img/footer.png differ
diff --git a/plugin/advancedsubscription/views/img/header.png b/plugin/advancedsubscription/views/img/header.png
new file mode 100644
index 0000000000..4558064679
Binary files /dev/null and b/plugin/advancedsubscription/views/img/header.png differ
diff --git a/plugin/advancedsubscription/views/img/line.png b/plugin/advancedsubscription/views/img/line.png
new file mode 100644
index 0000000000..7c349e2557
Binary files /dev/null and b/plugin/advancedsubscription/views/img/line.png differ
diff --git a/plugin/advancedsubscription/views/img/logo-minedu.png b/plugin/advancedsubscription/views/img/logo-minedu.png
new file mode 100644
index 0000000000..dcf6a20bc9
Binary files /dev/null and b/plugin/advancedsubscription/views/img/logo-minedu.png differ