Actualización
11
plugin/add_cas_login_button/README.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
Add CAS login button plugin
|
||||||
|
======
|
||||||
|
This plugin adds a button to allow users to login to Chamilo through CAS authentication.
|
||||||
|
|
||||||
|
In order for the plugin to work, you'll have to:
|
||||||
|
|
||||||
|
* enable your CAS connection to display this button
|
||||||
|
* configure your CAS connection to have the button work
|
||||||
|
* go to Administration > Configuration settings > CAS and follow the instructions
|
||||||
|
|
||||||
|
This plugin has been made to be added in the login_top region, but you can put it wherever you want.
|
||||||
12
plugin/add_cas_login_button/css.css
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
.cas_plugin_image {
|
||||||
|
float:left;
|
||||||
|
height:50px;
|
||||||
|
margin: 0px 5px 5px 0px;
|
||||||
|
}
|
||||||
|
.cas_plugin_comm {
|
||||||
|
font-style:italic;
|
||||||
|
}
|
||||||
|
.cas_plugin_clear {
|
||||||
|
clear:both;
|
||||||
|
height:1px;
|
||||||
|
}
|
||||||
29
plugin/add_cas_login_button/index.php
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
// Show the CAS button to login using CAS
|
||||||
|
require_once api_get_path(SYS_PATH).'main/auth/cas/cas_var.inc.php';
|
||||||
|
|
||||||
|
$_template['show_message'] = false;
|
||||||
|
|
||||||
|
if (api_is_anonymous()) {
|
||||||
|
$_template['cas_activated'] = api_is_cas_activated();
|
||||||
|
$_template['cas_configured'] = api_is_cas_activated() && phpCAS::isInitialized();
|
||||||
|
$_template['show_message'] = true;
|
||||||
|
// the default title
|
||||||
|
$button_label = "Connexion via CAS";
|
||||||
|
if (!empty($plugin_info['settings']['add_cas_login_button_cas_button_label'])) {
|
||||||
|
$button_label = api_htmlentities(
|
||||||
|
$plugin_info['settings']['add_cas_login_button_cas_button_label']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// the comm
|
||||||
|
$comm_label = api_htmlentities(
|
||||||
|
$plugin_info['settings']['add_cas_login_button_cas_button_comment']
|
||||||
|
);
|
||||||
|
// URL of the image
|
||||||
|
$url_label = $plugin_info['settings']['add_cas_login_button_cas_image_url'];
|
||||||
|
|
||||||
|
$_template['button_label'] = $button_label;
|
||||||
|
$_template['comm_label'] = $comm_label;
|
||||||
|
$_template['url_label'] = $url_label;
|
||||||
|
$_template['form'] = Template::displayCASLoginButton(get_lang('LoginEnter'));
|
||||||
|
}
|
||||||
49
plugin/add_cas_login_button/plugin.php
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This script is a configuration file for the date plugin. You can use it as a master for other platform plugins (course plugins are slightly different).
|
||||||
|
* These settings will be used in the administration interface for plugins (Chamilo configuration settings->Plugins).
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin
|
||||||
|
*
|
||||||
|
* @author Julio Montoya <gugli100@gmail.com>
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Plugin details (must be present).
|
||||||
|
*/
|
||||||
|
|
||||||
|
//the plugin title
|
||||||
|
$plugin_info['title'] = 'Add a button to login using CAS';
|
||||||
|
|
||||||
|
//the comments that go with the plugin
|
||||||
|
$plugin_info['comment'] = "If CAS is activated, this plugin add a text and a button on the login page to login with CAS. Configure plugin to add title, comment and logo.";
|
||||||
|
//the plugin version
|
||||||
|
$plugin_info['version'] = '1.0';
|
||||||
|
//the plugin author
|
||||||
|
$plugin_info['author'] = 'Hubert Borderiou';
|
||||||
|
|
||||||
|
//the plugin configuration
|
||||||
|
$form = new FormValidator('add_cas_button_form');
|
||||||
|
$form->addElement('text', 'cas_button_label', 'CAS connexion title', '');
|
||||||
|
$form->addElement('text', 'cas_button_comment', 'CAS connexion description', '');
|
||||||
|
$form->addElement('text', 'cas_image_url', 'Logo URL if any (image, 50px height)');
|
||||||
|
$form->addButtonSave(get_lang('Save'), 'submit_button');
|
||||||
|
//get default value for form
|
||||||
|
$tab_default_add_cas_login_button_cas_button_label = api_get_setting('add_cas_login_button_cas_button_label');
|
||||||
|
$tab_default_add_cas_login_button_cas_button_comment = api_get_setting('add_cas_login_button_cas_button_comment');
|
||||||
|
$tab_default_add_cas_login_button_cas_image_url = api_get_setting('add_cas_login_button_cas_image_url');
|
||||||
|
$defaults = [];
|
||||||
|
if ($tab_default_add_cas_login_button_cas_button_label) {
|
||||||
|
$defaults['cas_button_label'] = $tab_default_add_cas_login_button_cas_button_label['add_cas_login_button'];
|
||||||
|
}
|
||||||
|
if ($tab_default_add_cas_login_button_cas_button_comment) {
|
||||||
|
$defaults['cas_button_comment'] = $tab_default_add_cas_login_button_cas_button_comment['add_cas_login_button'];
|
||||||
|
}
|
||||||
|
if ($tab_default_add_cas_login_button_cas_image_url) {
|
||||||
|
$defaults['cas_image_url'] = $tab_default_add_cas_login_button_cas_image_url['add_cas_login_button'];
|
||||||
|
}
|
||||||
|
$form->setDefaults($defaults);
|
||||||
|
//display form
|
||||||
|
$plugin_info['settings_form'] = $form;
|
||||||
|
|
||||||
|
//set the templates that are going to be used
|
||||||
|
$plugin_info['templates'] = ['template.tpl'];
|
||||||
22
plugin/add_cas_login_button/template.tpl
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{% if add_cas_login_button.show_message %}
|
||||||
|
<link href="{{ _p.web_plugin }}add_cas_login_button/css.css" rel="stylesheet" type="text/css">
|
||||||
|
<div class="well">
|
||||||
|
{% if add_cas_login_button.url_label %}
|
||||||
|
<img src="{{ add_cas_login_button.url_label }}" class='cas_plugin_image'/>
|
||||||
|
{% endif %}
|
||||||
|
<h4>{{ add_cas_login_button.button_label }}</h4>
|
||||||
|
{% if add_cas_login_button.url_label %}
|
||||||
|
<div class='cas_plugin_clear'> </div>
|
||||||
|
{% endif %}
|
||||||
|
<div class='cas_plugin_comm'>{{ add_cas_login_button.comm_label }}</div>
|
||||||
|
{% if add_cas_login_button.cas_activated %}
|
||||||
|
{% if add_cas_login_button.cas_configured %}
|
||||||
|
{{ add_cas_login_button.form }}
|
||||||
|
{% else %}
|
||||||
|
CAS isn't configured. Go to Admin > Configuration > CAS.<br/>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
CAS isn't activated. Go to Admin > Configuration > CAS.<br/>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
12
plugin/add_cas_logout_button/README.md
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
Add CAS logout button plugin
|
||||||
|
===
|
||||||
|
|
||||||
|
This plugin adds a button to allow users to logout from their CAS session.
|
||||||
|
|
||||||
|
In order for the plugin to work, you'll have to:
|
||||||
|
|
||||||
|
* enable your CAS connection to display this button.
|
||||||
|
* configure your CAS connection to have the button works.
|
||||||
|
* go to Administration > Configuration settings > CAS and follow the instructions.
|
||||||
|
|
||||||
|
This plugin has been made to be added in the login_top region, but you can put it wherever you want.
|
||||||
12
plugin/add_cas_logout_button/css.css
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
.cas_plugin_image {
|
||||||
|
float:left;
|
||||||
|
height:50px;
|
||||||
|
margin: 0px 5px 5px 0px;
|
||||||
|
}
|
||||||
|
.cas_plugin_comm {
|
||||||
|
font-style:italic;
|
||||||
|
}
|
||||||
|
.cas_plugin_clear {
|
||||||
|
clear:both;
|
||||||
|
height:1px;
|
||||||
|
}
|
||||||
26
plugin/add_cas_logout_button/index.php
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
// Show the CAS button to logout to your CAS session
|
||||||
|
global $_user;
|
||||||
|
$_template['show_message'] = false;
|
||||||
|
|
||||||
|
if (!api_is_anonymous() &&
|
||||||
|
api_get_setting('cas_activate') == 'true' &&
|
||||||
|
$_user['auth_source'] == CAS_AUTH_SOURCE
|
||||||
|
) {
|
||||||
|
$_template['show_message'] = true;
|
||||||
|
// the default title
|
||||||
|
$logout_label = "Deconnexion de CAS";
|
||||||
|
if (!empty($plugin_info['settings']['add_cas_logout_button_cas_logout_label'])) {
|
||||||
|
$logout_label = api_htmlentities($plugin_info['settings']['add_cas_logout_button_cas_logout_label']);
|
||||||
|
}
|
||||||
|
// the comm
|
||||||
|
$logout_comment = api_htmlentities($plugin_info['settings']['add_cas_logout_button_cas_logout_comment']);
|
||||||
|
|
||||||
|
// URL of the image
|
||||||
|
$logout_image_url = $plugin_info['settings']['add_cas_logout_button_cas_logout_image_url'];
|
||||||
|
|
||||||
|
$_template['logout_label'] = $logout_label;
|
||||||
|
$_template['form'] = Template::displayCASLogoutButton(get_lang('Logout'));
|
||||||
|
$_template['logout_comment'] = $logout_comment;
|
||||||
|
$_template['logout_image_url'] = $logout_image_url;
|
||||||
|
}
|
||||||
50
plugin/add_cas_logout_button/plugin.php
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This script is a configuration file for the date plugin. You can use it as a master for other platform plugins (course plugins are slightly different).
|
||||||
|
* These settings will be used in the administration interface for plugins (Chamilo configuration settings->Plugins).
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin
|
||||||
|
*
|
||||||
|
* @author Julio Montoya <gugli100@gmail.com>
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Plugin details (must be present).
|
||||||
|
*/
|
||||||
|
|
||||||
|
//the plugin title
|
||||||
|
$plugin_info['title'] = 'Add a button to logout from CAS';
|
||||||
|
|
||||||
|
//the comments that go with the plugin
|
||||||
|
$plugin_info['comment'] = "If CAS is activated, this plugin add a text and a button on the user page to logout from a CAS session. Configure plugin to add title, comment and logo.";
|
||||||
|
//the plugin version
|
||||||
|
$plugin_info['version'] = '1.0';
|
||||||
|
//the plugin author
|
||||||
|
$plugin_info['author'] = 'Hubert Borderiou';
|
||||||
|
//the plugin configuration
|
||||||
|
$form = new FormValidator('add_cas_button_form');
|
||||||
|
$form->addElement('text', 'cas_logout_label', 'CAS logout title', '');
|
||||||
|
$form->addElement('text', 'cas_logout_comment', 'CAS logout description', '');
|
||||||
|
$form->addElement('text', 'cas_logout_image_url', 'Logo URL if any (image, 50px height)');
|
||||||
|
$form->addButtonSave(get_lang('Save'), 'submit_button');
|
||||||
|
//get default value for form
|
||||||
|
$defaults = [];
|
||||||
|
$tab_default_add_cas_logout_button_cas_logout_label = api_get_setting('add_cas_logout_button_cas_logout_label');
|
||||||
|
$tab_default_add_cas_logout_button_cas_logout_comment = api_get_setting('add_cas_logout_button_cas_logout_comment');
|
||||||
|
$tab_default_add_cas_logout_button_cas_logout_image_url = api_get_setting('add_cas_logout_button_cas_logout_image_url');
|
||||||
|
if ($tab_default_add_cas_logout_button_cas_logout_label) {
|
||||||
|
$defaults['cas_logout_label'] = $tab_default_add_cas_logout_button_cas_logout_label['add_cas_logout_button'];
|
||||||
|
}
|
||||||
|
if ($tab_default_add_cas_logout_button_cas_logout_comment) {
|
||||||
|
$defaults['cas_logout_comment'] = $tab_default_add_cas_logout_button_cas_logout_comment['add_cas_logout_button'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($tab_default_add_cas_logout_button_cas_logout_image_url) {
|
||||||
|
$defaults['cas_logout_image_url'] = $tab_default_add_cas_logout_button_cas_logout_image_url['add_cas_logout_button'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$form->setDefaults($defaults);
|
||||||
|
//display form
|
||||||
|
$plugin_info['settings_form'] = $form;
|
||||||
|
|
||||||
|
// Set the templates that are going to be used
|
||||||
|
$plugin_info['templates'] = ['template.tpl'];
|
||||||
15
plugin/add_cas_logout_button/template.tpl
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{% if add_cas_logout_button.show_message %}
|
||||||
|
<link href="{{ _p.web_plugin }}add_cas_logout_button/css.css" rel="stylesheet" type="text/css">
|
||||||
|
<div class="well">
|
||||||
|
{% if add_cas_logout_button.logout_image_url %}
|
||||||
|
<img src="{{add_cas_logout_button.logout_image_url}}" class='cas_plugin_image'/>
|
||||||
|
{% endif %}
|
||||||
|
<h4>{{add_cas_logout_button.logout_label}}</h4>
|
||||||
|
{% if add_cas_logout_button.logout_image_url %}
|
||||||
|
<div class='cas_plugin_clear'> </div>
|
||||||
|
{% endif %}
|
||||||
|
<div class='cas_plugin_comm'>{{add_cas_logout_button.logout_comment}}</div>
|
||||||
|
{{ add_cas_logout_button.form }}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
16
plugin/add_facebook_login_button/README.md
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
Add Facebook login button plugin
|
||||||
|
===
|
||||||
|
|
||||||
|
This plugin adds a button to allow users to log into Chamilo through their Facebook account.
|
||||||
|
|
||||||
|
To display this button on your portal, you have to:
|
||||||
|
|
||||||
|
* enable the Facebook authentication setting and configure it
|
||||||
|
* enable and configure Facebook authentication on your Chamilo platform: go to Administration > Configuration settings > Facebook
|
||||||
|
* add the App ID and the Secret Key provided by Facebook inside the app/config/auth.conf.php file
|
||||||
|
* set the following line in your app/config/configuration.php
|
||||||
|
```
|
||||||
|
$_configuration['facebook_auth'] = 1;
|
||||||
|
```
|
||||||
|
|
||||||
|
This plugin has been developed to be added to the login_top or login_bottom region in Chamilo, but you can put it in whichever region you want.
|
||||||
12
plugin/add_facebook_login_button/css.css
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
.cas_plugin_image {
|
||||||
|
float:left;
|
||||||
|
height:50px;
|
||||||
|
margin: 0px 5px 5px 0px;
|
||||||
|
}
|
||||||
|
.cas_plugin_comm {
|
||||||
|
font-style:italic;
|
||||||
|
}
|
||||||
|
.cas_plugin_clear {
|
||||||
|
clear:both;
|
||||||
|
height:1px;
|
||||||
|
}
|
||||||
17
plugin/add_facebook_login_button/index.php
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
// Show the FACEBOOK login button
|
||||||
|
$_template['show_message'] = false;
|
||||||
|
|
||||||
|
//if (api_is_anonymous() && api_get_setting('facebook_login_activate') == 'true') {
|
||||||
|
if (api_is_anonymous()) {
|
||||||
|
require_once api_get_path(SYS_CODE_PATH)."auth/external_login/facebook.inc.php";
|
||||||
|
$_template['show_message'] = true;
|
||||||
|
// the default title
|
||||||
|
$button_url = '';
|
||||||
|
$href_link = facebookGetLoginUrl();
|
||||||
|
if (!empty($plugin_info['settings']['add_facebook_login_button_facebook_button_url'])) {
|
||||||
|
$button_url = api_htmlentities($plugin_info['settings']['add_facebook_login_button_facebook_button_url']);
|
||||||
|
}
|
||||||
|
$_template['facebook_button_url'] = $button_url;
|
||||||
|
$_template['facebook_href_link'] = $href_link;
|
||||||
|
}
|
||||||
45
plugin/add_facebook_login_button/plugin.php
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @package chamilo.plugin.add_facebook_login_button
|
||||||
|
*
|
||||||
|
* @author Julio Montoya <gugli100@gmail.com>
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Plugin details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//the plugin title
|
||||||
|
$plugin_info['title'] = 'Add a button to login using a FACEBOOK account';
|
||||||
|
|
||||||
|
//the comments that go with the plugin
|
||||||
|
$plugin_info['comment'] = "If Facebook authentication is enabled, this plugin adds a button Facebook Connexion on the login page. Configure the plugin to add a title, a comment and a logo. Should be placed in login_top region";
|
||||||
|
//the plugin version
|
||||||
|
$plugin_info['version'] = '1.0';
|
||||||
|
//the plugin author
|
||||||
|
$plugin_info['author'] = 'Konrad Banasiak, Hubert Borderiou';
|
||||||
|
//the plugin configuration
|
||||||
|
$form = new FormValidator('add_facebook_button_form');
|
||||||
|
$form->addElement(
|
||||||
|
'text',
|
||||||
|
'facebook_button_url',
|
||||||
|
'Facebook connexion image URL',
|
||||||
|
''
|
||||||
|
);
|
||||||
|
$form->addButtonSave(get_lang('Save'), 'submit_button');
|
||||||
|
//get default value for form
|
||||||
|
$tab_default_add_facebook_login_button_facebook_button_url = api_get_setting(
|
||||||
|
'add_facebook_login_button_facebook_button_url'
|
||||||
|
);
|
||||||
|
|
||||||
|
$defaults = [];
|
||||||
|
|
||||||
|
if ($tab_default_add_facebook_login_button_facebook_button_url) {
|
||||||
|
$defaults['facebook_button_url'] = $tab_default_add_facebook_login_button_facebook_button_url['add_facebook_login_button'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$form->setDefaults($defaults);
|
||||||
|
//display form
|
||||||
|
$plugin_info['settings_form'] = $form;
|
||||||
|
|
||||||
|
// Set the templates that are going to be used
|
||||||
|
$plugin_info['templates'] = ['template.tpl'];
|
||||||
14
plugin/add_facebook_login_button/template.tpl
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{% if add_facebook_login_button.show_message %}
|
||||||
|
<hr>
|
||||||
|
{% if add_facebook_login_button.facebook_button_url %}
|
||||||
|
<a href="{{ add_facebook_login_button.facebook_href_link }}" title="{{ 'FacebookMainActivateTitle'|get_lang }}">
|
||||||
|
<img src="{{ add_facebook_login_button.facebook_button_url }}"
|
||||||
|
alt="{{ 'FacebookMainActivateTitle'|get_lang }}" style="display: block; margin: 0 auto;">
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
|
<a href="{{ add_facebook_login_button.facebook_href_link }}" class="btn btn-primary btn-block">
|
||||||
|
<span class="fa fa-facebook fa-fw" aria-hidden="true"></span> {{ 'FacebookMainActivateTitle'|get_lang }}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
<hr style="margin-bottom: 10px;">
|
||||||
|
{% endif %}
|
||||||
10
plugin/add_shibboleth_login_button/README.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
Add Shibboleth login button plugin
|
||||||
|
===
|
||||||
|
|
||||||
|
This plugin adds a button to allow users to login to Chamilo through Shibboleth authentication.
|
||||||
|
|
||||||
|
You have to configure your Shibboleth connexion before using this plugin.
|
||||||
|
|
||||||
|
To activate and configure Shibboleth for your Chamilo platform, go to Administration > Configuration settings > Shibboleth
|
||||||
|
|
||||||
|
This plugin has been created to be added in the login_top region, but you can put it wherever you want.
|
||||||
12
plugin/add_shibboleth_login_button/css.css
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
.shibboleth_plugin_image {
|
||||||
|
float:left;
|
||||||
|
height:50px;
|
||||||
|
margin: 0px 5px 5px 0px;
|
||||||
|
}
|
||||||
|
.shibboleth_plugin_comm {
|
||||||
|
font-style:italic;
|
||||||
|
}
|
||||||
|
.shibboleth_plugin_clear {
|
||||||
|
clear:both;
|
||||||
|
height:1px;
|
||||||
|
}
|
||||||
22
plugin/add_shibboleth_login_button/index.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
// Show the Shibboleth button to login using SHIBBOLETH
|
||||||
|
|
||||||
|
$_template['show_message'] = false;
|
||||||
|
|
||||||
|
if (api_is_anonymous()) {
|
||||||
|
$_template['show_message'] = true;
|
||||||
|
// the default title
|
||||||
|
$button_label = "Connexion via Shibboleth";
|
||||||
|
if (!empty($plugin_info['settings']['add_shibboleth_login_button_shibboleth_button_label'])) {
|
||||||
|
$button_label = api_htmlentities($plugin_info['settings']['add_shibboleth_login_button_shibboleth_button_label']);
|
||||||
|
}
|
||||||
|
// the comm
|
||||||
|
$comm_label = api_htmlentities($plugin_info['settings']['add_shibboleth_login_button_shibboleth_button_comment']);
|
||||||
|
|
||||||
|
// URL of the image
|
||||||
|
$url_label = $plugin_info['settings']['add_shibboleth_login_button_shibboleth_image_url'];
|
||||||
|
|
||||||
|
$_template['button_label'] = $button_label;
|
||||||
|
$_template['comm_label'] = $comm_label;
|
||||||
|
$_template['url_label'] = $url_label;
|
||||||
|
}
|
||||||
72
plugin/add_shibboleth_login_button/plugin.php
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This script is a configuration file for the date plugin. You can use it as a master for other platform plugins (course plugins are slightly different).
|
||||||
|
* These settings will be used in the administration interface for plugins (Chamilo configuration settings->Plugins).
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin
|
||||||
|
*
|
||||||
|
* @author Julio Montoya <gugli100@gmail.com>
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Plugin details (must be present).
|
||||||
|
*/
|
||||||
|
|
||||||
|
//the plugin title
|
||||||
|
$plugin_info['title'] = 'Add a button to login using Shibboleth';
|
||||||
|
|
||||||
|
//the comments that go with the plugin
|
||||||
|
$plugin_info['comment'] = "If Shibboleth is configured, this plugin add a text and a button on the login page to login with Shibboleth. Configure plugin to add title, comment and logo.";
|
||||||
|
//the plugin version
|
||||||
|
$plugin_info['version'] = '1.0';
|
||||||
|
//the plugin author
|
||||||
|
$plugin_info['author'] = 'Hubert Borderiou';
|
||||||
|
|
||||||
|
//the plugin configuration
|
||||||
|
$form = new FormValidator('add_shibboleth_button_form');
|
||||||
|
$form->addElement(
|
||||||
|
'text',
|
||||||
|
'shibboleth_button_label',
|
||||||
|
'shibboleth connexion title',
|
||||||
|
''
|
||||||
|
);
|
||||||
|
$form->addElement(
|
||||||
|
'text',
|
||||||
|
'shibboleth_button_comment',
|
||||||
|
'shibboleth connexion description',
|
||||||
|
''
|
||||||
|
);
|
||||||
|
$form->addElement(
|
||||||
|
'text',
|
||||||
|
'shibboleth_image_url',
|
||||||
|
'Logo URL if any (image, 50px height)'
|
||||||
|
);
|
||||||
|
$form->addButtonSave(get_lang('Save'), 'submit_button');
|
||||||
|
//get default value for form
|
||||||
|
$tab_default_add_shibboleth_login_button_shibboleth_button_label = api_get_setting(
|
||||||
|
'add_shibboleth_login_button_shibboleth_button_label'
|
||||||
|
);
|
||||||
|
$tab_default_add_shibboleth_login_button_shibboleth_button_comment = api_get_setting(
|
||||||
|
'add_shibboleth_login_button_shibboleth_button_comment'
|
||||||
|
);
|
||||||
|
$tab_default_add_shibboleth_login_button_shibboleth_image_url = api_get_setting(
|
||||||
|
'add_shibboleth_login_button_shibboleth_image_url'
|
||||||
|
);
|
||||||
|
$defaults = [];
|
||||||
|
if ($tab_default_add_shibboleth_login_button_shibboleth_button_label) {
|
||||||
|
$defaults['shibboleth_button_label'] = $tab_default_add_shibboleth_login_button_shibboleth_button_label['add_shibboleth_login_button'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($tab_default_add_shibboleth_login_button_shibboleth_button_comment) {
|
||||||
|
$defaults['shibboleth_button_comment'] = $tab_default_add_shibboleth_login_button_shibboleth_button_comment['add_shibboleth_login_button'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($tab_default_add_shibboleth_login_button_shibboleth_image_url) {
|
||||||
|
$defaults['shibboleth_image_url'] = $tab_default_add_shibboleth_login_button_shibboleth_image_url['add_shibboleth_login_button'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$form->setDefaults($defaults);
|
||||||
|
//display form
|
||||||
|
$plugin_info['settings_form'] = $form;
|
||||||
|
|
||||||
|
//set the templates that are going to be used
|
||||||
|
$plugin_info['templates'] = ['template.tpl'];
|
||||||
15
plugin/add_shibboleth_login_button/template.tpl
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
{% if add_shibboleth_login_button.show_message %}
|
||||||
|
<link href="{{ _p.web_plugin }}add_shibboleth_login_button/css.css" rel="stylesheet" type="text/css">
|
||||||
|
<div class="well">
|
||||||
|
{% if add_shibboleth_login_button.url_label %}
|
||||||
|
<img src="{{ add_shibboleth_login_button.url_label }}" class='shibboleth_plugin_image'/>
|
||||||
|
{% endif %}
|
||||||
|
<h4>{{ add_shibboleth_login_button.button_label }}</h4>
|
||||||
|
{% if add_shibboleth_login_button.url_label %}
|
||||||
|
<div class='shibboleth_plugin_clear'> </div>
|
||||||
|
{% endif %}
|
||||||
|
<div class='shibboleth_plugin_comm'>{{ add_shibboleth_login_button.comm_label }}</div>
|
||||||
|
<button class="btn btn-default" onclick="javascript:self.location.href='main/auth/shibboleth/login.php'">{{ "LoginEnter"|get_lang }}</button>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
59
plugin/advanced_subscription/README.md
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
Advanced subscription plugin for Chamilo LMS
|
||||||
|
=======================================
|
||||||
|
Plugin to manage the registration queue and communication to sessions
|
||||||
|
from an external website creating a queue to control session subscription
|
||||||
|
and sending emails to approve student subscription requests
|
||||||
|
|
||||||
|
# Requirements
|
||||||
|
Chamilo LMS 1.10.0 or greater
|
||||||
|
|
||||||
|
# Settings
|
||||||
|
|
||||||
|
These settings have to be configured in the Configuration screen for the plugin
|
||||||
|
|
||||||
|
Parameters | Description
|
||||||
|
------------- |-------------
|
||||||
|
Webservice url | Url to external website to get user profile (SOAP)
|
||||||
|
Induction requirement | Checkbox to enable induction as requirement
|
||||||
|
Courses count limit | Number of times a student is allowed at most to course by year
|
||||||
|
Yearly hours limit | Teaching hours a student is allowed at most to course by year
|
||||||
|
Yearly cost unit converter | The cost of a taxation unit value (TUV)
|
||||||
|
Yearly cost limit | Number of TUV student courses is allowed at most to cost by year
|
||||||
|
Year start date | Date (dd/mm) when the year limit is renewed
|
||||||
|
Minimum percentage profile | Minimum percentage required from external website profile
|
||||||
|
|
||||||
|
# Hooks
|
||||||
|
|
||||||
|
This plugin uses the following hooks (defined since Chamilo LMS 1.10.0):
|
||||||
|
|
||||||
|
* HookAdminBlock
|
||||||
|
* HookWSRegistration
|
||||||
|
* HookNotificationContent
|
||||||
|
* HookNotificationTitle
|
||||||
|
|
||||||
|
|
||||||
|
# Web services
|
||||||
|
|
||||||
|
This plugin also enables new webservices that can be used from registration.soap.php
|
||||||
|
|
||||||
|
* HookAdvancedSubscription..WSSessionListInCategory
|
||||||
|
* HookAdvancedSubscription..WSSessionGetDetailsByUser
|
||||||
|
* HookAdvancedSubscription..WSListSessionsDetailsByCategory
|
||||||
|
|
||||||
|
See `/plugin/advanced_subscription/src/HookAdvancedSubscription.php` to check Web services inputs and outputs
|
||||||
|
|
||||||
|
# How does this plugin works?
|
||||||
|
|
||||||
|
After install, fill the required parameters (described above)
|
||||||
|
Use web services to communicate course session inscription from external website
|
||||||
|
This allows students to search course sessions and subscribe if they match
|
||||||
|
the requirements.
|
||||||
|
|
||||||
|
The normal process is:
|
||||||
|
* Student searches course session
|
||||||
|
* Student reads session info depending student data
|
||||||
|
* Student requests to be subscribed
|
||||||
|
* A confirmation email is sent to student
|
||||||
|
* An authorization email is sent to student's superior (STUDENT BOSS role) or admins (when there is no superior) who will accept or reject the student request
|
||||||
|
* When the superior accepts or rejects, an email will be sent to the student and superior (or admin), respectively
|
||||||
|
* To complete the subscription, the request must be validated and accepted by an admin
|
||||||
350
plugin/advanced_subscription/ajax/advanced_subscription.ajax.php
Normal file
@@ -0,0 +1,350 @@
|
|||||||
|
<?php
|
||||||
|
/* For licensing terms, see /license.txt */
|
||||||
|
/**
|
||||||
|
* Script to receipt request to subscribe and confirmation action to queue.
|
||||||
|
*
|
||||||
|
* @author Daniel Alejandro Barreto Alva <daniel.barreto@beeznest.com>
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.advanced_subscription
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* 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['action'] = Security::remove_XSS($_REQUEST['a']);
|
||||||
|
$data['sessionId'] = intval($_REQUEST['s']);
|
||||||
|
$data['currentUserId'] = intval($_REQUEST['current_user_id']);
|
||||||
|
$data['studentUserId'] = intval($_REQUEST['u']);
|
||||||
|
$data['queueId'] = intval($_REQUEST['q']);
|
||||||
|
$data['newStatus'] = intval($_REQUEST['e']);
|
||||||
|
// Student always is connected
|
||||||
|
// $data['is_connected'] = isset($_REQUEST['is_connected']) ? boolval($_REQUEST['is_connected']) : false;
|
||||||
|
$data['is_connected'] = true;
|
||||||
|
$data['profile_completed'] = isset($_REQUEST['profile_completed']) ? floatval($_REQUEST['profile_completed']) : 0;
|
||||||
|
$data['accept_terms'] = isset($_REQUEST['accept_terms']) ? intval($_REQUEST['accept_terms']) : 0;
|
||||||
|
$data['courseId'] = isset($_REQUEST['c']) ? intval($_REQUEST['c']) : 0;
|
||||||
|
// Init result array
|
||||||
|
$result = ['error' => true, 'errorMessage' => get_lang('ThereWasAnError')];
|
||||||
|
$showJSON = true;
|
||||||
|
// Check if data is valid or is for start subscription
|
||||||
|
$verified = $plugin->checkHash($data, $hash) || $data['action'] == 'subscribe';
|
||||||
|
if ($verified) {
|
||||||
|
switch ($data['action']) {
|
||||||
|
case 'check': // Check minimum requirements
|
||||||
|
try {
|
||||||
|
$res = AdvancedSubscriptionPlugin::create()->isAllowedToDoRequest($data['studentUserId'], $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['studentUserId'],
|
||||||
|
$data['sessionId'],
|
||||||
|
$data
|
||||||
|
);
|
||||||
|
// Check if queue subscription was successful
|
||||||
|
if ($res === true) {
|
||||||
|
$legalEnabled = api_get_plugin_setting('courselegal', 'tool_enable');
|
||||||
|
if ($legalEnabled) {
|
||||||
|
// Save terms confirmation
|
||||||
|
CourseLegalPlugin::create()->saveUserLegal(
|
||||||
|
$data['studentUserId'],
|
||||||
|
$data['courseId'],
|
||||||
|
$data['sessionId'],
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Prepare data
|
||||||
|
// Get session data
|
||||||
|
// Assign variables
|
||||||
|
$fieldsArray = [
|
||||||
|
'description',
|
||||||
|
'target',
|
||||||
|
'mode',
|
||||||
|
'publication_end_date',
|
||||||
|
'recommended_number_of_participants',
|
||||||
|
];
|
||||||
|
$sessionArray = api_get_session_info($data['sessionId']);
|
||||||
|
$extraSession = new ExtraFieldValue('session');
|
||||||
|
$extraField = new ExtraField('session');
|
||||||
|
// Get session fields
|
||||||
|
$fieldList = $extraField->get_all([
|
||||||
|
'variable IN ( ?, ?, ?, ?, ?)' => $fieldsArray,
|
||||||
|
]);
|
||||||
|
// Index session fields
|
||||||
|
foreach ($fieldList as $field) {
|
||||||
|
$fields[$field['id']] = $field['variable'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$mergedArray = array_merge([$data['sessionId']], array_keys($fields));
|
||||||
|
$sessionFieldValueList = $extraSession->get_all(
|
||||||
|
[
|
||||||
|
'item_id = ? field_id IN ( ?, ?, ?, ?, ?, ?, ? )' => $mergedArray,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
foreach ($sessionFieldValueList as $sessionFieldValue) {
|
||||||
|
// Check if session field value is set in session field list
|
||||||
|
if (isset($fields[$sessionFieldValue['field_id']])) {
|
||||||
|
$var = $fields[$sessionFieldValue['field_id']];
|
||||||
|
$val = $sessionFieldValue['value'];
|
||||||
|
// Assign session field value to session
|
||||||
|
$sessionArray[$var] = $val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Get student data
|
||||||
|
$studentArray = api_get_user_info($data['studentUserId']);
|
||||||
|
$studentArray['picture'] = $studentArray['avatar'];
|
||||||
|
|
||||||
|
// Get superior data if exist
|
||||||
|
$superiorId = UserManager::getFirstStudentBoss($data['studentUserId']);
|
||||||
|
if (!empty($superiorId)) {
|
||||||
|
$superiorArray = api_get_user_info($superiorId);
|
||||||
|
} else {
|
||||||
|
$superiorArray = null;
|
||||||
|
}
|
||||||
|
// Get admin data
|
||||||
|
$adminsArray = UserManager::get_all_administrators();
|
||||||
|
$isWesternNameOrder = api_is_western_name_order();
|
||||||
|
foreach ($adminsArray as &$admin) {
|
||||||
|
$admin['complete_name'] = $isWesternNameOrder ?
|
||||||
|
$admin['firstname'].', '.$admin['lastname'] : $admin['lastname'].', '.$admin['firstname']
|
||||||
|
;
|
||||||
|
}
|
||||||
|
unset($admin);
|
||||||
|
// Set data
|
||||||
|
$data['action'] = '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, ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_APPROVED);
|
||||||
|
if (!empty($res)) {
|
||||||
|
// Prepare admin url
|
||||||
|
$data['admin_view_url'] = api_get_path(WEB_PLUGIN_PATH).
|
||||||
|
'advanced_subscription/src/admin_view.php?s='.$data['sessionId'];
|
||||||
|
// Send mails
|
||||||
|
$result['mailIds'] = $plugin->sendMail(
|
||||||
|
$data,
|
||||||
|
ADVANCED_SUBSCRIPTION_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
|
||||||
|
$url = $plugin->getRenderMailUrl(['queueId' => $result['mailIds']['render']]);
|
||||||
|
header('Location: '.$url);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Student boss does exist
|
||||||
|
// Get url to be accepted by boss
|
||||||
|
$data['newStatus'] = ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_APPROVED;
|
||||||
|
$data['student']['acceptUrl'] = $plugin->getQueueUrl($data);
|
||||||
|
// Get url to be rejected by boss
|
||||||
|
$data['newStatus'] = ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_DISAPPROVED;
|
||||||
|
$data['student']['rejectUrl'] = $plugin->getQueueUrl($data);
|
||||||
|
// Send mails
|
||||||
|
$result['mailIds'] = $plugin->sendMail($data, ADVANCED_SUBSCRIPTION_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
|
||||||
|
$url = $plugin->getRenderMailUrl(['queueId' => $result['mailIds']['render']]);
|
||||||
|
header('Location: '.$url);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$lastMessageId = $plugin->getLastMessageId($data['studentUserId'], $data['sessionId']);
|
||||||
|
if ($lastMessageId !== false) {
|
||||||
|
// Render mail
|
||||||
|
$url = $plugin->getRenderMailUrl(['queueId' => $lastMessageId]);
|
||||||
|
header('Location: '.$url);
|
||||||
|
exit;
|
||||||
|
} else {
|
||||||
|
if (is_string($res)) {
|
||||||
|
$result['errorMessage'] = $res;
|
||||||
|
} else {
|
||||||
|
$result['errorMessage'] = 'User can not be subscribed';
|
||||||
|
}
|
||||||
|
$result['pass'] = false;
|
||||||
|
$url = $plugin->getTermsUrl($data, ADVANCED_SUBSCRIPTION_TERMS_MODE_FINAL);
|
||||||
|
header('Location: '.$url);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'confirm':
|
||||||
|
// Check if new status is set
|
||||||
|
if (isset($data['newStatus'])) {
|
||||||
|
if ($data['newStatus'] === ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_APPROVED) {
|
||||||
|
try {
|
||||||
|
$isAllowToDoRequest = $plugin->isAllowedToDoRequest($data['studentUserId'], $data);
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
$messageTemplate = new Template(null, false, false);
|
||||||
|
$messageTemplate->assign(
|
||||||
|
'content',
|
||||||
|
Display::return_message($ex->getMessage(), 'error', false)
|
||||||
|
);
|
||||||
|
$messageTemplate->display_no_layout_template();
|
||||||
|
$showJSON = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update queue status
|
||||||
|
$res = $plugin->updateQueueStatus($data, $data['newStatus']);
|
||||||
|
if ($res === true) {
|
||||||
|
// Prepare data
|
||||||
|
// Prepare session data
|
||||||
|
$fieldsArray = [
|
||||||
|
'description',
|
||||||
|
'target',
|
||||||
|
'mode',
|
||||||
|
'publication_end_date',
|
||||||
|
'recommended_number_of_participants',
|
||||||
|
];
|
||||||
|
$sessionArray = api_get_session_info($data['sessionId']);
|
||||||
|
$extraSession = new ExtraFieldValue('session');
|
||||||
|
$extraField = new ExtraField('session');
|
||||||
|
// Get session fields
|
||||||
|
$fieldList = $extraField->get_all([
|
||||||
|
'variable IN ( ?, ?, ?, ?, ?)' => $fieldsArray,
|
||||||
|
]);
|
||||||
|
// Index session fields
|
||||||
|
foreach ($fieldList as $field) {
|
||||||
|
$fields[$field['id']] = $field['variable'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$mergedArray = array_merge([$data['sessionId']], array_keys($fields));
|
||||||
|
$sessionFieldValueList = $extraSession->get_all(
|
||||||
|
['session_id = ? field_id IN ( ?, ?, ?, ?, ?, ?, ? )' => $mergedArray]
|
||||||
|
);
|
||||||
|
foreach ($sessionFieldValueList as $sessionFieldValue) {
|
||||||
|
// Check if session field value is set in session field list
|
||||||
|
if (isset($fields[$sessionFieldValue['field_id']])) {
|
||||||
|
$var = $fields[$sessionFieldValue['field_id']];
|
||||||
|
$val = $sessionFieldValue['value'];
|
||||||
|
// Assign session field value to session
|
||||||
|
$sessionArray[$var] = $val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Prepare student data
|
||||||
|
$studentArray = api_get_user_info($data['studentUserId']);
|
||||||
|
$studentArray['picture'] = $studentArray['avatar'];
|
||||||
|
// Prepare superior data
|
||||||
|
$superiorId = UserManager::getFirstStudentBoss($data['studentUserId']);
|
||||||
|
if (!empty($superiorId)) {
|
||||||
|
$superiorArray = api_get_user_info($superiorId);
|
||||||
|
} else {
|
||||||
|
$superiorArray = null;
|
||||||
|
}
|
||||||
|
// Prepare admin data
|
||||||
|
$adminsArray = UserManager::get_all_administrators();
|
||||||
|
$isWesternNameOrder = api_is_western_name_order();
|
||||||
|
foreach ($adminsArray as &$admin) {
|
||||||
|
$admin['complete_name'] = $isWesternNameOrder ?
|
||||||
|
$admin['firstname'].', '.$admin['lastname'] : $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)
|
||||||
|
.'advanced_subscription/src/admin_view.php?s='.$data['sessionId'];
|
||||||
|
// Check if exist and action in data
|
||||||
|
if (empty($data['mailAction'])) {
|
||||||
|
// set action in data by new status
|
||||||
|
switch ($data['newStatus']) {
|
||||||
|
case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_APPROVED:
|
||||||
|
$data['mailAction'] = ADVANCED_SUBSCRIPTION_ACTION_SUPERIOR_APPROVE;
|
||||||
|
break;
|
||||||
|
case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_DISAPPROVED:
|
||||||
|
$data['mailAction'] = ADVANCED_SUBSCRIPTION_ACTION_SUPERIOR_DISAPPROVE;
|
||||||
|
break;
|
||||||
|
case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_APPROVED:
|
||||||
|
$data['mailAction'] = ADVANCED_SUBSCRIPTION_ACTION_ADMIN_APPROVE;
|
||||||
|
break;
|
||||||
|
case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_DISAPPROVED:
|
||||||
|
$data['mailAction'] = ADVANCED_SUBSCRIPTION_ACTION_ADMIN_DISAPPROVE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Student Session inscription
|
||||||
|
if ($data['newStatus'] == ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_APPROVED) {
|
||||||
|
SessionManager::subscribeUsersToSession(
|
||||||
|
$data['sessionId'],
|
||||||
|
[$data['studentUserId']],
|
||||||
|
null,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send mails
|
||||||
|
$result['mailIds'] = $plugin->sendMail($data, $data['mailAction']);
|
||||||
|
// 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
|
||||||
|
$url = $plugin->getRenderMailUrl(['queueId' => $result['mailIds']['render']]);
|
||||||
|
header('Location: '.$url);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$result['errorMessage'] = 'User queue can not be updated';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$result['errorMessage'] = 'This action does not exist!';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($showJSON) {
|
||||||
|
// Echo result as json
|
||||||
|
echo json_encode($result);
|
||||||
|
}
|
||||||
35
plugin/advanced_subscription/config.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
/* For licensing terms, see /license.txt */
|
||||||
|
/**
|
||||||
|
* Config the plugin.
|
||||||
|
*
|
||||||
|
* @author Daniel Alejandro Barreto Alva <daniel.barreto@beeznest.com>
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.advanced_subscription
|
||||||
|
*/
|
||||||
|
define('TABLE_ADVANCED_SUBSCRIPTION_QUEUE', 'plugin_advanced_subscription_queue');
|
||||||
|
|
||||||
|
define('ADVANCED_SUBSCRIPTION_ACTION_STUDENT_REQUEST', 0);
|
||||||
|
define('ADVANCED_SUBSCRIPTION_ACTION_SUPERIOR_APPROVE', 1);
|
||||||
|
define('ADVANCED_SUBSCRIPTION_ACTION_SUPERIOR_DISAPPROVE', 2);
|
||||||
|
define('ADVANCED_SUBSCRIPTION_ACTION_SUPERIOR_SELECT', 3);
|
||||||
|
define('ADVANCED_SUBSCRIPTION_ACTION_ADMIN_APPROVE', 4);
|
||||||
|
define('ADVANCED_SUBSCRIPTION_ACTION_ADMIN_DISAPPROVE', 5);
|
||||||
|
define('ADVANCED_SUBSCRIPTION_ACTION_STUDENT_REQUEST_NO_BOSS', 6);
|
||||||
|
define('ADVANCED_SUBSCRIPTION_ACTION_REMINDER_STUDENT', 7);
|
||||||
|
define('ADVANCED_SUBSCRIPTION_ACTION_REMINDER_SUPERIOR', 8);
|
||||||
|
define('ADVANCED_SUBSCRIPTION_ACTION_REMINDER_SUPERIOR_MAX', 9);
|
||||||
|
define('ADVANCED_SUBSCRIPTION_ACTION_REMINDER_ADMIN', 10);
|
||||||
|
|
||||||
|
define('ADVANCED_SUBSCRIPTION_QUEUE_STATUS_NO_QUEUE', -1);
|
||||||
|
define('ADVANCED_SUBSCRIPTION_QUEUE_STATUS_START', 0);
|
||||||
|
define('ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_DISAPPROVED', 1);
|
||||||
|
define('ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_APPROVED', 2);
|
||||||
|
define('ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_DISAPPROVED', 3);
|
||||||
|
define('ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_APPROVED', 10);
|
||||||
|
|
||||||
|
define('ADVANCED_SUBSCRIPTION_TERMS_MODE_POPUP', 0);
|
||||||
|
define('ADVANCED_SUBSCRIPTION_TERMS_MODE_REJECT', 1);
|
||||||
|
define('ADVANCED_SUBSCRIPTION_TERMS_MODE_FINAL', 2);
|
||||||
|
|
||||||
|
require_once __DIR__.'/../../main/inc/global.inc.php';
|
||||||
153
plugin/advanced_subscription/cron/notify_by_mail.php
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
<?php
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
/**
|
||||||
|
* This script generates four session categories.
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.advanced_subscription
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init.
|
||||||
|
*/
|
||||||
|
require_once __DIR__.'/../config.php';
|
||||||
|
$plugin = AdvancedSubscriptionPlugin::create();
|
||||||
|
$now = api_get_utc_datetime();
|
||||||
|
$weekAgo = api_get_utc_datetime('-1 week');
|
||||||
|
$sessionExtraField = new ExtraField('session');
|
||||||
|
$sessionExtraFieldValue = new ExtraFieldValue('session');
|
||||||
|
/**
|
||||||
|
* Get session list.
|
||||||
|
*/
|
||||||
|
$joinTables = Database::get_main_table(TABLE_MAIN_SESSION).' s INNER JOIN '.
|
||||||
|
Database::get_main_table(TABLE_MAIN_SESSION_USER).' su ON s.id = su.session_id INNER JOIN '.
|
||||||
|
Database::get_main_table(TABLE_MAIN_USER_REL_USER).' uu ON su.user_id = uu.user_id INNER JOIN '.
|
||||||
|
Database::get_main_table(TABLE_ADVANCED_SUBSCRIPTION_QUEUE).' asq ON su.session_id = asq.session_id AND su.user_id = asq.user_id';
|
||||||
|
$columns = 's.id AS session_id, uu.friend_user_id AS superior_id, uu.user_id AS student_id, asq.id AS queue_id, asq.status AS status';
|
||||||
|
$conditions = [
|
||||||
|
'where' => [
|
||||||
|
's.access_start_date >= ? AND uu.relation_type = ? AND asq.updated_at <= ?' => [
|
||||||
|
$now,
|
||||||
|
USER_RELATION_TYPE_BOSS,
|
||||||
|
$weekAgo,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'order' => 's.id',
|
||||||
|
];
|
||||||
|
|
||||||
|
$queueList = Database::select($columns, $joinTables, $conditions);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remind students.
|
||||||
|
*/
|
||||||
|
$sessionInfoList = [];
|
||||||
|
foreach ($queueList as $queueItem) {
|
||||||
|
if (!isset($sessionInfoList[$queueItem['session_id']])) {
|
||||||
|
$sessionInfoList[$queueItem['session_id']] = api_get_session_info($queueItem['session_id']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($queueList as $queueItem) {
|
||||||
|
switch ($queueItem['status']) {
|
||||||
|
case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_START:
|
||||||
|
case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_APPROVED:
|
||||||
|
$data = ['sessionId' => $queueItem['session_id']];
|
||||||
|
$data['session'] = api_get_session_info($queueItem['session_id']);
|
||||||
|
$data['student'] = api_get_user_info($queueItem['student_id']);
|
||||||
|
$plugin->sendMail($data, ADVANCED_SUBSCRIPTION_ACTION_REMINDER_STUDENT);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remind superiors.
|
||||||
|
*/
|
||||||
|
// Get recommended number of participants
|
||||||
|
$sessionRecommendedNumber = [];
|
||||||
|
foreach ($queueList as $queueItem) {
|
||||||
|
$row =
|
||||||
|
$sessionExtraFieldValue->get_values_by_handler_and_field_variable(
|
||||||
|
$queueItem['session_id'],
|
||||||
|
'recommended_number_of_participants'
|
||||||
|
);
|
||||||
|
$sessionRecommendedNumber[$queueItem['session_id']] = $row['value'];
|
||||||
|
}
|
||||||
|
// Group student by superior and session
|
||||||
|
$queueBySuperior = [];
|
||||||
|
foreach ($queueList as $queueItem) {
|
||||||
|
$queueBySuperior[$queueItem['session_id']][$queueItem['superior_id']][$queueItem['student_id']]['status'] = $queueItem['status'];
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($queueBySuperior as $sessionId => $superiorStudents) {
|
||||||
|
$data = [
|
||||||
|
'sessionId' => $sessionId,
|
||||||
|
'session' => $sessionInfoList[$sessionId],
|
||||||
|
'students' => [],
|
||||||
|
];
|
||||||
|
$dataUrl = [
|
||||||
|
'action' => 'confirm',
|
||||||
|
'sessionId' => $sessionId,
|
||||||
|
'currentUserId' => 0,
|
||||||
|
'newStatus' => ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_APPROVED,
|
||||||
|
'studentUserId' => 0,
|
||||||
|
'is_connected' => true,
|
||||||
|
'profile_completed' => 0,
|
||||||
|
];
|
||||||
|
foreach ($superiorStudents as $superiorId => $students) {
|
||||||
|
$data['superior'] = api_get_user_info($superiorId);
|
||||||
|
// Check if superior has at least one student
|
||||||
|
if (count($students) > 0) {
|
||||||
|
foreach ($students as $studentId => $studentInfo) {
|
||||||
|
if ($studentInfo['status'] == ADVANCED_SUBSCRIPTION_QUEUE_STATUS_START) {
|
||||||
|
$data['students'][$studentId] = api_get_user_info($studentId);
|
||||||
|
$dataUrl['studentUserId'] = $studentId;
|
||||||
|
$dataUrl['newStatus'] = ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_APPROVED;
|
||||||
|
$data['students'][$studentId]['acceptUrl'] = $plugin->getQueueUrl($dataUrl);
|
||||||
|
$dataUrl['newStatus'] = ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_DISAPPROVED;
|
||||||
|
$data['students'][$studentId]['rejectUrl'] = $plugin->getQueueUrl($dataUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_array($data['students']) && count($data['students']) > 0) {
|
||||||
|
// Check if superior have more than recommended
|
||||||
|
if ($sessionRecommendedNumber[$sessionId] >= count($students)) {
|
||||||
|
// Is greater or equal than recommended
|
||||||
|
$plugin->sendMail($data, ADVANCED_SUBSCRIPTION_ACTION_REMINDER_SUPERIOR);
|
||||||
|
} else {
|
||||||
|
// Is less than recommended
|
||||||
|
$plugin->sendMail($data, ADVANCED_SUBSCRIPTION_ACTION_REMINDER_SUPERIOR_MAX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remind admins.
|
||||||
|
*/
|
||||||
|
$admins = UserManager::get_all_administrators();
|
||||||
|
$isWesternNameOrder = api_is_western_name_order();
|
||||||
|
foreach ($admins as &$admin) {
|
||||||
|
$admin['complete_name'] = $isWesternNameOrder ?
|
||||||
|
$admin['firstname'].', '.$admin['lastname'] : $admin['lastname'].', '.$admin['firstname']
|
||||||
|
;
|
||||||
|
}
|
||||||
|
unset($admin);
|
||||||
|
$queueByAdmin = [];
|
||||||
|
foreach ($queueList as $queueItem) {
|
||||||
|
if ($queueItem['status'] == ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_APPROVED) {
|
||||||
|
$queueByAdmin[$queueItem['session_id']]['students'][$queueItem['student_id']]['user_id'] = $queueItem['student_id'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$data = [
|
||||||
|
'admins' => $admins,
|
||||||
|
];
|
||||||
|
foreach ($queueByAdmin as $sessionId => $studentInfo) {
|
||||||
|
$data['sessionId'] = $sessionId;
|
||||||
|
$data['admin_view_url'] = api_get_path(WEB_PLUGIN_PATH).
|
||||||
|
'advanced_subscription/src/admin_view.php?s='.$data['sessionId'];
|
||||||
|
$data['session'] = $sessionInfoList[$sessionId];
|
||||||
|
$data['students'] = $studentInfo['students'];
|
||||||
|
$plugin->sendMail($data, ADVANCED_SUBSCRIPTION_ACTION_REMINDER_ADMIN);
|
||||||
|
}
|
||||||
1
plugin/advanced_subscription/index.html
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
17
plugin/advanced_subscription/install.php
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
/**
|
||||||
|
* This script is included by main/admin/settings.lib.php and generally
|
||||||
|
* includes things to execute in the main database (settings_current table).
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.advanced_subscription
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialization.
|
||||||
|
*/
|
||||||
|
require_once __DIR__.'/config.php';
|
||||||
|
if (!api_is_platform_admin()) {
|
||||||
|
exit('You must have admin permissions to install plugins');
|
||||||
|
}
|
||||||
|
AdvancedSubscriptionPlugin::create()->install();
|
||||||
149
plugin/advanced_subscription/lang/english.php
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/* Strings for settings */
|
||||||
|
$strings['plugin_title'] = 'Advanced Subscription';
|
||||||
|
$strings['plugin_comment'] = 'Plugin for managing the registration queue and communication to sessions from an external website';
|
||||||
|
$strings['ws_url'] = 'Webservice url';
|
||||||
|
$strings['ws_url_help'] = 'The URL from which ingormation will be requested for the advanced subscription process';
|
||||||
|
$strings['check_induction'] = 'Enable induction course requirement';
|
||||||
|
$strings['check_induction_help'] = 'Check to make induction course mandatory';
|
||||||
|
$strings['yearly_cost_limit'] = 'Yearly TUV limit for courses (measured in Taxation units)';
|
||||||
|
$strings['yearly_cost_limit_help'] = "How much TUVs the student courses should cost at most.";
|
||||||
|
$strings['yearly_hours_limit'] = 'Yearly teaching hours limit for courses';
|
||||||
|
$strings['yearly_hours_limit_help'] = "How many teaching hours the student may follow by year.";
|
||||||
|
$strings['yearly_cost_unit_converter'] = 'Taxation unit value (TUV)';
|
||||||
|
$strings['yearly_cost_unit_converter_help'] = "The taxation unit value for the current year, in local currency";
|
||||||
|
$strings['courses_count_limit'] = 'Yearly courses limit';
|
||||||
|
$strings['courses_count_limit_help'] = "How many times a student can take courses. This value does <strong>not</strong> include induction courses";
|
||||||
|
$strings['course_session_credit_year_start_date'] = 'Year start date';
|
||||||
|
$strings['course_session_credit_year_start_date_help'] = "a date (dd/mm)";
|
||||||
|
$strings['min_profile_percentage'] = "Minimum required of completed percentage profile";
|
||||||
|
$strings['min_profile_percentage_help'] = "Percentage number( > 0.00 y < 100.00)";
|
||||||
|
$strings['secret_key'] = 'Secret key';
|
||||||
|
$strings['terms_and_conditions'] = 'Terms and conditions';
|
||||||
|
|
||||||
|
/* String for error message about requirements */
|
||||||
|
$strings['AdvancedSubscriptionNotConnected'] = "You are not connected to platform. Please login first";
|
||||||
|
$strings['AdvancedSubscriptionProfileIncomplete'] = "You must complete at least <strong>%d percent</strong> of your profile. You have only completed <strong>%d percent</strong> at this point";
|
||||||
|
$strings['AdvancedSubscriptionIncompleteInduction'] = "You have not yet completed induction course. Please complete it first";
|
||||||
|
$strings['AdvancedSubscriptionCostXLimitReached'] = "We are sorry, you have already reached yearly limit %s TUV cost for courses ";
|
||||||
|
$strings['AdvancedSubscriptionTimeXLimitReached'] = "We are sorry, you have already reached yearly limit %s hours for courses";
|
||||||
|
$strings['AdvancedSubscriptionCourseXLimitReached'] = "We are sorry, you have already reached yearly limit %s times for courses";
|
||||||
|
$strings['AdvancedSubscriptionNotMoreAble'] = "We are sorry, you no longer fulfills the initial conditions to subscribe this course";
|
||||||
|
$strings['AdvancedSubscriptionIncompleteParams'] = "The parameters are wrong or incomplete.";
|
||||||
|
$strings['AdvancedSubscriptionIsNotEnabled'] = "Advanced subscription is not enabled";
|
||||||
|
|
||||||
|
$strings['AdvancedSubscriptionNoQueue'] = "You are not subscribed for this course.";
|
||||||
|
$strings['AdvancedSubscriptionNoQueueIsAble'] = "You are not subscribed, but you are qualified for this course.";
|
||||||
|
$strings['AdvancedSubscriptionQueueStart'] = "Your subscription request is pending for approval by your boss, please wait attentive.";
|
||||||
|
$strings['AdvancedSubscriptionQueueBossDisapproved'] = "We are sorry, your subscription was rejected by your boss.";
|
||||||
|
$strings['AdvancedSubscriptionQueueBossApproved'] = "Your subscription request has been accepted by your boss, now is pending for vacancies.";
|
||||||
|
$strings['AdvancedSubscriptionQueueAdminDisapproved'] = "We are sorry, your subscription was rejected by the administrator.";
|
||||||
|
$strings['AdvancedSubscriptionQueueAdminApproved'] = "Congratulations!, your subscription request has been accepted by administrator.";
|
||||||
|
$strings['AdvancedSubscriptionQueueDefaultX'] = "There was an error, queue status %d is not defined by system.";
|
||||||
|
|
||||||
|
// Mail translations
|
||||||
|
$strings['MailStudentRequest'] = 'Student registration request';
|
||||||
|
$strings['MailBossAccept'] = 'Registration request accepted by boss';
|
||||||
|
$strings['MailBossReject'] = 'Registration request rejected by boss';
|
||||||
|
$strings['MailStudentRequestSelect'] = 'Student registration requests selection';
|
||||||
|
$strings['MailAdminAccept'] = 'Registration request accepted by administrator';
|
||||||
|
$strings['MailAdminReject'] = 'Registration request rejected by administrator';
|
||||||
|
$strings['MailStudentRequestNoBoss'] = 'Student registration request without boss';
|
||||||
|
$strings['MailRemindStudent'] = 'Subscription request reminder';
|
||||||
|
$strings['MailRemindSuperior'] = 'Subscription request are pending your approval';
|
||||||
|
$strings['MailRemindAdmin'] = 'Course subscription are pending your approval';
|
||||||
|
|
||||||
|
// TPL langs
|
||||||
|
$strings['SessionXWithoutVacancies'] = "The course \"%s\" has no vacancies.";
|
||||||
|
$strings['SuccessSubscriptionToSessionX'] = "<h4>¡Congratulations!</h4>Your subscription to \"%s\" course has been completed successfully.";
|
||||||
|
$strings['SubscriptionToOpenSession'] = "Subscription to open course";
|
||||||
|
$strings['GoToSessionX'] = "Go to \"%s\" course";
|
||||||
|
$strings['YouAreAlreadySubscribedToSessionX'] = "You are already subscribed to \"%s\" course.";
|
||||||
|
|
||||||
|
// Admin view
|
||||||
|
$strings['SelectASession'] = 'Select a training session';
|
||||||
|
$strings['SessionName'] = 'Session name';
|
||||||
|
$strings['Target'] = 'Target audience';
|
||||||
|
$strings['Vacancies'] = 'Vacancies';
|
||||||
|
$strings['RecommendedNumberOfParticipants'] = 'Recommended number of participants by area';
|
||||||
|
$strings['PublicationEndDate'] = 'Publication end date';
|
||||||
|
$strings['Mode'] = 'Mode';
|
||||||
|
$strings['Postulant'] = 'Postulant';
|
||||||
|
$strings['Area'] = 'Area';
|
||||||
|
$strings['Institution'] = 'Institution';
|
||||||
|
$strings['InscriptionDate'] = 'Inscription date';
|
||||||
|
$strings['BossValidation'] = 'Boss validation';
|
||||||
|
$strings['Decision'] = 'Decision';
|
||||||
|
$strings['AdvancedSubscriptionAdminViewTitle'] = 'Subscription request confirmation result';
|
||||||
|
|
||||||
|
$strings['AcceptInfinitive'] = 'Accept';
|
||||||
|
$strings['RejectInfinitive'] = 'Reject';
|
||||||
|
$strings['AreYouSureYouWantToAcceptSubscriptionOfX'] = 'Are you sure you want to accept the subscription of %s?';
|
||||||
|
$strings['AreYouSureYouWantToRejectSubscriptionOfX'] = 'Are you sure you want to reject the subscription of %s?';
|
||||||
|
|
||||||
|
$strings['MailTitle'] = 'Received request for course %s';
|
||||||
|
$strings['MailDear'] = 'Dear:';
|
||||||
|
$strings['MailThankYou'] = 'Thank you.';
|
||||||
|
$strings['MailThankYouCollaboration'] = 'Thank you for your help.';
|
||||||
|
|
||||||
|
// Admin Accept
|
||||||
|
$strings['MailTitleAdminAcceptToAdmin'] = 'Notification: subscription validation received';
|
||||||
|
$strings['MailContentAdminAcceptToAdmin'] = 'We have received and registered your subscription validation for student <strong>%s</strong> to course <strong>%s</strong>';
|
||||||
|
$strings['MailTitleAdminAcceptToStudent'] = 'Accepted: Your subscription to course %s has been accepted!';
|
||||||
|
$strings['MailContentAdminAcceptToStudent'] = 'We are pleased to inform you that your registration to course <strong>%s</strong> starting on <strong>%s</strong> was validated by an administrator. We wish you good luck and hope you will consider participating to another course soon.';
|
||||||
|
$strings['MailTitleAdminAcceptToSuperior'] = 'Notification: Subscription validation of %s to course %s';
|
||||||
|
$strings['MailContentAdminAcceptToSuperior'] = 'Subscription of student <strong>%s</strong> to course <strong>%s</strong> starting on <strong>%s</strong> was pending but has been validated a few minutes ago. We kindly hope we can count on you to ensure the necessary availability of your collaborator during the course period.';
|
||||||
|
|
||||||
|
// Admin Reject
|
||||||
|
$strings['MailTitleAdminRejectToAdmin'] = 'Notification: Rejection received';
|
||||||
|
$strings['MailContentAdminRejectToAdmin'] = 'We have received and registered your rejection for the subscription of student <strong>%s</strong> to course <strong>%s</strong>';
|
||||||
|
$strings['MailTitleAdminRejectToStudent'] = 'Your subscription to course %s was rejected';
|
||||||
|
$strings['MailContentAdminRejectToStudent'] = 'We regret to inform you that your subscription to course <strong>%s</strong> starting on <strong>%s</strong> was rejected because of a lack of vacancies. We hope you will consider participating to another course soon.';
|
||||||
|
$strings['MailTitleAdminRejectToSuperior'] = 'Notification: Subscription refusal for student %s to course %s';
|
||||||
|
$strings['MailContentAdminRejectToSuperior'] = 'The subscription of <strong>%s</strong> to course <strong>%s</strong> that you previously validated was rejected because of a lack of vacancies. Our sincere apologies.';
|
||||||
|
|
||||||
|
// Superior Accept
|
||||||
|
$strings['MailTitleSuperiorAcceptToAdmin'] = 'Approval for subscription of %s to course %s ';
|
||||||
|
$strings['MailContentSuperiorAcceptToAdmin'] = 'The subscription of student <strong>%s</strong> to course <strong>%s</strong> has been accepted by his superior. You can <a href="%s">manage subscriptions here</a>';
|
||||||
|
$strings['MailTitleSuperiorAcceptToSuperior'] = 'Confirmation: Approval received for %s';
|
||||||
|
$strings['MailContentSuperiorAcceptToSuperior'] = 'We have received and registered you validation of subscription to course <strong>%s</strong> of your collaborator <strong>%s</strong>';
|
||||||
|
$strings['MailContentSuperiorAcceptToSuperiorSecond'] = 'The subscription is now pending for a vacancies confirmation. We will keep you informed about changes of status for this subscription';
|
||||||
|
$strings['MailTitleSuperiorAcceptToStudent'] = 'Accepted: Your subscription to course %s has been approved by your superior';
|
||||||
|
$strings['MailContentSuperiorAcceptToStudent'] = 'We are pleased to inform you that your subscription to course <strong>%s</strong> has been accepted by your superior. Your inscription is now pending for a vacancies confirmation. We will notify you as soon as it is confirmed.';
|
||||||
|
|
||||||
|
// Superior Reject
|
||||||
|
$strings['MailTitleSuperiorRejectToStudent'] = 'Notification: Your subscription to course %s has been refused';
|
||||||
|
$strings['MailContentSuperiorRejectToStudent'] = 'We regret to inform your subscription to course <strong>%s</strong> was NOT accepted. We hope this will not reduce your motivation and encourage you to register to another course or, on another occasion, this same course soon.';
|
||||||
|
$strings['MailTitleSuperiorRejectToSuperior'] = 'Confirmation: Rejection of subscription received for %s';
|
||||||
|
$strings['MailContentSuperiorRejectToSuperior'] = 'We have received and registered your rejection of subscription to course <strong>%s</strong> for your collaborator <strong>%s</strong>';
|
||||||
|
|
||||||
|
// Student Request
|
||||||
|
$strings['MailTitleStudentRequestToStudent'] = 'Notification: Subscription approval received';
|
||||||
|
$strings['MailContentStudentRequestToStudent'] = 'We have received and registered your subscription request to course <strong>%s</strong> starting on <strong>%s</strong>';
|
||||||
|
$strings['MailContentStudentRequestToStudentSecond'] = 'Your subscription is pending approval, first from your superior, then for the availability of vacancies. An email has been sent to your superior for review and approval. We will inform you when this situation changes.';
|
||||||
|
$strings['MailTitleStudentRequestToSuperior'] = 'Course subscription request from your collaborator';
|
||||||
|
$strings['MailContentStudentRequestToSuperior'] = 'We have received an subscription request of <strong>%s</strong> to course <strong>%s</strong>, starting on <strong>%s</strong>. Course details: <strong>%s</strong>.';
|
||||||
|
$strings['MailContentStudentRequestToSuperiorSecond'] = 'Your are welcome to accept or reject this subscription, clicking the corresponding button.';
|
||||||
|
|
||||||
|
// Student Request No Boss
|
||||||
|
$strings['MailTitleStudentRequestNoSuperiorToStudent'] = 'Your subscription request for %s has been received';
|
||||||
|
$strings['MailContentStudentRequestNoSuperiorToStudent'] = 'We have received and registered your subscription to course <strong>%s</strong> starting on <strong>%s</strong>.';
|
||||||
|
$strings['MailContentStudentRequestNoSuperiorToStudentSecond'] = 'Your subscription is pending availability of vacancies. You will get the results of your request approval (or rejection) soon.';
|
||||||
|
$strings['MailTitleStudentRequestNoSuperiorToAdmin'] = 'Subscription request of %s to course %s';
|
||||||
|
$strings['MailContentStudentRequestNoSuperiorToAdmin'] = 'The subscription of <strong>%s</strong> to course <strong>%s</strong> has been approved by default (no direct superior defined). You can <a href="%s">manage subscriptions here</strong></a>';
|
||||||
|
|
||||||
|
// Reminders
|
||||||
|
$strings['MailTitleReminderAdmin'] = 'Subscriptions to %s are pending confirmation';
|
||||||
|
$strings['MailContentReminderAdmin'] = 'The subscription requests for course <strong>%s</strong> are pending validation to be accepted. Please, go to <a href="%s">Administration page</a> to validate them.';
|
||||||
|
$strings['MailTitleReminderStudent'] = 'Information: Your subscription request is pending approval for course %s';
|
||||||
|
$strings['MailContentReminderStudent'] = 'This email is just to confirm we have received and registered your subscription request to course <strong>%s</strong>, starting on <strong>%s</strong>.';
|
||||||
|
$strings['MailContentReminderStudentSecond'] = 'Your subscription has not been approved by your superior yet, so we sent him a e-mail reminder.';
|
||||||
|
$strings['MailTitleReminderSuperior'] = 'Course subscription request for your collaborators';
|
||||||
|
$strings['MailContentReminderSuperior'] = 'We kindly remind you that we have received the subscription requests below to course <strong>%s</strong> from your collaborators. This course is starting on <strong>%s</strong>. Course details: <strong>%s</strong>.';
|
||||||
|
$strings['MailContentReminderSuperiorSecond'] = 'We invite you to accept or reject this subscription request by clicking the corresponding button for each collaborator.';
|
||||||
|
$strings['MailTitleReminderMaxSuperior'] = 'Reminder: Course subscription request for your collaborators';
|
||||||
|
$strings['MailContentReminderMaxSuperior'] = 'We kindly remind you that we have received the subscription requests below to course <strong>%s</strong> from your collaborators. This course is starting on <strong>%s</strong>. Course details: <strong>%s</strong>.';
|
||||||
|
$strings['MailContentReminderMaxSuperiorSecond'] = 'This course have limited vacancies and has received a high subscription request rate, So we recommend all areas to accept at most <strong>%s</strong> candidates. We invite you to accept or reject the inscription request by clicking the corresponding button for each collaborator.';
|
||||||
|
|
||||||
|
$strings['YouMustAcceptTermsAndConditions'] = 'To subscribe to course <strong>%s</strong>, you must accept these terms and conditions.';
|
||||||
148
plugin/advanced_subscription/lang/french.php
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/* Strings for settings */
|
||||||
|
$strings['plugin_title'] = 'Inscriptions avancées';
|
||||||
|
$strings['plugin_comment'] = 'Plugin qui permet de gérer des listes d\'attente pour l\'inscription aux sessions, avec communications avec un portail extérieur';
|
||||||
|
$strings['ws_url'] = 'URL du Service Web';
|
||||||
|
$strings['ws_url_help'] = 'L\'URL depuis laquelle l\'information est requise pour le processus d\'inscription avancée';
|
||||||
|
$strings['check_induction'] = 'Activer le cours d\'induction comme pré-requis';
|
||||||
|
$strings['check_induction_help'] = 'Décidez s\'il est nécessaire de compléter les cours d\'induction';
|
||||||
|
$strings['yearly_cost_limit'] = 'Límite d\'unités de taxe';
|
||||||
|
$strings['yearly_cost_limit_help'] = "La limite d\'unités de taxe à utiliser pour des cours dans l\'année calendrier actuelle.";
|
||||||
|
$strings['yearly_hours_limit'] = 'Límite d\'heures académiques';
|
||||||
|
$strings['yearly_hours_limit_help'] = "La límite d\'heures académiques de cours qui peuvent être suivies en une année calendrier.";
|
||||||
|
$strings['yearly_cost_unit_converter'] = 'Valeur d\'une unité de taxe';
|
||||||
|
$strings['yearly_cost_unit_converter_help'] = "La valeur en devise locale d\'une unité de taxe de l\'année actuelle.";
|
||||||
|
$strings['courses_count_limit'] = 'Límite de sessions';
|
||||||
|
$strings['courses_count_limit_help'] = "La límite de nombre de cours (sessions) qui peuvent être suivis durant une année calendrier et qui <strong>ne sont pas</strong> le cours d'induction";
|
||||||
|
$strings['course_session_credit_year_start_date'] = 'Date de début';
|
||||||
|
$strings['course_session_credit_year_start_date_help'] = "Date de début de l'année (jour/mois)";
|
||||||
|
$strings['min_profile_percentage'] = 'Pourcentage du profil complété mínimum requis';
|
||||||
|
$strings['min_profile_percentage_help'] = 'Numéro pourcentage ( > 0.00 et < 100.00)';
|
||||||
|
$strings['secret_key'] = 'Clef secrète';
|
||||||
|
$strings['terms_and_conditions'] = 'Conditions d\'utilisation';
|
||||||
|
|
||||||
|
/* String for error message about requirements */
|
||||||
|
$strings['AdvancedSubscriptionNotConnected'] = "Vous n'êtes pas connecté à la plateforme. Merci d'introduire votre nom d'utilisateur / mot de passe afin de vous inscrire";
|
||||||
|
$strings['AdvancedSubscriptionProfileIncomplete'] = "Vous devez d'abord compléter votre profil <strong>à %d pourcents</strong> ou plus. Pour l'instant vous n'avez complété que <strong>%d pourcents</strong>";
|
||||||
|
$strings['AdvancedSubscriptionIncompleteInduction'] = "Vous n'avez pas encore passé le cours d'induction. Merci de commencer par cette étape.";
|
||||||
|
$strings['AdvancedSubscriptionCostXLimitReached'] = "Désolé, vous avez déjà atteint la limite de %s unités de taxe pour les cours que vous avez suivi cette année";
|
||||||
|
$strings['AdvancedSubscriptionTimeXLimitReached'] = "Désolé, vous avez déjà atteint la limite annuelle du nombre de %s heures pour les cours que vous avez suivi cette année";
|
||||||
|
$strings['AdvancedSubscriptionCourseXLimitReached'] = "Désolé, vous avez déjà atteint la limite annuelle du nombre de cours (%s) à suivre cette année";
|
||||||
|
$strings['AdvancedSubscriptionNotMoreAble'] = "Désolé, vous ne répondez plus aux conditions d'utilisation minimum pour l'inscription à un cours";
|
||||||
|
$strings['AdvancedSubscriptionIncompleteParams'] = "Les paramètres envoyés ne sont pas complets ou sont incorrects.";
|
||||||
|
$strings['AdvancedSubscriptionIsNotEnabled'] = "L'inscription avancée n'est pas activée";
|
||||||
|
$strings['AdvancedSubscriptionNoQueue'] = "Vous n'êtes pas inscrit dans ce cours";
|
||||||
|
$strings['AdvancedSubscriptionNoQueueIsAble'] = "Vous n'êtes pas inscrit mais vous qualifiez pour ce cours";
|
||||||
|
$strings['AdvancedSubscriptionQueueStart'] = "Votre demande d'inscription est en attente de l'approbation de votre supérieur(e). Merci de patienter.";
|
||||||
|
$strings['AdvancedSubscriptionQueueBossDisapproved'] = "Désolé, votre inscription a été déclinée par votre supérieur(e).";
|
||||||
|
$strings['AdvancedSubscriptionQueueBossApproved'] = "Votre demande d'inscription a été acceptée par votre supérieur(e), mais est en attente de places libres.";
|
||||||
|
$strings['AdvancedSubscriptionQueueAdminDisapproved'] = "Désolé, votre inscription a été déclinée par l'administrateur.";
|
||||||
|
$strings['AdvancedSubscriptionQueueAdminApproved'] = "Félicitations! Votre inscription a été acceptée par l'administrateur.";
|
||||||
|
$strings['AdvancedSubscriptionQueueDefaultX'] = "Une erreur est survenue: l'état de la file d'attente %s n'est pas défini dans le système.";
|
||||||
|
|
||||||
|
// Mail translations
|
||||||
|
$strings['MailStudentRequest'] = 'Demange d\'inscription d\'un(e) apprenant(e)';
|
||||||
|
$strings['MailBossAccept'] = 'Demande d\'inscription acceptée par votre supérieur(e)';
|
||||||
|
$strings['MailBossReject'] = 'Demande d\'inscription déclinée par votre supérieur(e)';
|
||||||
|
$strings['MailStudentRequestSelect'] = 'Sélection des demandes d\'inscriptions d\'apprenants';
|
||||||
|
$strings['MailAdminAccept'] = 'Demande d\'inscription acceptée par l\'administrateur';
|
||||||
|
$strings['MailAdminReject'] = 'Demande d\'inscription déclinée par l\'administrateur';
|
||||||
|
$strings['MailStudentRequestNoBoss'] = 'Demande d\'inscription d\'apprenant sans supérieur(e)';
|
||||||
|
$strings['MailRemindStudent'] = 'Rappel de demande d\'inscription';
|
||||||
|
$strings['MailRemindSuperior'] = 'Demandes d\'inscription en attente de votre approbation';
|
||||||
|
$strings['MailRemindAdmin'] = 'Inscriptions en attente de votre approbation';
|
||||||
|
|
||||||
|
// TPL translations
|
||||||
|
$strings['SessionXWithoutVacancies'] = "Le cours \"%s\" ne dispose plus de places libres.";
|
||||||
|
$strings['SuccessSubscriptionToSessionX'] = "<h4>Félicitations!</h4> Votre inscription au cours \"%s\" est en ordre.";
|
||||||
|
$strings['SubscriptionToOpenSession'] = "Inscription à cours ouvert";
|
||||||
|
$strings['GoToSessionX'] = "Aller dans le cours \"%s\"";
|
||||||
|
$strings['YouAreAlreadySubscribedToSessionX'] = "Vous êtes déjà inscrit(e) au cours \"%s\".";
|
||||||
|
|
||||||
|
// Admin view
|
||||||
|
$strings['SelectASession'] = 'Sélectionnez une session de formation';
|
||||||
|
$strings['SessionName'] = 'Nom de la session';
|
||||||
|
$strings['Target'] = 'Public cible';
|
||||||
|
$strings['Vacancies'] = 'Places libres';
|
||||||
|
$strings['RecommendedNumberOfParticipants'] = 'Nombre recommandé de participants par département';
|
||||||
|
$strings['PublicationEndDate'] = 'Date de fin de publication';
|
||||||
|
$strings['Mode'] = 'Modalité';
|
||||||
|
$strings['Postulant'] = 'Candidats';
|
||||||
|
$strings['Area'] = 'Département';
|
||||||
|
$strings['Institution'] = 'Institution';
|
||||||
|
$strings['InscriptionDate'] = 'Date d\'inscription';
|
||||||
|
$strings['BossValidation'] = 'Validation du supérieur';
|
||||||
|
$strings['Decision'] = 'Décision';
|
||||||
|
$strings['AdvancedSubscriptionAdminViewTitle'] = 'Résultat de confirmation de demande d\'inscription';
|
||||||
|
|
||||||
|
$strings['AcceptInfinitive'] = 'Accepter';
|
||||||
|
$strings['RejectInfinitive'] = 'Refuser';
|
||||||
|
$strings['AreYouSureYouWantToAcceptSubscriptionOfX'] = 'Êtes-vous certain de vouloir accepter l\'inscription de %s?';
|
||||||
|
$strings['AreYouSureYouWantToRejectSubscriptionOfX'] = 'Êtes-vous certain de vouloir refuser l\'inscription de %s?';
|
||||||
|
|
||||||
|
$strings['MailTitle'] = 'Demande reçue pour le cours %s';
|
||||||
|
$strings['MailDear'] = 'Cher/Chère';
|
||||||
|
$strings['MailThankYou'] = 'Merci.';
|
||||||
|
$strings['MailThankYouCollaboration'] = 'Merci de votre collaboration.';
|
||||||
|
|
||||||
|
// Admin Accept
|
||||||
|
$strings['MailTitleAdminAcceptToAdmin'] = 'Information: Validation d\'inscription reçue';
|
||||||
|
$strings['MailContentAdminAcceptToAdmin'] = 'Nous avons bien reçu et enregistré votre validation de l\'inscription de <strong>%s</strong> au cours <strong>%s</strong>';
|
||||||
|
$strings['MailTitleAdminAcceptToStudent'] = 'Approuvé(e): Votre inscription au cours %s a été confirmée!';
|
||||||
|
$strings['MailContentAdminAcceptToStudent'] = 'C\'est avec plaisir que nous vous informons que votre inscription au cours <strong>%s</strong> démarrant le <strong>%s</strong> a été validée par les administrateurs. Nous espérons que votre motivation s\'est maintenue à 100% et que vous participerez à d\'autres cours ou répétiez ce cours à l\'avenir.';
|
||||||
|
$strings['MailTitleAdminAcceptToSuperior'] = 'Information: Validation de l\'inscription de %s au cours %s';
|
||||||
|
$strings['MailContentAdminAcceptToSuperior'] = 'L\'inscription de <strong>%s</strong> au cours <strong>%s</strong> qui démarre le <strong>%s</strong>, qui était en attente de validation par les organisateurs du cours, vient d\'être validée. Nous espérons que vous nous donnerez un coup de main pour assurer la disponibilité complète de votre collaborateur pour toute la durée du cours';
|
||||||
|
|
||||||
|
// Admin Reject
|
||||||
|
$strings['MailTitleAdminRejectToAdmin'] = 'Information: refus d\'inscription reçu';
|
||||||
|
$strings['MailContentAdminRejectToAdmin'] = 'Nous avons bien reçu et enregistré votre refus pour l\'inscription de <strong>%s</strong> au cours <strong>%s</strong>';
|
||||||
|
$strings['MailTitleAdminRejectToStudent'] = 'Votre demande d\'inscription au cours %s a été refusée';
|
||||||
|
$strings['MailContentAdminRejectToStudent'] = 'Nous déplorons le besoin de vous informer que vote demande d\'inscription au cours <strong>%s</strong> démarrant le <strong>%s</strong> a été refusée pour manque de place. Nous espérons que vous maintiendrez votre motivation et que vous pourrez participer au même ou à un autre cours lors d\'une prochaine occasion.';
|
||||||
|
$strings['MailTitleAdminRejectToSuperior'] = 'Information: Refus d\'inscription de %s au cours %s';
|
||||||
|
$strings['MailContentAdminRejectToSuperior'] = 'L\'inscription de <strong>%s</strong> au cours <strong>%s</strong>, qui avait été approuvée antérieurement, a été refusée par manque de place. Nous vous présentons nos excuses sincères.';
|
||||||
|
|
||||||
|
// Superior Accept
|
||||||
|
$strings['MailTitleSuperiorAcceptToAdmin'] = 'Aprobación de %s al curso %s ';
|
||||||
|
$strings['MailContentSuperiorAcceptToAdmin'] = 'La inscripción del alumno <strong>%s</strong> al curso <strong>%s</strong> ha sido aprobada por su superior. Puede gestionar las inscripciones al curso <a href="%s"><strong>aquí</strong></a>';
|
||||||
|
$strings['MailTitleSuperiorAcceptToSuperior'] = 'Confirmación: Aprobación recibida para %s';
|
||||||
|
$strings['MailContentSuperiorAcceptToSuperior'] = 'Hemos recibido y registrado su decisión de aprobar el curso <strong>%s</strong> para su colaborador <strong>%s</strong>';
|
||||||
|
$strings['MailContentSuperiorAcceptToSuperiorSecond'] = 'Ahora la inscripción al curso está pendiente de la disponibilidad de cupos. Le mantendremos informado sobre el resultado de esta etapa';
|
||||||
|
$strings['MailTitleSuperiorAcceptToStudent'] = 'Aprobado: Su inscripción al curso %s ha sido aprobada por su superior ';
|
||||||
|
$strings['MailContentSuperiorAcceptToStudent'] = 'Nos complace informarle que su inscripción al curso <strong>%s</strong> ha sido aprobada por su superior. Su inscripción ahora solo se encuentra pendiente de disponibilidad de cupos. Le avisaremos tan pronto como se confirme este último paso.';
|
||||||
|
|
||||||
|
// Superior Reject
|
||||||
|
$strings['MailTitleSuperiorRejectToStudent'] = 'Información: Su inscripción al curso %s ha sido rechazada ';
|
||||||
|
$strings['MailContentSuperiorRejectToStudent'] = 'Lamentamos informarle que, en esta oportunidad, su inscripción al curso <strong>%s</strong> NO ha sido aprobada. Esperamos mantenga todo su ánimo y participe en otro curso o, en otra oportunidad, a este mismo curso.';
|
||||||
|
$strings['MailTitleSuperiorRejectToSuperior'] = 'Confirmación: Desaprobación recibida para %s';
|
||||||
|
$strings['MailContentSuperiorRejectToSuperior'] = 'Hemos recibido y registrado su decisión de desaprobar el curso <strong>%s</strong> para su colaborador <strong>%s</strong>';
|
||||||
|
|
||||||
|
// Student Request
|
||||||
|
$strings['MailTitleStudentRequestToStudent'] = 'Información: Validación de inscripción recibida';
|
||||||
|
$strings['MailContentStudentRequestToStudent'] = 'Hemos recibido y registrado su solicitud de inscripción al curso <strong>%s</strong> para iniciarse el <strong>%s</strong>.';
|
||||||
|
$strings['MailContentStudentRequestToStudentSecond'] = '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.';
|
||||||
|
$strings['MailTitleStudentRequestToSuperior'] = 'Solicitud de consideración de curso para un colaborador';
|
||||||
|
$strings['MailContentStudentRequestToSuperior'] = 'Hemos recibido una solicitud de inscripción de <strong>%s</strong> al curso <strong>%s</strong>, por iniciarse el <strong>%s</strong>. Detalles del curso: <strong>%s</strong>.';
|
||||||
|
$strings['MailContentStudentRequestToSuperiorSecond'] = 'Le invitamos a aprobar o desaprobar esta inscripción, dando clic en el botón correspondiente a continuación.';
|
||||||
|
|
||||||
|
// Student Request No Boss
|
||||||
|
$strings['MailTitleStudentRequestNoSuperiorToStudent'] = 'Solicitud recibida para el curso %s';
|
||||||
|
$strings['MailContentStudentRequestNoSuperiorToStudent'] = 'Hemos recibido y registrado su solicitud de inscripción al curso <strong>%s</strong> para iniciarse el <strong>%s</strong>.';
|
||||||
|
$strings['MailContentStudentRequestNoSuperiorToStudentSecond'] = 'Su inscripción es pendiente de la disponibilidad de cupos. Pronto recibirá los resultados de su aprobación de su solicitud.';
|
||||||
|
$strings['MailTitleStudentRequestNoSuperiorToAdmin'] = 'Solicitud de inscripción de %s para el curso %s';
|
||||||
|
$strings['MailContentStudentRequestNoSuperiorToAdmin'] = 'La inscripción del alumno <strong>%s</strong> al curso <strong>%s</strong> ha sido aprobada por defecto, a falta de superior. Puede gestionar las inscripciones al curso <a href="%s"><strong>aquí</strong></a>';
|
||||||
|
|
||||||
|
// Reminders
|
||||||
|
$strings['MailTitleReminderAdmin'] = 'Inscripciones a %s pendiente de confirmación';
|
||||||
|
$strings['MailContentReminderAdmin'] = 'Las inscripciones siguientes al curso <strong>%s</strong> están pendientes de validación para ser efectivas. Por favor, dirigese a la <a href="%s">página de administración</a> para validarlos.';
|
||||||
|
$strings['MailTitleReminderStudent'] = 'Información: Solicitud pendiente de aprobación para el curso %s';
|
||||||
|
$strings['MailContentReminderStudent'] = 'Este correo es para confirmar que hemos recibido y registrado su solicitud de inscripción al curso <strong>%s</strong>, por iniciarse el <strong>%s</strong>.';
|
||||||
|
$strings['MailContentReminderStudentSecond'] = '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.';
|
||||||
|
$strings['MailTitleReminderSuperior'] = 'Solicitud de consideración de curso para un colaborador';
|
||||||
|
$strings['MailContentReminderSuperior'] = 'Le recordamos que hemos recibido las siguientes solicitudes de suscripción para el curso <strong>%s</strong> de parte de sus colaboradores. El curso se iniciará el <strong>%s</strong>. Detalles del curso: <strong>%s</strong>.';
|
||||||
|
$strings['MailContentReminderSuperiorSecond'] = 'Le invitamos a aprobar o desaprobar las suscripciones, dando clic en el botón correspondiente a continuación para cada colaborador.';
|
||||||
|
$strings['MailTitleReminderMaxSuperior'] = 'Recordatorio: Solicitud de consideración de curso para colaborador(es)';
|
||||||
|
$strings['MailContentReminderMaxSuperior'] = 'Le recordamos que hemos recibido las siguientes solicitudes de suscripción al curso <strong>%s</strong> de parte de sus colaboradores. El curso se iniciará el <strong>%s</strong>. Detalles del curso: <strong>%s</strong>.';
|
||||||
|
$strings['MailContentReminderMaxSuperiorSecond'] = 'Este curso tiene una cantidad de cupos limitados y ha recibido una alta tasa de solicitudes de inscripción, por lo que recomendamos que cada área apruebe un máximo de <strong>%s</strong> candidatos. Le invitamos a aprobar o desaprobar las suscripciones, dando clic en el botón correspondiente a continuación para cada colaborador.';
|
||||||
|
|
||||||
|
$strings['YouMustAcceptTermsAndConditions'] = 'Para inscribirse al curso <strong>%s</strong>, debe aceptar estos términos y condiciones.';
|
||||||
149
plugin/advanced_subscription/lang/spanish.php
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/* Strings for settings */
|
||||||
|
$strings['plugin_title'] = 'Inscripción Avanzada';
|
||||||
|
$strings['plugin_comment'] = 'Plugin que permite gestionar la inscripción en cola a sesiones con comunicación a a un portal externo';
|
||||||
|
$strings['ws_url'] = 'URL del Webservice';
|
||||||
|
$strings['ws_url_help'] = 'La URL de la cual se solicitará información para el proceso de la inscripción avanzada';
|
||||||
|
$strings['check_induction'] = 'Activar requerimiento de curso inducción';
|
||||||
|
$strings['check_induction_help'] = 'Escoja si se requiere que se complete los cursos de inducción';
|
||||||
|
$strings['yearly_cost_limit'] = 'Límite de UITs';
|
||||||
|
$strings['yearly_cost_limit_help'] = "El límite de UITs de cursos que se pueden llevar en un año calendario del año actual.";
|
||||||
|
$strings['yearly_hours_limit'] = 'Límite de horas lectivas';
|
||||||
|
$strings['yearly_hours_limit_help'] = "El límite de horas lectivas de cursos que se pueden llevar en un año calendario del año actual.";
|
||||||
|
$strings['yearly_cost_unit_converter'] = 'Valor de un UIT';
|
||||||
|
$strings['yearly_cost_unit_converter_help'] = "El valor en Soles de un UIT del año actual.";
|
||||||
|
$strings['courses_count_limit'] = 'Límite de sesiones';
|
||||||
|
$strings['courses_count_limit_help'] = "El límite de cantidad de cursos (sesiones) que se pueden llevar en un año calendario del año actual y que <strong>no</strong> 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)';
|
||||||
|
$strings['secret_key'] = 'LLave secreta';
|
||||||
|
$strings['terms_and_conditions'] = 'Términos y condiciones';
|
||||||
|
|
||||||
|
/* 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'] = "Debe llenar el <strong>%d porciento</strong> de tu perfil como mínimo. Por ahora has llenado el <strong>%d porciento</strong>";
|
||||||
|
$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";
|
||||||
|
|
||||||
|
$strings['AdvancedSubscriptionNoQueue'] = "Usted no está inscrito para este curso.";
|
||||||
|
$strings['AdvancedSubscriptionNoQueueIsAble'] = "Usted no está inscrito, pero está calificado para este curso.";
|
||||||
|
$strings['AdvancedSubscriptionQueueStart'] = "Su solicitud de inscripción está pendiente de la aprobación de su jefe, por favor espere atentamente.";
|
||||||
|
$strings['AdvancedSubscriptionQueueBossDisapproved'] = "Lo sentimos, tu inscripción fue rechazada por tu jefe.";
|
||||||
|
$strings['AdvancedSubscriptionQueueBossApproved'] = "Tu solicitud de inscripción ha sido aceptado por tu jefe, ahora está en espera de vacantes.";
|
||||||
|
$strings['AdvancedSubscriptionQueueAdminDisapproved'] = "Lo sentimos, Tu inscripción ha sido rechazada por el administrador.";
|
||||||
|
$strings['AdvancedSubscriptionQueueAdminApproved'] = "¡Felicitaciones! Tu inscripción ha sido aceptada por el administrador.";
|
||||||
|
$strings['AdvancedSubscriptionQueueDefaultX'] = "Hubo un error el estado en cola %d no está definido en el sistema.";
|
||||||
|
|
||||||
|
// 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';
|
||||||
|
$strings['MailRemindStudent'] = 'Recordatorio de la solicitud de inscripción';
|
||||||
|
$strings['MailRemindSuperior'] = 'Solicitudes de inscripción estan pendientes de tu aprobación';
|
||||||
|
$strings['MailRemindAdmin'] = 'Inscripciones de cursos estan pendientes de tu aprobación';
|
||||||
|
|
||||||
|
// TPL translations
|
||||||
|
$strings['SessionXWithoutVacancies'] = "El curso \"%s\" no tiene cupos disponibles.";
|
||||||
|
$strings['SuccessSubscriptionToSessionX'] = "<h4>¡Felicitaciones!</h4> Tu inscripción al curso \"%s\" se realizó correctamente.";
|
||||||
|
$strings['SubscriptionToOpenSession'] = "Inscripcion a curso abierto";
|
||||||
|
$strings['GoToSessionX'] = "Ir al curso \"%s\"";
|
||||||
|
$strings['YouAreAlreadySubscribedToSessionX'] = "Usted ya está inscrito al curso \"%s\".";
|
||||||
|
|
||||||
|
// Admin view
|
||||||
|
$strings['SelectASession'] = 'Elija una sesión de formación';
|
||||||
|
$strings['SessionName'] = 'Nombre de la sesión';
|
||||||
|
$strings['Target'] = 'Publico objetivo';
|
||||||
|
$strings['Vacancies'] = 'Vacantes';
|
||||||
|
$strings['RecommendedNumberOfParticipants'] = 'Número recomendado de participantes por área';
|
||||||
|
$strings['PublicationEndDate'] = 'Fecha fin de publicación';
|
||||||
|
$strings['Mode'] = 'Modalidad';
|
||||||
|
$strings['Postulant'] = 'Postulante';
|
||||||
|
$strings['Area'] = 'Área';
|
||||||
|
$strings['Institution'] = 'Institución';
|
||||||
|
$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';
|
||||||
|
|
||||||
|
$strings['AcceptInfinitive'] = 'Aceptar';
|
||||||
|
$strings['RejectInfinitive'] = 'Rechazar';
|
||||||
|
$strings['AreYouSureYouWantToAcceptSubscriptionOfX'] = '¿Está seguro que quiere aceptar la inscripción de %s?';
|
||||||
|
$strings['AreYouSureYouWantToRejectSubscriptionOfX'] = '¿Está seguro que quiere rechazar la inscripción de %s?';
|
||||||
|
|
||||||
|
$strings['MailTitle'] = 'Solicitud recibida para el curso %s';
|
||||||
|
$strings['MailDear'] = 'Estimado(a):';
|
||||||
|
$strings['MailThankYou'] = 'Gracias.';
|
||||||
|
$strings['MailThankYouCollaboration'] = 'Gracias por su colaboración.';
|
||||||
|
|
||||||
|
// Admin Accept
|
||||||
|
$strings['MailTitleAdminAcceptToAdmin'] = 'Información: Validación de inscripción recibida';
|
||||||
|
$strings['MailContentAdminAcceptToAdmin'] = 'Hemos recibido y registrado su validación de la inscripción de <strong>%s</strong> al curso <strong>%s</strong>';
|
||||||
|
$strings['MailTitleAdminAcceptToStudent'] = 'Aprobada: ¡Su inscripción al curso %s fue confirmada!';
|
||||||
|
$strings['MailContentAdminAcceptToStudent'] = 'Nos complace informarle que su inscripción al curso <strong>%s</strong> iniciando el <strong>%s</strong> fue validada por los administradores. Esperamos mantenga todo su ánimo y participe en otro curso o, en otra oportunidad, a este mismo curso.';
|
||||||
|
$strings['MailTitleAdminAcceptToSuperior'] = 'Información: Validación de inscripción de %s al curso %s';
|
||||||
|
$strings['MailContentAdminAcceptToSuperior'] = 'La inscripción de <strong>%s</strong> al curso <strong>%s</strong> iniciando el <strong>%s</strong>, que estaba pendiente de validación por los organizadores del curso, fue validada hacen unos minutos. Esperamos nos ayude en asegurar la completa disponibilidad de su colaborador(a) para la duración completa del curso.';
|
||||||
|
|
||||||
|
// Admin Reject
|
||||||
|
$strings['MailTitleAdminRejectToAdmin'] = 'Información: rechazo de inscripción recibido';
|
||||||
|
$strings['MailContentAdminRejectToAdmin'] = 'Hemos recibido y registrado su rechazo de la inscripción de <strong>%s</strong> al curso <strong>%s</strong>';
|
||||||
|
$strings['MailTitleAdminRejectToStudent'] = 'Rechazamos su inscripción al curso %s';
|
||||||
|
$strings['MailContentAdminRejectToStudent'] = 'Lamentamos informarle que su inscripción al curso <strong>%s</strong> iniciando el <strong>%s</strong> fue rechazada por falta de cupos. Esperamos mantenga todo su ánimo y participe en otro curso o, en otra oportunidad, a este mismo curso.';
|
||||||
|
$strings['MailTitleAdminRejectToSuperior'] = 'Información: Rechazo de inscripción de %s al curso %s';
|
||||||
|
$strings['MailContentAdminRejectToSuperior'] = 'La inscripción de <strong>%s</strong> al curso <strong>%s</strong>, que había aprobado anteriormente, fue rechazada por falta de cupos. Les presentamos nuestras disculpas sinceras.';
|
||||||
|
|
||||||
|
// Superior Accept
|
||||||
|
$strings['MailTitleSuperiorAcceptToAdmin'] = 'Aprobación de %s al curso %s ';
|
||||||
|
$strings['MailContentSuperiorAcceptToAdmin'] = 'La inscripción del alumno <strong>%s</strong> al curso <strong>%s</strong> ha sido aprobada por su superior. Puede gestionar las inscripciones al curso <a href="%s"><strong>aquí</strong></a>';
|
||||||
|
$strings['MailTitleSuperiorAcceptToSuperior'] = 'Confirmación: Aprobación recibida para %s';
|
||||||
|
$strings['MailContentSuperiorAcceptToSuperior'] = 'Hemos recibido y registrado su decisión de aprobar el curso <strong>%s</strong> para su colaborador <strong>%s</strong>';
|
||||||
|
$strings['MailContentSuperiorAcceptToSuperiorSecond'] = 'Ahora la inscripción al curso está pendiente de la disponibilidad de cupos. Le mantendremos informado sobre el resultado de esta etapa';
|
||||||
|
$strings['MailTitleSuperiorAcceptToStudent'] = 'Aprobado: Su inscripción al curso %s ha sido aprobada por su superior ';
|
||||||
|
$strings['MailContentSuperiorAcceptToStudent'] = 'Nos complace informarle que su inscripción al curso <strong>%s</strong> ha sido aprobada por su superior. Su inscripción ahora solo se encuentra pendiente de disponibilidad de cupos. Le avisaremos tan pronto como se confirme este último paso.';
|
||||||
|
|
||||||
|
// Superior Reject
|
||||||
|
$strings['MailTitleSuperiorRejectToStudent'] = 'Información: Su inscripción al curso %s ha sido rechazada ';
|
||||||
|
$strings['MailContentSuperiorRejectToStudent'] = 'Lamentamos informarle que, en esta oportunidad, su inscripción al curso <strong>%s</strong> NO ha sido aprobada. Esperamos mantenga todo su ánimo y participe en otro curso o, en otra oportunidad, a este mismo curso.';
|
||||||
|
$strings['MailTitleSuperiorRejectToSuperior'] = 'Confirmación: Desaprobación recibida para %s';
|
||||||
|
$strings['MailContentSuperiorRejectToSuperior'] = 'Hemos recibido y registrado su decisión de desaprobar el curso <strong>%s</strong> para su colaborador <strong>%s</strong>';
|
||||||
|
|
||||||
|
// Student Request
|
||||||
|
$strings['MailTitleStudentRequestToStudent'] = 'Información: Validación de inscripción recibida';
|
||||||
|
$strings['MailContentStudentRequestToStudent'] = 'Hemos recibido y registrado su solicitud de inscripción al curso <strong>%s</strong> para iniciarse el <strong>%s</strong>.';
|
||||||
|
$strings['MailContentStudentRequestToStudentSecond'] = '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.';
|
||||||
|
$strings['MailTitleStudentRequestToSuperior'] = 'Solicitud de consideración de curso para un colaborador';
|
||||||
|
$strings['MailContentStudentRequestToSuperior'] = 'Hemos recibido una solicitud de inscripción de <strong>%s</strong> al curso <strong>%s</strong>, por iniciarse el <strong>%s</strong>. Detalles del curso: <strong>%s</strong>.';
|
||||||
|
$strings['MailContentStudentRequestToSuperiorSecond'] = 'Le invitamos a aprobar o desaprobar esta inscripción, dando clic en el botón correspondiente a continuación.';
|
||||||
|
|
||||||
|
// Student Request No Boss
|
||||||
|
$strings['MailTitleStudentRequestNoSuperiorToStudent'] = 'Solicitud recibida para el curso %s';
|
||||||
|
$strings['MailContentStudentRequestNoSuperiorToStudent'] = 'Hemos recibido y registrado su solicitud de inscripción al curso <strong>%s</strong> para iniciarse el <strong>%s</strong>.';
|
||||||
|
$strings['MailContentStudentRequestNoSuperiorToStudentSecond'] = 'Su inscripción es pendiente de la disponibilidad de cupos. Pronto recibirá los resultados de su aprobación de su solicitud.';
|
||||||
|
$strings['MailTitleStudentRequestNoSuperiorToAdmin'] = 'Solicitud de inscripción de %s para el curso %s';
|
||||||
|
$strings['MailContentStudentRequestNoSuperiorToAdmin'] = 'La inscripción del alumno <strong>%s</strong> al curso <strong>%s</strong> ha sido aprobada por defecto, a falta de superior. Puede gestionar las inscripciones al curso <a href="%s"><strong>aquí</strong></a>';
|
||||||
|
|
||||||
|
// Reminders
|
||||||
|
$strings['MailTitleReminderAdmin'] = 'Inscripciones a %s pendiente de confirmación';
|
||||||
|
$strings['MailContentReminderAdmin'] = 'Las inscripciones siguientes al curso <strong>%s</strong> están pendientes de validación para ser efectivas. Por favor, dirigese a la <a href="%s">página de administración</a> para validarlos.';
|
||||||
|
$strings['MailTitleReminderStudent'] = 'Información: Solicitud pendiente de aprobación para el curso %s';
|
||||||
|
$strings['MailContentReminderStudent'] = 'Este correo es para confirmar que hemos recibido y registrado su solicitud de inscripción al curso <strong>%s</strong>, por iniciarse el <strong>%s</strong>.';
|
||||||
|
$strings['MailContentReminderStudentSecond'] = '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.';
|
||||||
|
$strings['MailTitleReminderSuperior'] = 'Solicitud de consideración de curso para un colaborador';
|
||||||
|
$strings['MailContentReminderSuperior'] = 'Le recordamos que hemos recibido las siguientes solicitudes de suscripción para el curso <strong>%s</strong> de parte de sus colaboradores. El curso se iniciará el <strong>%s</strong>. Detalles del curso: <strong>%s</strong>.';
|
||||||
|
$strings['MailContentReminderSuperiorSecond'] = 'Le invitamos a aprobar o desaprobar las suscripciones, dando clic en el botón correspondiente a continuación para cada colaborador.';
|
||||||
|
$strings['MailTitleReminderMaxSuperior'] = 'Recordatorio: Solicitud de consideración de curso para colaborador(es)';
|
||||||
|
$strings['MailContentReminderMaxSuperior'] = 'Le recordamos que hemos recibido las siguientes solicitudes de suscripción al curso <strong>%s</strong> de parte de sus colaboradores. El curso se iniciará el <strong>%s</strong>. Detalles del curso: <strong>%s</strong>.';
|
||||||
|
$strings['MailContentReminderMaxSuperiorSecond'] = 'Este curso tiene una cantidad de cupos limitados y ha recibido una alta tasa de solicitudes de inscripción, por lo que recomendamos que cada área apruebe un máximo de <strong>%s</strong> candidatos. Le invitamos a aprobar o desaprobar las suscripciones, dando clic en el botón correspondiente a continuación para cada colaborador.';
|
||||||
|
|
||||||
|
$strings['YouMustAcceptTermsAndConditions'] = 'Para inscribirse al curso <strong>%s</strong>, debe aceptar estos términos y condiciones.';
|
||||||
1
plugin/advanced_subscription/license.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
This plugin, as the rest of Chamilo, is released under the GNU/GPLv3 license.
|
||||||
13
plugin/advanced_subscription/plugin.php
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
/**
|
||||||
|
* This script is a configuration file for the date plugin. You can use it as a master for other platform plugins (course plugins are slightly different).
|
||||||
|
* These settings will be used in the administration interface for plugins (Chamilo configuration settings->Plugins).
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.advanced_subscription
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Plugin details (must be present).
|
||||||
|
*/
|
||||||
|
require_once __DIR__.'/config.php';
|
||||||
|
$plugin_info = AdvancedSubscriptionPlugin::create()->get_info();
|
||||||
1534
plugin/advanced_subscription/src/AdvancedSubscriptionPlugin.php
Normal file
681
plugin/advanced_subscription/src/HookAdvancedSubscription.php
Normal file
@@ -0,0 +1,681 @@
|
|||||||
|
<?php
|
||||||
|
/* For licensing terms, see /license.txt */
|
||||||
|
/**
|
||||||
|
* Hook Observer for Advanced subscription plugin.
|
||||||
|
*
|
||||||
|
* @author Daniel Alejandro Barreto Alva <daniel.barreto@beeznest.com>
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.advanced_subscription
|
||||||
|
*/
|
||||||
|
require_once __DIR__.'/../config.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class HookAdvancedSubscription extends the HookObserver to implements
|
||||||
|
* specific behaviour when the AdvancedSubscription plugin is enabled.
|
||||||
|
*/
|
||||||
|
class HookAdvancedSubscription extends HookObserver implements HookAdminBlockObserverInterface, HookWSRegistrationObserverInterface, HookNotificationContentObserverInterface
|
||||||
|
{
|
||||||
|
public static $plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor. Calls parent, mainly.
|
||||||
|
*/
|
||||||
|
protected function __construct()
|
||||||
|
{
|
||||||
|
self::$plugin = AdvancedSubscriptionPlugin::create();
|
||||||
|
parent::__construct(
|
||||||
|
'plugin/advanced_subscription/src/HookAdvancedSubscription.class.php',
|
||||||
|
'advanced_subscription'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function hookAdminBlock(HookAdminBlockEventInterface $hook)
|
||||||
|
{
|
||||||
|
$data = $hook->getEventData();
|
||||||
|
// if ($data['type'] === HOOK_EVENT_TYPE_PRE) // Nothing to do
|
||||||
|
if ($data['type'] === HOOK_EVENT_TYPE_POST) {
|
||||||
|
if (isset($data['blocks'])) {
|
||||||
|
$data['blocks']['sessions']['items'][] = [
|
||||||
|
'url' => '../../plugin/advanced_subscription/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.
|
||||||
|
*
|
||||||
|
* @return mixed (int or false)
|
||||||
|
*/
|
||||||
|
public function hookWSRegistration(HookWSRegistrationEventInterface $hook)
|
||||||
|
{
|
||||||
|
$data = $hook->getEventData();
|
||||||
|
//if ($data['type'] === HOOK_EVENT_TYPE_PRE) // nothing to do
|
||||||
|
if ($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',
|
||||||
|
'',
|
||||||
|
[
|
||||||
|
// session.id
|
||||||
|
'id' => ['name' => 'id', 'type' => 'xsd:int'],
|
||||||
|
// session.name
|
||||||
|
'name' => ['name' => 'name', 'type' => 'xsd:string'],
|
||||||
|
// session.short_description
|
||||||
|
'short_description' => ['name' => 'short_description', 'type' => 'xsd:string'],
|
||||||
|
// session.mode
|
||||||
|
'mode' => ['name' => 'mode', 'type' => 'xsd:string'],
|
||||||
|
// session.date_start
|
||||||
|
'date_start' => ['name' => 'date_start', 'type' => 'xsd:string'],
|
||||||
|
// session.date_end
|
||||||
|
'date_end' => ['name' => 'date_end', 'type' => 'xsd:string'],
|
||||||
|
// session.human_text_duration
|
||||||
|
'human_text_duration' => ['name' => 'human_text_duration', 'type' => 'xsd:string'],
|
||||||
|
// session.vacancies
|
||||||
|
'vacancies' => ['name' => 'vacancies', 'type' => 'xsd:string'],
|
||||||
|
// session.schedule
|
||||||
|
'schedule' => ['name' => 'schedule', 'type' => 'xsd:string'],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
//Output params for WSSessionListInCategory
|
||||||
|
$server->wsdl->addComplexType(
|
||||||
|
'sessionBriefList',
|
||||||
|
'complexType',
|
||||||
|
'array',
|
||||||
|
'',
|
||||||
|
'SOAP-ENC:Array',
|
||||||
|
[],
|
||||||
|
[
|
||||||
|
['ref' => 'SOAP-ENC:arrayType',
|
||||||
|
'wsdl:arrayType' => 'tns:sessionBrief[]', ],
|
||||||
|
],
|
||||||
|
'tns:sessionBrief'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Input params for WSSessionListInCategory
|
||||||
|
$server->wsdl->addComplexType(
|
||||||
|
'sessionCategoryInput',
|
||||||
|
'complexType',
|
||||||
|
'struct',
|
||||||
|
'all',
|
||||||
|
'',
|
||||||
|
[
|
||||||
|
'id' => ['name' => 'id', 'type' => 'xsd:string'], // session_category.id
|
||||||
|
'name' => ['name' => 'name', 'type' => 'xsd:string'], // session_category.name
|
||||||
|
'target' => ['name' => 'target', 'type' => 'xsd:string'], // session.target
|
||||||
|
'secret_key' => ['name' => 'secret_key', 'type' => 'xsd:string'],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Input params for WSSessionGetDetailsByUser
|
||||||
|
$server->wsdl->addComplexType(
|
||||||
|
'advsubSessionDetailInput',
|
||||||
|
'complexType',
|
||||||
|
'struct',
|
||||||
|
'all',
|
||||||
|
'',
|
||||||
|
[
|
||||||
|
// user_field_values.value
|
||||||
|
'user_id' => ['name' => 'user_id', 'type' => 'xsd:int'],
|
||||||
|
// user_field.user_id
|
||||||
|
'user_field' => ['name' => 'user_field', 'type' => 'xsd:string'],
|
||||||
|
// session.id
|
||||||
|
'session_id' => ['name' => 'session_id', 'type' => 'xsd:int'],
|
||||||
|
// user.profile_completes
|
||||||
|
'profile_completed' => ['name' => 'profile_completed', 'type' => 'xsd:float'],
|
||||||
|
// user.is_connected
|
||||||
|
'is_connected' => ['name' => 'is_connected', 'type' => 'xsd:boolean'],
|
||||||
|
'secret_key' => ['name' => 'secret_key', 'type' => 'xsd:string'],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Output params for WSSessionGetDetailsByUser
|
||||||
|
$server->wsdl->addComplexType(
|
||||||
|
'advsubSessionDetail',
|
||||||
|
'complexType',
|
||||||
|
'struct',
|
||||||
|
'all',
|
||||||
|
'',
|
||||||
|
[
|
||||||
|
// session.id
|
||||||
|
'id' => ['name' => 'id', 'type' => 'xsd:string'],
|
||||||
|
// session.code
|
||||||
|
'code' => ['name' => 'code', 'type' => 'xsd:string'],
|
||||||
|
// session.place
|
||||||
|
'cost' => ['name' => 'cost', 'type' => 'xsd:float'],
|
||||||
|
// session.place
|
||||||
|
'place' => ['name' => 'place', 'type' => 'xsd:string'],
|
||||||
|
// session.allow_visitors
|
||||||
|
'allow_visitors' => ['name' => 'allow_visitors', 'type' => 'xsd:string'],
|
||||||
|
// session.teaching_hours
|
||||||
|
'teaching_hours' => ['name' => 'teaching_hours', 'type' => 'xsd:int'],
|
||||||
|
// session.brochure
|
||||||
|
'brochure' => ['name' => 'brochure', 'type' => 'xsd:string'],
|
||||||
|
// session.banner
|
||||||
|
'banner' => ['name' => 'banner', 'type' => 'xsd:string'],
|
||||||
|
// session.description
|
||||||
|
'description' => ['name' => 'description', 'type' => 'xsd:string'],
|
||||||
|
// status
|
||||||
|
'status' => ['name' => 'status', 'type' => 'xsd:string'],
|
||||||
|
// action_url
|
||||||
|
'action_url' => ['name' => 'action_url', 'type' => 'xsd:string'],
|
||||||
|
// message
|
||||||
|
'message' => ['name' => 'error_message', 'type' => 'xsd:string'],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
/** WSListSessionsDetailsByCategory */
|
||||||
|
|
||||||
|
// Input params for WSListSessionsDetailsByCategory
|
||||||
|
$server->wsdl->addComplexType(
|
||||||
|
'listSessionsDetailsByCategory',
|
||||||
|
'complexType',
|
||||||
|
'struct',
|
||||||
|
'all',
|
||||||
|
'',
|
||||||
|
[
|
||||||
|
// session_category.id
|
||||||
|
'id' => ['name' => 'id', 'type' => 'xsd:string'],
|
||||||
|
// session_category.access_url_id
|
||||||
|
'access_url_id' => ['name' => 'access_url_id', 'type' => 'xsd:int'],
|
||||||
|
// session_category.name
|
||||||
|
'category_name' => ['name' => 'category_name', 'type' => 'xsd:string'],
|
||||||
|
// secret key
|
||||||
|
'secret_key' => ['name' => 'secret_key', 'type' => 'xsd:string'],
|
||||||
|
],
|
||||||
|
[],
|
||||||
|
'tns:listSessionsDetailsByCategory'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Output params for sessionDetailsCourseList WSListSessionsDetailsByCategory
|
||||||
|
$server->wsdl->addComplexType(
|
||||||
|
'sessionDetailsCourse',
|
||||||
|
'complexType',
|
||||||
|
'struct',
|
||||||
|
'all',
|
||||||
|
'',
|
||||||
|
[
|
||||||
|
'course_id' => ['name' => 'course_id', 'type' => 'xsd:int'], // course.id
|
||||||
|
'course_code' => ['name' => 'course_code', 'type' => 'xsd:string'], // course.code
|
||||||
|
'course_title' => ['name' => 'course_title', 'type' => 'xsd:string'], // course.title
|
||||||
|
'coach_username' => ['name' => 'coach_username', 'type' => 'xsd:string'], // user.username
|
||||||
|
'coach_firstname' => ['name' => 'coach_firstname', 'type' => 'xsd:string'], // user.firstname
|
||||||
|
'coach_lastname' => ['name' => 'coach_lastname', 'type' => 'xsd:string'], // user.lastname
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Output array for sessionDetails WSListSessionsDetailsByCategory
|
||||||
|
$server->wsdl->addComplexType(
|
||||||
|
'sessionDetailsCourseList',
|
||||||
|
'complexType',
|
||||||
|
'array',
|
||||||
|
'',
|
||||||
|
'SOAP-ENC:Array',
|
||||||
|
[],
|
||||||
|
[
|
||||||
|
[
|
||||||
|
'ref' => 'SOAP-ENC:arrayType',
|
||||||
|
'wsdl:arrayType' => 'tns:sessionDetailsCourse[]',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'tns:sessionDetailsCourse'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Output params for sessionDetailsList WSListSessionsDetailsByCategory
|
||||||
|
$server->wsdl->addComplexType(
|
||||||
|
'sessionDetails',
|
||||||
|
'complexType',
|
||||||
|
'struct',
|
||||||
|
'all',
|
||||||
|
'',
|
||||||
|
[
|
||||||
|
// session.id
|
||||||
|
'id' => [
|
||||||
|
'name' => 'id',
|
||||||
|
'type' => 'xsd:int',
|
||||||
|
],
|
||||||
|
// session.id_coach
|
||||||
|
'coach_id' => [
|
||||||
|
'name' => 'coach_id',
|
||||||
|
'type' => 'xsd:int',
|
||||||
|
],
|
||||||
|
// session.name
|
||||||
|
'name' => [
|
||||||
|
'name' => 'name',
|
||||||
|
'type' => 'xsd:string',
|
||||||
|
],
|
||||||
|
// session.nbr_courses
|
||||||
|
'courses_num' => [
|
||||||
|
'name' => 'courses_num',
|
||||||
|
'type' => 'xsd:int',
|
||||||
|
],
|
||||||
|
// session.nbr_users
|
||||||
|
'users_num' => [
|
||||||
|
'name' => 'users_num',
|
||||||
|
'type' => 'xsd:int',
|
||||||
|
],
|
||||||
|
// session.nbr_classes
|
||||||
|
'classes_num' => [
|
||||||
|
'name' => 'classes_num',
|
||||||
|
'type' => 'xsd:int',
|
||||||
|
],
|
||||||
|
// session.date_start
|
||||||
|
'date_start' => [
|
||||||
|
'name' => 'date_start',
|
||||||
|
'type' => 'xsd:string',
|
||||||
|
],
|
||||||
|
// session.date_end
|
||||||
|
'date_end' => [
|
||||||
|
'name' => 'date_end',
|
||||||
|
'type' => 'xsd:string',
|
||||||
|
],
|
||||||
|
// session.nb_days_access_before_beginning
|
||||||
|
'access_days_before_num' => [
|
||||||
|
'name' => 'access_days_before_num',
|
||||||
|
'type' => 'xsd:int',
|
||||||
|
],
|
||||||
|
// session.nb_days_access_after_end
|
||||||
|
'access_days_after_num' => [
|
||||||
|
'name' => 'access_days_after_num',
|
||||||
|
'type' => 'xsd:int',
|
||||||
|
],
|
||||||
|
// session.session_admin_id
|
||||||
|
'session_admin_id' => [
|
||||||
|
'name' => 'session_admin_id',
|
||||||
|
'type' => 'xsd:int',
|
||||||
|
],
|
||||||
|
// session.visibility
|
||||||
|
'visibility' => [
|
||||||
|
'name' => 'visibility',
|
||||||
|
'type' => 'xsd:int',
|
||||||
|
],
|
||||||
|
// session.session_category_id
|
||||||
|
'session_category_id' => [
|
||||||
|
'name' => 'session_category_id',
|
||||||
|
'type' => 'xsd:int',
|
||||||
|
],
|
||||||
|
// session.promotion_id
|
||||||
|
'promotion_id' => [
|
||||||
|
'name' => 'promotion_id',
|
||||||
|
'type' => 'xsd:int',
|
||||||
|
],
|
||||||
|
// session.number of registered users validated
|
||||||
|
'validated_user_num' => [
|
||||||
|
'name' => 'validated_user_num',
|
||||||
|
'type' => 'xsd:int',
|
||||||
|
],
|
||||||
|
// session.number of registered users from waiting queue
|
||||||
|
'waiting_user_num' => [
|
||||||
|
'name' => 'waiting_user_num',
|
||||||
|
'type' => 'xsd:int',
|
||||||
|
],
|
||||||
|
// extra fields
|
||||||
|
// Array(field_name, field_value)
|
||||||
|
'extra' => [
|
||||||
|
'name' => 'extra',
|
||||||
|
'type' => 'tns:extrasList',
|
||||||
|
],
|
||||||
|
// course and coaches data
|
||||||
|
// Array(course_id, course_code, course_title, coach_username, coach_firstname, coach_lastname)
|
||||||
|
'course' => [
|
||||||
|
'name' => 'courses',
|
||||||
|
'type' => 'tns:sessionDetailsCourseList',
|
||||||
|
],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Output params for WSListSessionsDetailsByCategory
|
||||||
|
$server->wsdl->addComplexType(
|
||||||
|
'sessionDetailsList',
|
||||||
|
'complexType',
|
||||||
|
'array',
|
||||||
|
'',
|
||||||
|
'SOAP-ENC:Array',
|
||||||
|
[],
|
||||||
|
[
|
||||||
|
[
|
||||||
|
'ref' => 'SOAP-ENC:arrayType',
|
||||||
|
'wsdl:arrayType' => 'tns:sessionDetails[]',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'tns:sessionDetails'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register the method for WSSessionListInCategory
|
||||||
|
$server->register(
|
||||||
|
'HookAdvancedSubscription..WSSessionListInCategory', // method name
|
||||||
|
['sessionCategoryInput' => 'tns:sessionCategoryInput'], // input parameters
|
||||||
|
['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
|
||||||
|
['advsubSessionDetailInput' => 'tns:advsubSessionDetailInput'], // input parameters
|
||||||
|
['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
|
||||||
|
['name' => 'tns:listSessionsDetailsByCategory'], // input parameters
|
||||||
|
['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
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $params
|
||||||
|
*
|
||||||
|
* @return soap_fault|null
|
||||||
|
*/
|
||||||
|
public static function WSSessionListInCategory($params)
|
||||||
|
{
|
||||||
|
global $debug;
|
||||||
|
|
||||||
|
if ($debug) {
|
||||||
|
error_log(__FUNCTION__);
|
||||||
|
error_log('Params '.print_r($params, 1));
|
||||||
|
if (!WSHelperVerifyKey($params)) {
|
||||||
|
error_log(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
|
||||||
|
$fields = [
|
||||||
|
'id',
|
||||||
|
'short_description',
|
||||||
|
'mode',
|
||||||
|
'human_text_duration',
|
||||||
|
'vacancies',
|
||||||
|
'schedule',
|
||||||
|
];
|
||||||
|
$datePub = new DateTime();
|
||||||
|
$sessionList = SessionManager::getShortSessionListAndExtraByCategory(
|
||||||
|
$sessionCategoryId,
|
||||||
|
$params['target'],
|
||||||
|
$fields,
|
||||||
|
$datePub
|
||||||
|
);
|
||||||
|
|
||||||
|
return $sessionList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $params
|
||||||
|
*
|
||||||
|
* @return soap_fault|null
|
||||||
|
*/
|
||||||
|
public static function WSSessionGetDetailsByUser($params)
|
||||||
|
{
|
||||||
|
global $debug;
|
||||||
|
|
||||||
|
if ($debug) {
|
||||||
|
error_log('WSUserSubscribedInCourse');
|
||||||
|
error_log('Params '.print_r($params, 1));
|
||||||
|
}
|
||||||
|
if (!WSHelperVerifyKey($params)) {
|
||||||
|
return return_error(WS_ERROR_SECRET_KEY);
|
||||||
|
}
|
||||||
|
// Check params
|
||||||
|
if (is_array($params) && !empty($params['session_id']) && !empty($params['user_id'])) {
|
||||||
|
$userId = UserManager::get_user_id_from_original_id($params['user_id'], $params['user_field']);
|
||||||
|
$sessionId = (int) $params['session_id'];
|
||||||
|
// Check if user exists
|
||||||
|
if (UserManager::is_user_id_valid($userId) &&
|
||||||
|
SessionManager::isValidId($sessionId)
|
||||||
|
) {
|
||||||
|
// Check if student is already subscribed
|
||||||
|
$plugin = AdvancedSubscriptionPlugin::create();
|
||||||
|
$isOpen = $plugin->isSessionOpen($sessionId);
|
||||||
|
$status = $plugin->getQueueStatus($userId, $sessionId);
|
||||||
|
$vacancy = $plugin->getVacancy($sessionId);
|
||||||
|
$data = $plugin->getSessionDetails($sessionId);
|
||||||
|
$isUserInTargetGroup = $plugin->isUserInTargetGroup($userId, $sessionId);
|
||||||
|
if (!empty($data) && is_array($data)) {
|
||||||
|
$data['status'] = $status;
|
||||||
|
// Vacancy and queue status cases:
|
||||||
|
if ($isOpen) {
|
||||||
|
// Go to Course session
|
||||||
|
$data['action_url'] = self::$plugin->getOpenSessionUrl($userId, $params);
|
||||||
|
if (SessionManager::isUserSubscribedAsStudent($sessionId, $userId)) {
|
||||||
|
$data['status'] = 10;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!$isUserInTargetGroup) {
|
||||||
|
$data['status'] = -2;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
$isAllowed = self::$plugin->isAllowedToDoRequest($userId, $params);
|
||||||
|
$data['message'] = self::$plugin->getStatusMessage($status, $isAllowed);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$data['message'] = $e->getMessage();
|
||||||
|
}
|
||||||
|
$params['action'] = 'subscribe';
|
||||||
|
$params['sessionId'] = intval($sessionId);
|
||||||
|
$params['currentUserId'] = 0; // No needed
|
||||||
|
$params['studentUserId'] = intval($userId);
|
||||||
|
$params['queueId'] = 0; // No needed
|
||||||
|
$params['newStatus'] = ADVANCED_SUBSCRIPTION_QUEUE_STATUS_START;
|
||||||
|
if ($vacancy > 0) {
|
||||||
|
// Check conditions
|
||||||
|
if ($status == ADVANCED_SUBSCRIPTION_QUEUE_STATUS_NO_QUEUE) {
|
||||||
|
// No in Queue, require queue subscription url action
|
||||||
|
$data['action_url'] = self::$plugin->getTermsUrl($params);
|
||||||
|
} elseif ($status == ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_APPROVED) {
|
||||||
|
// send url action
|
||||||
|
$data['action_url'] = self::$plugin->getSessionUrl($sessionId);
|
||||||
|
} // Else: In queue, output status message, no more info.
|
||||||
|
} else {
|
||||||
|
if ($status == ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_APPROVED) {
|
||||||
|
$data['action_url'] = self::$plugin->getSessionUrl($sessionId);
|
||||||
|
} elseif ($status == ADVANCED_SUBSCRIPTION_QUEUE_STATUS_NO_QUEUE) {
|
||||||
|
// in Queue or not, cannot be subscribed to session
|
||||||
|
$data['action_url'] = self::$plugin->getTermsUrl($params);
|
||||||
|
} // Else: In queue, output status message, no more info.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$result = $data;
|
||||||
|
} else {
|
||||||
|
// Return soap fault No result was found
|
||||||
|
$result = return_error(WS_ERROR_NOT_FOUND_RESULT);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Return soap fault No result was found
|
||||||
|
$result = return_error(WS_ERROR_NOT_FOUND_RESULT);
|
||||||
|
}
|
||||||
|
} 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,
|
||||||
|
* access_start_date, access_end_date, 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 $params 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=>''])
|
||||||
|
*/
|
||||||
|
public static function WSListSessionsDetailsByCategory($params)
|
||||||
|
{
|
||||||
|
global $debug;
|
||||||
|
|
||||||
|
if ($debug) {
|
||||||
|
error_log('WSListSessionsDetailsByCategory');
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get validated and waiting queue users count for each session
|
||||||
|
AdvancedSubscriptionPlugin::create();
|
||||||
|
foreach ($sessionList as &$session) {
|
||||||
|
// Add validated and queue users count
|
||||||
|
$session['validated_user_num'] = self::$plugin->countQueueByParams(
|
||||||
|
[
|
||||||
|
'sessions' => [$session['id']],
|
||||||
|
'status' => [ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_APPROVED],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$session['waiting_user_num'] = self::$plugin->countQueueByParams(
|
||||||
|
[
|
||||||
|
'sessions' => [$session['id']],
|
||||||
|
'status' => [
|
||||||
|
ADVANCED_SUBSCRIPTION_QUEUE_STATUS_START,
|
||||||
|
ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_APPROVED,
|
||||||
|
],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sessionList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return notification content when the hook has been triggered.
|
||||||
|
*
|
||||||
|
* @return mixed (int or false)
|
||||||
|
*/
|
||||||
|
public function hookNotificationContent(HookNotificationContentEventInterface $hook)
|
||||||
|
{
|
||||||
|
$data = $hook->getEventData();
|
||||||
|
if ($data['type'] === HOOK_EVENT_TYPE_PRE) {
|
||||||
|
$data['advanced_subscription_pre_content'] = $data['content'];
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
} elseif ($data['type'] === HOOK_EVENT_TYPE_POST) {
|
||||||
|
if (isset($data['content']) &&
|
||||||
|
!empty($data['content']) &&
|
||||||
|
isset($data['advanced_subscription_pre_content']) &&
|
||||||
|
!empty($data['advanced_subscription_pre_content'])
|
||||||
|
) {
|
||||||
|
$data['content'] = str_replace(
|
||||||
|
[
|
||||||
|
'<br /><hr>',
|
||||||
|
'<br />',
|
||||||
|
'<br/>',
|
||||||
|
],
|
||||||
|
'',
|
||||||
|
$data['advanced_subscription_pre_content']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
} //Else hook type is not valid, nothing to do
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the notification data title if the hook was triggered.
|
||||||
|
*
|
||||||
|
* @return array|bool
|
||||||
|
*/
|
||||||
|
public function hookNotificationTitle(HookNotificationTitleEventInterface $hook)
|
||||||
|
{
|
||||||
|
$data = $hook->getEventData();
|
||||||
|
if ($data['type'] === HOOK_EVENT_TYPE_PRE) {
|
||||||
|
$data['advanced_subscription_pre_title'] = $data['title'];
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
} elseif ($data['type'] === HOOK_EVENT_TYPE_POST) {
|
||||||
|
if (isset($data['advanced_subscription_pre_title']) &&
|
||||||
|
!empty($data['advanced_subscription_pre_title'])
|
||||||
|
) {
|
||||||
|
$data['title'] = $data['advanced_subscription_pre_title'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
} // Else: hook type is not valid, nothing to do
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
104
plugin/advanced_subscription/src/admin_view.php
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
<?php
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
/**
|
||||||
|
* Index of the Advanced subscription plugin courses list.
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.advanced_subscription
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Init.
|
||||||
|
*/
|
||||||
|
require_once __DIR__.'/../config.php';
|
||||||
|
// protect
|
||||||
|
api_protect_admin_script();
|
||||||
|
// start plugin
|
||||||
|
$plugin = AdvancedSubscriptionPlugin::create();
|
||||||
|
// Session ID
|
||||||
|
$sessionId = isset($_REQUEST['s']) ? intval($_REQUEST['s']) : null;
|
||||||
|
|
||||||
|
// Init template
|
||||||
|
$tpl = new Template($plugin->get_lang('plugin_title'));
|
||||||
|
// Get all sessions
|
||||||
|
$sessionList = $plugin->listAllSessions();
|
||||||
|
|
||||||
|
if (!empty($sessionId)) {
|
||||||
|
// Get student list in queue
|
||||||
|
$studentList = $plugin->listAllStudentsInQueueBySession($sessionId);
|
||||||
|
// Set selected to current session
|
||||||
|
$sessionList[$sessionId]['selected'] = 'selected="selected"';
|
||||||
|
$studentList['session']['id'] = $sessionId;
|
||||||
|
// Assign variables
|
||||||
|
$fieldsArray = [
|
||||||
|
'description',
|
||||||
|
'target',
|
||||||
|
'mode',
|
||||||
|
'publication_end_date',
|
||||||
|
'recommended_number_of_participants',
|
||||||
|
'vacancies',
|
||||||
|
];
|
||||||
|
$sessionArray = api_get_session_info($sessionId);
|
||||||
|
$extraSession = new ExtraFieldValue('session');
|
||||||
|
$extraField = new ExtraField('session');
|
||||||
|
// Get session fields
|
||||||
|
$fieldList = $extraField->get_all([
|
||||||
|
'variable IN ( ?, ?, ?, ?, ?, ?)' => $fieldsArray,
|
||||||
|
]);
|
||||||
|
// Index session fields
|
||||||
|
foreach ($fieldList as $field) {
|
||||||
|
$fields[$field['id']] = $field['variable'];
|
||||||
|
}
|
||||||
|
$params = [' item_id = ? ' => $sessionId];
|
||||||
|
$sessionFieldValueList = $extraSession->get_all(['where' => $params]);
|
||||||
|
foreach ($sessionFieldValueList as $sessionFieldValue) {
|
||||||
|
// Check if session field value is set in session field list
|
||||||
|
if (isset($fields[$sessionFieldValue['field_id']])) {
|
||||||
|
$var = $fields[$sessionFieldValue['field_id']];
|
||||||
|
$val = $sessionFieldValue['value'];
|
||||||
|
// Assign session field value to session
|
||||||
|
$sessionArray[$var] = $val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$adminsArray = UserManager::get_all_administrators();
|
||||||
|
|
||||||
|
$data['action'] = 'confirm';
|
||||||
|
$data['sessionId'] = $sessionId;
|
||||||
|
$data['currentUserId'] = api_get_user_id();
|
||||||
|
$isWesternNameOrder = api_is_western_name_order();
|
||||||
|
|
||||||
|
foreach ($studentList['students'] as &$student) {
|
||||||
|
$studentId = intval($student['user_id']);
|
||||||
|
$data['studentUserId'] = $studentId;
|
||||||
|
|
||||||
|
$fieldValue = new ExtraFieldValue('user');
|
||||||
|
$areaField = $fieldValue->get_values_by_handler_and_field_variable($studentId, 'area', true);
|
||||||
|
|
||||||
|
$student['area'] = $areaField['value'];
|
||||||
|
if (substr($student['area'], 0, 6) == 'MINEDU') {
|
||||||
|
$student['institution'] = 'Minedu';
|
||||||
|
} else {
|
||||||
|
$student['institution'] = 'Regiones';
|
||||||
|
}
|
||||||
|
$student['userLink'] = api_get_path(WEB_CODE_PATH).'social/profile.php?u='.$studentId;
|
||||||
|
$data['queueId'] = intval($student['queue_id']);
|
||||||
|
$data['newStatus'] = ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_APPROVED;
|
||||||
|
$data['profile_completed'] = 100;
|
||||||
|
$student['acceptUrl'] = $plugin->getQueueUrl($data);
|
||||||
|
$data['newStatus'] = ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_DISAPPROVED;
|
||||||
|
$student['rejectUrl'] = $plugin->getQueueUrl($data);
|
||||||
|
$student['complete_name'] = $isWesternNameOrder ?
|
||||||
|
$student['firstname'].', '.$student['lastname'] : $student['lastname'].', '.$student['firstname'];
|
||||||
|
}
|
||||||
|
$tpl->assign('session', $sessionArray);
|
||||||
|
$tpl->assign('students', $studentList['students']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign variables
|
||||||
|
$tpl->assign('sessionItems', $sessionList);
|
||||||
|
$tpl->assign('approveAdmin', ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_APPROVED);
|
||||||
|
$tpl->assign('disapproveAdmin', ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_DISAPPROVED);
|
||||||
|
// Get rendered template
|
||||||
|
$content = $tpl->fetch('/advanced_subscription/views/admin_view.tpl');
|
||||||
|
// Assign into content
|
||||||
|
$tpl->assign('content', $content);
|
||||||
|
// Display
|
||||||
|
$tpl->display_one_col_template();
|
||||||
61
plugin/advanced_subscription/src/open_session.php
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
/* For licensing terms, see /license.txt */
|
||||||
|
/**
|
||||||
|
* Validate requirements for a open session.
|
||||||
|
*
|
||||||
|
* @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.advanced_subscription
|
||||||
|
*/
|
||||||
|
require_once __DIR__.'/../config.php';
|
||||||
|
|
||||||
|
$plugin = AdvancedSubscriptionPlugin::create();
|
||||||
|
|
||||||
|
if (!isset($_GET['session_id'], $_GET['user_id'], $_GET['profile_completed'])) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sessionInfo = api_get_session_info($_GET['session_id']);
|
||||||
|
|
||||||
|
$tpl = new Template(
|
||||||
|
$plugin->get_lang('plugin_title'),
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
$tpl->assign('session', $sessionInfo);
|
||||||
|
|
||||||
|
if (SessionManager::isUserSubscribedAsStudent(
|
||||||
|
$_GET['session_id'],
|
||||||
|
$_GET['user_id']
|
||||||
|
)) {
|
||||||
|
$tpl->assign('is_subscribed', false);
|
||||||
|
$tpl->assign(
|
||||||
|
'errorMessages',
|
||||||
|
[sprintf(
|
||||||
|
$plugin->get_lang('YouAreAlreadySubscribedToSessionX'),
|
||||||
|
$sessionInfo['name']
|
||||||
|
)]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if (!$plugin->isAllowedSubscribeToOpenSession($_GET)) {
|
||||||
|
$tpl->assign('is_subscribed', false);
|
||||||
|
$tpl->assign('errorMessages', $plugin->getErrorMessages());
|
||||||
|
} else {
|
||||||
|
SessionManager::subscribeUsersToSession(
|
||||||
|
$_GET['session_id'],
|
||||||
|
[$_GET['user_id']],
|
||||||
|
SESSION_VISIBLE_READ_ONLY,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
$tpl->assign('is_subscribed', true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$content = $tpl->fetch('/advanced_subscription/views/open_session.tpl');
|
||||||
|
|
||||||
|
$tpl->assign('content', $content);
|
||||||
|
$tpl->display_one_col_template();
|
||||||
26
plugin/advanced_subscription/src/render_mail.php
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
/**
|
||||||
|
* Render an email from data.
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.advanced_subscription
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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['queueId'] = intval($_REQUEST['q']);
|
||||||
|
// Check if data is valid or is for start subscription
|
||||||
|
$verified = $plugin->checkHash($data, $hash);
|
||||||
|
if ($verified) {
|
||||||
|
// Render mail
|
||||||
|
$message = MessageManager::get_message_by_id($data['queueId']);
|
||||||
|
$message = str_replace(['<br /><hr>', '<br />', '<br/>'], '', $message['content']);
|
||||||
|
echo $message;
|
||||||
|
}
|
||||||
@@ -0,0 +1,204 @@
|
|||||||
|
<?php
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
/**
|
||||||
|
* This script generates session fields needed for this plugin.
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.advanced_subscription
|
||||||
|
*/
|
||||||
|
|
||||||
|
//exit;
|
||||||
|
|
||||||
|
require_once __DIR__.'/../../config.php';
|
||||||
|
|
||||||
|
api_protect_admin_script();
|
||||||
|
|
||||||
|
$teachingHours = new ExtraField('session');
|
||||||
|
$teachingHours->save([
|
||||||
|
'field_type' => ExtraField::FIELD_TYPE_INTEGER,
|
||||||
|
'variable' => 'teaching_hours',
|
||||||
|
'display_text' => get_lang('TeachingHours'),
|
||||||
|
'visible_to_self' => 1,
|
||||||
|
'changeable' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$cost = new ExtraField('session');
|
||||||
|
$cost->save([
|
||||||
|
'field_type' => ExtraField::FIELD_TYPE_FLOAT,
|
||||||
|
'variable' => 'cost',
|
||||||
|
'display_text' => get_lang('Cost'),
|
||||||
|
'visible_to_self' => 1,
|
||||||
|
'changeable' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$vacancies = new ExtraField('session');
|
||||||
|
$vacancies->save([
|
||||||
|
'field_type' => ExtraField::FIELD_TYPE_INTEGER,
|
||||||
|
'variable' => 'vacancies',
|
||||||
|
'display_text' => get_lang('Vacancies'),
|
||||||
|
'visible_to_self' => 1,
|
||||||
|
'changeable' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$recommendedNumberOfParticipants = new ExtraField('session');
|
||||||
|
$recommendedNumberOfParticipants->save([
|
||||||
|
'field_type' => ExtraField::FIELD_TYPE_INTEGER,
|
||||||
|
'variable' => 'recommended_number_of_participants',
|
||||||
|
'display_text' => get_lang('RecommendedNumberOfParticipants'),
|
||||||
|
'visible_to_self' => 1,
|
||||||
|
'changeable' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$place = new ExtraField('session');
|
||||||
|
$place->save([
|
||||||
|
'field_type' => ExtraField::FIELD_TYPE_TEXT,
|
||||||
|
'variable' => 'place',
|
||||||
|
'display_text' => get_lang('Place'),
|
||||||
|
'visible_to_self' => 1,
|
||||||
|
'changeable' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$schedule = new ExtraField('session');
|
||||||
|
$schedule->save([
|
||||||
|
'field_type' => ExtraField::FIELD_TYPE_TEXT,
|
||||||
|
'variable' => 'schedule',
|
||||||
|
'display_text' => get_lang('Schedule'),
|
||||||
|
'visible_to_self' => 1,
|
||||||
|
'changeable' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$allowVisitors = new ExtraField('session');
|
||||||
|
$allowVisitors->save([
|
||||||
|
'field_type' => ExtraField::FIELD_TYPE_CHECKBOX,
|
||||||
|
'variable' => 'allow_visitors',
|
||||||
|
'display_text' => get_lang('AllowVisitors'),
|
||||||
|
'visible_to_self' => 1,
|
||||||
|
'changeable' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$modeOptions = [
|
||||||
|
get_lang('Online'),
|
||||||
|
get_lang('Presencial'),
|
||||||
|
get_lang('B-Learning'),
|
||||||
|
];
|
||||||
|
|
||||||
|
$mode = new ExtraField('session');
|
||||||
|
$mode->save([
|
||||||
|
'field_type' => ExtraField::FIELD_TYPE_SELECT,
|
||||||
|
'variable' => 'mode',
|
||||||
|
'display_text' => get_lang('Mode'),
|
||||||
|
'visible_to_self' => 1,
|
||||||
|
'changeable' => 1,
|
||||||
|
'field_options' => implode('; ', $modeOptions),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$isInductionSession = new ExtraField('session');
|
||||||
|
$isInductionSession->save([
|
||||||
|
'field_type' => ExtraField::FIELD_TYPE_CHECKBOX,
|
||||||
|
'variable' => 'is_induction_session',
|
||||||
|
'display_text' => get_lang('IsInductionSession'),
|
||||||
|
'visible_to_self' => 1,
|
||||||
|
'changeable' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$isOpenSession = new ExtraField('session');
|
||||||
|
$isOpenSession->save([
|
||||||
|
'field_type' => ExtraField::FIELD_TYPE_CHECKBOX,
|
||||||
|
'variable' => 'is_open_session',
|
||||||
|
'display_text' => get_lang('IsOpenSession'),
|
||||||
|
'visible_to_self' => 1,
|
||||||
|
'changeable' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$duration = new ExtraField('session');
|
||||||
|
$duration->save([
|
||||||
|
'field_type' => ExtraField::FIELD_TYPE_TEXT,
|
||||||
|
'variable' => 'human_text_duration',
|
||||||
|
'display_text' => get_lang('DurationInWords'),
|
||||||
|
'visible_to_self' => 1,
|
||||||
|
'changeable' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$showStatusOptions = [
|
||||||
|
get_lang('Open'),
|
||||||
|
get_lang('InProcess'),
|
||||||
|
get_lang('Closed'),
|
||||||
|
];
|
||||||
|
|
||||||
|
$showStatus = new ExtraField('session');
|
||||||
|
$showStatus->save([
|
||||||
|
'field_type' => ExtraField::FIELD_TYPE_SELECT,
|
||||||
|
'variable' => 'show_status',
|
||||||
|
'display_text' => get_lang('ShowStatus'),
|
||||||
|
'visible_to_self' => 1,
|
||||||
|
'changeable' => 1,
|
||||||
|
'field_options' => implode('; ', $showStatusOptions),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$publicationStartDate = new ExtraField('session');
|
||||||
|
$publicationStartDate->save([
|
||||||
|
'field_type' => ExtraField::FIELD_TYPE_DATE,
|
||||||
|
'variable' => 'publication_start_date',
|
||||||
|
'display_text' => get_lang('PublicationStartDate'),
|
||||||
|
'visible_to_self' => 1,
|
||||||
|
'changeable' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$publicationEndDate = new ExtraField('session');
|
||||||
|
$publicationEndDate->save([
|
||||||
|
'field_type' => ExtraField::FIELD_TYPE_DATE,
|
||||||
|
'variable' => 'publication_end_date',
|
||||||
|
'display_text' => get_lang('PublicationEndDate'),
|
||||||
|
'visible_to_self' => 1,
|
||||||
|
'changeable' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$banner = new ExtraField('session');
|
||||||
|
$banner->save([
|
||||||
|
'field_type' => ExtraField::FIELD_TYPE_FILE_IMAGE,
|
||||||
|
'variable' => 'banner',
|
||||||
|
'display_text' => get_lang('SessionBanner'),
|
||||||
|
'visible_to_self' => 1,
|
||||||
|
'changeable' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$brochure = new ExtraField('session');
|
||||||
|
$brochure->save([
|
||||||
|
'field_type' => ExtraField::FIELD_TYPE_FILE,
|
||||||
|
'variable' => 'brochure',
|
||||||
|
'display_text' => get_lang('Brochure'),
|
||||||
|
'visible_to_self' => 1,
|
||||||
|
'changeable' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$targetOptions = [
|
||||||
|
get_lang('Minedu'),
|
||||||
|
get_lang('Regiones'),
|
||||||
|
];
|
||||||
|
|
||||||
|
$target = new ExtraField('session');
|
||||||
|
$target->save([
|
||||||
|
'field_type' => ExtraField::FIELD_TYPE_SELECT,
|
||||||
|
'variable' => 'target',
|
||||||
|
'display_text' => get_lang('TargetAudience'),
|
||||||
|
'visible_to_self' => 1,
|
||||||
|
'changeable' => 1,
|
||||||
|
'field_options' => implode('; ', $targetOptions),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$shortDescription = new ExtraField('session');
|
||||||
|
$shortDescription->save([
|
||||||
|
'field_type' => ExtraField::FIELD_TYPE_TEXT,
|
||||||
|
'variable' => 'short_description',
|
||||||
|
'display_text' => get_lang('ShortDescription'),
|
||||||
|
'visible_to_self' => 1,
|
||||||
|
'changeable' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$id = new ExtraField('session');
|
||||||
|
$id->save([
|
||||||
|
'field_type' => ExtraField::FIELD_TYPE_TEXT,
|
||||||
|
'variable' => 'code',
|
||||||
|
'display_text' => get_lang('Code'),
|
||||||
|
'visible_to_self' => 1,
|
||||||
|
'changeable' => 1,
|
||||||
|
]);
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
/**
|
||||||
|
* This script generates four session categories.
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.advanced_subscription
|
||||||
|
*/
|
||||||
|
require_once __DIR__.'/../../config.php';
|
||||||
|
|
||||||
|
api_protect_admin_script();
|
||||||
|
|
||||||
|
$categories = [
|
||||||
|
'capacitaciones',
|
||||||
|
'programas',
|
||||||
|
'especializaciones',
|
||||||
|
'cursos prácticos',
|
||||||
|
];
|
||||||
|
$tableSessionCategory = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
|
||||||
|
foreach ($categories as $category) {
|
||||||
|
Database::query("INSERT INTO $tableSessionCategory (name) VALUES ('$category')");
|
||||||
|
}
|
||||||
85
plugin/advanced_subscription/src/terms_and_conditions.php
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
<?php
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
/**
|
||||||
|
* Script to show sessions terms and conditions.
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.advanced_subscription
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Init.
|
||||||
|
*/
|
||||||
|
require_once __DIR__.'/../config.php';
|
||||||
|
// start plugin
|
||||||
|
$plugin = AdvancedSubscriptionPlugin::create();
|
||||||
|
// Session ID
|
||||||
|
$data['action'] = Security::remove_XSS($_REQUEST['a']);
|
||||||
|
$data['sessionId'] = isset($_REQUEST['s']) ? intval($_REQUEST['s']) : 0;
|
||||||
|
$data['currentUserId'] = isset($_REQUEST['current_user_id']) ? intval($_REQUEST['current_user_id']) : 0;
|
||||||
|
$data['studentUserId'] = isset($_REQUEST['u']) ? intval($_REQUEST['u']) : 0;
|
||||||
|
$data['queueId'] = isset($_REQUEST['q']) ? intval($_REQUEST['q']) : 0;
|
||||||
|
$data['newStatus'] = isset($_REQUEST['e']) ? intval($_REQUEST['e']) : 0;
|
||||||
|
$data['is_connected'] = true;
|
||||||
|
$data['profile_completed'] = isset($_REQUEST['profile_completed']) ? floatval($_REQUEST['profile_completed']) : 0;
|
||||||
|
$data['termsRejected'] = isset($_REQUEST['r']) ? intval($_REQUEST['r']) : 0;
|
||||||
|
|
||||||
|
// Init template
|
||||||
|
$tpl = new Template($plugin->get_lang('plugin_title'));
|
||||||
|
|
||||||
|
$isAllowToDoRequest = $plugin->isAllowedToDoRequest($data['studentUserId'], $data, true);
|
||||||
|
|
||||||
|
if (!$isAllowToDoRequest) {
|
||||||
|
$tpl->assign('errorMessages', $plugin->getErrorMessages());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!empty($data['sessionId']) &&
|
||||||
|
!empty($data['studentUserId']) &&
|
||||||
|
api_get_plugin_setting('courselegal', 'tool_enable')
|
||||||
|
) {
|
||||||
|
$lastMessageId = $plugin->getLastMessageId($data['studentUserId'], $data['sessionId']);
|
||||||
|
if ($lastMessageId !== false) {
|
||||||
|
// Render mail
|
||||||
|
$url = $plugin->getRenderMailUrl(['queueId' => $lastMessageId]);
|
||||||
|
header('Location: '.$url);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
$courses = SessionManager::get_course_list_by_session_id($data['sessionId']);
|
||||||
|
$course = current($courses);
|
||||||
|
$data['courseId'] = $course['id'];
|
||||||
|
$legalEnabled = api_get_plugin_setting('courselegal', 'tool_enable');
|
||||||
|
if ($legalEnabled) {
|
||||||
|
$courseLegal = CourseLegalPlugin::create();
|
||||||
|
$termsAndConditions = $courseLegal->getData($data['courseId'], $data['sessionId']);
|
||||||
|
$termsAndConditions = $termsAndConditions['content'];
|
||||||
|
$termFiles = $courseLegal->getCurrentFile($data['courseId'], $data['sessionId']);
|
||||||
|
} else {
|
||||||
|
$termsAndConditions = $plugin->get('terms_and_conditions');
|
||||||
|
$termFiles = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$data['session'] = api_get_session_info($data['sessionId']);
|
||||||
|
$data['student'] = api_get_user_info($data['studentUserId']);
|
||||||
|
$data['course'] = api_get_course_info_by_id($data['courseId']);
|
||||||
|
$data['acceptTermsUrl'] = $plugin->getQueueUrl($data);
|
||||||
|
$data['rejectTermsUrl'] = $plugin->getTermsUrl($data, ADVANCED_SUBSCRIPTION_TERMS_MODE_REJECT);
|
||||||
|
// Use Twig with String loader
|
||||||
|
$termsContent = $plugin->renderTemplateString($termsAndConditions, $data);
|
||||||
|
} else {
|
||||||
|
$termsContent = '';
|
||||||
|
$termFiles = '';
|
||||||
|
$data['acceptTermsUrl'] = '#';
|
||||||
|
$data['rejectTermsUrl'] = '#';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign into content
|
||||||
|
$tpl->assign('termsRejected', $data['termsRejected']);
|
||||||
|
$tpl->assign('acceptTermsUrl', $data['acceptTermsUrl']);
|
||||||
|
$tpl->assign('rejectTermsUrl', $data['rejectTermsUrl']);
|
||||||
|
$tpl->assign('session', $data['session']);
|
||||||
|
$tpl->assign('student', $data['student']);
|
||||||
|
$tpl->assign('sessionId', $data['sessionId']);
|
||||||
|
$tpl->assign('termsContent', $termsContent);
|
||||||
|
$tpl->assign('termsFiles', $termFiles);
|
||||||
|
|
||||||
|
$content = $tpl->fetch('/advanced_subscription/views/terms_and_conditions.tpl');
|
||||||
|
echo $content;
|
||||||
134
plugin/advanced_subscription/test/mails.php
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
<?php
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
/**
|
||||||
|
* A script to render all mails templates.
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.advanced_subscription
|
||||||
|
*/
|
||||||
|
require_once __DIR__.'/../config.php';
|
||||||
|
|
||||||
|
// Protect test
|
||||||
|
api_protect_admin_script();
|
||||||
|
|
||||||
|
// exit;
|
||||||
|
$plugin = AdvancedSubscriptionPlugin::create();
|
||||||
|
// Get validation hash
|
||||||
|
$hash = Security::remove_XSS($_REQUEST['v']);
|
||||||
|
// Get data from request (GET or POST)
|
||||||
|
$data['action'] = 'confirm';
|
||||||
|
$data['currentUserId'] = 1;
|
||||||
|
$data['queueId'] = 0;
|
||||||
|
$data['is_connected'] = true;
|
||||||
|
$data['profile_completed'] = 90.0;
|
||||||
|
// Init result array
|
||||||
|
|
||||||
|
$data['sessionId'] = 1;
|
||||||
|
$data['studentUserId'] = 4;
|
||||||
|
|
||||||
|
// Prepare data
|
||||||
|
// Get session data
|
||||||
|
// Assign variables
|
||||||
|
$fieldsArray = [
|
||||||
|
'description',
|
||||||
|
'target',
|
||||||
|
'mode',
|
||||||
|
'publication_end_date',
|
||||||
|
'recommended_number_of_participants',
|
||||||
|
];
|
||||||
|
$sessionArray = api_get_session_info($data['sessionId']);
|
||||||
|
$extraSession = new ExtraFieldValue('session');
|
||||||
|
$extraField = new ExtraField('session');
|
||||||
|
// Get session fields
|
||||||
|
$fieldList = $extraField->get_all([
|
||||||
|
'variable IN ( ?, ?, ?, ?, ?)' => $fieldsArray,
|
||||||
|
]);
|
||||||
|
$fields = [];
|
||||||
|
// Index session fields
|
||||||
|
foreach ($fieldList as $field) {
|
||||||
|
$fields[$field['id']] = $field['variable'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$mergedArray = array_merge([$data['sessionId']], array_keys($fields));
|
||||||
|
$sessionFieldValueList = $extraSession->get_all(
|
||||||
|
['item_id = ? field_id IN ( ?, ?, ?, ?, ?, ?, ? )' => $mergedArray]
|
||||||
|
);
|
||||||
|
foreach ($sessionFieldValueList as $sessionFieldValue) {
|
||||||
|
// Check if session field value is set in session field list
|
||||||
|
if (isset($fields[$sessionFieldValue['field_id']])) {
|
||||||
|
$var = $fields[$sessionFieldValue['field_id']];
|
||||||
|
$val = $sessionFieldValue['value'];
|
||||||
|
// Assign session field value to session
|
||||||
|
$sessionArray[$var] = $val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Get student data
|
||||||
|
$studentArray = api_get_user_info($data['studentUserId']);
|
||||||
|
$studentArray['picture'] = $studentArray['avatar'];
|
||||||
|
|
||||||
|
// Get superior data if exist
|
||||||
|
$superiorId = UserManager::getFirstStudentBoss($data['studentUserId']);
|
||||||
|
if (!empty($superiorId)) {
|
||||||
|
$superiorArray = api_get_user_info($superiorId);
|
||||||
|
} else {
|
||||||
|
$superiorArray = api_get_user_info(3);
|
||||||
|
}
|
||||||
|
// Get admin data
|
||||||
|
$adminsArray = UserManager::get_all_administrators();
|
||||||
|
$isWesternNameOrder = api_is_western_name_order();
|
||||||
|
foreach ($adminsArray as &$admin) {
|
||||||
|
$admin['complete_name'] = $isWesternNameOrder ?
|
||||||
|
$admin['firstname'].', '.$admin['lastname'] : $admin['lastname'].', '.$admin['firstname']
|
||||||
|
;
|
||||||
|
}
|
||||||
|
unset($admin);
|
||||||
|
// Set data
|
||||||
|
$data['action'] = 'confirm';
|
||||||
|
$data['student'] = $studentArray;
|
||||||
|
$data['superior'] = $superiorArray;
|
||||||
|
$data['admins'] = $adminsArray;
|
||||||
|
$data['admin'] = current($adminsArray);
|
||||||
|
$data['session'] = $sessionArray;
|
||||||
|
$data['signature'] = api_get_setting('Institution');
|
||||||
|
$data['admin_view_url'] = api_get_path(WEB_PLUGIN_PATH).
|
||||||
|
'advanced_subscription/src/admin_view.php?s='.$data['sessionId'];
|
||||||
|
$data['newStatus'] = ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_APPROVED;
|
||||||
|
$data['student']['acceptUrl'] = $plugin->getQueueUrl($data);
|
||||||
|
$data['newStatus'] = ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_DISAPPROVED;
|
||||||
|
$data['student']['rejectUrl'] = $plugin->getQueueUrl($data);
|
||||||
|
$tpl = new Template($plugin->get_lang('plugin_title'));
|
||||||
|
$tpl->assign('data', $data);
|
||||||
|
$tplParams = [
|
||||||
|
'user',
|
||||||
|
'student',
|
||||||
|
'students',
|
||||||
|
'superior',
|
||||||
|
'admins',
|
||||||
|
'admin',
|
||||||
|
'session',
|
||||||
|
'signature',
|
||||||
|
'admin_view_url',
|
||||||
|
'acceptUrl',
|
||||||
|
'rejectUrl',
|
||||||
|
];
|
||||||
|
foreach ($tplParams as $tplParam) {
|
||||||
|
$tpl->assign($tplParam, $data[$tplParam]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$dir = __DIR__.'/../views/';
|
||||||
|
$files = scandir($dir);
|
||||||
|
|
||||||
|
echo '<br>', '<pre>', print_r($files, 1), '</pre>';
|
||||||
|
|
||||||
|
foreach ($files as $k => &$file) {
|
||||||
|
if (
|
||||||
|
is_file($dir.$file) &&
|
||||||
|
strpos($file, '.tpl') &&
|
||||||
|
$file != 'admin_view.tpl'
|
||||||
|
) {
|
||||||
|
echo '<pre>', $file, '</pre>';
|
||||||
|
echo $tpl->fetch('/advanced_subscription/views/'.$file);
|
||||||
|
} else {
|
||||||
|
unset($files[$k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
echo '<br>', '<pre>', print_r($files, 1), '</pre>';
|
||||||
47
plugin/advanced_subscription/test/terms_to_pdf.php
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
/**
|
||||||
|
* A script to render all mails templates.
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.advanced_subscription
|
||||||
|
*/
|
||||||
|
require_once __DIR__.'/../config.php';
|
||||||
|
|
||||||
|
// Protect test
|
||||||
|
api_protect_admin_script();
|
||||||
|
|
||||||
|
$data['action'] = 'confirm';
|
||||||
|
$data['currentUserId'] = 1;
|
||||||
|
$data['queueId'] = 0;
|
||||||
|
$data['is_connected'] = true;
|
||||||
|
$data['profile_completed'] = 90.0;
|
||||||
|
$data['sessionId'] = intval($_REQUEST['s']);
|
||||||
|
$data['studentUserId'] = intval($_REQUEST['u']);
|
||||||
|
$data['student'] = api_get_user_info($data['studentUserId']);
|
||||||
|
$data['session'] = api_get_session_info($data['sessionId']);
|
||||||
|
|
||||||
|
if (!empty($data['sessionId']) && !empty($data['studentUserId'])) {
|
||||||
|
$plugin = AdvancedSubscriptionPlugin::create();
|
||||||
|
|
||||||
|
if (api_get_plugin_setting('courselegal', 'tool_enable')) {
|
||||||
|
$courseLegal = CourseLegalPlugin::create();
|
||||||
|
$courses = SessionManager::get_course_list_by_session_id($data['sessionId']);
|
||||||
|
$course = current($courses);
|
||||||
|
$data['courseId'] = $course['id'];
|
||||||
|
$data['course'] = api_get_course_info_by_id($data['courseId']);
|
||||||
|
$termsAndConditions = $courseLegal->getData($data['courseId'], $data['sessionId']);
|
||||||
|
$termsAndConditions = $termsAndConditions['content'];
|
||||||
|
$termsAndConditions = $plugin->renderTemplateString($termsAndConditions, $data);
|
||||||
|
$tpl = new Template($plugin->get_lang('Terms'));
|
||||||
|
$tpl->assign('session', $data['session']);
|
||||||
|
$tpl->assign('student', $data['student']);
|
||||||
|
$tpl->assign('sessionId', $data['sessionId']);
|
||||||
|
$tpl->assign('termsContent', $termsAndConditions);
|
||||||
|
$termsAndConditions = $tpl->fetch('/advanced_subscription/views/terms_and_conditions_to_pdf.tpl');
|
||||||
|
$pdf = new PDF();
|
||||||
|
$filename = 'terms'.sha1(rand(0, 99999));
|
||||||
|
$pdf->content_to_pdf($termsAndConditions, null, $filename, null, 'F');
|
||||||
|
$fileDir = api_get_path(WEB_ARCHIVE_PATH).$filename.'.pdf';
|
||||||
|
echo '<pre>', print_r($fileDir, 1), '</pre>';
|
||||||
|
}
|
||||||
|
}
|
||||||
86
plugin/advanced_subscription/test/ws_session_user.php
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
/**
|
||||||
|
* A script to test session details by user web service.
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.advanced_subscription
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init.
|
||||||
|
*/
|
||||||
|
require_once __DIR__.'/../config.php';
|
||||||
|
// Protect test
|
||||||
|
api_protect_admin_script();
|
||||||
|
|
||||||
|
// exit;
|
||||||
|
|
||||||
|
$plugin = AdvancedSubscriptionPlugin::create();
|
||||||
|
$hookPlugin = HookAdvancedSubscription::create();
|
||||||
|
// Get params from request (GET or POST)
|
||||||
|
$params = [];
|
||||||
|
// Init result array
|
||||||
|
$params['user_id'] = intval($_REQUEST['u']);
|
||||||
|
$params['user_field'] = 'drupal_user_id';
|
||||||
|
$params['session_id'] = intval($_REQUEST['s']);
|
||||||
|
$params['profile_completed'] = 100;
|
||||||
|
$params['is_connected'] = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copied code from WSHelperVerifyKey function.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Start WSHelperVerifyKey.
|
||||||
|
*/
|
||||||
|
//error_log(print_r($params,1));
|
||||||
|
$check_ip = false;
|
||||||
|
$ip = trim($_SERVER['REMOTE_ADDR']);
|
||||||
|
// if we are behind a reverse proxy, assume it will send the
|
||||||
|
// HTTP_X_FORWARDED_FOR header and use this IP instead
|
||||||
|
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||||
|
list($ip1, $ip2) = split(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
|
||||||
|
$ip = trim($ip1);
|
||||||
|
}
|
||||||
|
// Check if a file that limits access from webservices exists and contains
|
||||||
|
// the restraining check
|
||||||
|
if (is_file(api_get_path(WEB_CODE_PATH).'webservices/webservice-auth-ip.conf.php')) {
|
||||||
|
include api_get_path(WEB_CODE_PATH).'webservices/webservice-auth-ip.conf.php';
|
||||||
|
if (!empty($ws_auth_ip)) {
|
||||||
|
$check_ip = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
global $_configuration;
|
||||||
|
if ($check_ip) {
|
||||||
|
$security_key = $_configuration['security_key'];
|
||||||
|
} else {
|
||||||
|
$security_key = $ip.$_configuration['security_key'];
|
||||||
|
//error_log($secret_key.'-'.$security_key);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* End WSHelperVerifyKey.
|
||||||
|
*/
|
||||||
|
$params['secret_key'] = sha1($security_key);
|
||||||
|
|
||||||
|
// Registration soap wsdl
|
||||||
|
$wsUrl = api_get_path(WEB_CODE_PATH).'webservices/registration.soap.php?wsdl';
|
||||||
|
$options = [
|
||||||
|
'location' => $wsUrl,
|
||||||
|
'uri' => $wsUrl,
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WS test.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
// Init soap client
|
||||||
|
$client = new SoapClient(null, $options);
|
||||||
|
// Soap call to WS
|
||||||
|
$result = $client->__soapCall('HookAdvancedSubscription..WSSessionGetDetailsByUser', [$params]);
|
||||||
|
if (is_object($result) && isset($result->action_url)) {
|
||||||
|
echo '<br />';
|
||||||
|
echo Display::url("message".$result->message, $result->action_url);
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
var_dump($e);
|
||||||
|
}
|
||||||
18
plugin/advanced_subscription/uninstall.php
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
/**
|
||||||
|
* This script is included by main/admin/settings.lib.php when unselecting a plugin
|
||||||
|
* and is meant to remove things installed by the install.php script in both
|
||||||
|
* the global database and the courses tables.
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.advanced_subscription
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries.
|
||||||
|
*/
|
||||||
|
require_once __DIR__.'/config.php';
|
||||||
|
if (!api_is_platform_admin()) {
|
||||||
|
exit('You must have admin permissions to uninstall plugins');
|
||||||
|
}
|
||||||
|
AdvancedSubscriptionPlugin::create()->uninstall();
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ "MailTitle"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name) }}</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/header.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td width="394"><img src="{{ _p.web_css }}/themes/{{ "stylesheets"|api_get_setting }}/images/header-logo.png" width="230" height="60" alt="Ministerio de Educación"></td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td style="color: #93c5cd; font-family: Times New Roman, Times, serif; font-size: 24px; font-weight: bold; border-bottom-width: 2px; border-bottom-style: solid; border-bottom-color: #93c5cd;">{{ "MailTitleAdminAcceptToAdmin"| get_plugin_lang('AdvancedSubscriptionPlugin') }}</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td height="356"> </td>
|
||||||
|
<td valign="top"><p>{{ "MailDear" | get_plugin_lang('AdvancedSubscriptionPlugin') }}</p>
|
||||||
|
<h2>{{ admin.complete_name }}</h2>
|
||||||
|
<p>{{ "MailContentAdminAcceptToAdmin" | get_plugin_lang('AdvancedSubscriptionPlugin') | format(student.complete_name_with_username, session.name) }}</p>
|
||||||
|
<p>{{ "MailThankYou" | get_plugin_lang('AdvancedSubscriptionPlugin') }}</p>
|
||||||
|
<h3>{{ signature }}</h3></td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
</table></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/footer.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ "MailTitle" | get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name) }}</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/header.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td width="394"><img src="{{ _p.web_css }}/themes/{{ "stylesheets"|api_get_setting }}/images/header-logo.png" width="230" height="60" alt="Ministerio de Educación"></td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td style="color: #93c5cd; font-family: Times New Roman, Times, serif; font-size: 24px; font-weight: bold; border-bottom-width: 2px; border-bottom-style: solid; border-bottom-color: #93c5cd;">{{ "MailTitleAdminAcceptToStudent" | get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name) }}</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td height="356"> </td>
|
||||||
|
<td valign="top"><p> {{ "MailDear" | get_plugin_lang('AdvancedSubscriptionPlugin') }} </p>
|
||||||
|
<h2>{{ student.complete_name }}</h2>
|
||||||
|
<p>{{ "MailContentAdminAcceptToStudent" | get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name, session.date_start) }}</p>
|
||||||
|
<p>{{ "MailThankYou" | get_plugin_lang('AdvancedSubscriptionPlugin') }}</p>
|
||||||
|
<h3>{{ signature }}</h3></td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
</table></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/footer.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ "MailTitle"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name) }}</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/header.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td width="394"><img src="{{ _p.web_css }}/themes/{{ "stylesheets"|api_get_setting }}/images/header-logo.png" width="230" height="60" alt="Ministerio de Educación"></td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td style="color: #93c5cd; font-family: Times New Roman, Times, serif; font-size: 24px; font-weight: bold; border-bottom-width: 2px; border-bottom-style: solid; border-bottom-color: #93c5cd;">{{ "MailTitleAdminAcceptToSuperior"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(student.complete_name, session.name) }}</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td height="356"> </td>
|
||||||
|
<td valign="top"><p>{{ "MailDear"| get_plugin_lang('AdvancedSubscriptionPlugin') }}</p>
|
||||||
|
<h2>{{ superior.complete_name }}</h2>
|
||||||
|
<p>{{ "MailContentAdminAcceptToSuperior"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(student.complete_name, session.name, session.date_start) }}</p>
|
||||||
|
<p>{{ "MailThankYou"| get_plugin_lang('AdvancedSubscriptionPlugin') }}</p>
|
||||||
|
<h3>{{ signature }}</h3></td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
</table></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/footer.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ "MailTitle"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name) }}</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/header.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td width="394"><img src="{{ _p.web_css }}/themes/{{ "stylesheets"|api_get_setting }}/images/header-logo.png" width="230" height="60" alt="Ministerio de Educación"></td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td style="color: #93c5cd; font-family: Times New Roman, Times, serif; font-size: 24px; font-weight: bold; border-bottom-width: 2px; border-bottom-style: solid; border-bottom-color: #93c5cd;">{{ "MailTitleAdminRejectToAdmin" | get_plugin_lang('AdvancedSubscriptionPlugin') }}</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td height="356"> </td>
|
||||||
|
<td valign="top"><p>{{ "MailDear" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h2>{{ admin.complete_name }}</h2>
|
||||||
|
<p>{{ "MailContentAdminRejectToAdmin"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(student.complete_name_with_username, session.name) }}</strong></p>
|
||||||
|
<p>{{ "MailThankYou" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h3>{{ signature }}</h3></td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
</table></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/footer.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ "MailTitle"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name) }}</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/header.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td width="394"><img src="{{ _p.web_css }}/themes/{{ "stylesheets"|api_get_setting }}/images/header-logo.png" width="230" height="60" alt="Ministerio de Educación"></td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td style="color: #93c5cd; font-family: Times New Roman, Times, serif; font-size: 24px; font-weight: bold; border-bottom-width: 2px; border-bottom-style: solid; border-bottom-color: #93c5cd;">{{ "MailTitleAdminRejectToStudent"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name) }}</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td height="356"> </td>
|
||||||
|
<td valign="top"><p>{{ "MailDear" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h2>{{ student.complete_name }}</h2>
|
||||||
|
<p>{{ "MailContentAdminRejectToStudent"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name, session.date_start) }}</p>
|
||||||
|
<p>{{ "MailThankYou" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h3>{{ signature }}</h3></td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
</table></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/footer.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ "MailTitle"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name) }}</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/header.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td width="394"><img src="{{ _p.web_css }}/themes/{{ "stylesheets"|api_get_setting }}/images/header-logo.png" width="230" height="60" alt="Ministerio de Educación"></td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td style="color: #93c5cd; font-family: Times New Roman, Times, serif; font-size: 24px; font-weight: bold; border-bottom-width: 2px; border-bottom-style: solid; border-bottom-color: #93c5cd;">{{ "MailTitleAdminRejectToSuperior"| get_plugin_lang("AdvancedSubscriptionPlugin") | format(student.complete_name, session.name) }}</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td height="356"> </td>
|
||||||
|
<td valign="top"><p>{{ "MailDear" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h2>{{ superior.complete_name }}</h2>
|
||||||
|
<p>{{ "MailContentAdminRejectToSuperior"| get_plugin_lang("AdvancedSubscriptionPlugin") | format(student.complete_name, session.name) }}</p>
|
||||||
|
<p>{{ "MailThankYou" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h3>{{ signature }}</h3></td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
</table></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/footer.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
167
plugin/advanced_subscription/views/admin_view.tpl
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
<form id="form_advanced_subscription_admin" class="form-search" method="post" action="/plugin/advanced_subscription/src/admin_view.php" name="form_advanced_subscription_admin">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<p class="text-title-select">{{ 'SelectASession' | get_plugin_lang('AdvancedSubscriptionPlugin') }}</p>
|
||||||
|
<select id="session-select" name="s">
|
||||||
|
<option value="0">
|
||||||
|
{{ "SelectASession" | get_plugin_lang('AdvancedSubscriptionPlugin') }}
|
||||||
|
</option>
|
||||||
|
{% for sessionItem in sessionItems %}
|
||||||
|
<option value="{{ sessionItem.id }}" {{ sessionItem.selected }}>
|
||||||
|
{{ sessionItem.name }}
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<h4>{{ "SessionName" | get_plugin_lang('AdvancedSubscriptionPlugin') }}</h4>
|
||||||
|
<h3 class="title-name-session">{{ session.name }}</h3>
|
||||||
|
<h4>{{ "Target" | get_plugin_lang('AdvancedSubscriptionPlugin') }}</h4>
|
||||||
|
<p>{{ session.target }}</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<p class="separate-badge">
|
||||||
|
<span class="badge badge-dis">{{ session.vacancies }}</span>
|
||||||
|
{{ "Vacancies" | get_plugin_lang('AdvancedSubscriptionPlugin') }}</p>
|
||||||
|
<p class="separate-badge">
|
||||||
|
<span class="badge badge-info">{{ session.nbr_users }}</span>
|
||||||
|
{{ 'CountOfSubscribedUsers'|get_lang }}
|
||||||
|
</p>
|
||||||
|
<p class="separate-badge">
|
||||||
|
<span class="badge badge-recom">{{ session.recommended_number_of_participants }}</span>
|
||||||
|
{{ "RecommendedNumberOfParticipants" | get_plugin_lang('AdvancedSubscriptionPlugin') }}</p>
|
||||||
|
<h4>{{ "PublicationEndDate" | get_plugin_lang('AdvancedSubscriptionPlugin') }}</h4> <p>{{ session.publication_end_date }}</p>
|
||||||
|
<h4>{{ "Mode" | get_plugin_lang('AdvancedSubscriptionPlugin') }}</h4> <p>{{ session.mode }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="student-list-table">
|
||||||
|
<table id="student_table" class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{{ "Postulant" | get_plugin_lang('AdvancedSubscriptionPlugin') }}</th>
|
||||||
|
<th>{{ "InscriptionDate" | get_plugin_lang('AdvancedSubscriptionPlugin') }}</th>
|
||||||
|
<th>{{ "Area" | get_plugin_lang('AdvancedSubscriptionPlugin') }}</th>
|
||||||
|
<th>{{ "Institution" | get_plugin_lang('AdvancedSubscriptionPlugin') }}</th>
|
||||||
|
<th>{{ "BossValidation" | get_plugin_lang('AdvancedSubscriptionPlugin') }}</th>
|
||||||
|
<th class="advanced-subscription-decision-column">{{ "Decision" | get_plugin_lang('AdvancedSubscriptionPlugin') }}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% set row_class = "row_odd" %}
|
||||||
|
{% for student in students %}
|
||||||
|
<tr class="{{ row_class }}">
|
||||||
|
<td class="name">
|
||||||
|
<a href="{{ student.userLink }}" target="_blank">{{ student.complete_name }}<a>
|
||||||
|
</td>
|
||||||
|
<td>{{ student.created_at }}</td>
|
||||||
|
<td>{{ student.area }}</td>
|
||||||
|
<td>{{ student.institution }}</td>
|
||||||
|
{% set cellClass = 'danger'%}
|
||||||
|
{% if student.validation == 'Yes' %}
|
||||||
|
{% set cellClass = 'success'%}
|
||||||
|
{% endif %}
|
||||||
|
<td>
|
||||||
|
{% if student.validation != '' %}
|
||||||
|
<span class="label label-{{ cellClass }}">
|
||||||
|
{{ student.validation | get_plugin_lang('AdvancedSubscriptionPlugin') }}
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if student.status != approveAdmin and student.status != disapproveAdmin %}
|
||||||
|
<a
|
||||||
|
class="btn btn-success btn-advanced-subscription btn-accept"
|
||||||
|
href="{{ student.acceptUrl }}"
|
||||||
|
>
|
||||||
|
{{ 'AcceptInfinitive' | get_plugin_lang('AdvancedSubscriptionPlugin') }}
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
class="btn btn-danger btn-advanced-subscription btn-reject"
|
||||||
|
href="{{ student.rejectUrl }}"
|
||||||
|
>
|
||||||
|
{{ 'RejectInfinitive' | get_plugin_lang('AdvancedSubscriptionPlugin') }}
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
|
{% if student.status == approveAdmin%}
|
||||||
|
<span class="label label-success">{{ 'Accepted'|get_lang }}</span>
|
||||||
|
{% elseif student.status == disapproveAdmin %}
|
||||||
|
<span class="label label-danger">{{ 'Rejected'|get_lang }}</span>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% if row_class == "row_even" %}
|
||||||
|
{% set row_class = "row_odd" %}
|
||||||
|
{% else %}
|
||||||
|
{% set row_class = "row_even" %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input name="f" value="social" type="hidden">
|
||||||
|
</form>
|
||||||
|
<div class="modal fade" id="modalMail" tabindex="-1" role="dialog" aria-labelledby="modalMailLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-lg">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
|
<h4 class="modal-title" id="modalMailLabel">{{ "AdvancedSubscriptionAdminViewTitle" | get_plugin_lang('AdvancedSubscriptionPlugin')}}</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<iframe id="iframeAdvsub" frameBorder="0">
|
||||||
|
</iframe>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-primary" data-dismiss="modal">Cerrar</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<link href="{{ _p.web_plugin }}advanced_subscription/views/css/style.css" rel="stylesheet" type="text/css">
|
||||||
|
<script>
|
||||||
|
$(document).ready(function(){
|
||||||
|
$("#session-select").change(function () {
|
||||||
|
$("#form_advanced_subscription_admin").submit();
|
||||||
|
});
|
||||||
|
$("a.btn-advanced-subscription").click(function(event){
|
||||||
|
event.preventDefault();
|
||||||
|
var confirmed = false;
|
||||||
|
var studentName = $.trim($(this).closest("tr").find(".name").text());
|
||||||
|
if (studentName) {
|
||||||
|
;
|
||||||
|
} else {
|
||||||
|
studentName = "";
|
||||||
|
}
|
||||||
|
var msgRe = /%s/;
|
||||||
|
if ($(this).hasClass('btn-accept')) {
|
||||||
|
var msg = "{{ 'AreYouSureYouWantToAcceptSubscriptionOfX' | get_plugin_lang('AdvancedSubscriptionPlugin') }}";
|
||||||
|
var confirmed = confirm(msg.replace(msgRe, studentName));
|
||||||
|
} else {
|
||||||
|
var msg = "{{ 'AreYouSureYouWantToRejectSubscriptionOfX' | get_plugin_lang('AdvancedSubscriptionPlugin') }}";
|
||||||
|
var confirmed = confirm(msg.replace(msgRe, studentName));
|
||||||
|
}
|
||||||
|
if (confirmed) {
|
||||||
|
var tdParent = $(this).closest("td");
|
||||||
|
var advancedSubscriptionUrl = $(this).attr("href");
|
||||||
|
$("#iframeAdvsub").attr("src", advancedSubscriptionUrl);
|
||||||
|
$("#modalMail").modal("show");
|
||||||
|
$.ajax({
|
||||||
|
dataType: "json",
|
||||||
|
url: advancedSubscriptionUrl
|
||||||
|
}).done(function(result){
|
||||||
|
if (result.error === true) {
|
||||||
|
tdParent.html('');
|
||||||
|
} else {
|
||||||
|
console.log(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
84
plugin/advanced_subscription/views/css/style.css
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
.text-title-select{
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
#session-select{
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.title-name-session{
|
||||||
|
display: block;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
font-weight: normal;
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
.badge-dis{
|
||||||
|
background-color: #008080;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
.badge-recom{
|
||||||
|
background-color:#88aa00 ;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
.badge-info {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
.separate-badge{
|
||||||
|
margin-bottom: 20px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
.date, .mode{
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.img-circle{
|
||||||
|
border-radius: 500px;
|
||||||
|
-moz-border-radius: 500px;
|
||||||
|
-webkit-border-radius: 500px;
|
||||||
|
}
|
||||||
|
#student_table.table td{
|
||||||
|
vertical-align: middle;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
#student_table.table td.name{
|
||||||
|
color: #084B8A;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
}
|
||||||
|
#student_table.table th{
|
||||||
|
font-size: 14px;
|
||||||
|
vertical-align: middle;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#modalMail .modal-body {
|
||||||
|
height: 360px;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
#iframeAdvsub {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legal-terms-popup{
|
||||||
|
margin-top: 5%;
|
||||||
|
margin-left: 5%;
|
||||||
|
margin-right: 5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legal-terms{
|
||||||
|
width: 90%;
|
||||||
|
height: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legal-terms-buttons {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legal-terms-title {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advanced-subscription-decision-column {
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
BIN
plugin/advanced_subscription/views/img/aprobar.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
plugin/advanced_subscription/views/img/avatar.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
plugin/advanced_subscription/views/img/desaprobar.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
plugin/advanced_subscription/views/img/footer.png
Normal file
|
After Width: | Height: | Size: 270 B |
BIN
plugin/advanced_subscription/views/img/header.png
Normal file
|
After Width: | Height: | Size: 267 B |
BIN
plugin/advanced_subscription/views/img/icon-avatar.png
Normal file
|
After Width: | Height: | Size: 493 B |
BIN
plugin/advanced_subscription/views/img/line.png
Normal file
|
After Width: | Height: | Size: 283 B |
54
plugin/advanced_subscription/views/open_session.tpl
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<link href="{{ _p.web_plugin }}advanced_subscription/views/css/style.css" rel="stylesheet" type="text/css">
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(function () {
|
||||||
|
$('#asp-close-window').on('click', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
window.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#asp-go-to').on('click', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
window.close();
|
||||||
|
window.opener.location.href = '{{ _p.web_main ~ 'session/index.php?session_id=' ~ session.id }}';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<h2 class="legal-terms-title legal-terms-popup">
|
||||||
|
{{ "SubscriptionToOpenSession"|get_plugin_lang('AdvancedSubscriptionPlugin') }}
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
{% if not is_subscribed %}
|
||||||
|
<div class="alert alert-warning legal-terms-popup">
|
||||||
|
<ul>
|
||||||
|
{% for errorMessage in errorMessages %}
|
||||||
|
<li>{{ errorMessage }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="legal-terms-buttons legal-terms-popup">
|
||||||
|
<a
|
||||||
|
class="btn btn-success btn-advanced-subscription btn-accept"
|
||||||
|
href="#" id="asp-close-window">
|
||||||
|
<em class="fa fa-check"></em>
|
||||||
|
{{ "AcceptInfinitive"|get_plugin_lang('AdvancedSubscriptionPlugin') }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="alert alert-success legal-terms-popup">
|
||||||
|
{{ 'SuccessSubscriptionToSessionX'|get_plugin_lang('AdvancedSubscriptionPlugin')|format(session.name) }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-right legal-terms-popup">
|
||||||
|
<a
|
||||||
|
class="btn btn-success btn-advanced-subscription btn-accept"
|
||||||
|
href="#" id="asp-go-to">
|
||||||
|
<em class="fa fa-external-link"></em>
|
||||||
|
{{ "GoToSessionX"|get_plugin_lang('AdvancedSubscriptionPlugin')|format(session.name) }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
75
plugin/advanced_subscription/views/reminder_notice_admin.tpl
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ "MailTitle"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name) }}</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/header.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td width="394"><img src="{{ _p.web_css }}/themes/{{ "stylesheets"|api_get_setting }}/images/header-logo.png" width="230" height="60" alt="Ministerio de Educación"></td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td style="color: #93c5cd; font-family: Times New Roman, Times, serif; font-size: 24px; font-weight: bold; border-bottom-width: 2px; border-bottom-style: solid; border-bottom-color: #93c5cd;">{{ "MailTitleReminderAdmin" | get_plugin_lang("AdvancedSubscriptionPlugin") | format(session.name)}}</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td height="356"> </td>
|
||||||
|
<td valign="top"><p>{{ "MailDear" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h2>{{ admin.complete_name }}</h2>
|
||||||
|
<p>{{ "MailContentReminderAdmin" | get_plugin_lang("AdvancedSubscriptionPlugin") | format(session.name, admin_view_url)}}</p>
|
||||||
|
<p>{{ "MailThankYou" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h3>{{ signature }}</h3></td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
</table></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/footer.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ "MailTitle"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name) }}</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/header.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td width="394"><img src="{{ _p.web_css }}/themes/{{ "stylesheets"|api_get_setting }}/images/header-logo.png" width="230" height="60" alt="Ministerio de Educación"></td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td style="color: #93c5cd; font-family: Times New Roman, Times, serif; font-size: 24px; font-weight: bold; border-bottom-width: 2px; border-bottom-style: solid; border-bottom-color: #93c5cd;">{{ "MailTitleReminderStudent"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name) }}</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td height="356"> </td>
|
||||||
|
<td valign="top"><p>{{ "MailDear" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h2>{{ student.complete_name }}</h2>
|
||||||
|
<p>{{ "MailContentReminderStudent"| get_plugin_lang("AdvancedSubscriptionPlugin") | format(session.name, session.date_start) }}</p>
|
||||||
|
<p>{{ "MailContentReminderStudentSecond"| get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<p>{{ "MailThankYouCollaboration"| get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<p>{{ signature }}</p></td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
</table></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/footer.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ "MailTitle"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name) }}</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/header.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td width="394"><img src="{{ _p.web_css }}/themes/{{ "stylesheets"|api_get_setting }}/images/header-logo.png" width="230" height="60" alt="Ministerio de Educación"></td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td style="color: #93c5cd; font-family: Times New Roman, Times, serif; font-size: 24px; font-weight: bold; border-bottom-width: 2px; border-bottom-style: solid; border-bottom-color: #93c5cd;">{{ "MailTitleReminderSuperior" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td height="356"> </td>
|
||||||
|
<td valign="top"><p>{{ "MailDear" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h2>{{ superior.complete_name }}</h2>
|
||||||
|
<p>{{ "MailContentReminderSuperior" | get_plugin_lang("AdvancedSubscriptionPlugin") | format(session.name, session.date_start, session.description) }}</p>
|
||||||
|
<p>{{ "MailContentReminderSuperiorSecond" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<table width="100%" border="0" cellspacing="3" cellpadding="4" style="background:#EDE9EA">
|
||||||
|
{% for student in students %}
|
||||||
|
<tr>
|
||||||
|
<td valign="middle"><img src="{{ student.avatar }}" width="50" height="50" alt=""></td>
|
||||||
|
<td valign="middle"><h4>{{ student.complete_name }}</h4></td>
|
||||||
|
<td valign="middle"><a href="{{ student.acceptUrl }}"><img src="{{ _p.web_plugin }}advanced_subscription/views/img/aprobar.png" width="90" height="25" alt=""></a></td>
|
||||||
|
<td valign="middle"><a href="{{ student.rejectUrl }}"><img src="{{ _p.web_plugin }}advanced_subscription/views/img/desaprobar.png" width="90" height="25" alt=""></a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
<p>{{ "MailThankYou" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<p>{{ signature }}</p></td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
</table></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/footer.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ "MailTitle"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name) }}</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/header.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td width="394"><img src="{{ _p.web_css }}/themes/{{ "stylesheets"|api_get_setting }}/images/header-logo.png" width="230" height="60" alt="Ministerio de Educación"></td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td style="color: #93c5cd; font-family: Times New Roman, Times, serif; font-size: 24px; font-weight: bold; border-bottom-width: 2px; border-bottom-style: solid; border-bottom-color: #93c5cd;">{{ "MailTitleReminderMaxSuperior" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td height="356"> </td>
|
||||||
|
<td valign="top">
|
||||||
|
<p>{{ "MailDear" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h2>{{ superior.complete_name }}</h2>
|
||||||
|
<p>{{ "MailContentReminderMaxSuperior" | get_plugin_lang("AdvancedSubscriptionPlugin") | format(session.name, session.date_start, session.description) }}</p>
|
||||||
|
<p>{{ "MailContentReminderMaxSuperiorSecond" | get_plugin_lang("AdvancedSubscriptionPlugin") | format(session.recommended_number_of_participants) }}</p>
|
||||||
|
<table width="100%" border="0" cellspacing="3" cellpadding="4" style="background:#EDE9EA">
|
||||||
|
{% for student in students %}
|
||||||
|
<tr>
|
||||||
|
<td valign="middle"><img src="{{ student.avatar }}" width="50" height="50" alt=""></td>
|
||||||
|
<td valign="middle"><h4>{{ student.complete_name }}</h4></td>
|
||||||
|
<td valign="middle"><a href="{{ student.acceptUrl }}"><img src="{{ _p.web_plugin }}advanced_subscription/views/img/aprobar.png" width="90" height="25" alt=""></a></td>
|
||||||
|
<td valign="middle"><a href="{{ student.rejectUrl }}"><img src="{{ _p.web_plugin }}advanced_subscription/views/img/desaprobar.png" width="90" height="25" alt=""></a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
<p>{{ "MailThankYou" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h3>{{ signature }}</h3></td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
</table></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/footer.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ "MailTitle"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name) }}</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/header.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td width="394"><img src="{{ _p.web_css }}/themes/{{ "stylesheets"|api_get_setting }}/images/header-logo.png" width="230" height="60" alt="Ministerio de Educación"></td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td style="color: #93c5cd; font-family: Times New Roman, Times, serif; font-size: 24px; font-weight: bold; border-bottom-width: 2px; border-bottom-style: solid; border-bottom-color: #93c5cd;">{{ "MailTitleStudentRequestNoSuperiorToAdmin"| get_plugin_lang("AdvancedSubscriptionPlugin") | format(student.complete_name, session.name) }}</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td height="356"> </td>
|
||||||
|
<td valign="top"><p>{{ "MailDear" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h2>{{ admin.complete_name }}</h2>
|
||||||
|
<p>{{ "MailContentStudentRequestNoSuperiorToAdmin"| get_plugin_lang("AdvancedSubscriptionPlugin") | format(student.complete_name_with_username, session.name, admin_view_url) }}</p>
|
||||||
|
<p>{{ "MailThankYou" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h3>{{ signature }}</h3></td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
</table></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/footer.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ "MailTitle"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name) }}</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/header.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td width="394"><img src="{{ _p.web_css }}/themes/{{ "stylesheets"|api_get_setting }}/images/header-logo.png" width="230" height="60" alt="Ministerio de Educación"></td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td style="color: #93c5cd; font-family: Times New Roman, Times, serif; font-size: 24px; font-weight: bold; border-bottom-width: 2px; border-bottom-style: solid; border-bottom-color: #93c5cd;">{{ "MailTitleStudentRequestNoSuperiorToStudent"| get_plugin_lang("AdvancedSubscriptionPlugin") | format(session.name) }}</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td height="356"> </td>
|
||||||
|
<td valign="top"><p>{{ "MailDear" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h2>{{ student.complete_name }}</h2>
|
||||||
|
<p>{{ "MailContentStudentRequestNoSuperiorToStudent"| get_plugin_lang("AdvancedSubscriptionPlugin") | format(session.name, session.date_start) }}</p>
|
||||||
|
<p>{{ "MailContentStudentRequestNoSuperiorToStudentSecond"| get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<p>{{ "MailThankYou" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<p>{{ signature }}</p></td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
</table></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/footer.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ "MailTitle"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name) }}</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/header.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td width="394"><img src="{{ _p.web_css }}/themes/{{ "stylesheets"|api_get_setting }}/images/header-logo.png" width="230" height="60" alt="Ministerio de Educación"></td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td style="color: #93c5cd; font-family: Times New Roman, Times, serif; font-size: 24px; font-weight: bold; border-bottom-width: 2px; border-bottom-style: solid; border-bottom-color: #93c5cd;">{{ "MailTitleStudentRequestToStudent"| get_plugin_lang("AdvancedSubscriptionPlugin") | format(session.name) }}</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td height="356"> </td>
|
||||||
|
<td valign="top"><p>{{ "MailDear" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h2>{{ student.complete_name }}</h2>
|
||||||
|
<p>{{ "MailContentStudentRequestToStudent"| get_plugin_lang("AdvancedSubscriptionPlugin") | format(session.name, session.date_start) }}</p>
|
||||||
|
<p>{{ "MailContentStudentRequestToStudentSecond" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<p>{{ signature }}</p></td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
</table></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/footer.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ "MailTitle"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name) }}</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/header.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td width="394"><img src="{{ _p.web_css }}/themes/{{ "stylesheets"|api_get_setting }}/images/header-logo.png" width="230" height="60" alt="Ministerio de Educación"></td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td style="color: #93c5cd; font-family: Times New Roman, Times, serif; font-size: 24px; font-weight: bold; border-bottom-width: 2px; border-bottom-style: solid; border-bottom-color: #93c5cd;">{{ "MailTitleStudentRequestToSuperior" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td height="356"> </td>
|
||||||
|
<td valign="top"><p>{{ "MailDear" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h2>{{ superior.complete_name }}</h2>
|
||||||
|
<p>{{ "MailContentStudentRequestToSuperior" | get_plugin_lang("AdvancedSubscriptionPlugin") | format(student.complete_name, session.name, session.date_start, session.description) }}</p>
|
||||||
|
<p>{{ "MailContentStudentRequestToSuperiorSecond" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<table width="100%" border="0" cellspacing="3" cellpadding="4" style="background:#EDE9EA">
|
||||||
|
<tr>
|
||||||
|
<td width="58" valign="middle"><img src="{{ student.picture.file }}" width="50" height="50" alt=""></td>
|
||||||
|
<td width="211" valign="middle"><h4>{{ student.complete_name }}</h4></td>
|
||||||
|
<td width="90" valign="middle"><a href="{{ student.acceptUrl }}&modal_size=lg" class="ajax"><img src="{{ _p.web_plugin }}advanced_subscription/views/img/aprobar.png" width="90" height="25" alt=""></a></td>
|
||||||
|
<td width="243" valign="middle"><a href="{{ student.rejectUrl }}&modal_size=lg" class="ajax"><img src="{{ _p.web_plugin }}advanced_subscription/views/img/desaprobar.png" width="90" height="25" alt=""></a></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<p>{{ "MailThankYou" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<p>{{ signature }}</p></td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
</table></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/footer.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ "MailTitle"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name) }}</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/header.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td width="394"><img src="{{ _p.web_css }}/themes/{{ "stylesheets"|api_get_setting }}/images/header-logo.png" width="230" height="60" alt="Ministerio de Educación"></td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td style="color: #93c5cd; font-family: Times New Roman, Times, serif; font-size: 24px; font-weight: bold; border-bottom-width: 2px; border-bottom-style: solid; border-bottom-color: #93c5cd;">{{ "MailTitleSuperiorAcceptToAdmin"| get_plugin_lang("AdvancedSubscriptionPlugin") | format(student.complete_name, session.name) }}</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td height="356"> </td>
|
||||||
|
<td valign="top"><p>{{ "MailDear" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h2>{{ admin.complete_name }}</h2>
|
||||||
|
<p>{{ "MailContentSuperiorAcceptToAdmin"| get_plugin_lang("AdvancedSubscriptionPlugin") | format(student.complete_name_with_username, session.name, admin_view_url) }}</p>
|
||||||
|
<p>{{ "MailThankYou" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h3>{{ signature }}</h3></td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
</table></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/footer.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ "MailTitle"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name) }}</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/header.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td width="394"><img src="{{ _p.web_css }}/themes/{{ "stylesheets"|api_get_setting }}/images/header-logo.png" width="230" height="60" alt="Ministerio de Educación"></td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td style="color: #93c5cd; font-family: Times New Roman, Times, serif; font-size: 24px; font-weight: bold; border-bottom-width: 2px; border-bottom-style: solid; border-bottom-color: #93c5cd;">{{ "MailTitleSuperiorAcceptToStudent" | get_plugin_lang("AdvancedSubscriptionPlugin") | format(session.name) }}</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td height="356"> </td>
|
||||||
|
<td valign="top">
|
||||||
|
<p>{{ "MailDear" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h2>{{ student.complete_name }}</h2>
|
||||||
|
<p>{{ "MailContentSuperiorAcceptToStudent" | get_plugin_lang("AdvancedSubscriptionPlugin") | format(session.name ) }}</p>
|
||||||
|
<p>{{ "MailThankYou" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h3>{{ signature }}</h3></td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
</table></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/footer.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ "MailTitle"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name) }}</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/header.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td width="394"><img src="{{ _p.web_css }}/themes/{{ "stylesheets"|api_get_setting }}/images/header-logo.png" width="230" height="60" alt="Ministerio de Educación"></td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td style="color: #93c5cd; font-family: Times New Roman, Times, serif; font-size: 24px; font-weight: bold; border-bottom-width: 2px; border-bottom-style: solid; border-bottom-color: #93c5cd;">{{ "MailTitleSuperiorAcceptToSuperior"| get_plugin_lang("AdvancedSubscriptionPlugin") | format(student.complete_name) }}</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td height="356"> </td>
|
||||||
|
<td valign="top"><p>{{ "MailDear" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h2>{{ superior.complete_name }}</h2>
|
||||||
|
<p>{{ "MailContentSuperiorAcceptToSuperior"| get_plugin_lang("AdvancedSubscriptionPlugin") | format(session.name, student.complete_name) }}</p>
|
||||||
|
<p>{{ "MailContentSuperiorAcceptToSuperiorSecond"| get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<p>{{ "MailThankYouCollaboration" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h3>{{ signature }}</h3></td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
</table></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/footer.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ "MailTitle"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name) }}</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/header.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td width="394"><img src="{{ _p.web_css }}/themes/{{ "stylesheets"|api_get_setting }}/images/header-logo.png" width="230" height="60" alt="Ministerio de Educación"></td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td style="color: #93c5cd; font-family: Times New Roman, Times, serif; font-size: 24px; font-weight: bold; border-bottom-width: 2px; border-bottom-style: solid; border-bottom-color: #93c5cd;">{{ "MailTitleSuperiorRejectToStudent" | get_plugin_lang("AdvancedSubscriptionPlugin") | format(session.name) }}</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td height="356"> </td>
|
||||||
|
<td valign="top"><p>{{ "MailDear" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h2>{{ student.complete_name }}</h2>
|
||||||
|
<p>{{ "MailContentSuperiorRejectToStudent" | get_plugin_lang("AdvancedSubscriptionPlugin") | format(session.name) }}</p>
|
||||||
|
<p>{{ "MailThankYou" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h3>{{ signature }}</h3></td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
</table></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/footer.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ "MailTitle"| get_plugin_lang('AdvancedSubscriptionPlugin') | format(session.name) }}</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/header.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><table width="700" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td width="394"><img src="{{ _p.web_css }}/themes/{{ "stylesheets"|api_get_setting }}/images/header-logo.png" width="230" height="60" alt="Ministerio de Educación"></td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td style="color: #93c5cd; font-family: Times New Roman, Times, serif; font-size: 24px; font-weight: bold; border-bottom-width: 2px; border-bottom-style: solid; border-bottom-color: #93c5cd;">{{ "MailTitleSuperiorRejectToSuperior"| get_plugin_lang("AdvancedSubscriptionPlugin") | format(student.complete_name) }}</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td height="356"> </td>
|
||||||
|
<td valign="top"><p>{{ "MailDear" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h2>{{ superior.complete_name }}</h2>
|
||||||
|
<p>{{ "MailContentSuperiorRejectToSuperior"| get_plugin_lang("AdvancedSubscriptionPlugin") | format(session.name, student.complete_name) }}</p>
|
||||||
|
<p>{{ "MailThankYouCollaboration" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
|
||||||
|
<h3>{{ signature }}</h3></td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="50"> </td>
|
||||||
|
<td> </td>
|
||||||
|
<td width="50"> </td>
|
||||||
|
</tr>
|
||||||
|
</table></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/line.png" width="700" height="25" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ _p.web_plugin }}advanced_subscription/views/img/footer.png" width="700" height="20" alt=""></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
61
plugin/advanced_subscription/views/terms_and_conditions.tpl
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
{# start copy from head.tpl #}
|
||||||
|
<meta charset="{{ system_charset }}" />
|
||||||
|
<link href="https://chamilo.org/chamilo-lms/" rel="help" />
|
||||||
|
<link href="https://chamilo.org/the-association/" rel="author" />
|
||||||
|
<link href="https://chamilo.org/the-association/" rel="copyright" />
|
||||||
|
{{ prefetch }}
|
||||||
|
{{ favico }}
|
||||||
|
{{ browser_specific_head }}
|
||||||
|
<link rel="apple-touch-icon" href="{{ _p.web }}apple-touch-icon.png" />
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
|
<meta name="Generator" content="{{ _s.software_name }} {{ _s.system_version|slice(0,1) }}" />
|
||||||
|
{# Use the latest engine in ie8/ie9 or use google chrome engine if available #}
|
||||||
|
{# Improve usability in portal devices #}
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>{{ title_string }}</title>
|
||||||
|
{{ css_static_file_to_string }}
|
||||||
|
{{ js_file_to_string }}
|
||||||
|
{{ css_custom_file_to_string }}
|
||||||
|
{{ css_style_print }}
|
||||||
|
{# end copy from head.tpl #}
|
||||||
|
<h2 class="legal-terms-title legal-terms-popup">
|
||||||
|
{{ "TermsAndConditions" | get_lang }}
|
||||||
|
</h2>
|
||||||
|
{% if termsRejected == 1 %}
|
||||||
|
<div class="error-message legal-terms-popup">
|
||||||
|
{{ "YouMustAcceptTermsAndConditions" | get_plugin_lang("AdvancedSubscriptionPlugin") | format(session.name) }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if errorMessages is defined %}
|
||||||
|
<div class="alert alert-warning legal-terms-popup">
|
||||||
|
<ul>
|
||||||
|
{% for errorMessage in errorMessages %}
|
||||||
|
<li>{{ errorMessage }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="legal-terms legal-terms-popup">
|
||||||
|
{{ termsContent }}
|
||||||
|
</div>
|
||||||
|
<div class="legal-terms-files legal-terms-popup">
|
||||||
|
{{ termsFiles }}
|
||||||
|
</div>
|
||||||
|
<div class="legal-terms-buttons legal-terms-popup">
|
||||||
|
<a
|
||||||
|
class="btn btn-success btn-advanced-subscription btn-accept"
|
||||||
|
href="{{ acceptTermsUrl }}"
|
||||||
|
>
|
||||||
|
{{ "AcceptInfinitive" | get_plugin_lang("AdvancedSubscriptionPlugin") }}
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
class="btn btn-danger btn-advanced-subscription btn-reject"
|
||||||
|
href="{{ rejectTermsUrl }}"
|
||||||
|
>
|
||||||
|
{{ "RejectInfinitive" | get_plugin_lang("AdvancedSubscriptionPlugin") }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<link href="{{ _p.web_plugin }}advanced_subscription/views/css/style.css" rel="stylesheet" type="text/css">
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
{# start copy from head.tpl #}
|
||||||
|
<meta charset="{{ system_charset }}" />
|
||||||
|
<link href="https://chamilo.org/chamilo-lms/" rel="help" />
|
||||||
|
<link href="https://chamilo.org/the-association/" rel="author" />
|
||||||
|
<link href="https://chamilo.org/the-association/" rel="copyright" />
|
||||||
|
{{ prefetch }}
|
||||||
|
{{ favico }}
|
||||||
|
{{ browser_specific_head }}
|
||||||
|
<link rel="apple-touch-icon" href="{{ _p.web }}apple-touch-icon.png" />
|
||||||
|
<link href="{{ _p.web_plugin }}advanced_subscription/views/css/style.css" rel="stylesheet" type="text/css">
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
|
<meta name="Generator" content="{{ _s.software_name }} {{ _s.system_version|slice(0,1) }}" />
|
||||||
|
{# Use the latest engine in ie8/ie9 or use google chrome engine if available #}
|
||||||
|
{# Improve usability in portal devices #}
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>{{ title_string }}</title>
|
||||||
|
{{ css_file_to_string }}
|
||||||
|
{{ css_style_print }}
|
||||||
|
{{ js_file_to_string }}
|
||||||
|
{# end copy from head.tpl #}
|
||||||
|
<div class="legal-terms-popup">
|
||||||
|
{{ termsContent }}
|
||||||
|
</div>
|
||||||
241
plugin/ai_helper/AiHelperPlugin.php
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
<?php
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
|
||||||
|
use Chamilo\PluginBundle\Entity\AiHelper\Requests;
|
||||||
|
use Doctrine\ORM\Tools\SchemaTool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description of AiHelperPlugin.
|
||||||
|
*
|
||||||
|
* @author Christian Beeznest <christian.fasanando@beeznest.com>
|
||||||
|
*/
|
||||||
|
class AiHelperPlugin extends Plugin
|
||||||
|
{
|
||||||
|
public const TABLE_REQUESTS = 'plugin_ai_helper_requests';
|
||||||
|
public const OPENAI_API = 'openai';
|
||||||
|
|
||||||
|
protected function __construct()
|
||||||
|
{
|
||||||
|
$version = '1.1';
|
||||||
|
$author = 'Christian Fasanando';
|
||||||
|
|
||||||
|
$message = 'Description';
|
||||||
|
|
||||||
|
$settings = [
|
||||||
|
$message => 'html',
|
||||||
|
'tool_enable' => 'boolean',
|
||||||
|
'api_name' => [
|
||||||
|
'type' => 'select',
|
||||||
|
'options' => $this->getApiList(),
|
||||||
|
],
|
||||||
|
'api_key' => 'text',
|
||||||
|
'organization_id' => 'text',
|
||||||
|
'tool_lp_enable' => 'boolean',
|
||||||
|
'tool_quiz_enable' => 'boolean',
|
||||||
|
'tokens_limit' => 'text',
|
||||||
|
];
|
||||||
|
|
||||||
|
parent::__construct($version, $author, $settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of apis availables.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getApiList()
|
||||||
|
{
|
||||||
|
$list = [
|
||||||
|
self::OPENAI_API => 'OpenAI',
|
||||||
|
];
|
||||||
|
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the completion text from openai.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function openAiGetCompletionText(
|
||||||
|
string $prompt,
|
||||||
|
string $toolName
|
||||||
|
) {
|
||||||
|
if (!$this->validateUserTokensLimit(api_get_user_id())) {
|
||||||
|
return [
|
||||||
|
'error' => true,
|
||||||
|
'message' => $this->get_lang('ErrorTokensLimit'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once __DIR__.'/src/openai/OpenAi.php';
|
||||||
|
|
||||||
|
$apiKey = $this->get('api_key');
|
||||||
|
$organizationId = $this->get('organization_id');
|
||||||
|
|
||||||
|
$ai = new OpenAi($apiKey, $organizationId);
|
||||||
|
|
||||||
|
$temperature = 0.2;
|
||||||
|
$model = 'gpt-3.5-turbo-instruct';
|
||||||
|
$maxTokens = 2000;
|
||||||
|
$frequencyPenalty = 0;
|
||||||
|
$presencePenalty = 0.6;
|
||||||
|
$topP = 1.0;
|
||||||
|
|
||||||
|
$complete = $ai->completion([
|
||||||
|
'model' => $model,
|
||||||
|
'prompt' => $prompt,
|
||||||
|
'temperature' => $temperature,
|
||||||
|
'max_tokens' => $maxTokens,
|
||||||
|
'frequency_penalty' => $frequencyPenalty,
|
||||||
|
'presence_penalty' => $presencePenalty,
|
||||||
|
'top_p' => $topP,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$result = json_decode($complete, true);
|
||||||
|
$resultText = '';
|
||||||
|
if (!empty($result['choices'])) {
|
||||||
|
$resultText = $result['choices'][0]['text'];
|
||||||
|
// saves information of user results.
|
||||||
|
$values = [
|
||||||
|
'user_id' => api_get_user_id(),
|
||||||
|
'tool_name' => $toolName,
|
||||||
|
'prompt' => $prompt,
|
||||||
|
'prompt_tokens' => (int) $result['usage']['prompt_tokens'],
|
||||||
|
'completion_tokens' => (int) $result['usage']['completion_tokens'],
|
||||||
|
'total_tokens' => (int) $result['usage']['total_tokens'],
|
||||||
|
];
|
||||||
|
$this->saveRequest($values);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $resultText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates tokens limit of a user per current month.
|
||||||
|
*/
|
||||||
|
public function validateUserTokensLimit(int $userId): bool
|
||||||
|
{
|
||||||
|
$em = Database::getManager();
|
||||||
|
$repo = $em->getRepository('ChamiloPluginBundle:AiHelper\Requests');
|
||||||
|
|
||||||
|
$startDate = api_get_utc_datetime(
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
true)
|
||||||
|
->modify('first day of this month')->setTime(00, 00, 00)
|
||||||
|
;
|
||||||
|
$endDate = api_get_utc_datetime(
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
true)
|
||||||
|
->modify('last day of this month')->setTime(23, 59, 59)
|
||||||
|
;
|
||||||
|
|
||||||
|
$qb = $repo->createQueryBuilder('e')
|
||||||
|
->select('sum(e.totalTokens) as total')
|
||||||
|
->andWhere('e.requestedAt BETWEEN :dateMin AND :dateMax')
|
||||||
|
->andWhere('e.userId = :user')
|
||||||
|
->setMaxResults(1)
|
||||||
|
->setParameters(
|
||||||
|
[
|
||||||
|
'dateMin' => $startDate->format('Y-m-d h:i:s'),
|
||||||
|
'dateMax' => $endDate->format('Y-m-d h:i:s'),
|
||||||
|
'user' => $userId,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$result = $qb->getQuery()->getOneOrNullResult();
|
||||||
|
$totalTokens = !empty($result) ? (int) $result['total'] : 0;
|
||||||
|
|
||||||
|
$valid = true;
|
||||||
|
$tokensLimit = $this->get('tokens_limit');
|
||||||
|
if (!empty($tokensLimit)) {
|
||||||
|
$valid = ($totalTokens <= (int) $tokensLimit);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the plugin directory name.
|
||||||
|
*/
|
||||||
|
public function get_name(): string
|
||||||
|
{
|
||||||
|
return 'ai_helper';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the class instance.
|
||||||
|
*
|
||||||
|
* @staticvar AiHelperPlugin $result
|
||||||
|
*/
|
||||||
|
public static function create(): AiHelperPlugin
|
||||||
|
{
|
||||||
|
static $result = null;
|
||||||
|
|
||||||
|
return $result ?: $result = new self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save user information of openai request.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function saveRequest(array $values)
|
||||||
|
{
|
||||||
|
$em = Database::getManager();
|
||||||
|
|
||||||
|
$objRequest = new Requests();
|
||||||
|
$objRequest
|
||||||
|
->setUserId($values['user_id'])
|
||||||
|
->setToolName($values['tool_name'])
|
||||||
|
->setRequestedAt(new DateTime())
|
||||||
|
->setRequestText($values['prompt'])
|
||||||
|
->setPromptTokens($values['prompt_tokens'])
|
||||||
|
->setCompletionTokens($values['completion_tokens'])
|
||||||
|
->setTotalTokens($values['total_tokens'])
|
||||||
|
;
|
||||||
|
$em->persist($objRequest);
|
||||||
|
$em->flush();
|
||||||
|
|
||||||
|
return $objRequest->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Install the plugin. Set the database up.
|
||||||
|
*/
|
||||||
|
public function install()
|
||||||
|
{
|
||||||
|
$em = Database::getManager();
|
||||||
|
|
||||||
|
if ($em->getConnection()->getSchemaManager()->tablesExist([self::TABLE_REQUESTS])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$schemaTool = new SchemaTool($em);
|
||||||
|
$schemaTool->createSchema(
|
||||||
|
[
|
||||||
|
$em->getClassMetadata(Requests::class),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unistall plugin. Clear the database.
|
||||||
|
*/
|
||||||
|
public function uninstall()
|
||||||
|
{
|
||||||
|
$em = Database::getManager();
|
||||||
|
|
||||||
|
if (!$em->getConnection()->getSchemaManager()->tablesExist([self::TABLE_REQUESTS])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$schemaTool = new SchemaTool($em);
|
||||||
|
$schemaTool->dropSchema(
|
||||||
|
[
|
||||||
|
$em->getClassMetadata(Requests::class),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
171
plugin/ai_helper/Entity/Requests.php
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
<?php
|
||||||
|
/* For licensing terms, see /license.txt */
|
||||||
|
|
||||||
|
namespace Chamilo\PluginBundle\Entity\AiHelper;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Platform.
|
||||||
|
*
|
||||||
|
* @package Chamilo\PluginBundle\Entity\AiHelper
|
||||||
|
*
|
||||||
|
* @ORM\Table(name="plugin_ai_helper_requests")
|
||||||
|
* @ORM\Entity()
|
||||||
|
*/
|
||||||
|
class Requests
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*
|
||||||
|
* @ORM\Column(name="id", type="integer")
|
||||||
|
* @ORM\Id()
|
||||||
|
* @ORM\GeneratedValue()
|
||||||
|
*/
|
||||||
|
protected $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*
|
||||||
|
* @ORM\Column(name="user_id", type="integer")
|
||||||
|
*/
|
||||||
|
private $userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*
|
||||||
|
* @ORM\Column(name="tool_name", type="string")
|
||||||
|
*/
|
||||||
|
private $toolName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \DateTime
|
||||||
|
*
|
||||||
|
* @ORM\Column(name="requested_at", type="datetime", nullable=true)
|
||||||
|
*/
|
||||||
|
private $requestedAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*
|
||||||
|
* @ORM\Column(name="request_text", type="string")
|
||||||
|
*/
|
||||||
|
private $requestText;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*
|
||||||
|
* @ORM\Column(name="prompt_tokens", type="integer")
|
||||||
|
*/
|
||||||
|
private $promptTokens;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*
|
||||||
|
* @ORM\Column(name="completion_tokens", type="integer")
|
||||||
|
*/
|
||||||
|
private $completionTokens;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*
|
||||||
|
* @ORM\Column(name="total_tokens", type="integer")
|
||||||
|
*/
|
||||||
|
private $totalTokens;
|
||||||
|
|
||||||
|
public function getUserId(): int
|
||||||
|
{
|
||||||
|
return $this->userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUserId(int $userId): Requests
|
||||||
|
{
|
||||||
|
$this->userId = $userId;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getId(): int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setId(int $id): Requests
|
||||||
|
{
|
||||||
|
$this->id = $id;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRequestedAt(): \DateTime
|
||||||
|
{
|
||||||
|
return $this->requestedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setRequestedAt(\DateTime $requestedAt): Requests
|
||||||
|
{
|
||||||
|
$this->requestedAt = $requestedAt;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRequestText(): string
|
||||||
|
{
|
||||||
|
return $this->requestText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setRequestText(string $requestText): Requests
|
||||||
|
{
|
||||||
|
$this->requestText = $requestText;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPromptTokens(): int
|
||||||
|
{
|
||||||
|
return $this->promptTokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPromptTokens(int $promptTokens): Requests
|
||||||
|
{
|
||||||
|
$this->promptTokens = $promptTokens;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCompletionTokens(): int
|
||||||
|
{
|
||||||
|
return $this->completionTokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setCompletionTokens(int $completionTokens): Requests
|
||||||
|
{
|
||||||
|
$this->completionTokens = $completionTokens;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTotalTokens(): int
|
||||||
|
{
|
||||||
|
return $this->totalTokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTotalTokens(int $totalTokens): Requests
|
||||||
|
{
|
||||||
|
$this->totalTokens = $totalTokens;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolName(): string
|
||||||
|
{
|
||||||
|
return $this->toolName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setToolName(string $toolName): Requests
|
||||||
|
{
|
||||||
|
$this->toolName = $toolName;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
||||||
46
plugin/ai_helper/README.md
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
AI Helper plugin
|
||||||
|
======
|
||||||
|
|
||||||
|
Version 1.1
|
||||||
|
|
||||||
|
> This plugin is meant to be later integrated into Chamilo (in a major version
|
||||||
|
release).
|
||||||
|
|
||||||
|
The AI helper plugin integrates into parts of the platform that seem the most useful to teachers/trainers or learners.
|
||||||
|
Because available Artificial Intelligence (to use the broad term) now allows us to ask for meaningful texts to be generated, we can use those systems to pre-generate content, then let the teacher/trainer review the content before publication.
|
||||||
|
|
||||||
|
Currently, this plugin is only integrated into:
|
||||||
|
|
||||||
|
- exercises: in the Aiken import form, scrolling down
|
||||||
|
- learnpaths: option to create one with openai
|
||||||
|
|
||||||
|
### OpenAI/ChatGPT
|
||||||
|
|
||||||
|
The plugin, created in early 2023, currently only supports OpenAI's ChatGPT API.
|
||||||
|
Create an account at https://platform.openai.com/signup (if you already have an API account, go
|
||||||
|
to https://platform.openai.com/login), then generate a secret key at https://platform.openai.com/account/api-keys
|
||||||
|
or click on "Personal" -> "View API keys".
|
||||||
|
Click the "Create new secret key" button, copy the key and use it to fill the "API key" field on the
|
||||||
|
plugin configuration page.
|
||||||
|
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
## v1.1
|
||||||
|
|
||||||
|
Added tracking for requests and differential settings to enable only in exercises, only in learning paths, or both.
|
||||||
|
|
||||||
|
To update from v1.0, execute the following queries manually.
|
||||||
|
```sql
|
||||||
|
CREATE TABLE plugin_ai_helper_requests (
|
||||||
|
id int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
user_id int(11) NOT NULL,
|
||||||
|
tool_name varchar(255) COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
requested_at datetime DEFAULT NULL,
|
||||||
|
request_text varchar(255) COLLATE utf8_unicode_ci NOT NULL,
|
||||||
|
prompt_tokens int(11) NOT NULL,
|
||||||
|
completion_tokens int(11) NOT NULL,
|
||||||
|
total_tokens int(11) NOT NULL,
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB;
|
||||||
|
```
|
||||||
|
If you got this update through Git, you will also need to run `composer install` to update the autoload mechanism.
|
||||||
16
plugin/ai_helper/install.php
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Install the Ai Helper Plugin.
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.ai_helper
|
||||||
|
*/
|
||||||
|
require_once __DIR__.'/../../main/inc/global.inc.php';
|
||||||
|
require_once __DIR__.'/AiHelperPlugin.php';
|
||||||
|
|
||||||
|
if (!api_is_platform_admin()) {
|
||||||
|
exit('You must have admin permissions to install plugins');
|
||||||
|
}
|
||||||
|
|
||||||
|
AiHelperPlugin::create()->install();
|
||||||
18
plugin/ai_helper/lang/english.php
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
|
||||||
|
$strings['plugin_title'] = 'AI Helper plugin';
|
||||||
|
$strings['plugin_comment'] = 'Connects to AI services to help teachers and students through the generation of smart content, like creating questions on any given topic.';
|
||||||
|
$strings['Description'] = 'Artificial Intelligence services (to use the broad term) now allow you to ask for meaningful texts to be generated, we can use those systems to pre-generate content, then let the teacher/trainer review the content before publication. See Aiken import page in the exercises tool once enabled.';
|
||||||
|
$strings['tool_enable'] = 'Enable plugin';
|
||||||
|
$strings['api_name'] = 'AI API to use';
|
||||||
|
$strings['api_key'] = 'Api key';
|
||||||
|
$strings['api_key_help'] = 'Secret key generated for your Ai api';
|
||||||
|
$strings['organization_id'] = 'Organization ID';
|
||||||
|
$strings['organization_id_help'] = 'In case your api account is from an organization.';
|
||||||
|
$strings['OpenAI'] = 'OpenAI';
|
||||||
|
$strings['tool_lp_enable'] = 'Enable in learning paths';
|
||||||
|
$strings['tool_quiz_enable'] = 'Enable in exercises (Aiken section)';
|
||||||
|
$strings['tokens_limit'] = 'AI tokens limit';
|
||||||
|
$strings['tokens_limit_help'] = 'Limit the maximum number of tokens each user has available per month, to avoid high costs of service.';
|
||||||
|
$strings['ErrorTokensLimit'] = 'Sorry, you have reached the maximum number of tokens or requests configured by the platform administrator for the current calendar month. Please contact your support team or wait for next month before you can issue new requests to the AI Helper.';
|
||||||
18
plugin/ai_helper/lang/french.php
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
|
||||||
|
$strings['plugin_title'] = 'Assistant IA.';
|
||||||
|
$strings['plugin_comment'] = "Système d'intelligence artificielle (IA) intégré aux endroits qui semblent les plus utiles aux enseignants pour la génération de contenu d'exemple, comme la création de banques de questions sur n'importe quel sujet.";
|
||||||
|
$strings['Description'] = "L'intelligence artificielle (pour utiliser le terme large) disponible aujourd'hui vous permet de demander la génération de textes réalistes sur n'importe quel sujet. Vous pouvez utiliser ces systèmes pour pré-générer du contenu, et que l'enseignant/formateur puisse perfectionner le contenu avant sa publication.";
|
||||||
|
$strings['tool_enable'] = 'Activer le plug-in';
|
||||||
|
$strings['api_name'] = "API de l'IA pour se connecter";
|
||||||
|
$strings['api_key'] = "API key";
|
||||||
|
$strings['api_key_help'] = 'Clé secrète générée pour votre API AI';
|
||||||
|
$strings['organization_id'] = "ID de l'organisation";
|
||||||
|
$strings['organization_id_help'] = "Si votre compte api provient d'une organisation.";
|
||||||
|
$strings['OpenAI'] = 'OpenAI';
|
||||||
|
$strings['tool_lp_enable'] = "Activer dans les parcours";
|
||||||
|
$strings['tool_quiz_enable'] = "Activer dans les exercices";
|
||||||
|
$strings['tokens_limit'] = "Limite de jetons IA";
|
||||||
|
$strings['tokens_limit_help'] = 'Limiter le nombre maximum de jetons disponibles pour chaque utilisateur, par mois, pour éviter des frais de service surdimensionnés.';
|
||||||
|
$strings['ErrorTokensLimit'] = 'Désolé, vous avez atteint le nombre maximum de jetons ou de requêtes configurés par l\'administrateur de la plateforme pour le mois civil en cours. Veuillez contacter votre équipe d\'assistance ou attendre le mois prochain avant de pouvoir envoyer de nouvelles demandes à AI Helper.';
|
||||||
18
plugin/ai_helper/lang/spanish.php
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
|
||||||
|
$strings['plugin_title'] = 'Asistente de IA.';
|
||||||
|
$strings['plugin_comment'] = 'Este plugin se integra en la plataforma para habilitar la generación automatizada de contenido inteligente, como preguntas de elección múltiple.';
|
||||||
|
$strings['Description'] = 'Debido a que la Inteligencia Artificial (para usar el término amplio) disponible ahora nos permite solicitar que se generen textos significativos, podemos usar esos sistemas para generar contenido previamente y luego dejar que el maestro/entrenador revise el contenido antes de publicarlo..';
|
||||||
|
$strings['tool_enable'] = 'Habilitar complemento';
|
||||||
|
$strings['api_name'] = 'API IA para conectar';
|
||||||
|
$strings['api_key'] = 'Clave API';
|
||||||
|
$strings['api_key_help'] = 'Clave secreta generada para su API de IA';
|
||||||
|
$strings['organization_id'] = 'Identificación de la organización';
|
||||||
|
$strings['organization_id_help'] = 'En caso de que su cuenta API sea de una organización.';
|
||||||
|
$strings['OpenAI'] = 'OpenAI';
|
||||||
|
$strings['tool_lp_enable'] = "Activarlo en las lecciones";
|
||||||
|
$strings['tool_quiz_enable'] = "Activarlo en los ejercicios";
|
||||||
|
$strings['tokens_limit'] = "Limite de tokens IA";
|
||||||
|
$strings['tokens_limit_help'] = 'Limitar la cantidad máxima de tokens disponibles por usuario por mes para evitar un alto costo de servicio.';
|
||||||
|
$strings['ErrorTokensLimit'] = 'Lo sentimos, ha alcanzado la cantidad máxima de tokens o solicitudes configuradas por el administrador de la plataforma para el mes calendario actual. Comuníquese con su equipo de soporte o espere hasta el próximo mes antes de poder enviar nuevas solicitudes a AI Helper.';
|
||||||
6
plugin/ai_helper/plugin.php
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?php
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
|
||||||
|
require_once __DIR__.'/AiHelperPlugin.php';
|
||||||
|
|
||||||
|
$plugin_info = AiHelperPlugin::create()->get_info();
|
||||||
332
plugin/ai_helper/src/openai/OpenAi.php
Normal file
@@ -0,0 +1,332 @@
|
|||||||
|
<?php
|
||||||
|
/* For licensing terms, see /license.txt */
|
||||||
|
|
||||||
|
require_once 'OpenAiUrl.php';
|
||||||
|
|
||||||
|
class OpenAi
|
||||||
|
{
|
||||||
|
private $model = "gpt-4o"; // See https://platform.openai.com/docs/models for possible models
|
||||||
|
private $headers;
|
||||||
|
private $contentTypes;
|
||||||
|
private $timeout = 0;
|
||||||
|
private $streamMethod;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
string $apiKey,
|
||||||
|
string $organizationId = ''
|
||||||
|
) {
|
||||||
|
$this->contentTypes = [
|
||||||
|
"application/json" => "Content-Type: application/json",
|
||||||
|
"multipart/form-data" => "Content-Type: multipart/form-data",
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->headers = [
|
||||||
|
$this->contentTypes["application/json"],
|
||||||
|
"Authorization: Bearer $apiKey",
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!empty($organizationId)) {
|
||||||
|
$this->headers[] = "OpenAI-Organization: $organizationId";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function listModels()
|
||||||
|
{
|
||||||
|
$url = OpenAiUrl::fineTuneModel();
|
||||||
|
|
||||||
|
return $this->sendRequest($url, 'GET');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $model
|
||||||
|
*
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function retrieveModel($model)
|
||||||
|
{
|
||||||
|
$model = "/$model";
|
||||||
|
$url = OpenAiUrl::fineTuneModel().$model;
|
||||||
|
|
||||||
|
return $this->sendRequest($url, 'GET');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $opts
|
||||||
|
* @param null $stream
|
||||||
|
*
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function completion($opts, $stream = null)
|
||||||
|
{
|
||||||
|
if ($stream != null && array_key_exists('stream', $opts)) {
|
||||||
|
if (!$opts['stream']) {
|
||||||
|
throw new Exception('Please provide a stream function.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->streamMethod = $stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
$opts['model'] = $opts['model'] ?? $this->model;
|
||||||
|
$url = OpenAiUrl::completionsURL();
|
||||||
|
|
||||||
|
return $this->sendRequest($url, 'POST', $opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $opts
|
||||||
|
*
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function createEdit($opts)
|
||||||
|
{
|
||||||
|
$url = OpenAiUrl::editsUrl();
|
||||||
|
|
||||||
|
return $this->sendRequest($url, 'POST', $opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $opts
|
||||||
|
*
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function image($opts)
|
||||||
|
{
|
||||||
|
$url = OpenAiUrl::imageUrl()."/generations";
|
||||||
|
|
||||||
|
return $this->sendRequest($url, 'POST', $opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $opts
|
||||||
|
*
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function imageEdit($opts)
|
||||||
|
{
|
||||||
|
$url = OpenAiUrl::imageUrl()."/edits";
|
||||||
|
|
||||||
|
return $this->sendRequest($url, 'POST', $opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $opts
|
||||||
|
*
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function createImageVariation($opts)
|
||||||
|
{
|
||||||
|
$url = OpenAiUrl::imageUrl()."/variations";
|
||||||
|
|
||||||
|
return $this->sendRequest($url, 'POST', $opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $opts
|
||||||
|
*
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function moderation($opts)
|
||||||
|
{
|
||||||
|
$url = OpenAiUrl::moderationUrl();
|
||||||
|
|
||||||
|
return $this->sendRequest($url, 'POST', $opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $opts
|
||||||
|
*
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function uploadFile($opts)
|
||||||
|
{
|
||||||
|
$url = OpenAiUrl::filesUrl();
|
||||||
|
|
||||||
|
return $this->sendRequest($url, 'POST', $opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function listFiles()
|
||||||
|
{
|
||||||
|
$url = OpenAiUrl::filesUrl();
|
||||||
|
|
||||||
|
return $this->sendRequest($url, 'GET');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $fileId
|
||||||
|
*
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function retrieveFile($fileId)
|
||||||
|
{
|
||||||
|
$fileId = "/$fileId";
|
||||||
|
$url = OpenAiUrl::filesUrl().$fileId;
|
||||||
|
|
||||||
|
return $this->sendRequest($url, 'GET');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $fileId
|
||||||
|
*
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function retrieveFileContent($fileId)
|
||||||
|
{
|
||||||
|
$fileId = "/$fileId/content";
|
||||||
|
$url = OpenAiUrl::filesUrl().$fileId;
|
||||||
|
|
||||||
|
return $this->sendRequest($url, 'GET');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $fileId
|
||||||
|
*
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function deleteFile($fileId)
|
||||||
|
{
|
||||||
|
$fileId = "/$fileId";
|
||||||
|
$url = OpenAiUrl::filesUrl().$fileId;
|
||||||
|
|
||||||
|
return $this->sendRequest($url, 'DELETE');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $opts
|
||||||
|
*
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function createFineTune($opts)
|
||||||
|
{
|
||||||
|
$url = OpenAiUrl::fineTuneUrl();
|
||||||
|
|
||||||
|
return $this->sendRequest($url, 'POST', $opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function listFineTunes()
|
||||||
|
{
|
||||||
|
$url = OpenAiUrl::fineTuneUrl();
|
||||||
|
|
||||||
|
return $this->sendRequest($url, 'GET');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $fineTuneId
|
||||||
|
*
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function retrieveFineTune($fineTuneId)
|
||||||
|
{
|
||||||
|
$fineTuneId = "/$fineTuneId";
|
||||||
|
$url = OpenAiUrl::fineTuneUrl().$fineTuneId;
|
||||||
|
|
||||||
|
return $this->sendRequest($url, 'GET');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $fineTuneId
|
||||||
|
*
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function cancelFineTune($fineTuneId)
|
||||||
|
{
|
||||||
|
$fineTuneId = "/$fineTuneId/cancel";
|
||||||
|
$url = OpenAiUrl::fineTuneUrl().$fineTuneId;
|
||||||
|
|
||||||
|
return $this->sendRequest($url, 'POST');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $fineTuneId
|
||||||
|
*
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function listFineTuneEvents($fineTuneId)
|
||||||
|
{
|
||||||
|
$fineTuneId = "/$fineTuneId/events";
|
||||||
|
$url = OpenAiUrl::fineTuneUrl().$fineTuneId;
|
||||||
|
|
||||||
|
return $this->sendRequest($url, 'GET');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $fineTuneId
|
||||||
|
*
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function deleteFineTune($fineTuneId)
|
||||||
|
{
|
||||||
|
$fineTuneId = "/$fineTuneId";
|
||||||
|
$url = OpenAiUrl::fineTuneModel().$fineTuneId;
|
||||||
|
|
||||||
|
return $this->sendRequest($url, 'DELETE');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $opts
|
||||||
|
*
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function embeddings($opts)
|
||||||
|
{
|
||||||
|
$url = OpenAiUrl::embeddings();
|
||||||
|
|
||||||
|
return $this->sendRequest($url, 'POST', $opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTimeout(int $timeout)
|
||||||
|
{
|
||||||
|
$this->timeout = $timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function sendRequest(
|
||||||
|
string $url,
|
||||||
|
string $method,
|
||||||
|
array $opts = []
|
||||||
|
) {
|
||||||
|
$post_fields = json_encode($opts);
|
||||||
|
|
||||||
|
if (array_key_exists('file', $opts) || array_key_exists('image', $opts)) {
|
||||||
|
$this->headers[0] = $this->contentTypes["multipart/form-data"];
|
||||||
|
$post_fields = $opts;
|
||||||
|
} else {
|
||||||
|
$this->headers[0] = $this->contentTypes["application/json"];
|
||||||
|
}
|
||||||
|
$curl_info = [
|
||||||
|
CURLOPT_URL => $url,
|
||||||
|
CURLOPT_RETURNTRANSFER => true,
|
||||||
|
CURLOPT_ENCODING => '',
|
||||||
|
CURLOPT_MAXREDIRS => 10,
|
||||||
|
CURLOPT_TIMEOUT => $this->timeout,
|
||||||
|
CURLOPT_FOLLOWLOCATION => true,
|
||||||
|
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
|
||||||
|
CURLOPT_CUSTOMREQUEST => $method,
|
||||||
|
CURLOPT_POSTFIELDS => $post_fields,
|
||||||
|
CURLOPT_HTTPHEADER => $this->headers,
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($opts == []) {
|
||||||
|
unset($curl_info[CURLOPT_POSTFIELDS]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('stream', $opts) && $opts['stream']) {
|
||||||
|
$curl_info[CURLOPT_WRITEFUNCTION] = $this->streamMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
$curl = curl_init();
|
||||||
|
|
||||||
|
curl_setopt_array($curl, $curl_info);
|
||||||
|
$response = curl_exec($curl);
|
||||||
|
curl_close($curl);
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
}
|
||||||
74
plugin/ai_helper/src/openai/OpenAiUrl.php
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<?php
|
||||||
|
/* For licensing terms, see /license.txt */
|
||||||
|
|
||||||
|
class OpenAiUrl
|
||||||
|
{
|
||||||
|
public const ORIGIN = 'https://api.openai.com';
|
||||||
|
public const API_VERSION = 'v1';
|
||||||
|
public const OPEN_AI_URL = self::ORIGIN."/".self::API_VERSION;
|
||||||
|
|
||||||
|
public static function completionsURL(): string
|
||||||
|
{
|
||||||
|
return self::OPEN_AI_URL."/completions";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function editsUrl(): string
|
||||||
|
{
|
||||||
|
return self::OPEN_AI_URL."/edits";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function searchURL(string $engine): string
|
||||||
|
{
|
||||||
|
return self::OPEN_AI_URL."/engines/$engine/search";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function enginesUrl(): string
|
||||||
|
{
|
||||||
|
return self::OPEN_AI_URL."/engines";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function engineUrl(string $engine): string
|
||||||
|
{
|
||||||
|
return self::OPEN_AI_URL."/engines/$engine";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function classificationsUrl(): string
|
||||||
|
{
|
||||||
|
return self::OPEN_AI_URL."/classifications";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function moderationUrl(): string
|
||||||
|
{
|
||||||
|
return self::OPEN_AI_URL."/moderations";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function filesUrl(): string
|
||||||
|
{
|
||||||
|
return self::OPEN_AI_URL."/files";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function fineTuneUrl(): string
|
||||||
|
{
|
||||||
|
return self::OPEN_AI_URL."/fine-tunes";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function fineTuneModel(): string
|
||||||
|
{
|
||||||
|
return self::OPEN_AI_URL."/models";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function answersUrl(): string
|
||||||
|
{
|
||||||
|
return self::OPEN_AI_URL."/answers";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function imageUrl(): string
|
||||||
|
{
|
||||||
|
return self::OPEN_AI_URL."/images";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function embeddings(): string
|
||||||
|
{
|
||||||
|
return self::OPEN_AI_URL."/embeddings";
|
||||||
|
}
|
||||||
|
}
|
||||||
57
plugin/ai_helper/tool/answers.php
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
|
||||||
|
/**
|
||||||
|
Answer questions based on existing knowledge.
|
||||||
|
*/
|
||||||
|
require_once __DIR__.'/../../../main/inc/global.inc.php';
|
||||||
|
require_once __DIR__.'/../AiHelperPlugin.php';
|
||||||
|
require_once __DIR__.'/../src/openai/OpenAi.php';
|
||||||
|
|
||||||
|
$plugin = AiHelperPlugin::create();
|
||||||
|
|
||||||
|
$apiList = $plugin->getApiList();
|
||||||
|
$apiName = $plugin->get('api_name');
|
||||||
|
|
||||||
|
if (!in_array($apiName, array_keys($apiList))) {
|
||||||
|
throw new Exception("Ai API is not available for this request.");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($apiName) {
|
||||||
|
case AiHelperPlugin::OPENAI_API:
|
||||||
|
|
||||||
|
$questionTypes = [
|
||||||
|
'multiple_choice' => 'multiple choice',
|
||||||
|
'unique_answer' => 'unique answer',
|
||||||
|
];
|
||||||
|
|
||||||
|
$nQ = (int) $_REQUEST['nro_questions'];
|
||||||
|
$lang = (string) $_REQUEST['language'];
|
||||||
|
$topic = (string) $_REQUEST['quiz_name'];
|
||||||
|
$questionType = $questionTypes[$_REQUEST['question_type']] ?? $questionTypes['multiple_choice'];
|
||||||
|
|
||||||
|
$prompt = 'Generate %d "%s" questions in Aiken format in the %s language about "%s", making sure there is a \'ANSWER\' line for each question. \'ANSWER\' lines must only mention the letter of the correct answer, not the full answer text and not a parenthesis. The line starting with \'ANSWER\' must not be separated from the last possible answer by a blank line. Each answer starts with an uppercase letter, a dot, one space and the answer text without quotes. Include an \'ANSWER_EXPLANATION\' line after the \'ANSWER\' line for each question. The terms between single quotes above must not be translated. There must be a blank line between each question.';
|
||||||
|
$prompt = sprintf($prompt, $nQ, $questionType, $lang, $topic);
|
||||||
|
|
||||||
|
$resultText = $plugin->openAiGetCompletionText($prompt, 'quiz');
|
||||||
|
|
||||||
|
if (isset($resultText['error']) && true === $resultText['error']) {
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'text' => $resultText['message'],
|
||||||
|
]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the text answers generated.
|
||||||
|
$return = ['success' => false, 'text' => ''];
|
||||||
|
if (!empty($resultText)) {
|
||||||
|
$return = [
|
||||||
|
'success' => true,
|
||||||
|
'text' => trim($resultText),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
echo json_encode($return);
|
||||||
|
break;
|
||||||
|
}
|
||||||
216
plugin/ai_helper/tool/learnpath.php
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
<?php
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
|
||||||
|
/**
|
||||||
|
Create a learnpath with contents based on existing knowledge.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use Chamilo\CoreBundle\Component\Utils\ChamiloApi;
|
||||||
|
|
||||||
|
require_once __DIR__.'/../../../main/inc/global.inc.php';
|
||||||
|
require_once __DIR__.'/../AiHelperPlugin.php';
|
||||||
|
require_once api_get_path(SYS_CODE_PATH).'exercise/export/aiken/aiken_classes.php';
|
||||||
|
require_once api_get_path(SYS_CODE_PATH).'exercise/export/aiken/aiken_import.inc.php';
|
||||||
|
|
||||||
|
$plugin = AiHelperPlugin::create();
|
||||||
|
|
||||||
|
$apiList = $plugin->getApiList();
|
||||||
|
$apiName = $plugin->get('api_name');
|
||||||
|
|
||||||
|
if (!in_array($apiName, array_keys($apiList))) {
|
||||||
|
throw new Exception("Ai API is not available for this request.");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($apiName) {
|
||||||
|
case AiHelperPlugin::OPENAI_API:
|
||||||
|
|
||||||
|
$courseLanguage = (string) $_REQUEST['language'];
|
||||||
|
$chaptersCount = (int) $_REQUEST['nro_items'];
|
||||||
|
$topic = (string) $_REQUEST['lp_name'];
|
||||||
|
$wordsCount = (int) $_REQUEST['words_count'];
|
||||||
|
$courseCode = (string) $_REQUEST['course_code'];
|
||||||
|
$sessionId = (int) $_REQUEST['session_id'];
|
||||||
|
$addTests = ('true' === $_REQUEST['add_tests']);
|
||||||
|
$nQ = ($addTests ? (int) $_REQUEST['nro_questions'] : 0);
|
||||||
|
|
||||||
|
$messageGetItems = 'Generate the table of contents of a course in "%s" in %d or less chapters on the topic of "%s" and return it as a list of items separated by CRLF. Do not provide chapter numbering. Do not include a conclusion chapter.';
|
||||||
|
$prompt = sprintf($messageGetItems, $courseLanguage, $chaptersCount, $topic);
|
||||||
|
$resultText = $plugin->openAiGetCompletionText($prompt, 'learnpath');
|
||||||
|
|
||||||
|
if (isset($resultText['error']) && true === $resultText['error']) {
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'text' => $resultText['message'],
|
||||||
|
]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$lpItems = [];
|
||||||
|
if (!empty($resultText)) {
|
||||||
|
$style = api_get_css_asset('bootstrap/dist/css/bootstrap.min.css');
|
||||||
|
$style .= api_get_css_asset('fontawesome/css/font-awesome.min.css');
|
||||||
|
$style .= api_get_css(ChamiloApi::getEditorDocStylePath());
|
||||||
|
$style .= api_get_css_asset('ckeditor/plugins/codesnippet/lib/highlight/styles/default.css');
|
||||||
|
$style .= api_get_asset('ckeditor/plugins/codesnippet/lib/highlight/highlight.pack.js');
|
||||||
|
$style .= '<script>hljs.initHighlightingOnLoad();</script>';
|
||||||
|
|
||||||
|
$items = explode("\n", $resultText);
|
||||||
|
$position = 1;
|
||||||
|
foreach ($items as $item) {
|
||||||
|
if (substr($item, 0, 2) === '- ') {
|
||||||
|
$item = substr($item, 2);
|
||||||
|
}
|
||||||
|
$explodedItem = preg_split('/\d\./', $item);
|
||||||
|
$title = count($explodedItem) > 1 ? $explodedItem[1] : $explodedItem[0];
|
||||||
|
if (!empty($title)) {
|
||||||
|
$lpItems[$position]['title'] = trim($title);
|
||||||
|
$messageGetItemContent = 'In the context of "%s", generate a document with HTML tags in "%s" with %d words of content or less, about "%s", as to be included as one chapter in a larger document on "%s". Consider the context is established for the reader and you do not need to repeat it.';
|
||||||
|
$promptItem = sprintf($messageGetItemContent, $topic, $courseLanguage, $wordsCount, $title, $topic);
|
||||||
|
$resultContentText = $plugin->openAiGetCompletionText($promptItem, 'learnpath');
|
||||||
|
$lpItemContent = (!empty($resultContentText) ? trim($resultContentText) : '');
|
||||||
|
if (false !== stripos($lpItemContent, '</head>')) {
|
||||||
|
$lpItemContent = preg_replace("|</head>|i", "\r\n$style\r\n\\0", $lpItemContent);
|
||||||
|
} else {
|
||||||
|
$lpItemContent = '<html><head><title>'.trim($title).'</title>'.$style.'</head><body>'.$lpItemContent.'</body></html>';
|
||||||
|
}
|
||||||
|
$lpItems[$position]['content'] = $lpItemContent;
|
||||||
|
$position++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the learnpath and return the id generated.
|
||||||
|
$return = ['success' => false, 'lp_id' => 0];
|
||||||
|
if (!empty($lpItems)) {
|
||||||
|
$lpId = learnpath::add_lp(
|
||||||
|
$courseCode,
|
||||||
|
$topic,
|
||||||
|
'',
|
||||||
|
'chamilo',
|
||||||
|
'manual'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!empty($lpId)) {
|
||||||
|
learnpath::toggle_visibility($lpId, 0);
|
||||||
|
$courseInfo = api_get_course_info($courseCode);
|
||||||
|
$lp = new \learnpath(
|
||||||
|
$courseCode,
|
||||||
|
$lpId,
|
||||||
|
api_get_user_id()
|
||||||
|
);
|
||||||
|
$lp->generate_lp_folder($courseInfo, $topic);
|
||||||
|
$order = 1;
|
||||||
|
$lpItemsIds = [];
|
||||||
|
foreach ($lpItems as $dspOrder => $item) {
|
||||||
|
$documentId = $lp->create_document(
|
||||||
|
$courseInfo,
|
||||||
|
$item['content'],
|
||||||
|
$item['title'],
|
||||||
|
'html'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!empty($documentId)) {
|
||||||
|
$prevDocItem = (isset($lpItemsIds[$order - 1]) ? (int) $lpItemsIds[$order - 1]['item_id'] : 0);
|
||||||
|
$lpItemId = $lp->add_item(
|
||||||
|
0,
|
||||||
|
$prevDocItem,
|
||||||
|
'document',
|
||||||
|
$documentId,
|
||||||
|
$item['title'],
|
||||||
|
'',
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
api_get_user_id(),
|
||||||
|
$order
|
||||||
|
);
|
||||||
|
$lpItemsIds[$order]['item_id'] = $lpItemId;
|
||||||
|
$lpItemsIds[$order]['item_type'] = 'document';
|
||||||
|
if ($addTests && !empty($lpItemId)) {
|
||||||
|
$promptQuiz = 'Generate %d "%s" questions in Aiken format in the %s language about "%s", making sure there is a \'ANSWER\' line for each question. \'ANSWER\' lines must only mention the letter of the correct answer, not the full answer text and not a parenthesis. The line starting with \'ANSWER\' must not be separated from the last possible answer by a blank line. Each answer starts with an uppercase letter, a dot, one space and the answer text without quotes. Include an \'ANSWER_EXPLANATION\' line after the \'ANSWER\' line for each question. The terms between single quotes above must not be translated. There must be a blank line between each question. Show the question directly without any prefix.';
|
||||||
|
$promptQuiz = sprintf($promptQuiz, $nQ, $courseLanguage, $item['title'], $topic);
|
||||||
|
$resultQuizText = $plugin->openAiGetCompletionText($promptQuiz, 'quiz');
|
||||||
|
if (!empty($resultQuizText)) {
|
||||||
|
$request = [];
|
||||||
|
$request['quiz_name'] = get_lang('Exercise').': '.$item['title'];
|
||||||
|
$request['nro_questions'] = $nQ;
|
||||||
|
$request['course_id'] = api_get_course_int_id($courseCode);
|
||||||
|
$request['aiken_format'] = trim($resultQuizText);
|
||||||
|
$exerciseId = aikenImportExercise(null, $request);
|
||||||
|
if (!empty($exerciseId)) {
|
||||||
|
$order++;
|
||||||
|
$prevQuizItem = (isset($lpItemsIds[$order - 1]) ? (int) $lpItemsIds[$order - 1]['item_id'] : 0);
|
||||||
|
$lpQuizItemId = $lp->add_item(
|
||||||
|
0,
|
||||||
|
$prevQuizItem,
|
||||||
|
'quiz',
|
||||||
|
$exerciseId,
|
||||||
|
$request['quiz_name'],
|
||||||
|
'',
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
api_get_user_id(),
|
||||||
|
$order
|
||||||
|
);
|
||||||
|
if (!empty($lpQuizItemId)) {
|
||||||
|
$maxScore = (float) $nQ;
|
||||||
|
$minScore = round($nQ / 2, 2);
|
||||||
|
$lpItemsIds[$order]['item_id'] = $lpQuizItemId;
|
||||||
|
$lpItemsIds[$order]['item_type'] = 'quiz';
|
||||||
|
$lpItemsIds[$order]['min_score'] = $minScore;
|
||||||
|
$lpItemsIds[$order]['max_score'] = $maxScore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$order++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the final item
|
||||||
|
if ($addTests) {
|
||||||
|
$finalTitle = get_lang('EndOfLearningPath');
|
||||||
|
$finalContent = file_get_contents(api_get_path(SYS_CODE_PATH).'lp/final_item_template/template.html');
|
||||||
|
$finalDocId = $lp->create_document(
|
||||||
|
$courseInfo,
|
||||||
|
$finalContent,
|
||||||
|
$finalTitle
|
||||||
|
);
|
||||||
|
$prevFinalItem = (isset($lpItemsIds[$order - 1]) ? (int) $lpItemsIds[$order - 1]['item_id'] : 0);
|
||||||
|
$lpFinalItemId = $lp->add_item(
|
||||||
|
0,
|
||||||
|
$prevFinalItem,
|
||||||
|
TOOL_LP_FINAL_ITEM,
|
||||||
|
$finalDocId,
|
||||||
|
$finalTitle,
|
||||||
|
'',
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
api_get_user_id(),
|
||||||
|
$order
|
||||||
|
);
|
||||||
|
$lpItemsIds[$order]['item_id'] = $lpFinalItemId;
|
||||||
|
$lpItemsIds[$order]['item_type'] = TOOL_LP_FINAL_ITEM;
|
||||||
|
|
||||||
|
// Set lp items prerequisites
|
||||||
|
if (count($lpItemsIds) > 0) {
|
||||||
|
for ($i = 1; $i <= count($lpItemsIds); $i++) {
|
||||||
|
$prevIndex = ($i - 1);
|
||||||
|
if (isset($lpItemsIds[$prevIndex])) {
|
||||||
|
$itemId = $lpItemsIds[$i]['item_id'];
|
||||||
|
$prerequisite = $lpItemsIds[$prevIndex]['item_id'];
|
||||||
|
$minScore = ('quiz' === $lpItemsIds[$prevIndex]['item_type'] ? $lpItemsIds[$prevIndex]['min_score'] : 0);
|
||||||
|
$maxScore = ('quiz' === $lpItemsIds[$prevIndex]['item_type'] ? $lpItemsIds[$prevIndex]['max_score'] : 100);
|
||||||
|
$lp->edit_item_prereq($itemId, $prerequisite, $minScore, $maxScore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$return = [
|
||||||
|
'success' => true,
|
||||||
|
'lp_id' => $lpId,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
echo json_encode($return);
|
||||||
|
break;
|
||||||
|
}
|
||||||
16
plugin/ai_helper/uninstall.php
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uninstall the Ai Helper Plugin.
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.ai_helper
|
||||||
|
*/
|
||||||
|
require_once __DIR__.'/../../main/inc/global.inc.php';
|
||||||
|
require_once __DIR__.'/AiHelperPlugin.php';
|
||||||
|
|
||||||
|
if (!api_is_platform_admin()) {
|
||||||
|
exit('You must have admin permissions to install plugins');
|
||||||
|
}
|
||||||
|
|
||||||
|
AiHelperPlugin::create()->uninstall();
|
||||||
40
plugin/azure_active_directory/CHANGELOG.md
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# Azure Active Directory Changelog
|
||||||
|
|
||||||
|
## 2.4 - 2024-08-28
|
||||||
|
|
||||||
|
* Added a new user extra field to save the unique Azure ID (internal UID).
|
||||||
|
This requires manually doing the following changes to your database if you are upgrading from v2.3
|
||||||
|
```sql
|
||||||
|
INSERT INTO extra_field (extra_field_type, field_type, variable, display_text, default_value, field_order, visible_to_self, visible_to_others, changeable, filter, created_at) VALUES (1, 1, 'azure_uid', 'Azure UID (internal ID)', '', 1, null, null, null, null, '2024-08-28 00:00:00');
|
||||||
|
```
|
||||||
|
* Added a new option to set the order to verify the existing user in Chamilo
|
||||||
|
```sql
|
||||||
|
INSERT INTO settings_current (variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url, access_url_changeable, access_url_locked) VALUES ('azure_active_directory_existing_user_verification_order', 'azure_active_directory', 'setting', 'Plugins', '', 'azure_active_directory', '', '', '', 1, 1, 0);
|
||||||
|
```
|
||||||
|
* Added a new option to update user info during the login proccess.
|
||||||
|
```sql
|
||||||
|
INSERT INTO settings_current (variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url, access_url_changeable, access_url_locked) VALUES ('azure_active_directory_update_users', 'azure_active_directory', 'setting', 'Plugins', '', 'azure_active_directory', '', '', '', 1, 1, 0);
|
||||||
|
```
|
||||||
|
* Added new scripts to syncronize users and groups with users and usergroups (classes). And an option to deactivate accounts in Chamilo that do not exist in Azure.
|
||||||
|
```sql
|
||||||
|
INSERT INTO settings_current (variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url, access_url_changeable, access_url_locked) VALUES ('azure_active_directory_tenant_id', 'azure_active_directory', 'setting', 'Plugins', '', 'azure_active_directory', '', '', '', 1, 1, 0);
|
||||||
|
INSERT INTO settings_current (variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url, access_url_changeable, access_url_locked) VALUES ('azure_active_directory_deactivate_nonexisting_users', 'azure_active_directory', 'setting', 'Plugins', '', 'azure_active_directory', '', '', '', 1, 1, 0);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2.3 - 2021-03-30
|
||||||
|
|
||||||
|
* Added admin, session admin and teacher groups. This requires adding the following fields to your database if
|
||||||
|
upgrading from a previous version of the plugin manually:
|
||||||
|
```
|
||||||
|
INSERT INTO settings_current (variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url, access_url_changeable, access_url_locked) VALUES ('azure_active_directory_group_id_admin', 'azure_active_directory', 'setting', 'Plugins', '', 'azure_active_directory', '', null, null, 1, 1, 0);
|
||||||
|
INSERT INTO settings_current (variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url, access_url_changeable, access_url_locked) VALUES ('azure_active_directory_group_id_session_admin', 'azure_active_directory', 'setting', 'Plugins', '', 'azure_active_directory', '', null, null, 1, 1, 0);
|
||||||
|
INSERT INTO settings_current (variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url, access_url_changeable, access_url_locked) VALUES ('azure_active_directory_group_id_teacher', 'azure_active_directory', 'setting', 'Plugins', '', 'azure_active_directory', '', null, null, 1, 1, 0);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2.2 - 2021-03-02
|
||||||
|
|
||||||
|
* Added provisioning setting
|
||||||
|
|
||||||
|
## 2.1 - 2020
|
||||||
|
|
||||||
|
* Initial tested implementation of Azure Active Directory single sign on
|
||||||
46
plugin/azure_active_directory/README.md
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# The Azure Active Directory Plugin
|
||||||
|
|
||||||
|
This plugin allows users to authenticate (with OAuth2) through Microsoft's Azure Active Directory.
|
||||||
|
This will modify the login form to either substitute the default login form or add another option to connect through
|
||||||
|
Azure.
|
||||||
|
An option allows you to automatically provision/create users in Chamilo from their account on Azure if they don't exist
|
||||||
|
in Chamilo yet.
|
||||||
|
|
||||||
|
This plugin adds two extra fields for users:
|
||||||
|
|
||||||
|
* `organisationemail`, the email registered in Azure Active Directory for each user (under _Email_ in the _Contact info_ section).
|
||||||
|
* `azure_id`, to save the internal ID for each user in Azure (which is also the prefix before the _@_ sign in the _User Principal Name_).
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
This plugin will *not* work if you do not use HTTPS.
|
||||||
|
Make sure your portal is in HTTPS before you configure this plugin.
|
||||||
|
|
||||||
|
### To configure Azure Active Directory
|
||||||
|
* Create and configure an application in your Azure panel (Azure Active Directory -> Applications registration -> New registration)).
|
||||||
|
* In the _Authentication_ section, set an _Reply URL_ (or _Redirect URIs_) of `https://{CHAMILO_URL}/plugin/azure_active_directory/src/callback.php`.
|
||||||
|
* In the _Front-channel logout URL_, use `https://{CHAMILO_URL}/index.php?logout=logout`.
|
||||||
|
* Leave the rest of the _Authentication_ section unchanged.
|
||||||
|
* In _Certificates & secrets_, create a secret string (or application password). Keep the _Value_ field at hand. If you don't copy it somewhere at this point, it will later be hidden, so take a copy, seriously!
|
||||||
|
* Make sure you actually have users.
|
||||||
|
|
||||||
|
### To configure this plugin
|
||||||
|
* _Enable_: You can enable the plugin once everything is configured correctly. Disabling it will return to the normal Chamilo login procedure.
|
||||||
|
* _Application ID_: Enter the _Application (client) ID_ assigned to your app when you created it in your Azure Active Directory interface, under _App registrations_.
|
||||||
|
* _Application secret_: Enter the client secret _value_ created in _Certificate & secrets_ above.
|
||||||
|
* _Block name_: (Optional) The name to show above the login button.
|
||||||
|
* _Force logout button_: (Optional) Add a button to force logout from Azure.
|
||||||
|
* _Management login_: (Optional) Disable the chamilo login and enable an alternative login page for users.
|
||||||
|
You will need copy the `/plugin/azure_active_directory/layout/login_form.tpl` file to `/main/template/overrides/layout/` directory.
|
||||||
|
* _Name for the management login_: A name for the manager login. By default, it is set to "Management Login".
|
||||||
|
* _Automated provisioning_: Enable if you want users to be created automatically in Chamilo (as students) when they don't exist yet.
|
||||||
|
* Assign a region in which the login option will appear. Preferably `login_bottom`.
|
||||||
|
|
||||||
|
### Enable through the normal login form
|
||||||
|
You can configure the external login procedure to work with the classic Chamilo form login.
|
||||||
|
To do it, make sure users have _azure_ in their auth_source field, then add this line in `configuration.php` file
|
||||||
|
```php
|
||||||
|
$extAuthSource["azure"]["login"] = $_configuration['root_sys']."main/auth/external_login/login.azure.php";
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
> This plugin uses the [`thenetworg/oauth2-azure`](https://github.com/TheNetworg/oauth2-azure) package.
|
||||||
38
plugin/azure_active_directory/index.php
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
/* For licensing terms, see /license.txt */
|
||||||
|
/**
|
||||||
|
* @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.azure_active_directory
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Check if AzureActiveDirectory exists, since this is not loaded as a page.
|
||||||
|
// index.php is shown as a block when showing the region to which the plugin is assigned
|
||||||
|
if (class_exists(AzureActiveDirectory::class)) {
|
||||||
|
/** @var AzureActiveDirectory $activeDirectoryPlugin */
|
||||||
|
$activeDirectoryPlugin = AzureActiveDirectory::create();
|
||||||
|
|
||||||
|
if ($activeDirectoryPlugin->get(AzureActiveDirectory::SETTING_ENABLE) === 'true') {
|
||||||
|
$_template['block_title'] = $activeDirectoryPlugin->get(AzureActiveDirectory::SETTING_BLOCK_NAME);
|
||||||
|
|
||||||
|
$_template['signin_url'] = $activeDirectoryPlugin->getUrl(AzureActiveDirectory::URL_TYPE_AUTHORIZE);
|
||||||
|
|
||||||
|
if ('true' === $activeDirectoryPlugin->get(AzureActiveDirectory::SETTING_FORCE_LOGOUT_BUTTON)) {
|
||||||
|
$_template['signout_url'] = $activeDirectoryPlugin->getUrl(AzureActiveDirectory::URL_TYPE_LOGOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
$managementLoginEnabled = 'true' === $activeDirectoryPlugin->get(AzureActiveDirectory::SETTING_MANAGEMENT_LOGIN_ENABLE);
|
||||||
|
|
||||||
|
$_template['management_login_enabled'] = $managementLoginEnabled;
|
||||||
|
|
||||||
|
if ($managementLoginEnabled) {
|
||||||
|
$managementLoginName = $activeDirectoryPlugin->get(AzureActiveDirectory::SETTING_MANAGEMENT_LOGIN_NAME);
|
||||||
|
|
||||||
|
if (empty($managementLoginName)) {
|
||||||
|
$managementLoginName = $activeDirectoryPlugin->get_lang('ManagementLogin');
|
||||||
|
}
|
||||||
|
|
||||||
|
$_template['management_login_name'] = $managementLoginName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
plugin/azure_active_directory/install.php
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
/* For licensing terms, see /license.txt */
|
||||||
|
|
||||||
|
if (!api_is_platform_admin()) {
|
||||||
|
exit('You must have admin permissions to install plugins');
|
||||||
|
}
|
||||||
|
|
||||||
|
AzureActiveDirectory::create()->install();
|
||||||
48
plugin/azure_active_directory/lang/dutch.php
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
/* For licensing terms, see /license.txt */
|
||||||
|
/**
|
||||||
|
* Strings to Dutch L10n.
|
||||||
|
*
|
||||||
|
* @author Yannick Warnier <yannick.warnier@beeznest.com>
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.azure_active_directory
|
||||||
|
*/
|
||||||
|
$strings['plugin_title'] = 'Azure Active Directory';
|
||||||
|
$strings['plugin_comment'] = 'Sta authenticatie met Microsoft\'s Azure Active Directory toe';
|
||||||
|
|
||||||
|
$strings['enable'] = 'Inschakelen';
|
||||||
|
$strings['app_id'] = 'Applicatie ID';
|
||||||
|
$strings['app_id_help'] = 'Voeg de Applicatie Id toegewezen aan uw app bij de Azure portal, b.v. 580e250c-8f26-49d0-bee8-1c078add1609';
|
||||||
|
$strings['app_secret'] = 'Applicatie gehem';
|
||||||
|
$strings['force_logout'] = 'Forceer uitlogknop';
|
||||||
|
$strings['force_logout_help'] = 'Toon een knop om afmeldingssessie van Azure af te dwingen.';
|
||||||
|
$strings['block_name'] = 'Blok naam';
|
||||||
|
$strings['management_login_enable'] = 'Beheer login';
|
||||||
|
$strings['management_login_enable_help'] = 'Schakel de chamilo-login uit en schakel een alternatieve inlogpagina in voor gebruikers.<br>'
|
||||||
|
.'U zult moeten kopiëren de <code>/plugin/azure_active_directory/layout/login_form.tpl</code> bestand in het <code>/main/template/overrides/layout/</code> dossier.';
|
||||||
|
$strings['management_login_name'] = 'Naam voor de beheeraanmelding';
|
||||||
|
$strings['management_login_name_help'] = 'De standaardinstelling is "Beheer login".';
|
||||||
|
$strings['existing_user_verification_order'] = 'Existing user verification order';
|
||||||
|
$strings['existing_user_verification_order_help'] = 'This value indicates the order in which the user will be searched in Chamilo to verify its existence. '
|
||||||
|
.'By default is <code>1, 2, 3</code>.'
|
||||||
|
.'<ol><li>EXTRA_FIELD_ORGANISATION_EMAIL (<code>mail</code>)</li><li>EXTRA_FIELD_AZURE_ID (<code>mailNickname</code>)</li><li>EXTRA_FIELD_AZURE_UID (<code>id</code> of <code>objectId</code>)</li></ol>';
|
||||||
|
$strings['OrganisationEmail'] = 'Organisatie e-mail';
|
||||||
|
$strings['AzureId'] = 'Azure ID (mailNickname)';
|
||||||
|
$strings['AzureUid'] = 'Azure UID (internal ID)';
|
||||||
|
$strings['ManagementLogin'] = 'Beheer Login';
|
||||||
|
$strings['InvalidId'] = 'Deze identificatie is niet geldig (verkeerde log-in of wachtwoord). Errocode: AZMNF';
|
||||||
|
$strings['provisioning'] = 'Geautomatiseerde inrichting';
|
||||||
|
$strings['update_users'] = 'Update users';
|
||||||
|
$strings['update_users_help'] = 'Allow user data to be updated at the start of the session.';
|
||||||
|
$strings['provisioning_help'] = 'Maak automatisch nieuwe gebruikers (als studenten) vanuit Azure wanneer ze niet in Chamilo zijn.';
|
||||||
|
$strings['group_id_admin'] = 'Groeps-ID voor platformbeheerders';
|
||||||
|
$strings['group_id_admin_help'] = 'De groeps-ID is te vinden in de details van de gebruikersgroep en ziet er ongeveer zo uit: ae134eef-cbd4-4a32-ba99-49898a1314b6. Indien leeg, wordt er automatisch geen gebruiker aangemaakt als admin.';
|
||||||
|
$strings['group_id_session_admin'] = 'Groeps-ID voor sessiebeheerders';
|
||||||
|
$strings['group_id_session_admin_help'] = 'De groeps-ID voor sessiebeheerders. Indien leeg, wordt er automatisch geen gebruiker aangemaakt als sessiebeheerder.';
|
||||||
|
$strings['group_id_teacher'] = 'Groeps-ID voor docenten';
|
||||||
|
$strings['group_id_teacher_help'] = 'De groeps-ID voor docenten. Indien leeg, wordt er automatisch geen gebruiker aangemaakt als docent.';
|
||||||
|
$strings['additional_interaction_required'] = 'Er is aanvullende interactie vereist om u te authenticeren. Log rechtstreeks in via <a href="https://login.microsoftonline.com" target="_blank">uw authenticatiesysteem</a> en kom dan terug naar deze pagina om in te loggen.';
|
||||||
|
$strings['tenant_id'] = 'Mandanten-ID';
|
||||||
|
$strings['tenant_id_help'] = 'Required to run scripts.';
|
||||||
|
$strings['deactivate_nonexisting_users'] = 'Deactivate non-existing users';
|
||||||
|
$strings['deactivate_nonexisting_users_help'] = 'Compare registered users in Chamilo with those in Azure and deactivate accounts in Chamilo that do not exist in Azure.';
|
||||||
48
plugin/azure_active_directory/lang/english.php
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
/* For licensing terms, see /license.txt */
|
||||||
|
/**
|
||||||
|
* Strings to English L10n.
|
||||||
|
*
|
||||||
|
* @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.azure_active_directory
|
||||||
|
*/
|
||||||
|
$strings['plugin_title'] = 'Azure Active Directory';
|
||||||
|
$strings['plugin_comment'] = 'Allow authentication with Microsoft\'s Azure Active Directory';
|
||||||
|
|
||||||
|
$strings['enable'] = 'Enable';
|
||||||
|
$strings['app_id'] = 'Application ID';
|
||||||
|
$strings['app_id_help'] = 'Enter the Application Id assigned to your app by the Azure portal, e.g. 580e250c-8f26-49d0-bee8-1c078add1609';
|
||||||
|
$strings['app_secret'] = 'Application secret';
|
||||||
|
$strings['force_logout'] = 'Force logout button';
|
||||||
|
$strings['force_logout_help'] = 'Show a button to force logout session from Azure.';
|
||||||
|
$strings['block_name'] = 'Block name';
|
||||||
|
$strings['management_login_enable'] = 'Management login';
|
||||||
|
$strings['management_login_enable_help'] = 'Disable the chamilo login and enable an alternative login page for admin users.<br>'
|
||||||
|
.'You will need to copy the <code>/plugin/azure_active_directory/layout/login_form.tpl</code> file to <code>/main/template/overrides/layout/</code> directory.';
|
||||||
|
$strings['management_login_name'] = 'Name for the management login';
|
||||||
|
$strings['management_login_name_help'] = 'The default is "Management Login".';
|
||||||
|
$strings['existing_user_verification_order'] = 'Existing user verification order';
|
||||||
|
$strings['existing_user_verification_order_help'] = 'This value indicates the order in which the user will be searched in Chamilo to verify its existence. '
|
||||||
|
.'By default is <code>1, 2, 3</code>.'
|
||||||
|
.'<ol><li>EXTRA_FIELD_ORGANISATION_EMAIL (<code>mail</code>)</li><li>EXTRA_FIELD_AZURE_ID (<code>mailNickname</code>)</li><li>EXTRA_FIELD_AZURE_UID (<code>id</code> or <code>objectId</code>)</li></ol>';
|
||||||
|
$strings['OrganisationEmail'] = 'Organisation e-mail';
|
||||||
|
$strings['AzureId'] = 'Azure ID (mailNickname)';
|
||||||
|
$strings['AzureUid'] = 'Azure UID (internal ID)';
|
||||||
|
$strings['ManagementLogin'] = 'Management Login';
|
||||||
|
$strings['InvalidId'] = 'Login failed - incorrect login or password. Errocode: AZMNF';
|
||||||
|
$strings['provisioning'] = 'Automated provisioning';
|
||||||
|
$strings['provisioning_help'] = 'Automatically create new users (as students) from Azure when they are not in Chamilo.';
|
||||||
|
$strings['update_users'] = 'Update users';
|
||||||
|
$strings['update_users_help'] = 'Allow user data to be updated at the start of the session.';
|
||||||
|
$strings['group_id_admin'] = 'Group ID for platform admins';
|
||||||
|
$strings['group_id_admin_help'] = 'The group ID can be found in the user group details, looking similar to this: ae134eef-cbd4-4a32-ba99-49898a1314b6. If empty, no user will be automatically created as admin.';
|
||||||
|
$strings['group_id_session_admin'] = 'Group ID for session admins';
|
||||||
|
$strings['group_id_session_admin_help'] = 'The group ID for session admins. If empty, no user will be automatically created as session admin.';
|
||||||
|
$strings['group_id_teacher'] = 'Group ID for teachers';
|
||||||
|
$strings['group_id_teacher_help'] = 'The group ID for teachers. If empty, no user will be automatically created as teacher.';
|
||||||
|
$strings['additional_interaction_required'] = 'Some additional interaction is required to authenticate you. Please login directly through <a href="https://login.microsoftonline.com" target="_blank">your authentication system</a>, then come back to this page to login.';
|
||||||
|
$strings['tenant_id'] = 'Tenant ID';
|
||||||
|
$strings['tenant_id_help'] = 'Required to run scripts.';
|
||||||
|
$strings['deactivate_nonexisting_users'] = 'Deactivate non-existing users';
|
||||||
|
$strings['deactivate_nonexisting_users_help'] = 'Compare registered users in Chamilo with those in Azure and deactivate accounts in Chamilo that do not exist in Azure.';
|
||||||
48
plugin/azure_active_directory/lang/french.php
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
/* For licensing terms, see /license.txt */
|
||||||
|
/**
|
||||||
|
* Strings to French L10n.
|
||||||
|
*
|
||||||
|
* @author Yannick Warnier <yannick.warnier@beeznest.com>
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.azure_active_directory
|
||||||
|
*/
|
||||||
|
$strings['plugin_title'] = 'Azure Active Directory';
|
||||||
|
$strings['plugin_comment'] = 'Permet l\'authentification des utilisateurs via Azure Active Directory de Microsoft';
|
||||||
|
|
||||||
|
$strings['enable'] = 'Activer';
|
||||||
|
$strings['app_id'] = 'ID de l\'application';
|
||||||
|
$strings['app_id_help'] = 'Introduisez l\'ID de l\'application assigné à votre app par le portail d\'Azure, p.ex. 580e250c-8f26-49d0-bee8-1c078add1609';
|
||||||
|
$strings['app_secret'] = 'Clef secrète de l\'application';
|
||||||
|
$strings['force_logout'] = 'Bouton de logout';
|
||||||
|
$strings['force_logout_help'] = 'Affiche un bouton pour se délogger d\'Azure.';
|
||||||
|
$strings['block_name'] = 'Nom du bloc';
|
||||||
|
$strings['management_login_enable'] = 'Login de gestion';
|
||||||
|
$strings['management_login_enable_help'] = 'Désactiver le login de Chamilo et permettre une page de login alternative pour les utilisateurs administrateurs.<br>'
|
||||||
|
.'Vous devez, pour cela, copier le fichier <code>/plugin/azure_active_directory/layout/login_form.tpl</code> dans le répertoire <code>/main/template/overrides/layout/</code>.';
|
||||||
|
$strings['management_login_name'] = 'Nom du login de gestion';
|
||||||
|
$strings['management_login_name_help'] = 'Le nom par défaut est "Login de gestion".';
|
||||||
|
$strings['existing_user_verification_order'] = 'Existing user verification order';
|
||||||
|
$strings['existing_user_verification_order_help'] = 'This value indicates the order in which the user will be searched in Chamilo to verify its existence. '
|
||||||
|
.'By default is <code>1, 2, 3</code>.'
|
||||||
|
.'<ol><li>EXTRA_FIELD_ORGANISATION_EMAIL (<code>mail</code>)</li><li>EXTRA_FIELD_AZURE_ID (<code>mailNickname</code>)</li><li>EXTRA_FIELD_AZURE_UID (<code>id</code> ou <code>objectId</code>)</li></ol>';
|
||||||
|
$strings['OrganisationEmail'] = 'E-mail professionnel';
|
||||||
|
$strings['AzureId'] = 'ID Azure (mailNickname)';
|
||||||
|
$strings['AzureUid'] = 'Azure UID (internal ID)';
|
||||||
|
$strings['ManagementLogin'] = 'Login de gestion';
|
||||||
|
$strings['InvalidId'] = 'Échec du login - nom d\'utilisateur ou mot de passe incorrect. Errocode: AZMNF';
|
||||||
|
$strings['provisioning'] = 'Création automatisée';
|
||||||
|
$strings['provisioning_help'] = 'Créer les utilisateurs automatiquement (en tant qu\'apprenants) depuis Azure s\'ils n\'existent pas encore dans Chamilo.';
|
||||||
|
$strings['update_users'] = 'Actualiser les utilisateurs';
|
||||||
|
$strings['update_users_help'] = 'Permettre d\'actualiser les données de l\'utilisateur lors du démarrage de la session.';
|
||||||
|
$strings['group_id_admin'] = 'ID du groupe administrateur';
|
||||||
|
$strings['group_id_admin_help'] = 'L\'id du groupe peut être trouvé dans les détails du groupe, et ressemble à ceci : ae134eef-cbd4-4a32-ba99-49898a1314b6. Si ce champ est laissé vide, aucun utilisateur ne sera créé en tant qu\'administrateur.';
|
||||||
|
$strings['group_id_session_admin'] = 'ID du groupe administrateur de sessions';
|
||||||
|
$strings['group_id_session_admin_help'] = 'The group ID for session admins. Si ce champ est laissé vide, aucun utilisateur ne sera créé en tant qu\'administrateur de sessions.';
|
||||||
|
$strings['group_id_teacher'] = 'ID du groupe enseignant';
|
||||||
|
$strings['group_id_teacher_help'] = 'The group ID for teachers. Si ce champ est laissé vide, aucun utilisateur ne sera créé en tant qu\'enseignant.';
|
||||||
|
$strings['additional_interaction_required'] = 'Une interaction supplémentaire est nécessaire pour vous authentifier. Veuillez vous connecter directement auprès de <a href="https://login.microsoftonline.com" target="_blank">votre système d\'authentification</a>, puis revenir ici pour vous connecter.';
|
||||||
|
$strings['tenant_id'] = 'ID du client';
|
||||||
|
$strings['tenant_id_help'] = 'Nécessaire pour exécuter des scripts.';
|
||||||
|
$strings['deactivate_nonexisting_users'] = 'Deactivate non-existing users';
|
||||||
|
$strings['deactivate_nonexisting_users_help'] = 'Compare registered users in Chamilo with those in Azure and deactivate accounts in Chamilo that do not exist in Azure.';
|
||||||
48
plugin/azure_active_directory/lang/spanish.php
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
/* For licensing terms, see /license.txt */
|
||||||
|
/**
|
||||||
|
* Strings to Spanish L10n.
|
||||||
|
*
|
||||||
|
* @author Yannick Warnier <yannick.warnier@beeznest.com>
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.azure_active_directory
|
||||||
|
*/
|
||||||
|
$strings['plugin_title'] = 'Azure Active Directory';
|
||||||
|
$strings['plugin_comment'] = 'Permite la autenticación de usuarios por Azure Active Directory de Microsoft';
|
||||||
|
|
||||||
|
$strings['enable'] = 'Activar';
|
||||||
|
$strings['app_id'] = 'ID de la aplicación';
|
||||||
|
$strings['app_id_help'] = 'Introduzca el ID de la aplicación asignado a su app en el portal de Azure, p.ej. 580e250c-8f26-49d0-bee8-1c078add1609';
|
||||||
|
$strings['app_secret'] = 'Clave secreta de la aplicación';
|
||||||
|
$strings['force_logout'] = 'Botón de logout';
|
||||||
|
$strings['force_logout_help'] = 'Muestra un botón para hacer logout de Azure.';
|
||||||
|
$strings['block_name'] = 'Nombre del bloque';
|
||||||
|
$strings['management_login_enable'] = 'Login de gestión';
|
||||||
|
$strings['management_login_enable_help'] = 'Desactivar el login de Chamilo y activar una página de login alternativa para los usuarios de administración.<br>'
|
||||||
|
.'Para ello, tendrá que copiar el archivo <code>/plugin/azure_active_directory/layout/login_form.tpl</code> en la carpeta <code>/main/template/overrides/layout/</code>.';
|
||||||
|
$strings['management_login_name'] = 'Nombre del bloque de login de gestión';
|
||||||
|
$strings['management_login_name_help'] = 'El nombre por defecto es "Login de gestión".';
|
||||||
|
$strings['existing_user_verification_order'] = 'Orden de verificación de usuario existente';
|
||||||
|
$strings['existing_user_verification_order_help'] = 'Este valor indica el orden en que el usuario serña buscado en Chamilo para verificar su existencia. '
|
||||||
|
.'Por defecto es <code>1, 2, 3</code>.'
|
||||||
|
.'<ol><li>EXTRA_FIELD_ORGANISATION_EMAIL (<code>mail</code>)</li><li>EXTRA_FIELD_AZURE_ID (<code>mailNickname</code>)</li><li>EXTRA_FIELD_AZURE_UID (<code>id</code> o <code>objectId</code>)</li></ol>';
|
||||||
|
$strings['OrganisationEmail'] = 'E-mail profesional';
|
||||||
|
$strings['AzureId'] = 'ID Azure (mailNickname)';
|
||||||
|
$strings['AzureUid'] = 'UID Azure (ID interno)';
|
||||||
|
$strings['ManagementLogin'] = 'Login de gestión';
|
||||||
|
$strings['InvalidId'] = 'Problema en el login - nombre de usuario o contraseña incorrecto. Errocode: AZMNF';
|
||||||
|
$strings['provisioning'] = 'Creación automatizada';
|
||||||
|
$strings['provisioning_help'] = 'Crear usuarios automáticamente (como alumnos) desde Azure si no existen en Chamilo todavía.';
|
||||||
|
$strings['update_users'] = 'Actualizar los usuarios';
|
||||||
|
$strings['update_users_help'] = 'Permite actualizar los datos del usuario al iniciar sesión.';
|
||||||
|
$strings['group_id_admin'] = 'ID de grupo administrador';
|
||||||
|
$strings['group_id_admin_help'] = 'El ID de grupo se encuentra en los detalles del grupo en Azure, y parece a: ae134eef-cbd4-4a32-ba99-49898a1314b6. Si deja este campo vacío, ningún usuario será creado como administrador.';
|
||||||
|
$strings['group_id_session_admin'] = 'ID de grupo admin de sesiones';
|
||||||
|
$strings['group_id_session_admin_help'] = 'El ID de grupo para administradores de sesiones. Si deja este campo vacío, ningún usuario será creado como administrador de sesiones.';
|
||||||
|
$strings['group_id_teacher'] = 'ID de grupo profesor';
|
||||||
|
$strings['group_id_teacher_help'] = 'El ID de grupo para profesores. Si deja este campo vacío, ningún usuario será creado como profesor.';
|
||||||
|
$strings['additional_interaction_required'] = 'Alguna interacción adicional es necesaria para identificarlo/a. Por favor conéctese primero a través de su <a href="https://login.microsoftonline.com" target="_blank">sistema de autenticación</a>, luego regrese aquí para logearse.';
|
||||||
|
$strings['tenant_id'] = 'Id. del inquilino';
|
||||||
|
$strings['tenant_id_help'] = 'Necesario para ejecutar scripts.';
|
||||||
|
$strings['deactivate_nonexisting_users'] = 'Desactivar usuarios no existentes';
|
||||||
|
$strings['deactivate_nonexisting_users_help'] = 'Compara los usuarios registrados en Chamilo con los de Azure y desactiva las cuentas en Chamilo que no existan en Azure.';
|
||||||
51
plugin/azure_active_directory/layout/login_form.tpl
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
{% if _u.logged == 0 %}
|
||||||
|
{% if login_form %}
|
||||||
|
<div id="login-block" class="panel panel-default">
|
||||||
|
<div class="panel-body">
|
||||||
|
{{ login_language_form }}
|
||||||
|
{% if plugin_login_top is not null %}
|
||||||
|
<div id="plugin_login_top">
|
||||||
|
{{ plugin_login_top }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{{ login_failed }}
|
||||||
|
|
||||||
|
{% set azure_plugin_enabled = 'azure_active_directory'|api_get_plugin_setting('enable') %}
|
||||||
|
{% set azure_plugin_manage_login = 'azure_active_directory'|api_get_plugin_setting('manage_login_enable') %}
|
||||||
|
|
||||||
|
{% if 'false' == azure_plugin_enabled or 'false' == azure_plugin_manage_login %}
|
||||||
|
{{ login_form }}
|
||||||
|
|
||||||
|
{% if "allow_lostpassword" | api_get_setting == 'true' or "allow_registration"|api_get_setting == 'true' %}
|
||||||
|
<ul class="nav nav-pills nav-stacked">
|
||||||
|
{% if "allow_registration"|api_get_setting != 'false' %}
|
||||||
|
<li><a href="{{ _p.web_main }}auth/inscription.php"> {{ 'SignUp'|get_lang }} </a></li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if "allow_lostpassword" | api_get_setting == 'true' %}
|
||||||
|
{% set pass_reminder_link = 'pass_reminder_custom_link'|api_get_configuration_value %}
|
||||||
|
{% set lost_password_link = _p.web_main ~ 'auth/lostPassword.php' %}
|
||||||
|
|
||||||
|
{% if not pass_reminder_link is empty %}
|
||||||
|
{% set lost_password_link = pass_reminder_link %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a href="{{ lost_password_link }}"> {{ 'LostPassword' | get_lang }} </a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if plugin_login_bottom is not null %}
|
||||||
|
<div id="plugin_login_bottom">
|
||||||
|
{{ plugin_login_bottom }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
35
plugin/azure_active_directory/login.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
|
||||||
|
require __DIR__.'/../../main/inc/global.inc.php';
|
||||||
|
|
||||||
|
$plugin = AzureActiveDirectory::create();
|
||||||
|
|
||||||
|
$pluginEnabled = $plugin->get(AzureActiveDirectory::SETTING_ENABLE);
|
||||||
|
$managementLoginEnabled = $plugin->get(AzureActiveDirectory::SETTING_MANAGEMENT_LOGIN_ENABLE);
|
||||||
|
|
||||||
|
if ('true' !== $pluginEnabled || 'true' !== $managementLoginEnabled) {
|
||||||
|
header('Location: '.api_get_path(WEB_PATH));
|
||||||
|
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$userId = api_get_user_id();
|
||||||
|
|
||||||
|
if (!($userId) || api_is_anonymous($userId)) {
|
||||||
|
$managementLoginName = $plugin->get(AzureActiveDirectory::SETTING_MANAGEMENT_LOGIN_NAME);
|
||||||
|
|
||||||
|
if (empty($managementLoginName)) {
|
||||||
|
$managementLoginName = $plugin->get_lang('ManagementLogin');
|
||||||
|
}
|
||||||
|
|
||||||
|
$template = new Template($managementLoginName);
|
||||||
|
// Only display if the user isn't logged in.
|
||||||
|
$template->assign('login_language_form', api_display_language_form(true, true));
|
||||||
|
$template->assign('login_form', $template->displayLoginForm());
|
||||||
|
|
||||||
|
$content = $template->fetch('azure_active_directory/view/login.tpl');
|
||||||
|
|
||||||
|
$template->assign('content', $content);
|
||||||
|
$template->display_one_col_template();
|
||||||
|
}
|
||||||
10
plugin/azure_active_directory/plugin.php
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
/* For licensing terms, see /license.txt */
|
||||||
|
/**
|
||||||
|
* @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.azure_active_directory
|
||||||
|
*/
|
||||||
|
$plugin_info = AzureActiveDirectory::create()->get_info();
|
||||||
|
|
||||||
|
$plugin_info['templates'] = ['view/block.tpl'];
|
||||||
388
plugin/azure_active_directory/src/AzureActiveDirectory.php
Normal file
@@ -0,0 +1,388 @@
|
|||||||
|
<?php
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
|
||||||
|
use Chamilo\UserBundle\Entity\User;
|
||||||
|
use TheNetworg\OAuth2\Client\Provider\Azure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AzureActiveDirectory plugin class.
|
||||||
|
*
|
||||||
|
* @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
|
||||||
|
*
|
||||||
|
* @package chamilo.plugin.azure_active_directory
|
||||||
|
*/
|
||||||
|
class AzureActiveDirectory extends Plugin
|
||||||
|
{
|
||||||
|
public const SETTING_ENABLE = 'enable';
|
||||||
|
public const SETTING_APP_ID = 'app_id';
|
||||||
|
public const SETTING_APP_SECRET = 'app_secret';
|
||||||
|
public const SETTING_BLOCK_NAME = 'block_name';
|
||||||
|
public const SETTING_FORCE_LOGOUT_BUTTON = 'force_logout';
|
||||||
|
public const SETTING_MANAGEMENT_LOGIN_ENABLE = 'management_login_enable';
|
||||||
|
public const SETTING_MANAGEMENT_LOGIN_NAME = 'management_login_name';
|
||||||
|
public const SETTING_PROVISION_USERS = 'provisioning';
|
||||||
|
public const SETTING_UPDATE_USERS = 'update_users';
|
||||||
|
public const SETTING_GROUP_ID_ADMIN = 'group_id_admin';
|
||||||
|
public const SETTING_GROUP_ID_SESSION_ADMIN = 'group_id_session_admin';
|
||||||
|
public const SETTING_GROUP_ID_TEACHER = 'group_id_teacher';
|
||||||
|
public const SETTING_EXISTING_USER_VERIFICATION_ORDER = 'existing_user_verification_order';
|
||||||
|
public const SETTING_TENANT_ID = 'tenant_id';
|
||||||
|
public const SETTING_DEACTIVATE_NONEXISTING_USERS = 'deactivate_nonexisting_users';
|
||||||
|
|
||||||
|
public const URL_TYPE_AUTHORIZE = 'login';
|
||||||
|
public const URL_TYPE_LOGOUT = 'logout';
|
||||||
|
|
||||||
|
public const EXTRA_FIELD_ORGANISATION_EMAIL = 'organisationemail';
|
||||||
|
public const EXTRA_FIELD_AZURE_ID = 'azure_id';
|
||||||
|
public const EXTRA_FIELD_AZURE_UID = 'azure_uid';
|
||||||
|
|
||||||
|
public const API_PAGE_SIZE = 999;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AzureActiveDirectory constructor.
|
||||||
|
*/
|
||||||
|
protected function __construct()
|
||||||
|
{
|
||||||
|
$settings = [
|
||||||
|
self::SETTING_ENABLE => 'boolean',
|
||||||
|
self::SETTING_APP_ID => 'text',
|
||||||
|
self::SETTING_APP_SECRET => 'text',
|
||||||
|
self::SETTING_BLOCK_NAME => 'text',
|
||||||
|
self::SETTING_FORCE_LOGOUT_BUTTON => 'boolean',
|
||||||
|
self::SETTING_MANAGEMENT_LOGIN_ENABLE => 'boolean',
|
||||||
|
self::SETTING_MANAGEMENT_LOGIN_NAME => 'text',
|
||||||
|
self::SETTING_PROVISION_USERS => 'boolean',
|
||||||
|
self::SETTING_UPDATE_USERS => 'boolean',
|
||||||
|
self::SETTING_GROUP_ID_ADMIN => 'text',
|
||||||
|
self::SETTING_GROUP_ID_SESSION_ADMIN => 'text',
|
||||||
|
self::SETTING_GROUP_ID_TEACHER => 'text',
|
||||||
|
self::SETTING_EXISTING_USER_VERIFICATION_ORDER => 'text',
|
||||||
|
self::SETTING_TENANT_ID => 'text',
|
||||||
|
self::SETTING_DEACTIVATE_NONEXISTING_USERS => 'boolean',
|
||||||
|
];
|
||||||
|
|
||||||
|
parent::__construct('2.4', 'Angel Fernando Quiroz Campos, Yannick Warnier', $settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance the plugin.
|
||||||
|
*
|
||||||
|
* @staticvar null $result
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public static function create()
|
||||||
|
{
|
||||||
|
static $result = null;
|
||||||
|
|
||||||
|
return $result ? $result : $result = new self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get_name()
|
||||||
|
{
|
||||||
|
return 'azure_active_directory';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Azure
|
||||||
|
*/
|
||||||
|
public function getProvider()
|
||||||
|
{
|
||||||
|
$provider = new Azure([
|
||||||
|
'clientId' => $this->get(self::SETTING_APP_ID),
|
||||||
|
'clientSecret' => $this->get(self::SETTING_APP_SECRET),
|
||||||
|
'redirectUri' => api_get_path(WEB_PLUGIN_PATH).'azure_active_directory/src/callback.php',
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getProviderForApiGraph(): Azure
|
||||||
|
{
|
||||||
|
$provider = $this->getProvider();
|
||||||
|
$provider->urlAPI = "https://graph.microsoft.com/v1.0/";
|
||||||
|
$provider->resource = "https://graph.microsoft.com/";
|
||||||
|
$provider->tenant = $this->get(AzureActiveDirectory::SETTING_TENANT_ID);
|
||||||
|
$provider->authWithResource = false;
|
||||||
|
|
||||||
|
return $provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $urlType Type of URL to generate
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getUrl($urlType)
|
||||||
|
{
|
||||||
|
if (self::URL_TYPE_LOGOUT === $urlType) {
|
||||||
|
$provider = $this->getProvider();
|
||||||
|
|
||||||
|
return $provider->getLogoutUrl(
|
||||||
|
api_get_path(WEB_PATH)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return api_get_path(WEB_PLUGIN_PATH).$this->get_name().'/src/callback.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create extra fields for user when installing.
|
||||||
|
*/
|
||||||
|
public function install()
|
||||||
|
{
|
||||||
|
UserManager::create_extra_field(
|
||||||
|
self::EXTRA_FIELD_ORGANISATION_EMAIL,
|
||||||
|
ExtraField::FIELD_TYPE_TEXT,
|
||||||
|
$this->get_lang('OrganisationEmail'),
|
||||||
|
''
|
||||||
|
);
|
||||||
|
UserManager::create_extra_field(
|
||||||
|
self::EXTRA_FIELD_AZURE_ID,
|
||||||
|
ExtraField::FIELD_TYPE_TEXT,
|
||||||
|
$this->get_lang('AzureId'),
|
||||||
|
''
|
||||||
|
);
|
||||||
|
UserManager::create_extra_field(
|
||||||
|
self::EXTRA_FIELD_AZURE_UID,
|
||||||
|
ExtraField::FIELD_TYPE_TEXT,
|
||||||
|
$this->get_lang('AzureUid'),
|
||||||
|
''
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getExistingUserVerificationOrder(): array
|
||||||
|
{
|
||||||
|
$defaultOrder = [1, 2, 3];
|
||||||
|
|
||||||
|
$settingValue = $this->get(self::SETTING_EXISTING_USER_VERIFICATION_ORDER);
|
||||||
|
$selectedOrder = array_filter(
|
||||||
|
array_map(
|
||||||
|
'trim',
|
||||||
|
explode(',', $settingValue)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$selectedOrder = array_map('intval', $selectedOrder);
|
||||||
|
$selectedOrder = array_filter(
|
||||||
|
$selectedOrder,
|
||||||
|
function ($position) use ($defaultOrder): bool {
|
||||||
|
return in_array($position, $defaultOrder);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($selectedOrder) {
|
||||||
|
return $selectedOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $defaultOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUserIdByVerificationOrder(array $azureUserData, string $azureUidKey = 'objectId'): ?int
|
||||||
|
{
|
||||||
|
$selectedOrder = $this->getExistingUserVerificationOrder();
|
||||||
|
|
||||||
|
$extraFieldValue = new ExtraFieldValue('user');
|
||||||
|
$positionsAndFields = [
|
||||||
|
1 => $extraFieldValue->get_item_id_from_field_variable_and_field_value(
|
||||||
|
AzureActiveDirectory::EXTRA_FIELD_ORGANISATION_EMAIL,
|
||||||
|
$azureUserData['mail']
|
||||||
|
),
|
||||||
|
2 => $extraFieldValue->get_item_id_from_field_variable_and_field_value(
|
||||||
|
AzureActiveDirectory::EXTRA_FIELD_AZURE_ID,
|
||||||
|
$azureUserData['mailNickname']
|
||||||
|
),
|
||||||
|
3 => $extraFieldValue->get_item_id_from_field_variable_and_field_value(
|
||||||
|
AzureActiveDirectory::EXTRA_FIELD_AZURE_UID,
|
||||||
|
$azureUserData[$azureUidKey]
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($selectedOrder as $position) {
|
||||||
|
if (!empty($positionsAndFields[$position]) && isset($positionsAndFields[$position]['item_id'])) {
|
||||||
|
return (int) $positionsAndFields[$position]['item_id'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function registerUser(
|
||||||
|
array $azureUserInfo,
|
||||||
|
string $azureUidKey = 'objectId'
|
||||||
|
) {
|
||||||
|
if (empty($azureUserInfo)) {
|
||||||
|
throw new Exception('Groups info not found.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$userId = $this->getUserIdByVerificationOrder($azureUserInfo, $azureUidKey);
|
||||||
|
|
||||||
|
if (empty($userId)) {
|
||||||
|
// If we didn't find the user
|
||||||
|
if ($this->get(self::SETTING_PROVISION_USERS) !== 'true') {
|
||||||
|
throw new Exception('User not found when checking the extra fields from '.$azureUserInfo['mail'].' or '.$azureUserInfo['mailNickname'].' or '.$azureUserInfo[$azureUidKey].'.');
|
||||||
|
}
|
||||||
|
|
||||||
|
[
|
||||||
|
$firstNme,
|
||||||
|
$lastName,
|
||||||
|
$username,
|
||||||
|
$email,
|
||||||
|
$phone,
|
||||||
|
$authSource,
|
||||||
|
$active,
|
||||||
|
$extra,
|
||||||
|
] = $this->formatUserData($azureUserInfo, $azureUidKey);
|
||||||
|
|
||||||
|
// If the option is set to create users, create it
|
||||||
|
$userId = UserManager::create_user(
|
||||||
|
$firstNme,
|
||||||
|
$lastName,
|
||||||
|
STUDENT,
|
||||||
|
$email,
|
||||||
|
$username,
|
||||||
|
'',
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
$phone,
|
||||||
|
null,
|
||||||
|
$authSource,
|
||||||
|
null,
|
||||||
|
$active,
|
||||||
|
null,
|
||||||
|
$extra,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!$userId) {
|
||||||
|
throw new Exception(get_lang('UserNotAdded').' '.$azureUserInfo['userPrincipalName']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->get(self::SETTING_UPDATE_USERS) === 'true') {
|
||||||
|
[
|
||||||
|
$firstNme,
|
||||||
|
$lastName,
|
||||||
|
$username,
|
||||||
|
$email,
|
||||||
|
$phone,
|
||||||
|
$authSource,
|
||||||
|
$active,
|
||||||
|
$extra,
|
||||||
|
] = $this->formatUserData($azureUserInfo, $azureUidKey);
|
||||||
|
|
||||||
|
$userId = UserManager::update_user(
|
||||||
|
$userId,
|
||||||
|
$firstNme,
|
||||||
|
$lastName,
|
||||||
|
$username,
|
||||||
|
'',
|
||||||
|
$authSource,
|
||||||
|
$email,
|
||||||
|
STUDENT,
|
||||||
|
null,
|
||||||
|
$phone,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
$active,
|
||||||
|
null,
|
||||||
|
0,
|
||||||
|
$extra
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!$userId) {
|
||||||
|
throw new Exception(get_lang('CouldNotUpdateUser').' '.$azureUserInfo['userPrincipalName']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, string|false>
|
||||||
|
*/
|
||||||
|
public function getGroupUidByRole(): array
|
||||||
|
{
|
||||||
|
$groupUidList = [
|
||||||
|
'admin' => $this->get(self::SETTING_GROUP_ID_ADMIN),
|
||||||
|
'sessionAdmin' => $this->get(self::SETTING_GROUP_ID_SESSION_ADMIN),
|
||||||
|
'teacher' => $this->get(self::SETTING_GROUP_ID_TEACHER),
|
||||||
|
];
|
||||||
|
|
||||||
|
return array_filter($groupUidList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, callable>
|
||||||
|
*/
|
||||||
|
public function getUpdateActionByRole(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'admin' => function (User $user) {
|
||||||
|
$user->setStatus(COURSEMANAGER);
|
||||||
|
|
||||||
|
UserManager::addUserAsAdmin($user, false);
|
||||||
|
},
|
||||||
|
'sessionAdmin' => function (User $user) {
|
||||||
|
$user->setStatus(SESSIONADMIN);
|
||||||
|
|
||||||
|
UserManager::removeUserAdmin($user, false);
|
||||||
|
},
|
||||||
|
'teacher' => function (User $user) {
|
||||||
|
$user->setStatus(COURSEMANAGER);
|
||||||
|
|
||||||
|
UserManager::removeUserAdmin($user, false);
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function formatUserData(
|
||||||
|
array $azureUserInfo,
|
||||||
|
string $azureUidKey
|
||||||
|
): array {
|
||||||
|
$phone = null;
|
||||||
|
|
||||||
|
if (isset($azureUserInfo['telephoneNumber'])) {
|
||||||
|
$phone = $azureUserInfo['telephoneNumber'];
|
||||||
|
} elseif (isset($azureUserInfo['businessPhones'][0])) {
|
||||||
|
$phone = $azureUserInfo['businessPhones'][0];
|
||||||
|
} elseif (isset($azureUserInfo['mobilePhone'])) {
|
||||||
|
$phone = $azureUserInfo['mobilePhone'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the option is set to create users, create it
|
||||||
|
$firstNme = $azureUserInfo['givenName'];
|
||||||
|
$lastName = $azureUserInfo['surname'];
|
||||||
|
$email = $azureUserInfo['mail'];
|
||||||
|
$username = $azureUserInfo['userPrincipalName'];
|
||||||
|
$authSource = 'azure';
|
||||||
|
$active = ($azureUserInfo['accountEnabled'] ? 1 : 0);
|
||||||
|
$extra = [
|
||||||
|
'extra_'.self::EXTRA_FIELD_ORGANISATION_EMAIL => $azureUserInfo['mail'],
|
||||||
|
'extra_'.self::EXTRA_FIELD_AZURE_ID => $azureUserInfo['mailNickname'],
|
||||||
|
'extra_'.self::EXTRA_FIELD_AZURE_UID => $azureUserInfo[$azureUidKey],
|
||||||
|
];
|
||||||
|
|
||||||
|
return [
|
||||||
|
$firstNme,
|
||||||
|
$lastName,
|
||||||
|
$username,
|
||||||
|
$email,
|
||||||
|
$phone,
|
||||||
|
$authSource,
|
||||||
|
$active,
|
||||||
|
$extra,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
188
plugin/azure_active_directory/src/AzureCommand.php
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/* For license terms, see /license.txt */
|
||||||
|
|
||||||
|
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
|
||||||
|
use League\OAuth2\Client\Token\AccessTokenInterface;
|
||||||
|
use TheNetworg\OAuth2\Client\Provider\Azure;
|
||||||
|
|
||||||
|
abstract class AzureCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var AzureActiveDirectory
|
||||||
|
*/
|
||||||
|
protected $plugin;
|
||||||
|
/**
|
||||||
|
* @var Azure
|
||||||
|
*/
|
||||||
|
protected $provider;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->plugin = AzureActiveDirectory::create();
|
||||||
|
$this->plugin->get_settings(true);
|
||||||
|
$this->provider = $this->plugin->getProviderForApiGraph();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws IdentityProviderException
|
||||||
|
*/
|
||||||
|
protected function generateOrRefreshToken(?AccessTokenInterface &$token)
|
||||||
|
{
|
||||||
|
if (!$token || ($token->getExpires() && !$token->getRefreshToken())) {
|
||||||
|
$token = $this->provider->getAccessToken(
|
||||||
|
'client_credentials',
|
||||||
|
['resource' => $this->provider->resource]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*
|
||||||
|
* @return Generator<int, array<string, string>>
|
||||||
|
*/
|
||||||
|
protected function getAzureUsers(): Generator
|
||||||
|
{
|
||||||
|
$userFields = [
|
||||||
|
'givenName',
|
||||||
|
'surname',
|
||||||
|
'mail',
|
||||||
|
'userPrincipalName',
|
||||||
|
'businessPhones',
|
||||||
|
'mobilePhone',
|
||||||
|
'accountEnabled',
|
||||||
|
'mailNickname',
|
||||||
|
'id',
|
||||||
|
];
|
||||||
|
|
||||||
|
$query = sprintf(
|
||||||
|
'$top=%d&$select=%s',
|
||||||
|
AzureActiveDirectory::API_PAGE_SIZE,
|
||||||
|
implode(',', $userFields)
|
||||||
|
);
|
||||||
|
|
||||||
|
$token = null;
|
||||||
|
|
||||||
|
do {
|
||||||
|
$this->generateOrRefreshToken($token);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$azureUsersRequest = $this->provider->request(
|
||||||
|
'get',
|
||||||
|
"users?$query",
|
||||||
|
$token
|
||||||
|
);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
throw new Exception('Exception when requesting users from Azure: '.$e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
$azureUsersInfo = $azureUsersRequest['value'] ?? [];
|
||||||
|
|
||||||
|
foreach ($azureUsersInfo as $azureUserInfo) {
|
||||||
|
yield $azureUserInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
$hasNextLink = false;
|
||||||
|
|
||||||
|
if (!empty($azureUsersRequest['@odata.nextLink'])) {
|
||||||
|
$hasNextLink = true;
|
||||||
|
$query = parse_url($azureUsersRequest['@odata.nextLink'], PHP_URL_QUERY);
|
||||||
|
}
|
||||||
|
} while ($hasNextLink);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*
|
||||||
|
* @return Generator<int, array<string, string>>
|
||||||
|
*/
|
||||||
|
protected function getAzureGroups(): Generator
|
||||||
|
{
|
||||||
|
$groupFields = [
|
||||||
|
'id',
|
||||||
|
'displayName',
|
||||||
|
'description',
|
||||||
|
];
|
||||||
|
|
||||||
|
$query = sprintf(
|
||||||
|
'$top=%d&$select=%s',
|
||||||
|
AzureActiveDirectory::API_PAGE_SIZE,
|
||||||
|
implode(',', $groupFields)
|
||||||
|
);
|
||||||
|
|
||||||
|
$token = null;
|
||||||
|
|
||||||
|
do {
|
||||||
|
$this->generateOrRefreshToken($token);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$azureGroupsRequest = $this->provider->request('get', "groups?$query", $token);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
throw new Exception('Exception when requesting groups from Azure: '.$e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
$azureGroupsInfo = $azureGroupsRequest['value'] ?? [];
|
||||||
|
|
||||||
|
foreach ($azureGroupsInfo as $azureGroupInfo) {
|
||||||
|
yield $azureGroupInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
$hasNextLink = false;
|
||||||
|
|
||||||
|
if (!empty($azureGroupsRequest['@odata.nextLink'])) {
|
||||||
|
$hasNextLink = true;
|
||||||
|
$query = parse_url($azureGroupsRequest['@odata.nextLink'], PHP_URL_QUERY);
|
||||||
|
}
|
||||||
|
} while ($hasNextLink);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*
|
||||||
|
* @return Generator<int, array<string, string>>
|
||||||
|
*/
|
||||||
|
protected function getAzureGroupMembers(string $groupUid): Generator
|
||||||
|
{
|
||||||
|
$userFields = [
|
||||||
|
'mail',
|
||||||
|
'mailNickname',
|
||||||
|
'id',
|
||||||
|
];
|
||||||
|
|
||||||
|
$query = sprintf(
|
||||||
|
'$top=%d&$select=%s',
|
||||||
|
AzureActiveDirectory::API_PAGE_SIZE,
|
||||||
|
implode(',', $userFields)
|
||||||
|
);
|
||||||
|
|
||||||
|
$token = null;
|
||||||
|
|
||||||
|
do {
|
||||||
|
$this->generateOrRefreshToken($token);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$azureGroupMembersRequest = $this->provider->request(
|
||||||
|
'get',
|
||||||
|
"groups/$groupUid/members?$query",
|
||||||
|
$token
|
||||||
|
);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
throw new Exception('Exception when requesting group members from Azure: '.$e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
$azureGroupMembers = $azureGroupMembersRequest['value'] ?? [];
|
||||||
|
|
||||||
|
foreach ($azureGroupMembers as $azureGroupMember) {
|
||||||
|
yield $azureGroupMember;
|
||||||
|
}
|
||||||
|
|
||||||
|
$hasNextLink = false;
|
||||||
|
|
||||||
|
if (!empty($azureGroupMembersRequest['@odata.nextLink'])) {
|
||||||
|
$hasNextLink = true;
|
||||||
|
$query = parse_url($azureGroupMembersRequest['@odata.nextLink'], PHP_URL_QUERY);
|
||||||
|
}
|
||||||
|
} while ($hasNextLink);
|
||||||
|
}
|
||||||
|
}
|
||||||