diff --git a/documentation/changelog.html b/documentation/changelog.html index 03740c77e2..fe33b8c08d 100755 --- a/documentation/changelog.html +++ b/documentation/changelog.html @@ -1068,6 +1068,8 @@ All security issues are published and patches are attached on d64a02c1 - #7272) Fix SQL injection threats and replace SESSION variable with api_get_user_id
  • (58796166 - #7275) Add security token to course copy tool
  • (#7440) Fix a series of SQL injection vulnerabilities due to integer filtering
  • +
  • (1307b662 - BT#10295) Remove XSS when add/edit career
  • +
  • (1b320e57 - BT#10298) Avoid XSS when event is created on agenda
  • Possibly breaking changes

    @@ -1131,6 +1133,24 @@ All security issues are published and patches are attached on e406e2ee - #7768) Fix install process to avoid re-install plugin +
  • (edf83bdc - #7768) Add filter by user on sales report
  • +
  • (fa29e02a - #7841) Remove chat button from elfinder popup file selector for 1.10.x
  • +
  • (90e28522) If chamilo exercise added in LP has pass % then change status to passed/failed
  • +
  • (fa9b35e8 - #7558) Show messages for status from video chat connection
  • +
  • (4c9a8d4a) Update FontAwesome version
  • +
  • (d357cb23 - #7181) Added new lib to upgrade to webcamJS from JPEGCam
  • +
  • (b91733cc - #7835) Avoid blocked icons by ad blockers
  • +
  • (0829fd88) Move constant in api.lib.php
  • +
  • (d1aa7a96 - #279) Added new lib for vCard Exports
  • +
  • (ed50ffd6 - BT#10311) add jquery.timelinr and img
  • +
  • (249f7c9c - BT#10311) fix timeline panel
  • +
  • (a20b8fc7 - BT#10281) Apply format to session dates on session list
  • +
  • (fdb64746 - BT#10308) Improve send message on social network
  • +
  • (f2a03393 - #7558) Add method to get a HTML code for a icon by Font Awesome
  • +
  • (e94602ec - #7837) Replace old code with api_get_user_info
  • +
  • (4e0fb4a3 - BT#10217) Replace http with https
  • +
  • (57f99efb - BT#10253) Add dropbox_hide_general_coach setting
  • (110060be - #7462) Fix pages blocked due to course restriction
  • (299ba994 - #7477) Restore admin view in reports (was lost in 1.9.8)
  • (7f55f837) Rename the custompages php files in order to avoid overwrites
  • diff --git a/main/admin/user_add.php b/main/admin/user_add.php index 05ef0ea28e..27a22c00c0 100755 --- a/main/admin/user_add.php +++ b/main/admin/user_add.php @@ -25,8 +25,8 @@ if ($checkPass == 'true') { $htmlHeadXtra[] = ' JS; + $this->removeAttribute('class'); + $this->removeAttribute('url'); + $this->setAttribute('style', 'width: 100%;'); + $attrs = $this->getAttributes(); + + $selectName = $this->getAttribute('name'); + + if ($this->getAttribute('multiple')) { + $selectName = "{$this->getAttribute('name')}[]"; + } + $html .= Display::select( - $this->getAttribute('name'), + $selectName, $defaultValues, array_keys($defaultValues), - [ - 'id' => $this->getAttribute('name'), - 'style' => 'width: 100%;' - ], + $attrs, false ); return $html; diff --git a/main/inc/lib/plugin.class.php b/main/inc/lib/plugin.class.php index ae900829a2..1f6a6151b0 100755 --- a/main/inc/lib/plugin.class.php +++ b/main/inc/lib/plugin.class.php @@ -321,7 +321,7 @@ class Plugin $interfaceLanguageId = api_get_language_id($language_interface); $interfaceLanguageInfo = api_get_language_info($interfaceLanguageId); - $languageParentId = intval($interfaceLanguageInfo['parent_id']); + $languageParentId = (!empty($interfaceLanguageInfo['parent_id'])?intval($interfaceLanguageInfo['parent_id']):0); //1. Loading english if exists $english_path = $root.$plugin_name."/lang/english.php"; diff --git a/main/inc/lib/social.lib.php b/main/inc/lib/social.lib.php index 3934bf39de..fb8151a2a6 100755 --- a/main/inc/lib/social.lib.php +++ b/main/inc/lib/social.lib.php @@ -1808,7 +1808,7 @@ class SocialManager extends UserManager if ($number_friends != 0) { - $friendHtml.= ''; + $friendHtml.=''; } else { $friendHtml.= '
    '.get_lang('NoFriendsInYourContactList').' ' .' '. get_lang('TryAndFindSomeFriends').'
    '; diff --git a/main/inc/lib/template.lib.php b/main/inc/lib/template.lib.php index a1de398101..babce73bc5 100755 --- a/main/inc/lib/template.lib.php +++ b/main/inc/lib/template.lib.php @@ -617,11 +617,16 @@ class Template $isoCode = api_get_language_isocode(); - //JS files + $selectLink = 'bootstrap-select/js/i18n/defaults-' . $isoCode . '_' . strtoupper($isoCode) . '.min.js'; + + if ($isoCode == 'en') { + $selectLink = 'bootstrap-select/js/i18n/defaults-' . $isoCode . '_US.min.js'; + } + // JS files $js_files = array( 'chosen/chosen.jquery.min.js', 'bootstrap-select/js/bootstrap-select.min.js', - 'bootstrap-select/js/i18n/defaults-' . $isoCode . '_' . strtoupper($isoCode) . '.min.js' + $selectLink ); $viewBySession = api_get_setting('my_courses_view_by_session') === 'true'; diff --git a/main/inc/lib/usermanager.lib.php b/main/inc/lib/usermanager.lib.php index 3d78e6d4ae..7a012ec7ae 100755 --- a/main/inc/lib/usermanager.lib.php +++ b/main/inc/lib/usermanager.lib.php @@ -259,7 +259,9 @@ class UserManager $num = self::get_number_of_users(); if ($num >= $_configuration[$access_url_id]['hosting_limit_users']) { api_warn_hosting_contact('hosting_limit_users'); - return api_set_failure('portal users limit reached'); + Display::addFlash(Display::return_message(get_lang('PortalUsersLimitReached'), 'warning')); + + return false; } } @@ -270,13 +272,17 @@ class UserManager ) { $num = self::get_number_of_users(1); if ($num >= $_configuration[$access_url_id]['hosting_limit_teachers']) { + Display::addFlash(Display::return_message(get_lang('PortalTeachersLimitReached'), 'warning')); api_warn_hosting_contact('hosting_limit_teachers'); - return api_set_failure('portal teachers limit reached'); + + return false; } } if (empty($password)) { - return api_set_failure('ThisFieldIsRequired'); + Display::addFlash(Display::return_message(get_lang('ThisFieldIsRequired').': '.get_lang('Password') , 'warning')); + + return false; } // database table definition @@ -575,7 +581,7 @@ class UserManager a user has 4 different sized photos to be deleted. */ $user_info = api_get_user_info($user_id); if (strlen($user_info['picture_uri']) > 0) { - $path = self::getUserPathById($user_id); + $path = self::getUserPathById($user_id, 'system'); $img_path = $path.$user_info['picture_uri']; if (file_exists($img_path)) unlink($img_path); diff --git a/main/install/configuration.dist.php b/main/install/configuration.dist.php index 5d153dcb33..38934b1e64 100755 --- a/main/install/configuration.dist.php +++ b/main/install/configuration.dist.php @@ -224,3 +224,5 @@ $_configuration['system_stable'] = NEW_VERSION_STABLE; // 0 = No link (not clickable) // 2 = Link to the course if there is only one course //$_configuration['courses_list_session_title_link'] = 1; +// Fix embedded videos inside lps, adding an optional popup +//$_configuration['lp_fix_embed_content'] = false; diff --git a/main/lang/english/trad4all.inc.php b/main/lang/english/trad4all.inc.php index 01e50e549b..4676eacad7 100644 --- a/main/lang/english/trad4all.inc.php +++ b/main/lang/english/trad4all.inc.php @@ -7528,4 +7528,5 @@ $ConnectionFailed = "Connection failed"; $ConnectionClosed = "Connection closed"; $LocalConnectionFailed = "Local connection failed"; $RemoteConnectionFailed = "Remote connection failed"; +$ViewStudents = "View students"; ?> \ No newline at end of file diff --git a/main/lang/french/trad4all.inc.php b/main/lang/french/trad4all.inc.php index 4a6a6baf18..e0aa590fda 100644 --- a/main/lang/french/trad4all.inc.php +++ b/main/lang/french/trad4all.inc.php @@ -7508,4 +7508,12 @@ $CourseCategory = "Catégorie de cours"; $VideoChatBetweenUserXAndUserY = "Appel vidéo entre %s et %s"; $Enable = "Activer"; $Disable = "Désactiver"; +$AvoidChangingPageAsThisWillCutYourCurrentVideoChatSession = "Évitez de changer de page durant la conférence pour éviter de couper la communication (vous pouvez toutefois ouvrir de nouveaux onglets)."; +$ConnectingToPeer = "En cours de connexion..."; +$ConnectionEstablished = "Connexion établie"; +$ConnectionFailed = "Connexion échouée"; +$ConnectionClosed = "Connexion terminée"; +$LocalConnectionFailed = "Échec de la connexion locale"; +$RemoteConnectionFailed = "Échec de la connexion distante"; +$ViewStudents = "Voir apprenants"; ?> \ No newline at end of file diff --git a/main/lang/spanish/trad4all.inc.php b/main/lang/spanish/trad4all.inc.php index e8be336351..39f6167ecd 100644 --- a/main/lang/spanish/trad4all.inc.php +++ b/main/lang/spanish/trad4all.inc.php @@ -7553,4 +7553,5 @@ $ConnectionFailed = "Conexión fallida"; $ConnectionClosed = "Conexión cerrada"; $LocalConnectionFailed = "Conexión local fallida"; $RemoteConnectionFailed = "Conexión remota fallida"; +$ViewStudents = "Ver estudiantes"; ?> \ No newline at end of file diff --git a/main/messages/new_message.php b/main/messages/new_message.php index 1f7765d723..d2fb084b1f 100755 --- a/main/messages/new_message.php +++ b/main/messages/new_message.php @@ -38,49 +38,6 @@ function validate(form, list) { '; $htmlHeadXtra[] = ''; +$htmlHeadXtra[] = ''; +$htmlHeadXtra[] = ''; +$htmlHeadXtra[] = ''; $htmlHeadXtra[] = ' diff --git a/main/template/default/social/home.tpl b/main/template/default/social/home.tpl index e1ec5446e2..34f46f65f4 100644 --- a/main/template/default/social/home.tpl +++ b/main/template/default/social/home.tpl @@ -31,9 +31,7 @@
    -
    - {{ social_friend_block }} -
    + {{ social_friend_block }}
    diff --git a/main/template/default/social/profile.tpl b/main/template/default/social/profile.tpl index af9262b907..75cc2a0983 100644 --- a/main/template/default/social/profile.tpl +++ b/main/template/default/social/profile.tpl @@ -26,9 +26,7 @@
    -
    - {{ social_friend_block }} -
    + {{ social_friend_block }}
    diff --git a/main/template/default/social/user_block.tpl b/main/template/default/social/user_block.tpl index 325f67d128..72f454e0ff 100644 --- a/main/template/default/social/user_block.tpl +++ b/main/template/default/social/user_block.tpl @@ -19,7 +19,10 @@ {% if chat_enabled == 1 %}
  • - {% if user.user_is_online_in_chat != 0 %} + {% if user.id == _u.id %} + {{ + {{ "Chat" | get_lang }} ({{ "Online" | get_lang }}) + {% elseif user.user_is_online_in_chat != 0 %} {{ {{ "Chat" | get_lang }} ({{ "Online" | get_lang }}) diff --git a/main/work/work.lib.php b/main/work/work.lib.php index f5a7419224..f9d00aaf54 100755 --- a/main/work/work.lib.php +++ b/main/work/work.lib.php @@ -49,7 +49,7 @@ function display_action_links($id, $cur_dir_path, $action) $display_output .= ''; $display_output .= Display::return_icon('settings.png', get_lang('EditToolOptions'),'',ICON_SIZE_MEDIUM).''; } - $display_output .= '' . Display::return_icon('listwork.png', get_lang('viewStudents'),'',ICON_SIZE_MEDIUM) . ''; + $display_output .= '' . Display::return_icon('listwork.png', get_lang('ViewStudents'),'',ICON_SIZE_MEDIUM) . ''; } @@ -70,11 +70,12 @@ function display_action_links($id, $cur_dir_path, $action) } /** - * Displays all options for this tool. + * Returns a form displaying all options for this tool. * These are * - make all files visible / invisible * - set the default visibility of uploaded files * @param $defaults + * @return string The HTML form */ function settingsForm($defaults) { diff --git a/main/work/work_list_all.php b/main/work/work_list_all.php index ad730898a2..247b94ddc0 100755 --- a/main/work/work_list_all.php +++ b/main/work/work_list_all.php @@ -172,7 +172,7 @@ if (api_is_allowed_to_session_edit(false, true) && !empty($workId) && !$isDrhOfC $count = get_count_work($workId); if ($count > 0) { $display_output .= ''. - Display::return_icon('save_pack.png', get_lang('Save'), array('style' => 'float:right;'), ICON_SIZE_MEDIUM).''; + Display::return_icon('save_pack.png', get_lang('Save'), null, ICON_SIZE_MEDIUM).''; } $actionsLeft .= $display_output; diff --git a/plugin/buycourses/CHANGELOG.md b/plugin/buycourses/CHANGELOG.md index 6576068e46..06b5a2daf1 100644 --- a/plugin/buycourses/CHANGELOG.md +++ b/plugin/buycourses/CHANGELOG.md @@ -12,6 +12,7 @@ in a currency other than the others courses or sessions Allowing filter the sales by its status - The plugin Registration page was removed. Instead the Chamilo LMS registrarion page is used. +- Added the ability to record beneficiaries with the sale of courses/sessions ##Changes in database structure @@ -40,6 +41,7 @@ The __new database__ structure is formed for the tables: - `plugin_buycourses_currency` The list of countries with their currencies - `plugin_buycourses_item` The registered courses and sessions in the platform +- `plugin_buycourses_item_re_beneficiary` The beneficiaries users with the sale of courses - `plugin_buycourses_paypal_account` The PayPal account info - `plugin_buycourses_sale` The sales of courses and sessions that were made - `plugin_buycourses_transfer` The bank accounts for transfers diff --git a/plugin/buycourses/database.php b/plugin/buycourses/database.php index c4f135f38a..e3dddb98c9 100644 --- a/plugin/buycourses/database.php +++ b/plugin/buycourses/database.php @@ -97,6 +97,30 @@ $itemTable->addForeignKeyConstraint( ['onDelete' => 'CASCADE'] ); +$itemBeneficiary = $pluginSchema->createTable(BuyCoursesPlugin::TABLE_ITEM_BENEFICIARY); +$itemBeneficiary->addColumn( + 'id', + \Doctrine\DBAL\Types\Type::INTEGER, + ['autoincrement' => true, 'unsigned' => true] +); +$itemBeneficiary->addColumn( + 'item_id', + \Doctrine\DBAL\Types\Type::INTEGER, + ['unsigned' => true] +); +$itemBeneficiary->addColumn( + 'user_id', + \Doctrine\DBAL\Types\Type::INTEGER, + ['unsigned' => true] +); +$itemBeneficiary->setPrimaryKey(['id']); +$itemBeneficiary->addForeignKeyConstraint( + $itemTable, + ['item_id'], + ['id'], + ['onDelete' => 'CASCADE'] +); + $saleTable = $pluginSchema->createTable(BuyCoursesPlugin::TABLE_SALE); $saleTable->addColumn( 'id', @@ -104,7 +128,7 @@ $saleTable->addColumn( ['autoincrement' => true, 'unsigned' => true] ); $saleTable->addColumn('reference', \Doctrine\DBAL\Types\Type::STRING); -$saleTable->addColumn('date', \Doctrine\DBAL\Types\Type::DATE); +$saleTable->addColumn('date', \Doctrine\DBAL\Types\Type::DATETIME); $saleTable->addColumn( 'user_id', \Doctrine\DBAL\Types\Type::INTEGER, diff --git a/plugin/buycourses/js/buycourses.js b/plugin/buycourses/js/buycourses.js deleted file mode 100644 index 25c1927ade..0000000000 --- a/plugin/buycourses/js/buycourses.js +++ /dev/null @@ -1,36 +0,0 @@ -/* For licensing terms, see /license.txt */ -/** - * JS library for the Chamilo buy-courses plugin - * @package chamilo.plugin.buycourses - */ -$(document).ready(function () { - $(".bc-button-save").click(function () { - var currentRow = $(this).closest("tr"); - var courseOrSessionObject = { - tab: "save_mod", - visible: currentRow.find("[name='visible']").is(':checked') ? 1 : 0, - price: currentRow.find("[name='price']").val() - }; - - var itemField = currentRow.data('type') + '_id'; - - courseOrSessionObject[itemField] = currentRow.data('item') || 0; - - $.post( - "function.php", - courseOrSessionObject, - function (data) { - if (!data.status) { - return; - } - - currentRow.addClass('success'); - - window.setTimeout(function () { - currentRow.removeClass('success'); - }, 3000); - }, - "json" - ); - }); -}); diff --git a/plugin/buycourses/lang/english.php b/plugin/buycourses/lang/english.php index f8ff35d464..f0c2ecd3e3 100644 --- a/plugin/buycourses/lang/english.php +++ b/plugin/buycourses/lang/english.php @@ -1,6 +1,6 @@ SummaryAPI d\'accès, cloquer sur l\'option Mettre à jour"; $strings['InfoApiStepThree'] = "Dans l\'option 2 de Configuration des données et permissions API, cliquer sur Voir signature API. Copier ces donées dans le formulaire de configuration de ce plugin"; $strings['ErrorOccurred'] = "Une erreur est survenue. Code: %s. Message: %s. Veuillez contacter l'administrateur de la plateforme"; +$strings['VisibleInCatalog'] = "Visible dans le catalogue"; +$strings['Beneficiaries'] = "Bénéficiaires"; +$strings['AvailableCourse'] = "Cours disponibles"; +$strings['ShowOnCourseCatalog'] = "Afficher dans le catalogue de cours"; diff --git a/plugin/buycourses/lang/spanish.php b/plugin/buycourses/lang/spanish.php index 6aaa5df52c..f53ee22d93 100644 --- a/plugin/buycourses/lang/spanish.php +++ b/plugin/buycourses/lang/spanish.php @@ -1,6 +1,6 @@ Perfil de PayPalget_installed_plugins(); + + if (in_array($this->get_name(), $installedPlugins)) { + return false; + } + require_once api_get_path(SYS_PLUGIN_PATH) . 'buycourses/database.php'; } @@ -73,6 +81,7 @@ class BuyCoursesPlugin extends Plugin $tablesToBeDeleted = array( self::TABLE_PAYPAL, self::TABLE_TRANSFER, + self::TABLE_ITEM_BENEFICIARY, self::TABLE_ITEM, self::TABLE_SALE, self::TABLE_CURRENCY @@ -285,26 +294,7 @@ class BuyCoursesPlugin extends Plugin $currency = $this->getSelectedCurrency(); foreach ($courses as $course) { - $courseItem = [ - 'course_id' => $course->getId(), - 'course_visual_code' => $course->getVisualCode(), - 'course_code' => $course->getCode(), - 'course_title' => $course->getTitle(), - 'course_visibility' => $course->getVisibility(), - 'visible' => false, - 'currency' => empty($currency) ? null : $currency['iso_code'], - 'price' => 0.00 - ]; - - $item = $this->getItemByProduct($course->getId(), self::PRODUCT_TYPE_COURSE); - - if ($item !== false) { - $courseItem['visible'] = true; - $courseItem['currency'] = $item['iso_code']; - $courseItem['price'] = $item['price']; - } - - $configurationCourses[] = $courseItem; + $configurationCourses[] = $this->getCourseForConfiguration($course, $currency); } return $configurationCourses; @@ -316,9 +306,6 @@ class BuyCoursesPlugin extends Plugin */ public function getSessionsForConfiguration() { - $buyItemTable = Database::get_main_table(BuyCoursesPlugin::TABLE_ITEM); - $buyCurrencyTable = Database::get_main_table(BuyCoursesPlugin::TABLE_CURRENCY); - $auth = new Auth(); $sessions = $auth->browseSessions(); @@ -326,55 +313,8 @@ class BuyCoursesPlugin extends Plugin $items = []; - $fakeItemFrom = " - $buyItemTable i - INNER JOIN $buyCurrencyTable c - ON i.currency_id = c.id - "; - foreach ($sessions as $session) { - $sessionItem = [ - 'session_id' => $session->getId(), - 'session_name' => $session->getName(), - 'session_visibility' => $session->getVisibility(), - 'session_display_start_date' => null, - 'session_display_end_date' => null, - 'visible' => false, - 'currency' => empty($currency) ? null : $currency['iso_code'], - 'price' => 0.00 - ]; - - if (!empty($session->getDisplayStartDate())) { - $sessionItem['session_display_start_date'] = api_format_date( - $session->getDisplayStartDate()->format('Y-m-d h:i:s') - ); - } - - if (!empty($session->getDisplayEndDate())) { - $sessionItem['session_display_end_date'] = api_format_date( - $session->getDisplayEndDate()->format('Y-m-d h:i:s') - ); - } - - $item = Database::select( - ['i.*', 'c.iso_code'], - $fakeItemFrom, - [ - 'where' => [ - 'i.product_id = ? AND ' => $session->getId(), - 'i.product_type = ?' => self::PRODUCT_TYPE_SESSION - ] - ], - 'first' - ); - - if ($item !== false) { - $sessionItem['visible'] = true; - $sessionItem['currency'] = $item['iso_code']; - $sessionItem['price'] = $item['price']; - } - - $items[] = $sessionItem; + $items[] = $this->getSessionForConfiguration($session, $currency); } return $items; @@ -540,10 +480,6 @@ class BuyCoursesPlugin extends Plugin return 'NO'; } - /** - * Lists current user course details - * @return array - */ /** * Lists current user course details * @param string $name Optional. The name filter @@ -915,8 +851,8 @@ class BuyCoursesPlugin extends Plugin /** * Get a list of sales by the status - * @param type $status - * @return type + * @param int $status The status to filter + * @return array The sale list. Otherwise return false */ public function getSaleListByStatus($status = self::SALE_STATUS_PENDING) { @@ -925,10 +861,8 @@ class BuyCoursesPlugin extends Plugin $userTable = Database::get_main_table(TABLE_MAIN_USER); $innerJoins = " - INNER JOIN $currencyTable c - ON s.currency_id = c.id - INNER JOIN $userTable u - ON s.user_id = u.id + INNER JOIN $currencyTable c ON s.currency_id = c.id + INNER JOIN $userTable u ON s.user_id = u.id "; return Database::select( @@ -1127,4 +1061,262 @@ class BuyCoursesPlugin extends Plugin ); } + /** + * Get a list of sales by the user + * @param string $term The search term + * @return array The sale list. Otherwise return false + */ + public function getSaleListByUser($term) + { + $term = trim($term); + + if (empty($term)) { + return []; + } + + $saleTable = Database::get_main_table(BuyCoursesPlugin::TABLE_SALE); + $currencyTable = Database::get_main_table(BuyCoursesPlugin::TABLE_CURRENCY); + $userTable = Database::get_main_table(TABLE_MAIN_USER); + + $innerJoins = " + INNER JOIN $currencyTable c ON s.currency_id = c.id + INNER JOIN $userTable u ON s.user_id = u.id + "; + + return Database::select( + ['c.iso_code', 'u.firstname', 'u.lastname', 's.*'], + "$saleTable s $innerJoins", + [ + 'where' => [ + 'u.username LIKE %?% OR ' => $term, + 'u.lastname LIKE %?% OR ' => $term, + 'u.firstname LIKE %?%' => $term + ], + 'order' => 'id DESC' + ] + ); + } + + /** + * Convert the course info to array with necessary course data for save item + * @param \Chamilo\CoreBundle\Entity\Course $course + * @param array $defaultCurrency Optional. Currency data + * @return array + */ + public function getCourseForConfiguration(\Chamilo\CoreBundle\Entity\Course $course, $defaultCurrency = null) + { + $courseItem = [ + 'item_id' => null, + 'course_id' => $course->getId(), + 'course_visual_code' => $course->getVisualCode(), + 'course_code' => $course->getCode(), + 'course_title' => $course->getTitle(), + 'course_visibility' => $course->getVisibility(), + 'visible' => false, + 'currency' => empty($defaultCurrency) ? null : $defaultCurrency['iso_code'], + 'price' => 0.00 + ]; + + $item = $this->getItemByProduct($course->getId(), self::PRODUCT_TYPE_COURSE); + + if ($item !== false) { + $courseItem['item_id'] = $item['id']; + $courseItem['visible'] = true; + $courseItem['currency'] = $item['iso_code']; + $courseItem['price'] = $item['price']; + } + + return $courseItem; + } + + /** + * Convert the session info to array with necessary session data for save item + * @param Chamilo\CoreBundle\Entity\Session $session The session data + * @param array $defaultCurrency Optional. Currency data + * @return array + */ + public function getSessionForConfiguration(Chamilo\CoreBundle\Entity\Session $session, $defaultCurrency = null) + { + $buyItemTable = Database::get_main_table(BuyCoursesPlugin::TABLE_ITEM); + $buyCurrencyTable = Database::get_main_table(BuyCoursesPlugin::TABLE_CURRENCY); + + $fakeItemFrom = " + $buyItemTable i + INNER JOIN $buyCurrencyTable c ON i.currency_id = c.id + "; + + $sessionItem = [ + 'item_id' => null, + 'session_id' => $session->getId(), + 'session_name' => $session->getName(), + 'session_visibility' => $session->getVisibility(), + 'session_display_start_date' => null, + 'session_display_end_date' => null, + 'visible' => false, + 'currency' => empty($defaultCurrency) ? null : $defaultCurrency['iso_code'], + 'price' => 0.00 + ]; + + if (!empty($session->getDisplayStartDate())) { + $sessionItem['session_display_start_date'] = api_format_date( + $session->getDisplayStartDate()->format('Y-m-d h:i:s') + ); + } + + if (!empty($session->getDisplayEndDate())) { + $sessionItem['session_display_end_date'] = api_format_date( + $session->getDisplayEndDate()->format('Y-m-d h:i:s'), + DATE_TIME_FORMAT_LONG_24H + ); + } + + $item = Database::select( + ['i.*', 'c.iso_code'], + $fakeItemFrom, + [ + 'where' => [ + 'i.product_id = ? AND ' => $session->getId(), + 'i.product_type = ?' => self::PRODUCT_TYPE_SESSION + ] + ], + 'first' + ); + + if ($item !== false) { + $sessionItem['item_id'] = $item['id']; + $sessionItem['visible'] = true; + $sessionItem['currency'] = $item['iso_code']; + $sessionItem['price'] = $item['price']; + } + + return $sessionItem; + } + + /** + * Get all beneficiaries for a item + * @param int $itemId The item ID + * @return array The beneficiries. Otherwise return false + */ + public function getItemBeneficiaries($itemId) + { + $beneficiaryTable = Database::get_main_table(self::TABLE_ITEM_BENEFICIARY); + + return Database::select( + '*', + $beneficiaryTable, + ['where' => [ + 'item_id = ?' => intval($itemId) + ]] + ); + } + + /** + * Delete a item with its beneficiaries + * @param int $itemId The item ID + * @return int The number of affected rows. Otherwise return false + */ + public function deleteItem($itemId) + { + $itemTable = Database::get_main_table(BuyCoursesPlugin::TABLE_ITEM); + + $affectedRows = Database::delete( + $itemTable, + ['id = ?' => intval($itemId)] + ); + + if (!$affectedRows) { + return false; + } + + return $this->deleteItemBeneficiaries($itemId); + } + + /** + * Register a item + * @param array $itemData The item data + * @return int The item ID. Otherwise return false + */ + public function registerItem(array $itemData) + { + $itemTable = Database::get_main_table(BuyCoursesPlugin::TABLE_ITEM); + + return Database::insert($itemTable, $itemData); + } + + /** + * Update the item data by product + * @param array $itemData The item data to be updated + * @param int $productId The product ID + * @param int $productType The type of product + * @return int The number of affected rows. Otherwise return false + */ + public function updateItem(array $itemData, $productId, $productType) + { + $itemTable = Database::get_main_table(BuyCoursesPlugin::TABLE_ITEM); + + return Database::update( + $itemTable, + $itemData, + [ + 'product_id = ? AND ' => intval($productId), + 'product_type' => $productType + ] + ); + } + + /** + * Remove all beneficiaries for a item + * @param int $itemId The user ID + * @return int The number of affected rows. Otherwise return false + */ + public function deleteItemBeneficiaries($itemId) + { + $beneficiaryTable = Database::get_main_table(BuyCoursesPlugin::TABLE_ITEM_BENEFICIARY); + + return Database::delete( + $beneficiaryTable, + ['item_id = ?' => intval($itemId)] + ); + } + + /** + * Register the beneficiaries users with the sale of item + * @param int $itemId The item ID + * @param array $userIds The beneficiary user ID + */ + public function registerItemBeneficiaries($itemId, array $userIds) + { + $beneficiaryTable = Database::get_main_table(BuyCoursesPlugin::TABLE_ITEM_BENEFICIARY); + + $this->deleteItemBeneficiaries($itemId); + + foreach ($userIds as $userId) { + Database::insert( + $beneficiaryTable, + [ + 'item_id' => intval($itemId), + 'user_id' => intval($userId) + ] + ); + } + } + + /** + * Check if a course is valid for sale + * @param Chamilo\CoreBundle\Entity\Course $course The course + * @return boolean + */ + public function isValidCourse(Chamilo\CoreBundle\Entity\Course $course) + { + $courses = $this->getCourses(); + + foreach ($courses as $_c) { + if ($_c->getCode() === $course->getCode()) { + return true; + } + } + + return false; + } + } diff --git a/plugin/buycourses/src/configuration.php b/plugin/buycourses/src/configuration.php index ceb4106250..7a49bee247 100644 --- a/plugin/buycourses/src/configuration.php +++ b/plugin/buycourses/src/configuration.php @@ -30,6 +30,8 @@ $interbreadcrumb[] = [ $templateName = $plugin->get_lang('AvailableCourses'); $tpl = new Template($templateName); +$tpl->assign('product_type_course', BuyCoursesPlugin::PRODUCT_TYPE_COURSE); +$tpl->assign('product_type_session', BuyCoursesPlugin::PRODUCT_TYPE_SESSION); $tpl->assign('courses', $courses); $tpl->assign('sessions_are_included', $includeSession); diff --git a/plugin/buycourses/src/configure_course.php b/plugin/buycourses/src/configure_course.php new file mode 100644 index 0000000000..594bc2d162 --- /dev/null +++ b/plugin/buycourses/src/configure_course.php @@ -0,0 +1,220 @@ +get('include_sessions') === 'true'; + +$editingCourse = intval($_REQUEST['t']) === BuyCoursesPlugin::PRODUCT_TYPE_COURSE; +$editingSession = intval($_REQUEST['t']) === BuyCoursesPlugin::PRODUCT_TYPE_SESSION; + +$entityManager = Database::getManager(); +$userRepo = $entityManager->getRepository('ChamiloUserBundle:User'); + +$currency = $plugin->getSelectedCurrency(); +$currencyIso = null; + +if ($editingCourse) { + $course = $entityManager->find('ChamiloCoreBundle:Course', $_REQUEST['i']); + + if (!$course) { + api_not_allowed(true); + } + + if (!$plugin->isValidCourse($course)) { + api_not_allowed(true); + } + + $courseItem = $plugin->getCourseForConfiguration($course, $currency); + $defaultBeneficiaries = []; + $teachers = $course->getTeachers(); + $teachersOptions = []; + + foreach ($teachers as $courseTeacher) { + $teacher = $courseTeacher->getUser(); + + $teachersOptions[] = [ + 'text' => $teacher->getCompleteName(), + 'value' => $teacher->getId() + ]; + + $defaultBeneficiaries[] = $teacher->getId(); + } + + $currentBeneficiaries = $plugin->getItemBeneficiaries($courseItem['item_id']); + + if (!empty($currentBeneficiaries)) { + $defaultBeneficiaries = array_column($currentBeneficiaries, 'user_id'); + } + + $currencyIso = $courseItem['currency']; + $formDefaults = [ + 'product_type' => get_lang('Course'), + 'i' => $courseItem['course_id'], + 't' => BuyCoursesPlugin::PRODUCT_TYPE_COURSE, + 'name' => $courseItem['course_title'], + 'visible' => $courseItem['visible'], + 'price' => $courseItem['price'], + 'beneficiaries' => $defaultBeneficiaries + ]; +} elseif ($editingSession) { + if (!$includeSession) { + api_not_allowed(true); + } + + $session = $entityManager->find('ChamiloCoreBundle:Session', $_REQUEST['i']); + + if (!$session) { + api_not_allowed(true); + } + + $sessionItem = $plugin->getSessionForConfiguration($session, $currency); + $generalCoach = $session->getGeneralCoach(); + $generalCoachOption = [ + 'text' => $generalCoach->getCompleteName(), + 'value' => $generalCoach->getId() + ]; + $defaultBeneficiaries = [ + $generalCoach->getId() + ]; + $courseCoachesOptions = []; + $sessionCourses = $session->getCourses(); + + foreach ($sessionCourses as $sessionCourse) { + $courseCoaches = $userRepo->getCoachesForSessionCourse($session, $sessionCourse->getCourse()); + + foreach ($courseCoaches as $courseCoach) { + if ($generalCoach->getId() === $courseCoach->getId()) { + continue; + } + + $courseCoachesOptions[] = [ + 'text' => $courseCoach->getCompleteName(), + 'value' => $courseCoach->getId() + ]; + $defaultBeneficiaries[] = $courseCoach->getId(); + } + } + + $currentBeneficiaries = $plugin->getItemBeneficiaries($sessionItem['item_id']); + + if (!empty($currentBeneficiaries)) { + $defaultBeneficiaries = array_column($currentBeneficiaries, 'user_id'); + } + + $currencyIso = $sessionItem['currency']; + $formDefaults = [ + 'product_type' => get_lang('Session'), + 'i' => $session->getId(), + 't' => BuyCoursesPlugin::PRODUCT_TYPE_SESSION, + 'name' => $sessionItem['session_name'], + 'visible' => $sessionItem['visible'], + 'price' => $sessionItem['price'], + 'beneficiaries' => $defaultBeneficiaries + ]; +} else { + api_not_allowed(true); +} + +$form = new FormValidator('beneficiaries'); +$form->addText('product_type', $plugin->get_lang('ProductType'), false); +$form->addText('name', get_lang('Name'), false); +$visibleCheckbox = $form->addCheckBox( + 'visible', + $plugin->get_lang('VisibleInCatalog'), + $plugin->get_lang('ShowOnCourseCatalog') +); +$form->addElement( + 'number', + 'price', + [$plugin->get_lang('Price'), null, $currencyIso], + ['step' => 0.01] +); +$beneficiariesSelect = $form->addSelect( + 'beneficiaries', + $plugin->get_lang('Beneficiaries'), + null, + ['multiple' => 'multiple'] +); + +if ($editingCourse) { + $beneficiariesSelect->addOptGroup($teachersOptions, get_lang('Teachers')); +} elseif ($editingSession) { + $beneficiariesSelect->addOptGroup([$generalCoachOption], get_lang('SessionGeneralCoach')); + $beneficiariesSelect->addOptGroup($courseCoachesOptions, get_lang('SessionCourseCoach')); +} + +$form->addHidden('t', null); +$form->addHidden('i', null); +$form->addButtonSave(get_lang('Save')); +$form->freeze(['product_type', 'name']); + +if ($form->validate()) { + $formValues = $form->exportValues(); + $productItem = $plugin->getItemByProduct($formValues['i'], $formValues['t']); + + if (isset($formValues['visible'])) { + if (!empty($productItem)) { + $plugin->updateItem( + ['price' => floatval($formValues['price'])], + $formValues['i'], + $formValues['t'] + ); + } else { + $itemId = $plugin->registerItem([ + 'currency_id' => $currency['id'], + 'product_type' => $formValues['t'], + 'product_id' => intval($formValues['i']), + 'price' => floatval($_POST['price']) + ]); + $productItem['id'] = $itemId; + } + + $plugin->deleteItemBeneficiaries($productItem['id']); + + if (isset($formValues['beneficiaries'])) { + $plugin->registerItemBeneficiaries($productItem['id'], $formValues['beneficiaries']); + } + } else { + $plugin->deleteItem($productItem['id']); + } + + header('Location: ' . api_get_path(WEB_PLUGIN_PATH) . 'buycourses/src/configuration.php'); + exit; +} + +$form->setDefaults($formDefaults); + +//View +$templateName = $plugin->get_lang('AvailableCourse'); + +$interbreadcrumb[] = [ + 'url' => 'paymentsetup.php', + 'name' => get_lang('Configuration') +]; +$interbreadcrumb[] = [ + 'url' => 'configuration.php', + 'name' => $plugin->get_lang('AvailableCourses') +]; + +$template = new Template($templateName); +$template->assign('header', $templateName); +$template->assign('content', $form->returnForm()); +$template->display_one_col_template(); diff --git a/plugin/buycourses/src/function.php b/plugin/buycourses/src/function.php deleted file mode 100644 index 5dca375fef..0000000000 --- a/plugin/buycourses/src/function.php +++ /dev/null @@ -1,85 +0,0 @@ -getSelectedCurrency(); - -if ($_REQUEST['tab'] == 'save_mod') { - if (isset($_REQUEST['course_id'])) { - $productId = $_REQUEST['course_id']; - $productType = BuyCoursesPlugin::PRODUCT_TYPE_COURSE; - } else { - $productId = $_REQUEST['session_id']; - $productType = BuyCoursesPlugin::PRODUCT_TYPE_SESSION; - } - - $affectedRows = false; - - if ($_POST['visible'] == 1) { - $item = Database::select( - 'COUNT(1) AS qty', - $itemTable, - [ - 'where' => [ - 'product_id = ? AND ' => intval($productId), - 'product_type = ?' => $productType - ] - ], - 'first' - ); - - if ($item['qty'] > 0) { - $affectedRows = Database::update( - $itemTable, - ['price' => floatval($_POST['price'])], - [ - 'product_id = ? AND ' => intval($productId), - 'product_type' => $productType - ] - ); - } else { - $affectedRows = Database::insert( - $itemTable, - [ - 'currency_id' => $currency['id'], - 'product_type' => $productType, - 'product_id' => intval($productId), - 'price' => floatval($_POST['price']) - ] - ); - } - } else { - $affectedRows = Database::delete( - $itemTable, - [ - 'product_id = ? AND ' => intval($productId), - 'product_type = ?' => $productType - ] - ); - } - - if ($affectedRows > 0) { - $jsonResult = [ - "status" => true, - "itemId" => $productId - ]; - } else { - $jsonResult = [ - "status" => false, - "content" => $plugin->get_lang('ItemNotSaved') - ]; - } - - echo json_encode($jsonResult); - exit; -} diff --git a/plugin/buycourses/src/index.buycourses.php b/plugin/buycourses/src/index.buycourses.php index 8a65c2049c..96f6ebee2d 100644 --- a/plugin/buycourses/src/index.buycourses.php +++ b/plugin/buycourses/src/index.buycourses.php @@ -21,7 +21,6 @@ if ($guess_enable == "true" || isset($_SESSION['_user'])) { $content = $tpl->fetch('buycourses/view/index.tpl'); - $tpl->assign('header', $plugin->get_lang('plugin_title')); $tpl->assign('content', $content); $tpl->display_one_col_template(); diff --git a/plugin/buycourses/src/sales_report.php b/plugin/buycourses/src/sales_report.php index 3aa02b040e..e325916252 100644 --- a/plugin/buycourses/src/sales_report.php +++ b/plugin/buycourses/src/sales_report.php @@ -1,4 +1,5 @@ BuyCoursesPlugin::SALE_STATUS_COMPLETED, - 'sale' => $sale['id'] + 'sale' => $sale['id'] ]); break; case 'cancel': @@ -50,7 +51,7 @@ if (isset($_GET['order'])) { $urlToRedirect .= http_build_query([ 'status' => BuyCoursesPlugin::SALE_STATUS_CANCELED, - 'sale' => $sale['id'] + 'sale' => $sale['id'] ]); break; } @@ -61,24 +62,55 @@ if (isset($_GET['order'])) { $productTypes = $plugin->getProductTypes(); $saleStatuses = $plugin->getSaleStatuses(); +$paymentTypes = $plugin->getPaymentTypes(); + +$selectedFilterType = '0'; $selectedStatus = isset($_GET['status']) ? $_GET['status'] : BuyCoursesPlugin::SALE_STATUS_PENDING; $selectedSale = isset($_GET['sale']) ? intval($_GET['sale']) : 0; +$searchTerm = ''; $form = new FormValidator('search', 'get'); if ($form->validate()) { + $selectedFilterType = $form->getSubmitValue('filter_type'); $selectedStatus = $form->getSubmitValue('status'); + $searchTerm = $form->getSubmitValue('user'); if ($selectedStatus === false) { $selectedStatus = BuyCoursesPlugin::SALE_STATUS_PENDING; } + + if ($selectedFilterType === false) { + $selectedFilterType = '0'; + } } +$form->addRadio( + 'filter_type', + get_lang('FilterBy'), + [$plugin->get_lang('ByStatus'), $plugin->get_lang('ByUser')] +); +$form->addHtml('
    '); $form->addSelect('status', $plugin->get_lang('OrderStatus'), $saleStatuses); +$form->addHtml('
    '); +$form->addHtml('
    '); +$form->addText('user', get_lang('UserName'), false); +$form->addHtml('
    '); $form->addButtonFilter($plugin->get_lang('SearchByStatus')); -$form->setDefaults(['status' => $selectedStatus]); +$form->setDefaults([ + 'filter_type' => $selectedFilterType, + 'status' => $selectedStatus +]); + +switch ($selectedFilterType) { + case '0': + $sales = $plugin->getSaleListByStatus($selectedStatus); + break; + case '1': + $sales = $plugin->getSaleListByUser($searchTerm); + break; +} -$sales = $plugin->getSaleListByStatus($selectedStatus); $saleList = []; foreach ($sales as $sale) { @@ -86,12 +118,13 @@ foreach ($sales as $sale) { 'id' => $sale['id'], 'reference' => $sale['reference'], 'status' => $sale['status'], - 'date' => api_format_date($sale['date'], DATE_FORMAT_LONG_NO_DAY), + 'date' => api_format_date($sale['date'], DATE_TIME_FORMAT_LONG_24H), 'currency' => $sale['iso_code'], 'price' => $sale['price'], 'product_name' => $sale['product_name'], 'product_type' => $productTypes[$sale['product_type']], - 'complete_user_name' => api_get_person_name($sale['firstname'], $sale['lastname']) + 'complete_user_name' => api_get_person_name($sale['firstname'], $sale['lastname']), + 'payment_type' => $paymentTypes[$sale['payment_type']] ]; } diff --git a/plugin/buycourses/view/catalog.tpl b/plugin/buycourses/view/catalog.tpl index 772748e5d0..1bea2bce23 100644 --- a/plugin/buycourses/view/catalog.tpl +++ b/plugin/buycourses/view/catalog.tpl @@ -23,7 +23,7 @@ {% if showing_courses %} {% for course in courses %}
    -
    +
    {{ course.title }}
    {% set course_description_url = _p.web_ajax ~ 'course_home.ajax.php?' ~ {'code': course.code, 'a': 'show_course_information'}|url_encode() %} @@ -53,7 +53,7 @@
    {{ 'WaitingToReceiveThePayment'|get_plugin_lang('BuyCoursesPlugin') }}
    {% endif %}
    -
    +
    {% endfor %} {% endif %} @@ -61,7 +61,7 @@ {% if showing_sessions %} {% for session in sessions %}
    -
    +
    {{ session.name }}

    @@ -100,7 +100,7 @@
    {{ 'WaitingToReceiveThePayment'|get_plugin_lang('BuyCoursesPlugin') }}
    {% endif %}

    -
    +
    {% endfor %} {% endif %} diff --git a/plugin/buycourses/view/configuration.tpl b/plugin/buycourses/view/configuration.tpl index 9609b62b1c..3d1c4f7d62 100644 --- a/plugin/buycourses/view/configuration.tpl +++ b/plugin/buycourses/view/configuration.tpl @@ -21,9 +21,9 @@ {{ 'Title'|get_lang }} {{ 'OfficialCode'|get_lang }} - {{ 'Visible'|get_lang }} + {{ 'VisibleInCatalog'|get_plugin_lang('BuyCoursesPlugin') }} {{ 'Price'|get_plugin_lang('BuyCoursesPlugin') }} - {{ 'Option'|get_lang }} + {{ 'Options '|get_lang }} @@ -50,26 +50,19 @@ {{ item.course_code }} - {% if item.visible == 1 %} - + {% if item.visible %} + {% else %} - + {% endif %} - - {% if item.currency %} -
    - {{ item.currency }} - -
    - {% else %} - - {% endif %} + + {{ "#{item.price} #{tem.currency ?: item.currency}" }} - + + {{ 'Configure'|get_lang }} + {% endfor %} @@ -87,9 +80,9 @@ {{ 'Title'|get_lang }} {{ 'StartDate'|get_lang }} {{ 'EndDate'|get_lang }} - {{ 'Visible'|get_lang }} + {{ 'VisibleInCatalog'|get_plugin_lang('BuyCoursesPlugin') }} {{ 'Price'|get_plugin_lang('BuyCoursesPlugin') }} - {{ 'Option'|get_lang }} + {{ 'Options'|get_lang }} @@ -118,25 +111,18 @@ {% if item.visible %} - + {% else %} - + {% endif %} - {% if item.currency %} -
    - {{ item.currency }} - -
    - {% else %} - - {% endif %} + {{ "#{item.price} #{tem.currency ?: item.currency}" }} - - + + + {{ 'Configure'|get_lang }} + {% endfor %} diff --git a/plugin/buycourses/view/index.tpl b/plugin/buycourses/view/index.tpl index 03370ffaae..9d2e91dbcb 100644 --- a/plugin/buycourses/view/index.tpl +++ b/plugin/buycourses/view/index.tpl @@ -1,80 +1,75 @@ +{% if _u.is_admin %} +
    +
    +
    +

    {{ 'TitlePlugin'|get_plugin_lang('BuyCoursesPlugin') }}

    +

    {{ 'PluginPresentation'|get_plugin_lang('BuyCoursesPlugin') }}

    +
      +
    • + {{ 'Instructions'|get_plugin_lang('BuyCoursesPlugin') }} +
        +
      • {{ 'InstructionsStepOne'|get_plugin_lang('BuyCoursesPlugin') }}
      • +
      • {{ 'InstructionsStepTwo'|get_plugin_lang('BuyCoursesPlugin') }}
      • +
      • {{ 'InstructionsStepThree'|get_plugin_lang('BuyCoursesPlugin') }}
      • +
      +
    • +
    +
    +
    +
    +{% endif %} +
    -
    - {% if _u.is_admin %} -
    -
    -
    -
    -
    -

    {{ 'TitlePlugin'|get_plugin_lang('BuyCoursesPlugin') }}

    -

    {{ 'PluginPresentation'|get_plugin_lang('BuyCoursesPlugin') }}

    -

     

    -
    -
    -
    -
    -
    -
    - {{ 'Instructions'|get_plugin_lang('BuyCoursesPlugin') }} -
    -
    -
      -
    • {{ 'InstructionsStepOne'|get_plugin_lang('BuyCoursesPlugin') }}
    • -
    • {{ 'InstructionsStepTwo'|get_plugin_lang('BuyCoursesPlugin') }}
    • -
    • {{ 'InstructionsStepThree'|get_plugin_lang('BuyCoursesPlugin') }}
    • -
    -
    -
    -
    -
    + -
    -
    -
    - - - - + {% if _u.is_admin %} + diff --git a/plugin/buycourses/view/sales_report.tpl b/plugin/buycourses/view/sales_report.tpl index 565646cfcb..9496bfcc91 100644 --- a/plugin/buycourses/view/sales_report.tpl +++ b/plugin/buycourses/view/sales_report.tpl @@ -7,13 +7,12 @@ {{ 'OrderReference'|get_plugin_lang('BuyCoursesPlugin') }} {{ 'OrderStatus'|get_plugin_lang('BuyCoursesPlugin') }} {{ 'OrderDate'|get_plugin_lang('BuyCoursesPlugin') }} + {{ 'PaymentMethod'|get_plugin_lang('BuyCoursesPlugin') }} {{ 'Price'|get_plugin_lang('BuyCoursesPlugin') }} {{ 'ProductType'|get_plugin_lang('BuyCoursesPlugin') }} {{ 'Name'|get_lang }} {{ 'UserName'|get_lang }} - {% if selected_status == sale_status_pending %} - {{ 'Options'|get_lang }} - {% endif %} + {{ 'Options'|get_lang }} @@ -30,24 +29,39 @@ {% endif %} {{ sale.date }} + {{ sale.payment_type }} {{ sale.currency ~ ' ' ~ sale.price }} {{ sale.product_type }} {{ sale.product_name }} {{ sale.complete_user_name }} - {% if selected_status == sale_status_pending %} - - {% if sale.status == sale_status_pending %} - - {{ 'SubscribeUser'|get_plugin_lang('BuyCoursesPlugin') }} - - - {{ 'DeleteOrder'|get_plugin_lang('BuyCoursesPlugin') }} - - {% endif %} - - {% endif %} + + {% if sale.status == sale_status_pending %} + + {{ 'SubscribeUser'|get_plugin_lang('BuyCoursesPlugin') }} + + + {{ 'DeleteOrder'|get_plugin_lang('BuyCoursesPlugin') }} + + {% endif %} + {% endfor %}
    + + diff --git a/tests/features/courseTools.feature b/tests/features/courseTools.feature index 70f5db98bd..cd0ac6bc9c 100644 --- a/tests/features/courseTools.feature +++ b/tests/features/courseTools.feature @@ -5,6 +5,13 @@ Feature: Course tools basic testing As a teacher I need to be able to enter a course and each of its tools + Scenario: Create a course before testing + Given I am a platform administrator + And I am on "/main/admin/course_add.php" + When I fill in "title" with "TEMP" + And I press "submit" + Then I should see "Course list" + Scenario: Make sure the course exists Given I am a platform administrator Given course "TEMP" exists diff --git a/tests/features/createUser.feature b/tests/features/createUser.feature index 567096979e..7f5001ac70 100644 --- a/tests/features/createUser.feature +++ b/tests/features/createUser.feature @@ -27,7 +27,7 @@ Feature: Users management as admin Scenario: Search and delete a user Given I am a platform administrator And I am on "/main/admin/user_list.php" - And I fill in "user-search-keyword" with "smarshall" + And I fill in "keyword" with "smarshall" And I press "submit" When I follow "Delete" Then I should see "The user has been deleted" diff --git a/tests/scripts/delete_old_tasks.php b/tests/scripts/delete_old_tasks.php new file mode 100644 index 0000000000..459e365476 --- /dev/null +++ b/tests/scripts/delete_old_tasks.php @@ -0,0 +1,139 @@ + + * @author Percy Santiago + * @author Yannick Warnier + */ +exit(); //remove this line to execute from the command line +if (PHP_SAPI !== 'cli') { + die('This script can only be executed from the command line'); +} + +require __DIR__.'/../../main/inc/conf/configuration.php'; + +// Dates +$expiryDate = '2015-06-01'; //session start date must be < to be considered +$fromDate = '2011-01-01'; //session start date must be > to be considered + +$sessionCourses = array(); +$coursesCodes = array(); +$coursesDirs = array(); +if (!$conexion = mysql_connect($_configuration['db_host'], $_configuration['db_user'], $_configuration['db_password'])) { + echo 'Could not connect to database'; + exit; +} + +if (!mysql_select_db($_configuration['main_database'], $conexion)) { + echo 'Could not select database '.$_configuration['main_database']; + exit; +} +echo "[".time()."] Querying sessions\n"; +$sql = "SELECT id FROM session where access_start_date < '$expiryDate' AND access_start_date > '$fromDate'"; + +$res = mysql_query($sql, $conexion); +if ($res === false) { + //die("Error querying sessions: ".Database::error($res)."\n"); +} + +$countSessions = mysql_num_rows($res); +$sql = "SELECT count(*) FROM session"; +$resc = mysql_query($sql, $conexion); +if ($resc === false) { + //die("Error querying sessions: ".Database::error($res)."\n"); +} +$countAllSessions = mysql_result($resc, 0, 0); +echo "[".time()."] Found $countSessions sessions between $fromDate and $expiryDate on a total of $countAllSessions sessions."."\n"; + +while ($session = mysql_fetch_assoc($res)) { + $sql2 = "SELECT c.id AS cid, c.code as ccode, c.directory as cdir + FROM course c, session_rel_course s + WHERE s.id_session = ".$session['id']." + AND s.course_code = c.code"; + $res2 = mysql_query($sql2, $conexion); //Database::query($sql2); + + if ($res2 === false) { + die("Error querying courses for session ".$session['id'].": ".mysql_error($res2)."\n"); + } + + if (mysql_num_rows($res2) > 0) { + while ($course = mysql_fetch_assoc($res2)) { + $sessionCourses[$session['id']] = $course['cid']; + //$_SESSION['session_course'] = $sessionCourses; + + if (empty($coursesCodes[$course['cid']])) { + $coursesCodes[$course['cid']] = $course['ccode']; + } + if (empty($coursesDirs[$course['cid']])) { + $coursesDirs[$course['cid']] = $course['cdir']; + } + } + } +} +echo "[".time()."] Filled courses arrays. Now checking tasks...\n"; +/** + * Locate and destroy the expired tasks + */ +//$sessionCourse = $_SESSION['session_course']; + +$totalSize = 0; +foreach ($sessionCourses as $sid => $cid) { + // Check if a folder already exists in this session + // Folders are exclusive to sessions. If a folder already exists in + // another session, you will not be allowed to create the same folder in + // another session. As such, folders belong to one and only one session. + $sql = "SELECT id, url FROM c_student_publication + WHERE filetype = 'folder' + AND c_id = $cid + AND session_id = $sid + AND active = 1 + AND url LIKE '%ALP%'"; + + $resCarpetas = mysql_query($sql, $conexion); //Database::query($sql); + + if (mysql_num_rows($resCarpetas) > 0) { + while ($rowDemo = mysql_fetch_assoc($resCarpetas)) { + + $carpetaAlpElimina = $_configuration['root_sys'].'courses/'.$coursesDirs[$cid].'/work'.$rowDemo['url']; + + //echo "rm -rf ".$carpetaAlpElimina."\n"; + $size = folderSize($carpetaAlpElimina); + $totalSize += $size; + echo "Freeing $size of a total $totalSize bytes in $carpetaAlpElimina\n"; + exec('rm -rf '.$carpetaAlpElimina); + } + + $sqldel = "DELETE FROM c_student_publication + WHERE + c_id = $cid + AND session_id = $sid AND active = 1;"; + $resdel = mysql_query($sqldel); + if ($resdel === false) { + echo "Error querying sessions: ".Database::error($resdel)."\n"; + } + } +} +echo "[".time()."] Deleted tasks from $countSessions sessions between $fromDate and $expiryDate on a total of $countAllSessions sessions."."\n"; + +/** + * Helper function to calculate size of a folder + * @author See php.net comments on filesize() + */ +function folderSize($dir) { + $size = 0; + $contents = glob(rtrim($dir, '/').'/*', GLOB_NOSORT); + foreach ($contents as $contents_value) { + if (is_file($contents_value)) { + $size += filesize($contents_value); + } else { + $size += folderSize($contents_value); + } + } + return $size; +}