Browse Source

Merge branch '1.11.x' of github.com:chamilo/chamilo-lms into 1.11.x

jmontoyaa 8 years ago
parent
commit
527a961ed2

+ 3 - 0
.htaccess

@@ -53,5 +53,8 @@ RewriteRule ^main/exercice/(.*)$ main/exercise/$1 [QSA,L]
 # Support old URLs using the newscorm folder rather than lp
 RewriteRule ^main/newscorm/(.*)$ main/lp/$1 [QSA,L]
 
+# service Information
+RewriteRule ^service/(\d{1,})$ plugin/buycourses/src/service_information.php?service_id=$1 [L]
+
 # Deny access
 RewriteRule ^(tests|.git) - [F,L,NC]

+ 1 - 0
main/inc/lib/api.lib.php

@@ -823,6 +823,7 @@ function api_get_path($path = '', $configuration = [])
             $paths[$root_web][SYS_HOME_PATH] = api_add_trailing_slash($virtualChamilo[SYS_HOME_PATH]);
             $paths[$root_web][SYS_COURSE_PATH] = api_add_trailing_slash($virtualChamilo[SYS_COURSE_PATH]);
             $paths[$root_web][SYS_UPLOAD_PATH] = api_add_trailing_slash($virtualChamilo[SYS_UPLOAD_PATH]);
+            $paths[$root_web][WEB_UPLOAD_PATH] = api_add_trailing_slash($virtualChamilo[WEB_UPLOAD_PATH]);
             //$paths[$root_web][REL_PATH] = $virtualChamilo[REL_PATH];
             //$paths[$root_web][REL_COURSE_PATH] = $virtualChamilo[REL_COURSE_PATH];
         }

+ 1 - 0
main/inc/lib/formvalidator/FormValidator.class.php

@@ -832,6 +832,7 @@ EOT;
                 </div>'
             );
             $this->addHidden($id.'_crop_result', '');
+            $this->addHidden($id.'_crop_image_base_64', '');
         }
     }
 

+ 1 - 0
main/inc/lib/pear/HTML/QuickForm/file.php

@@ -300,6 +300,7 @@ class HTML_QuickForm_file extends HTML_QuickForm_input
                 $image.attr("src", dataUrl);
                 $image.cropper("destroy");
                 $cropButton.addClass("hidden");
+                $("[name='.$id.'_crop_image_base_64]").val($("#'.$id.'_preview_image").attr("src"));
                 return false;
             });
         });

+ 5 - 1
plugin/buycourses/lang/spanish.php

@@ -39,7 +39,7 @@ $strings['Buyer'] = "Comprador";
 $strings['BankTransfer'] = "Transferencia Bancaria";
 $strings['SaleInfo'] = "Información de la venta";
 $strings['SaleStatusPending'] = "Venta pendiente";
-$strings['SaleStatusCanceled'] = "Venta cancelada";
+$strings['SaleStatusCancelled'] = "Venta cancelada";
 $strings['SaleStatusCompleted'] = "Venta completada";
 $strings['PayoutStatusPending'] = "Pago pendiente";
 $strings['PayoutStatusCanceled'] = "Pago cancelado";
@@ -143,3 +143,7 @@ $strings['ServiceInformation'] = "Información del servicio";
 $strings['EditService'] = "Editar servicio";
 $strings['ServiceAdded'] = "Servicio agregado";
 $strings['ServiceEdited'] = "Servicio editado";
+$strings['ServiceSaleInfo'] = "Información del servicio";
+$strings['ListOfServicesOnSale'] = "Lista de servicios a la venta";
+$strings['AdditionalInfo'] = "Información adicional";
+$strings['PleaseSelectTheCorrectInfoToApplyTheService'] = "Porfavor Seleccione la información correcta para aplicar el servicio";

+ 30 - 1
plugin/buycourses/resources/css/style.css

@@ -1,5 +1,34 @@
 .buy-courses-tabs {
-    margin-bottom: 15px;
+  margin-bottom: 15px;
+}
+
+.buy-courses-page-header {
+  padding-bottom: 9px;
+  margin: 40px 0 20px;
+  border-bottom: 1px solid #eee;
+}
+
+.buy-courses-block-button {
+  display: block;
+  width: 100%;
+  height: 50px;
+  line-height: 35px;
+  font-size: 16px;
+}
+
+.buy-courses-cross-out {
+  text-decoration:line-through;
+}
+
+.buy-courses-title-color {
+  color: #5DC3E1;
+  padding-bottom: 10px;
+}
+
+.buy-courses-description-service {
+  text-align: justify;
+  font-size: 18px;
+  line-height: 1.42857;
 }
 
 @-moz-keyframes wobblebar-loader {

+ 88 - 4
plugin/buycourses/src/buy_course_plugin.class.php

@@ -38,6 +38,9 @@ class BuyCoursesPlugin extends Plugin
     const SERVICE_STATUS_PENDING = 0;
     const SERVICE_STATUS_COMPLETED = 1;
     const SERVICE_STATUS_CANCELLED = -1;
+    const SERVICE_TYPE_USER = 1;
+    const SERVICE_TYPE_COURSE = 2;
+    const SERVICE_TYPE_SESSION = 3;
 
     /**
      *
@@ -1699,7 +1702,7 @@ class BuyCoursesPlugin extends Plugin
         );
 
         if ($return) {
-            $img = str_replace('data:image/png;base64,', '', $service['cropResult']);
+            $img = str_replace('data:image/png;base64,', '', $service['picture_crop_image_base_64']);
             $img = str_replace(' ', '+', $img);
             $data = base64_decode($img);
             $file = api_get_path(SYS_PLUGIN_PATH).'buycourses/uploads/services/images/simg-'.$return.'.png';
@@ -1725,9 +1728,8 @@ class BuyCoursesPlugin extends Plugin
     public function updateService($service, $id)
     {
         $servicesTable = Database::get_main_table(BuyCoursesPlugin::TABLE_SERVICES);
-
-        if (!empty($service['cropResult'])) {
-            $img = str_replace('data:image/png;base64,', '', $service['cropResult']);
+        if (!empty($service['picture_crop_image_base_64'])) {
+            $img = str_replace('data:image/png;base64,', '', $service['picture_crop_image_base_64']);
             $img = str_replace(' ', '+', $img);
             $data = base64_decode($img);
             $file = api_get_path(SYS_PLUGIN_PATH).'buycourses/uploads/services/images/simg-'.$id.'.png';
@@ -1889,6 +1891,7 @@ class BuyCoursesPlugin extends Plugin
             $hot = "count(ss.service_id) as hot, ";
             $conditions = ['ORDER' => 'hot DESC', 'LIMIT' => '6'];
             $groupBy = "GROUP BY ss.service_id";
+            "clean_teacher_files.php";
         }
 
         $innerJoins = "INNER JOIN $servicesTable s ON ss.service_id = s.id $groupBy";
@@ -2002,4 +2005,85 @@ class BuyCoursesPlugin extends Plugin
         return true;
     }
 
+    /**
+     * Lists current service details
+     * @param string $name Optional. The name filter
+     * @param int $min Optional. The minimum price filter
+     * @param int $max Optional. The maximum price filter
+     * @param mixed $appliesTo Optional.
+     * @return array
+     */
+    public function getCatalogServiceList($name = null, $min = 0, $max = 0, $appliesTo = '')
+    {
+        $servicesTable = Database::get_main_table(BuyCoursesPlugin::TABLE_SERVICES);
+        $userTable = Database::get_main_table(TABLE_MAIN_USER);
+
+        $whereConditions = [
+            's.id <> ? ' => 0
+        ];
+
+        if (!empty($name)) {
+            $whereConditions['AND s.name LIKE %?%'] = $name;
+        }
+
+        if (!empty($min)) {
+            $whereConditions['AND s.price >= ?'] = $min;
+        }
+
+        if (!empty($max)) {
+            $whereConditions['AND s.price <= ?'] = $max;
+        }
+
+        if (!$appliesTo == '') {
+            $whereConditions['AND s.applies_to = ?'] = $appliesTo;
+        }
+
+        $innerJoins = "INNER JOIN $userTable u ON s.owner_id = u.id";
+        $currency = $this->getSelectedCurrency();
+        $isoCode = $currency['iso_code'];
+        $return = Database::select(
+            "s.*, '$isoCode' as currency, u.firstname, u.lastname",
+            "$servicesTable s $innerJoins",
+            ['WHERE' => $whereConditions]
+        );
+
+        $services = [];
+
+        foreach ($return as $index => $service) {
+            $services[$index]['id'] = $service['id'];
+            $services[$index]['name'] = $service['name'];
+            $services[$index]['description'] = $service['description'];
+            $services[$index]['price'] = $service['price'];
+            $services[$index]['currency'] = $service['currency'];
+            $services[$index]['duration_days'] = $service['duration_days'];
+            $services[$index]['applies_to'] = $service['applies_to'];
+            $services[$index]['owner_id'] = $service['owner_id'];
+            $services[$index]['owner_name'] = api_get_person_name($service['firstname'], $service['lastname']);
+            $services[$index]['visibility'] = $service['visibility'];
+            $services[$index]['image'] = api_get_path(WEB_PLUGIN_PATH).'buycourses/uploads/services/images/'.$service['image'];
+            $services[$index]['video_url'] = $service['video_url'];
+            $services[$index]['service_information'] = $service['service_information'];
+        }
+
+        return $services;
+
+    }
+
+    /**
+     * Update the service sale status
+     * @param int $serviceSaleId The service sale ID
+     * @param int $newStatus The new status
+     * @return boolean
+     */
+    private function updateServiceSaleStatus($serviceSaleId, $newStatus = self::SERVICE_STATUS_PENDING)
+    {
+        $serviceSaleTable = Database::get_main_table(self::TABLE_SERVICES_SALE);
+
+        return Database::update(
+            $serviceSaleTable,
+            ['status' => intval($newStatus)],
+            ['id = ?' => intval($serviceSaleId)]
+        );
+    }
+
 }

+ 1 - 1
plugin/buycourses/src/configuration.php

@@ -24,7 +24,7 @@ $courses = $plugin->getCoursesForConfiguration();
 // breadcrumbs
 $interbreadcrumb[] = [
     'url' => api_get_path(WEB_PLUGIN_PATH) . 'buycourses/index.php',
-    'name' => $plugin->get_lang('Home')
+    'name' => $plugin->get_lang('plugin_title')
 ];
 
 $templateName = $plugin->get_lang('AvailableCourses');

+ 2 - 0
plugin/buycourses/src/course_catalog.php

@@ -12,6 +12,7 @@ require_once __DIR__.'/../../../main/inc/global.inc.php';
 
 $plugin = BuyCoursesPlugin::create();
 $includeSessions = $plugin->get('include_sessions') === 'true';
+$includeServices = $plugin->get('include_services') === 'true';
 
 $nameFilter = null;
 $minFilter = 0;
@@ -68,6 +69,7 @@ $tpl->assign('search_filter_form', $form->returnForm());
 $tpl->assign('showing_courses', true);
 $tpl->assign('courses', $courseList);
 $tpl->assign('sessions_are_included', $includeSessions);
+$tpl->assign('services_are_included', $includeServices);
 
 $content = $tpl->fetch('buycourses/view/catalog.tpl');
 

+ 89 - 0
plugin/buycourses/src/service_catalog.php

@@ -0,0 +1,89 @@
+<?php
+/**
+ * List of services
+ * @package chamilo.plugin.buycourses
+ */
+/**
+ * Initialization
+ */
+
+$cidReset = true;
+
+require_once '../../../main/inc/global.inc.php';
+
+$plugin = BuyCoursesPlugin::create();
+$includeSessions = $plugin->get('include_sessions') === 'true';
+$includeServices = $plugin->get('include_services') === 'true';
+
+$nameFilter = null;
+$minFilter = 0;
+$maxFilter = 0;
+$appliesToFilter = '';
+
+$form = new FormValidator('search_filter_form', 'get', null, null, [], FormValidator::LAYOUT_INLINE);
+
+if ($form->validate()) {
+    $formValues = $form->getSubmitValues();
+    $nameFilter = isset($formValues['name']) ? $formValues['name'] : null;
+    $minFilter = isset($formValues['min']) ? $formValues['min'] : 0;
+    $maxFilter = isset($formValues['max']) ? $formValues['max'] : 0;
+    $appliesToFilter = isset($formValues['applies_to']) ? $formValues['applies_to'] : '';
+}
+
+$form->addHeader($plugin->get_lang('SearchFilter'));
+$form->addText('name', $plugin->get_lang('ServiceName'), false);
+$form->addElement(
+    'number',
+    'min',
+    $plugin->get_lang('MinimumPrice'),
+    ['step' => '0.01', 'min' => '0']
+);
+$form->addElement(
+    'number',
+    'max',
+    $plugin->get_lang('MaximumPrice'),
+    ['step' => '0.01', 'min' => '0']
+);
+$appliesToOptions = [
+    '' => get_lang('Any'),
+    0 => get_lang('None'),
+    1 => get_lang('User'),
+    2 => get_lang('Course'),
+    3 => get_lang('Session')
+];
+$form->addSelect('applies_to', $plugin->get_lang('AppliesTo'), $appliesToOptions);
+$form->addHtml('<hr>');
+$form->addButtonFilter(get_lang('Search'));
+
+$serviceList = $plugin->getCatalogServiceList($nameFilter, $minFilter, $maxFilter, $appliesToFilter);
+
+//View
+if (api_is_platform_admin()) {
+    $interbreadcrumb[] = [
+        'url' => 'configuration.php',
+        'name' => $plugin->get_lang('AvailableCoursesConfiguration')
+    ];
+    $interbreadcrumb[] = [
+        'url' => 'paymentsetup.php',
+        'name' => $plugin->get_lang('PaymentsConfiguration')
+    ];
+} else {
+    $interbreadcrumb[] = [
+        'url' => '../index.php',
+        'name' => $plugin->get_lang('UserPanel')
+    ];
+}
+
+$templateName = $plugin->get_lang('ListOfServicesOnSale');
+$tpl = new Template($templateName);
+$tpl->assign('search_filter_form', $form->returnForm());
+$tpl->assign('showing_services', true);
+$tpl->assign('services', $serviceList);
+$tpl->assign('sessions_are_included', $includeSessions);
+$tpl->assign('services_are_included', $includeServices);
+
+$content = $tpl->fetch('buycourses/view/catalog.tpl');
+
+$tpl->assign('header', $templateName);
+$tpl->assign('content', $content);
+$tpl->display_one_col_template();

+ 39 - 0
plugin/buycourses/src/service_information.php

@@ -0,0 +1,39 @@
+<?php
+
+/* For licensing terms, see /license.txt */
+/**
+ * Service information page
+ * Show information about a service (for custom purposes)
+ * @author José Loguercio Silva <jose.loguercio@beeznest.com>
+ * @package chamilo.buycourses_plugin
+ */
+
+$cidReset = true;
+
+require_once '../../../main/inc/global.inc.php';
+
+$serviceId = isset($_GET['service_id']) ? intval($_GET['service_id']) : false;
+
+$plugin = BuyCoursesPlugin::create();
+
+$includeServices = $plugin->get('include_services') === 'true';
+
+if (!$includeServices) {
+    api_not_allowed(true);
+}
+
+$service = $plugin->getServices($serviceId);
+
+if (!$service['id']) {
+    api_not_allowed(true);
+}
+
+$template = new Template(false);
+$template->assign('pageUrl', api_get_path(WEB_PATH) . "service/{$serviceId}/information/");
+$template->assign('service', $service);
+$template->assign('essence', Essence\Essence::instance());
+
+$content = $template->fetch('buycourses/view/service_information.tpl');
+
+$template->assign('content', $content);
+$template->display_one_col_template();

+ 234 - 0
plugin/buycourses/src/service_process.php

@@ -0,0 +1,234 @@
+<?php
+/* For license terms, see /license.txt */
+/**
+ * Process payments for the Buy Courses plugin
+ * @package chamilo.plugin.buycourses
+ */
+/**
+ * Initialization
+ */
+
+$cidReset = true;
+
+require_once '../config.php';
+
+if (!isset($_REQUEST['t'], $_REQUEST['i'])) {
+    header('Location: ' . api_get_path(WEB_PLUGIN_PATH) . 'buycourses/src/service_catalog.php');
+}
+
+$currentUserId = api_get_user_id();
+$serviceId = intval($_REQUEST['i']);
+
+if (empty($currentUserId)) {
+    api_not_allowed(true);
+}
+
+$em = Database::getManager();
+$plugin = BuyCoursesPlugin::create();
+$includeServices = $plugin->get('include_services');
+$paypalEnabled = $plugin->get('paypal_enable') === 'true';
+$transferEnabled = $plugin->get('transfer_enable') === 'true';
+$wizard = true;
+$additionalQueryString = '';
+if ($includeServices !== 'true') {
+    api_not_allowed(true);
+}
+
+$typeUser = intval($_REQUEST['t']) === BuyCoursesPlugin::SERVICE_TYPE_USER;
+$typeCourse = intval($_REQUEST['t']) === BuyCoursesPlugin::SERVICE_TYPE_COURSE;
+$typeSession = intval($_REQUEST['t']) === BuyCoursesPlugin::SERVICE_TYPE_SESSION;
+$queryString = 'i=' . intval($_REQUEST['i']) . '&t=' . intval($_REQUEST['t']).$additionalQueryString;
+
+$serviceInfo = $plugin->getServices(intval($_REQUEST['i']));
+$userInfo = api_get_user_info($currentUserId);
+
+$form = new FormValidator('confirm_sale');
+
+if ($form->validate()) {
+    $formValues = $form->getSubmitValues();
+    
+    if (!$formValues['payment_type']) {
+        Display::addFlash(
+            Display::return_message($plugin->get_lang('NeedToSelectPaymentType'), 'error', false)
+        );
+        header('Location:' . api_get_self() . '?' . $queryString);
+        exit;
+    }
+
+    if (!$formValues['info_select']) {
+        Display::addFlash(
+            Display::return_message($plugin->get_lang('AdditionalInfoRequired'), 'error', false)
+        );
+        header('Location:' . api_get_self() . '?' . $queryString);
+        exit;
+    }
+
+    $userGroup = $em->getRepository('ChamiloCoreBundle:Usergroup')->findBy(['name' => $formValues['info_select']]);
+
+    if ($userGroup) {
+        Display::addFlash(
+            Display::return_message($plugin->get_lang('StoreNameAlreadyExist'), 'error', false)
+        );
+        header('Location:' . api_get_self() . '?' . $queryString);
+        exit;
+    }
+    
+    $serviceSaleId = $plugin->registerServiceSale($serviceId, $formValues['payment_type'], $formValues['info_select'], $formValues['enable_trial']);
+
+    if (!empty($formValues['store_code'])) {
+        $data = [
+            'store_code' => Security::remove_XSS($formValues['store_code']),
+            'store_name' => Security::remove_XSS($formValues['info_select']),
+            'parent_id' => 0,
+            'description' => 'Registered by User in buying process',
+            'type' => 1,
+            'discount' => 0
+        ];
+
+        $verification = $plugin->getDiscountByCode($data['store_code']);
+
+        if (!$verification) {
+            $plugin->addDiscountCode($data);
+        }
+    }
+
+    if ($serviceSaleId !== false) {
+        $_SESSION['bc_service_sale_id'] = $serviceSaleId;
+        
+        if ($verification['discount'] == 100) {
+
+            $serviceSale = $plugin->getServiceSale($serviceSaleId);
+
+            $serviceSaleIsCompleted = $plugin->completeServiceSale($serviceSale['id']);
+            if ($serviceSaleIsCompleted) {
+                Display::addFlash(Display::return_message(sprintf($plugin->get_lang('SubscriptionToServiceXSuccessful'), $serviceSale['service']['name']), 'success'));
+
+                $plugin->SendSubscriptionMail(intval($serviceSale['id']));
+
+                unset($_SESSION['bc_service_sale_id']);
+
+                header('Location: ' . api_get_path(WEB_PLUGIN_PATH) . 'buycourses/src/package_panel.php?id='.$serviceSale['id']);
+                exit;
+            }
+        }
+        
+        if ($wizard) {
+            header('Location: ' . api_get_path(WEB_PLUGIN_PATH) . 'buycourses/src/service_process_confirm.php?from=register');
+        } else {
+            header('Location: ' . api_get_path(WEB_PLUGIN_PATH) . 'buycourses/src/service_process_confirm.php');
+        }
+    }
+
+    exit;
+}
+
+// Reset discount code
+unset($_SESSION['s_discount']);
+
+$paymentTypesOptions = $plugin->getPaymentTypes(true);
+
+$form->addHeader('');
+$form->addRadio('payment_type', null, $paymentTypesOptions);
+$form->addHtml('<h3 class="panel-heading">'.$plugin->get_lang('AdditionalInfo').'</h3>');
+$form->addHeader('');
+$form->addHtml(Display::return_message($plugin->get_lang('PleaseSelectTheCorrectInfoToApplyTheService'), 'info'));
+$selectOptions = [];
+
+if ($typeUser) {
+    $users = $em->getRepository('ChamiloUserBundle:User')->findAll();
+    $selectOptions[$userInfo['user_id']] = api_get_person_name($userInfo['firstname'], $userInfo['lastname']) . ' (' . get_lang('Myself') . ')';
+    if (!empty($users)) {
+        foreach ($users as $user) {
+            if (intval($userInfo['user_id']) !== intval($user->getId())) {
+                $selectOptions[$user->getId()] = $user->getCompleteNameWithUsername();
+            }
+        }
+    }
+    $form->addSelect('info_select', get_lang('User'), $selectOptions);
+} elseif ($typeCourse) {
+    $user = $em->getRepository('ChamiloUserBundle:User')->find($currentUserId);
+    $courses = $user->getCourses();
+    if (!empty($courses)) {
+        foreach ($courses as $course) {
+            $selectOptions[$course->getCourse()->getId()] = $course->getCourse()->getTitle();
+        }
+    }
+    $form->addSelect('info_select', get_lang('Course'), $selectOptions);
+} elseif ($typeSession) {
+    $user = $em->getRepository('ChamiloUserBundle:User')->find($currentUserId);
+    $sessions = $user->getSessionCourseSubscriptions();
+    if (!empty($sessions)) {
+        foreach ($sessions as $session) {
+            $selectOptions[$session->getSession()->getId()] = $session->getSession()->getName();
+        }
+    }
+    $form->addSelect('info_select', get_lang('Session'), $selectOptions);
+} elseif ($typeSubscriptionPackage) {
+    $trial = intval($serviceInfo['allow_trial']);
+
+    if ($trial) {
+        $trialTime = $serviceInfo['trial_period'] == 'Month' ? get_lang($serviceInfo['trial_period']) . '(es)' : get_lang($serviceInfo['trial_period']) . '(s)';
+        $form->addHtml('
+            <div class="form-group ">
+                <label for="qf_373cc5" class="col-sm-6">
+                    ' . sprintf($plugin->get_lang('EnableTrialSubscription'), $serviceInfo['trial_frequency'] . ' ' . $trialTime) . '
+                </label>
+                <div class="col-sm-6">
+                    <input cols-size="" name="enable_trial" value="1" id="qf_373cc5" type="checkbox"></div>
+                <div class="col-sm-0"></div>
+            </div>
+            <div class="form-group ">
+                <div class="col-sm-12">
+                    <p class="help-block">' . sprintf($plugin->get_lang('EnableTrialSubscriptionHelpText'), $serviceInfo['trial_frequency'] . ' ' . $trialTime) . '</p>
+                </div>
+            </div>
+        ');
+    }
+    $form->addText('store_code', $plugin->get_lang('DiscountCodeProcess'), true, ['cols-size' => [6, 6, 0], 'id' => 'store_code']);
+    $form->addText('info_select_trick', $plugin->get_lang('StoreName'), true, ['cols-size' => [6, 6, 0], 'id' => 'info_select_trick']);
+    $form->addHidden('info_select', '');
+    $form->addHtml('
+        <div class="form-group">
+            <div class="col-sm-2 pull-right">
+                <a id="code-checker" class="btn btn-xs btn-warning">' . $plugin->get_lang('Check') . '</a>
+            </div>
+            <div id="code-verificator-text" class="col-sm-4 pull-right">
+            </div>
+        </div>
+        <div id="code-verificator-info">
+
+        </div>
+        <div class="form-group">
+            <div class="col-sm-12">
+                <p class="help-block">' . $plugin->get_lang('DiscountCodeInfoText') . '</p>
+            </div>
+        </div>
+    ');
+}
+
+
+$form->addHidden('t', intval($_GET['t']));
+$form->addHidden('i', intval($_GET['i']));
+
+$form->addButton('submit', $plugin->get_lang('ConfirmOrder'), 'check', 'success');
+
+// View
+$templateName = $plugin->get_lang('PaymentMethods');
+$interbreadcrumb[] = array("url" => "service_catalog.php", "name" => $plugin->get_lang('ListOfServicesOnSale'));
+
+$tpl = new Template($templateName);
+if (isset($_GET['from'])) {
+    if($_GET['from'] == 'register') {
+        $tpl->assign('wizard', true);
+    }
+}
+$tpl->assign('buying_service', true);
+$tpl->assign('service', $serviceInfo);
+$tpl->assign('user', api_get_user_info());
+$tpl->assign('form', $form->returnForm());
+
+
+$content = $tpl->fetch('buycourses/view/process.tpl');
+
+$tpl->assign('content', $content);
+$tpl->display_one_col_template();

+ 1 - 5
plugin/buycourses/src/service_sales_report.php

@@ -17,7 +17,6 @@ $plugin = BuyCoursesPlugin::create();
 $paypalEnable = $plugin->get('paypal_enable');
 $commissionsEnable = $plugin->get('commissions_enable');
 $includeServices = $plugin->get('include_services');
-$servicesOnly = $plugin->get('show_services_only');
 
 $saleStatuses = $plugin->getServiceSaleStatuses();
 $paymentTypes = $plugin->getPaymentTypes();
@@ -41,9 +40,7 @@ foreach ($servicesSales as $sale) {
         'price' => $sale['price'],
         'service_type' => $sale['service']['applies_to'],
         'service_name' => $sale['service']['name'],
-        'complete_user_name' => $sale['buyer']['name'],
-        'recurring_payment' => $sale['recurring_payment'],
-        'payment_type' => $paymentTypes[$sale['payment_type']]
+        'complete_user_name' => $sale['buyer']['name']
     ];
 }
 
@@ -85,7 +82,6 @@ if ($commissionsEnable == 'true') {
 }
 $template->assign('form', $form->returnForm());
 $template->assign('showing_services', true);
-$template->assign('show_services_only', $servicesOnly);
 $template->assign('services_are_included', $includeServices);
 $template->assign('sale_list', $serviceSaleList);
 $template->assign('sale_status_cancelled', BuyCoursesPlugin::SERVICE_STATUS_CANCELLED);

+ 1 - 1
plugin/buycourses/src/services_add.php

@@ -95,7 +95,7 @@ $form->addFile(
     (get_lang(
         'AddImage'
     )),
-    array('id' => 'picture', 'class' => 'picture-form', 'crop_image' => true, 'crop_ratio' => '4 / 3')
+    array('id' => 'picture', 'class' => 'picture-form', 'crop_image' => true, 'crop_ratio' => '16 / 9')
 );
 $form->addText('video_url', get_lang('VideoUrl'), false);
 $form->addHtmlEditor('service_information', $plugin->get_lang('ServiceInformation'), false);

+ 1 - 1
plugin/buycourses/src/services_edit.php

@@ -113,7 +113,7 @@ $form->addFile(
     ($formDefaultValues['image'] != '' ? get_lang('UpdateImage') : get_lang(
         'AddImage'
     )),
-    array('id' => 'picture', 'class' => 'picture-form', 'crop_image' => true, 'crop_ratio' => '4 / 3')
+    array('id' => 'picture', 'class' => 'picture-form', 'crop_image' => true, 'crop_ratio' => '16 / 9')
 );
 $form->addText('video_url', get_lang('VideoUrl'), false);
 $form->addHtmlEditor('service_information', $plugin->get_lang('ServiceInformation'), false);

+ 2 - 0
plugin/buycourses/src/session_catalog.php

@@ -12,6 +12,7 @@ require_once __DIR__.'/../../../main/inc/global.inc.php';
 
 $plugin = BuyCoursesPlugin::create();
 $includeSessions = $plugin->get('include_sessions') === 'true';
+$includeServices = $plugin->get('include_services') === 'true';
 
 if (!$includeSessions) {
     api_not_allowed(true);
@@ -66,6 +67,7 @@ $templateName = $plugin->get_lang('CourseListOnSale');
 $template = new Template($templateName);
 $template->assign('search_filter_form', $form->returnForm());
 $template->assign('sessions_are_included', $includeSessions);
+$template->assign('services_are_included', $includeServices);
 $template->assign('showing_sessions', true);
 $template->assign('sessions', $sessionList);
 

+ 3 - 0
plugin/buycourses/uploads/services/images/.gitignore

@@ -0,0 +1,3 @@
+*
+
+!.gitignore

+ 52 - 0
plugin/buycourses/view/catalog.tpl

@@ -9,6 +9,11 @@
             <li id="buy-sessions-tab" class="{{ showing_sessions ? 'active' : '' }}" role="presentation">
                 <a href="session_catalog.php" aria-controls="buy-sessions" role="tab">{{ 'Sessions'|get_lang }}</a>
             </li>
+            {% if services_are_included %}
+                <li id="buy-services-tab" class="{{ showing_services ? 'active' : '' }}" role="presentation">
+                    <a href="service_catalog.php" aria-controls="buy-services" role="tab">{{ 'Services'|get_plugin_lang('BuyCoursesPlugin') }}</a>
+                </li>
+            {% endif %}
         </ul>
     {% endif %}
 
@@ -104,6 +109,53 @@
                                 </div>
                             {% endfor %}
                         {% endif %}
+
+                        {% if showing_services %}
+                            {% for service in services %}
+                                <div class="col-md-4 col-sm-6">
+                                    <div class="items-course">
+                                        <div class="items-course-image">
+                                            <a href="{{ _p.web }}service/{{ service.id }}"><img alt="{{ service.name }}" class="img-responsive" src="{{ service.image }}"></a>
+                                        </div>
+                                        <div class="items-course-info">
+                                            <h4 class="title">
+                                                <a title="{{ service.name }}" href="{{ _p.web }}service/{{ service.id }}" >
+                                                    {{ service.name }}
+                                                </a>
+                                            </h4>
+                                            <ul class="list-unstyled">
+                                                <li><em class="fa fa-clock-o"></em> {{ 'Duration'|get_plugin_lang('BuyCoursesPlugin') }} : {{ service.duration_days == 0 ? 'NoLimit' | get_lang  : service.duration_days ~ ' ' ~ 'Days' | get_lang }}</li>
+                                                {% if service.applies_to == 0 %}
+                                                    <li><em class="fa fa-hand-o-right"></em> {{ 'AppliesTo'|get_plugin_lang('BuyCoursesPlugin') }} {{ 'None' | get_lang }}</li>
+                                                {% elseif service.applies_to == 1 %}
+                                                    <li><em class="fa fa-hand-o-right"></em> {{ 'AppliesTo'|get_plugin_lang('BuyCoursesPlugin') }} {{ 'User' | get_lang }}</li>
+                                                {% elseif service.applies_to == 2 %}
+                                                    <li><em class="fa fa-hand-o-right"></em> {{ 'AppliesTo'|get_plugin_lang('BuyCoursesPlugin') }} {{ 'Course' | get_lang }}</li>
+                                                {% elseif service.applies_to == 3 %}
+                                                    <li><em class="fa fa-hand-o-right"></em> {{ 'AppliesTo'|get_plugin_lang('BuyCoursesPlugin') }} {{ 'Session' | get_lang }}</li>
+                                                {% elseif service.applies_to == 4 %}
+                                                    <li><em class="fa fa-hand-o-right"></em> {{ 'AppliesTo'|get_plugin_lang('BuyCoursesPlugin') }} {{ 'SubscriptionPackage' | get_plugin_lang('BuyCoursesPlugin') }}</li>
+                                                {% endif %}
+                                                <li><em class="fa fa-user"></em> {{ service.owner_name }}</li>
+                                            </ul>
+                                            <p class="text-right">
+                                                <span class="label label-primary">
+                                                    {{ service.currency == 'BRL' ? 'R$' : service.currency }} {{ service.price }}
+                                                </span>
+                                            </p>
+                                            <div class="toolbar">
+                                                <a class="btn btn-info btn-block btn-sm" title="" href="{{ _p.web }}service/{{ service.id }}">
+                                                    <em class="fa fa-info-circle"></em> {{ 'ServiceInformation'|get_plugin_lang('BuyCoursesPlugin') }}
+                                                </a>
+                                                <a class="btn btn-success btn-block btn-sm" title="" href="{{ _p.web_plugin ~ 'buycourses/src/service_process.php?' ~ {'i': service.id, 't': service.applies_to}|url_encode() }}">
+                                                    <em class="fa fa-shopping-cart"></em> {{ 'Buy'|get_plugin_lang('BuyCoursesPlugin') }}
+                                                </a>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </div>
+                            {% endfor %}
+                        {% endif %}
                     </div>
                 </div>
             </div>

+ 91 - 3
plugin/buycourses/view/process.tpl

@@ -1,8 +1,9 @@
 <script type='text/javascript' src="../js/buycourses.js"></script>
 
 <div class="row">
-    <div class="col-md-7">
-        <h3 class="page-header">{{ 'PurchaseData'|get_plugin_lang('BuyCoursesPlugin') }}</h3>
+    <div class="col-md-5 panel panel-default buycourse-panel-default">
+        <h3 class="panel-heading">{{ 'PurchaseData'|get_plugin_lang('BuyCoursesPlugin') }}</h3>
+        <legend></legend>
         <div class="row">
             {% if buying_course %}
                 <div class="col-sm-6 col-md-5">
@@ -43,10 +44,97 @@
                         {% endfor %}
                     </dl>
                 </div>
+            {% elseif buying_service %}
+                <div class="col-sm-12 col-md-12 col-xs-12">
+                    <a href='{{ _p.web }}service/{{ service.id }}'>
+                        <img alt="{{ service.name }}" class="img-responsive" src="{{ _p.web }}plugin/buycourses/uploads/services/images/{{ service.image }}">
+                    </a>
+                </div>
+                <div class="col-sm-12 col-md-12 col-xs-12">
+                    <h3>
+                        <a href='{{ _p.web }}service/{{ service.id }}'>{{ service.name }}</a>
+                    </h3>
+                    <ul class="list-unstyled">
+                        {% if service.applies_to == 0 %}
+                            <li><em class="fa fa-hand-o-right"></em> {{ 'AppliesTo'|get_plugin_lang('BuyCoursesPlugin') }} {{ 'None' | get_lang }}</li>
+                        {% elseif service.applies_to == 1 %}
+                            <li><em class="fa fa-hand-o-right"></em> {{ 'AppliesTo'|get_plugin_lang('BuyCoursesPlugin') }} {{ 'User' | get_lang }}</li>
+                        {% elseif service.applies_to == 2 %}
+                            <li><em class="fa fa-hand-o-right"></em> {{ 'AppliesTo'|get_plugin_lang('BuyCoursesPlugin') }} {{ 'Course' | get_lang }}</li>
+                        {% elseif service.applies_to == 3 %}
+                            <li><em class="fa fa-hand-o-right"></em> {{ 'AppliesTo'|get_plugin_lang('BuyCoursesPlugin') }} {{ 'Session' | get_lang }}</li>
+                        {% endif %}
+                        <li><em class="fa fa-money"></em> {{ 'Price'|get_plugin_lang('BuyCoursesPlugin') }} : {{ service.currency == 'BRL' ? 'R$' : service.currency }} {{ service.price }} / {{ service.duration_days == 0 ? 'NoLimit' | get_lang  : service.duration_days ~ ' ' ~ 'Days' | get_lang }} </li>
+                        <li><em class="fa fa-user"></em> {{ service.owner_name }}</li>
+                        <li><em class="fa fa-align-justify"></em> {{ service.description }}</li>
+                    </ul>
+                    <p id="n-price" class="lead text-right" style="color: white;"><span class="label label-primary">{{ service.currency == 'BRL' ? 'R$' : service.currency }} {{ service.price }}</span></p>
+                    <p id="s-price" class="lead text-right"></p>
+                </div>
+                <script>
+                    $(document).ready(function() {
+                        $("input[name=info_select_trick]").prop('disabled', true);
+                        $("input[name=payment_type]").attr('hidden', true);
+                        $("input[name=payment_type]").attr('checked', true);
+                        $("#paypal-icon").html(' <em class="fa fa-check text-success fa-2x" aria-hidden="true"></em>');
+                        $("input[name=payment_type]").click(function () {
+                            $("#paypal-icon").html(' <em class="fa fa-check text-success fa-2x" aria-hidden="true"></em>');
+                        })
+                        $("label").removeClass('control-label');
+                        $('.form_required').remove();
+                        $("small").remove();
+                        $("label[for=submit]").remove();
+                        $("input[name=enable_trial]").attr('checked', true);
+
+                        $("#code-checker").click(function () {
+                            var code = $("#store_code").val();
+                            $.ajax({
+                                beforeSend: function() {
+                                    $("#code-checker").html('<em class="fa fa-refresh fa-spin"></em> {{ 'Loading' | get_lang }}');
+                                },
+                                type: "POST",
+                                url: "{{ _p.web_plugin ~ 'buycourses/src/buycourses.ajax.php?a=verify_discount_code' }}",
+                                data : { store_code: code},
+                                success: function(response) {
+                                    $("#code-checker").html('{{ 'Check' | get_plugin_lang('BuyCoursesPlugin') }}');
+                                    if (response.msg == 'true') {
+                                        var store_name = response.store_name;
+                                        var description = response.description;
+                                        var type = response.type;
+                                        var parent = '';
+                                        if (response.parent) {
+                                            parent = '<div class="form-group"><label for="code_parent" class="col-sm-6">{{ 'Parent' | get_plugin_lang('BuyCoursesPlugin') }}</label><div class="col-sm-6">' + response.parent + '</div></div>'
+                                        }
+                                        $("input[name=info_select]").val(store_name);
+                                        $("#info_select_trick").val(store_name);
+                                        $("#code-verificator-text").html('<p style="color: green">{{ 'ValidCode' | get_plugin_lang('BuyCoursesPlugin') }}</p>');
+                                        $("#code-verificator-info").html('' +
+                                            '<div class="form-group"><label for="code_description" class="col-sm-6">{{ 'Description' | get_plugin_lang('BuyCoursesPlugin') }}</label><div class="col-sm-6">' + description + '</div></div>' +
+                                            '<div class="form-group"><label for="code_type" class="col-sm-6">{{ 'Type' | get_plugin_lang('BuyCoursesPlugin') }}</label><div class="col-sm-6">' + type + '</div></div>' + parent +
+                                            '');
+                                        var price = {{ service.price }};
+                                        var show = response.discount;
+                                        var discount = price * (response.discount / 100);
+                                        var total = price - discount;
+                                        $("#n-price").css('text-decoration', 'line-through');
+                                        $("#s-price").html('<b>Desconto especial de ' + show + '%</b> <span class="label label-success">{{ service.currency == 'BRL' ? 'R$' : service.currency }} ' + total.toFixed(2) + '</span>');
+                                    } else if (response.msg == 'false') {
+                                        $("#code-verificator-text").html('<p style="color: red">{{ 'CodeDoesntExist' | get_plugin_lang('BuyCoursesPlugin') }}</p>');
+                                        $("input[name=info_select]").val($("#store_code").val());
+                                        $("#info_select_trick").val($("#store_code").val());
+                                    }
+                                }
+                            });
+                        });
+                    });
+                </script>
             {% endif %}
         </div>
     </div>
-    <div class="col-md-5">
+    <div class="col-md-1">
+    </div>
+    <div class="col-md-6 panel panel-default buycourse-panel-default">
+        <h3 class="panel-heading">{{ 'PaymentMethods' | get_plugin_lang('BuyCoursesPlugin') }}</h3>
         {{ form }}
     </div>
 </div>

+ 80 - 0
plugin/buycourses/view/service_information.tpl

@@ -0,0 +1,80 @@
+<link rel="stylesheet" type="text/css" href="{{ _p.web_plugin ~ 'buycourses/resources/css/style.css' }}"/>
+
+<div id="service-information">
+
+    <div class="row">
+        <div class="col-xs-12">
+            <h3 class="text-uppercase buy-courses-title-color">{{ service.name }}</h3>
+        </div>
+
+        {% if service.video_url %}
+            <div class="col-sm-6 col-md-7 col-xs-12">
+                <div class="embed-responsive embed-responsive-16by9">
+                    {{ essence.replace(service.video_url) }}
+                </div>
+            </div>
+        {% endif %}
+
+        <div class="{{ service.video_url ? 'col-sm-6 col-md-5 col-xs-12' : 'col-sm-12 col-xs-12' }}">
+            <div class="block">
+                <div class="panel panel-default">
+                    <div class="panel-heading">
+                        <h4>{{ "Description"|get_lang }}</h4>
+                    </div>
+                    <div class="panel-body">
+                        <p><em class="fa fa-flag-o"></em> <b>{{ 'AppliesTo'|get_plugin_lang('BuyCoursesPlugin') }}</b> :
+                            {% if service.applies_to == 1 %}
+                                {{ 'User' | get_lang }}
+                            {% elseif service.applies_to == 2 %}
+                                {{ 'Course' | get_lang }}
+                            {% elseif service.applies_to == 3 %}
+                                {{ 'Session' | get_lang }}
+                            {% endif %}
+                        </p>
+                        <p><em class="fa fa-money"></em> <b>{{ 'Price'|get_plugin_lang('BuyCoursesPlugin') }}</b> : {{ service.currency == 'BRL' ? 'R$' : service.currency }} {{ service.price }}</p>
+                        <p><em class="fa fa-align-justify"></em> <b>{{ 'Details' | get_lang }}</b> : {{ service.description }}</p>
+                        <div class="text-right" style="padding-bottom: 20px;">
+                            <a href="{{ _p.web_plugin ~ 'buycourses/src/service_process.php?t=4&i=' ~ service.id }}" class="btn btn-success btn-lg">
+                                <em class="fa fa-shopping-cart"></em> {{ 'Buy'|get_plugin_lang('BuyCoursesPlugin') }}
+                            </a>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    </br>
+    </br>
+    <div class="row info-course">
+        <div class="col-xs-12 col-md-7">
+            <div class="panel panel-default">
+                <div class="panel-heading">
+                    <h4>{{ 'ServiceInformation'|get_plugin_lang('BuyCoursesPlugin') }}</h4>
+                </div>
+                <div class="panel-body">
+                    {{ service.service_information }}
+                </div>
+            </div>
+        </div>
+        <div class="col-xs-12 col-md-5">
+            <div class="panel panel-default social-share">
+                <div class="panel-heading">
+                    <h4>{{ "ShareWithYourFriends"|get_lang }}</h4>
+                </div>
+                <div class="panel-body">
+                    <div class="icons-social text-center">
+                        <a href="https://www.facebook.com/sharer/sharer.php?{{ {'u': pageUrl}|url_encode }}" target="_blank" class="btn bnt-link btn-lg">
+                            <em class="fa fa-facebook fa-2x"></em>
+                        </a>
+                        <a href="https://twitter.com/home?{{ {'status': session.getName() ~ ' ' ~ pageUrl}|url_encode }}" target="_blank" class="btn bnt-link btn-lg">
+                            <em class="fa fa-twitter fa-2x"></em>
+                        </a>
+                        <a href="https://www.linkedin.com/shareArticle?{{ {'mini': 'true', 'url': pageUrl, 'title': session.getName() }|url_encode }}" target="_blank" class="btn bnt-link btn-lg">
+                            <em class="fa fa-linkedin fa-2x"></em>
+                        </a>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>

+ 12 - 8
plugin/buycourses/view/service_sales_report.tpl

@@ -1,7 +1,19 @@
 <link rel="stylesheet" type="text/css" href="../resources/css/style.css"/>
 <script type="text/javascript" src="../resources/js/modals.js"></script>
+
+<ul class="nav nav-tabs buy-courses-sessions-tabs" role="tablist">
+    <li id="buy-courses-sessions-tab" class="" role="presentation">
+        <a href="sales_report.php" aria-controls="buy-courses_sessions" role="tab">{{ 'CourseSessionBlock'|get_lang }}</a>
+    </li>
+    <li id="buy-services-tab" class="active" role="presentation">
+        <a href="service_sales_report.php" aria-controls="buy-services" role="tab">{{ 'Services'|get_plugin_lang('BuyCoursesPlugin') }}</a>
+    </li>
+</ul>
+</br>
+</br>
 <div class="row">
     <div class="col-md-3 col-sm-12 col-xs-12">
+        <h4><b>{{ 'Filter' | get_lang }}</b></h4>
         {{ form }}
     </div>
     <div class="col-md-9 col-sm-12 col-xs-12">
@@ -14,7 +26,6 @@
                     <th class="text-center">{{ 'OrderStatus'|get_plugin_lang('BuyCoursesPlugin') }}</th>
                     <th class="text-center">{{ 'OrderDate'|get_plugin_lang('BuyCoursesPlugin') }}</th>
                     <th class="text-right">{{ 'Price'|get_plugin_lang('BuyCoursesPlugin') }}</th>
-                    <th class="text-center">{{ 'Renewable'|get_plugin_lang('BuyCoursesPlugin') }}</th>
                     <th class="text-center">{{ 'ServiceSaleInfo'|get_plugin_lang('BuyCoursesPlugin')  }}</th>
                 </tr>
                 </thead>
@@ -34,13 +45,6 @@
                         </td>
                         <td class="text-center">{{ sale.date }}</td>
                         <td class="text-right">{{ sale.currency ~ ' ' ~ sale.price }}</td>
-                        {% if sale.recurring_payment == 0 %}
-                            <td class="text-center">{{ 'No' | get_lang }}</td>
-                        {% else %}
-                            <td class="text-center">
-                                <a id="renewable_info" tag="{{ sale.id }}" name="r_{{ sale.id }}" class="btn btn-warning btn-sm">{{ 'Info' | get_lang }}</a>
-                            </td>
-                        {% endif %}
                         <td class="text-center">
                             <a id="service_sale_info" tag="{{ sale.id }}" name="s_{{ sale.id }}" class="btn btn-info btn-sm">{{ 'Info' | get_lang }}</a>
                         </td>

+ 8 - 3
plugin/vchamilo/lib/Virtual.php

@@ -29,7 +29,7 @@ class Virtual
         self::getHostName($_configuration);
 
         // We are on physical chamilo. Let original config play
-        $virtualChamiloWebRoot = $_configuration['vchamilo_web_root'].'/';
+        $virtualChamiloWebRoot = rtrim($_configuration['vchamilo_web_root'], '/') . '/';
 
         $virtualChamilo = [];
         if ($_configuration['root_web'] == $virtualChamiloWebRoot) {
@@ -99,6 +99,7 @@ class Virtual
                 $data['SYS_HOME_PATH'] = self::addTrailingSlash($homePath).$data['slug'];
                 $data['SYS_COURSE_PATH'] = self::addTrailingSlash($coursePath).$data['slug'];
                 $data['SYS_UPLOAD_PATH'] = self::addTrailingSlash($uploadPath).$data['slug'];
+                $data['WEB_UPLOAD_PATH'] = $_configuration['vchamilo_web_root'] . 'var/upload/' . $data['slug'];
 
                 if (!empty($passwordEncryption)) {
                     $_configuration['password_encryption'] = $passwordEncryption;
@@ -124,7 +125,11 @@ class Virtual
         ) {
             $protocol = 'https';
         } else {
-            $protocol = 'http';
+            if ($_SERVER['HTTPS']) {
+                $protocol = 'https';
+            } else {
+                $protocol = 'http';
+            }
         }
 
         if (defined('CLI_VCHAMILO_OVERRIDE')) {
@@ -955,7 +960,7 @@ class Virtual
         }
 
         $data->root_web = api_add_trailing_slash($data->root_web);
-        if (substr($data->root_web, 4) != 'http') {
+        if (substr($data->root_web, 0, 4) != 'http') {
             $data->root_web = api_get_protocol().'://'.$data->root_web;
         }