Merge pull request #8 from chamilo/1.11.x

1.11.x
pull/2487/head
hi-rafa 9 years ago committed by GitHub
commit a92cc6dcb4
  1. 1
      .gitignore
  2. 16
      app/Resources/public/assets/bootstrap-daterangepicker/.bower.json
  3. 168
      app/Resources/public/assets/bootstrap-daterangepicker/README.md
  4. 6
      app/Resources/public/assets/bootstrap-daterangepicker/bower.json
  5. 303
      app/Resources/public/assets/bootstrap-daterangepicker/daterangepicker-bs2.css
  6. 335
      app/Resources/public/assets/bootstrap-daterangepicker/daterangepicker-bs3.css
  7. 2114
      app/Resources/public/assets/bootstrap-daterangepicker/daterangepicker.js
  8. 272
      app/Resources/public/assets/bootstrap-daterangepicker/examples.html
  9. 6
      app/Resources/public/assets/bootstrap-daterangepicker/package.js
  10. 14
      app/Resources/public/assets/bootstrap-daterangepicker/package.json
  11. 2
      bower.json
  12. 6
      certificates/index.php
  13. 9282
      composer.lock
  14. 3
      main/admin/user_edit.php
  15. 20
      main/admin/user_information.php
  16. 47
      main/cron/cleanup.php
  17. 6
      main/exercise/hotspot_actionscript.as.php
  18. 628
      main/inc/lib/TicketManager.php
  19. 68
      main/inc/lib/agenda.lib.php
  20. 9
      main/inc/lib/api.lib.php
  21. 23
      main/inc/lib/banner.lib.php
  22. 4
      main/inc/lib/course.lib.php
  23. 2
      main/inc/lib/exercise.lib.php
  24. 7
      main/inc/lib/formvalidator/Element/DateRangePicker.php
  25. 143
      main/inc/lib/social.lib.php
  26. 2
      main/inc/lib/template.lib.php
  27. 138
      main/inc/lib/tracking.lib.php
  28. 9
      main/inc/lib/usermanager.lib.php
  29. 3
      main/install/configuration.dist.php
  30. 6
      main/lang/english/trad4all.inc.php
  31. 3
      main/lang/french/trad4all.inc.php
  32. 3
      main/lang/spanish/trad4all.inc.php
  33. 41
      main/lp/lp_add_item.php
  34. 2
      main/lp/lp_view.php
  35. 110
      main/session/index.php
  36. 4
      main/social/invitations.php
  37. 7
      main/template/default/admin/settings_index.tpl
  38. 7
      main/ticket/new_ticket.php
  39. 100
      main/ticket/ticket_details.php
  40. 10
      main/ticket/tickets.php
  41. 59
      main/user/user.php
  42. 21
      main/work/work.lib.php
  43. 18
      src/Chamilo/CourseBundle/Component/CourseCopy/CourseArchiver.php
  44. 2
      tests/behat/README.md
  45. 17
      tests/behat/features/bootstrap/FeatureContext.php
  46. 22
      tests/behat/features/course.feature
  47. 45
      tests/behat/features/createCourse.feature
  48. 48
      tests/behat/features/toolAgenda.feature
  49. 5
      tests/behat/features/toolForum.feature

1
.gitignore vendored

@ -45,7 +45,6 @@ main/cron/incoming/*
plugin/vchamilo/templates/*
# Stuff updated through composer - Remove just before release
composer.lock
vendor
web/assets/*

@ -2,7 +2,7 @@
"name": "bootstrap-daterangepicker",
"main": [
"daterangepicker.js",
"daterangepicker-bs3.css"
"daterangepicker.css"
],
"ignore": [
"**/.*",
@ -14,18 +14,18 @@
"moment.min.js"
],
"dependencies": {
"jquery": ">=1.10",
"moment": "~2.9.0"
"jquery": "1.9.1 - 3",
"moment": ">=2.9.0"
},
"homepage": "https://github.com/dangrossman/bootstrap-daterangepicker",
"version": "1.3.23",
"_release": "1.3.23",
"version": "2.1.25",
"_release": "2.1.25",
"_resolution": {
"type": "version",
"tag": "v1.3.23",
"commit": "f000ab2a40a0e930c2913855b96a4e4d59c8920f"
"tag": "v2.1.25",
"commit": "29bbf5a04df69fda363cedb534272ac344524e57"
},
"_source": "https://github.com/dangrossman/bootstrap-daterangepicker.git",
"_target": "1.3.*",
"_target": "2.1.*",
"_originalSource": "bootstrap-daterangepicker"
}

@ -6,169 +6,13 @@ This date range picker component for Bootstrap creates a dropdown menu from whic
select a range of dates. I created it while building the UI for [Improvely](http://www.improvely.com),
which needed a way to select date ranges for reports.
If invoked with no options, it will present two calendars to choose a start
and end date from. Optionally, you can provide a list of date ranges the user can select from instead
of choosing dates from the calendars. If attached to a text input, the selected dates will be inserted
into the text box. Otherwise, you can provide a custom callback function to receive the selection.
Features include limiting the selectable date range, localizable strings and date formats,
a single date picker mode, optional time picker (for e.g. making appointments or reservations),
and styles that match the default Bootstrap 3 theme.
The component can also be used as a single date picker by setting the `singleDatePicker` option to `true`.
## [Documentation and Live Usage Examples](http://www.daterangepicker.com)
**[View some examples](http://www.daterangepicker.com/)** or **[Try it in a live application](https://awio.iljmp.com/5/drpdemogh)**
## Usage
This component relies on [Bootstrap](http://getbootstrap.com),
[Moment.js](http://momentjs.com/) and [jQuery](http://jquery.com/).
Separate stylesheets are included for use with Bootstrap 2 or Bootstrap 3.
Basic usage:
```
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="moment.js"></script>
<script type="text/javascript" src="daterangepicker.js"></script>
<link rel="stylesheet" type="text/css" href="bootstrap.css" />
<link rel="stylesheet" type="text/css" href="daterangepicker-bs3.css" />
<script type="text/javascript">
$(document).ready(function() {
$('input[name="daterange"]').daterangepicker();
});
</script>
```
The constructor also takes an optional options object and callback function. The function will be called whenever
the selected date range has been changed by the user, and is passed the start and end dates (moment date objects)
and the predefined range label chosen (if any), as parameters. It will not fire if the picker is closed without
any change to the selected dates.
````
$('input[name="daterange"]').daterangepicker(
{
format: 'YYYY-MM-DD',
startDate: '2013-01-01',
endDate: '2013-12-31'
},
function(start, end, label) {
alert('A date range was chosen: ' + start.format('YYYY-MM-DD') + ' to ' + end.format('YYYY-MM-DD'));
}
);
````
Options may also be set using HTML5 data attributes. For example, timePicker="true" would be set with:
```
<input type="text" data-time-picker="true" name="daterange">
```
## Options
`startDate`: (Date object, moment object or string) The start of the initially selected date range
`endDate`: (Date object, moment object or string) The end of the initially selected date range
`minDate`: (Date object, moment object or string) The earliest date a user may select
`maxDate`: (Date object, moment object or string) The latest date a user may select
`dateLimit`: (object) The maximum span between the selected start and end dates. Can have any property you can add to a moment object (i.e. days, months)
`timeZone`: (string or number) The timezone that will be used to display the startDate and endDate in the calendar. This may be a string such as "08:00" or an offset in minutes from Greenwich Mean Time. Uses Moment.js #utcOffset, [see the docs here](http://momentjs.com/docs/#/manipulating/utc-offset/) for more information. If the timeZone option is not set, the calendar will use the time zone set on the startDate that has been passed in through the options, if it has one. Defaults to the local time zone
`showDropdowns`: (boolean) Show year and month select boxes above calendars to jump to a specific month and year
`showWeekNumbers`: (boolean) Show week numbers at the start of each week on the calendars
`timePicker`: (boolean) Allow selection of dates with times, not just dates
`timePickerIncrement`: (number) Increment of the minutes selection list for times (i.e. 30 to allow only selection of times ending in 0 or 30)
`timePicker12Hour`: (boolean) Use 12-hour instead of 24-hour times, adding an AM/PM select box
`timePickerSeconds`: (boolean) Show seconds in the timePicker
`ranges`: (object) Set predefined date ranges the user can select from. Each key is the label for the range, and its value an array with two dates representing the bounds of the range
`opens`: (string: 'left'/'right'/'center') Whether the picker appears aligned to the left, to the right, or centered under the HTML element it's attached to
`drops`: (string: 'down' or 'up') Whether the picker opens below (default) or above the element it's attached to
`buttonClasses`: (array) CSS class names that will be added to all buttons in the picker
`applyClass`: (string) CSS class string that will be added to the apply button
`cancelClass`: (string) CSS class string that will be added to the cancel button
`format`: (string) Date/time format string used by moment when parsing or displaying the selected dates
`separator`: (string) Separator string to display between the start and end date when populating a text input the picker is attached to
`locale`: (object) Allows you to provide localized strings for buttons and labels, and the first day of week for the calendars
`singleDatePicker`: (boolean) Show only a single calendar to choose one date, instead of a range picker with two calendars; the start and end dates provided to your callback will be the same single date chosen
`parentEl`: (string) jQuery selector of the parent element that the date range picker will be added to, if not provided this will be `'body'`
## Functions
Several functions are provided for updating the picker's option and state after initialization:
`setOptions(object, function)`: This function has the same signature and purpose as the date range picker's constructor: it sets the picker's options to their defaults, overrides them with any values in an options object you provide, and sets the callback for selection changes to whatever function you provide
`setStartDate(Date/moment/string)`: Sets the date range picker's currently selected start date to the provided date
`setEndDate(Date/moment/string)`: Sets the date range picker's currently selected end date to the provided date
Example usage:
````
//create a new date range picker
$('#daterange').daterangepicker({ startDate: '2014-03-05', endDate: '2014-03-06' });
//change the selected date range of that picker
$('#daterange').data('daterangepicker').setStartDate('2014-03-01');
$('#daterange').data('daterangepicker').setEndDate('2014-03-31');
````
## Events
Several events are triggered on the element you attach the picker to, which you can listen for:
`show.daterangepicker`: Triggered when the picker is shown
`hide.daterangepicker`: Triggered when the picker is hidden
`showCalendar.daterangepicker`: Triggered when the calendar is shown
`hideCalendar.daterangepicker`: Triggered when the calendar is hidden
`apply.daterangepicker`: Triggered when the apply button is clicked
`cancel.daterangepicker`: Triggered when the cancel button is clicked
Some applications need a "clear" instead of a "cancel" functionality, which can be achieved by changing the button label and watching for the cancel event:
````
$('#daterange').daterangepicker({
locale: { cancelLabel: 'Clear' }
});
$('#daterange').on('cancel.daterangepicker', function(ev, picker) {
//do something, like clearing an input
$('#daterange').val('');
});
````
While passing in a callback to the constructor is the easiest way to listen for changes in the selected date range, you can also do something every time the apply button is clicked even if the selection hasn't changed:
````
$('#daterange').daterangepicker();
$('#daterange').on('apply.daterangepicker', function(ev, picker) {
console.log(picker.startDate.format('YYYY-MM-DD'));
console.log(picker.endDate.format('YYYY-MM-DD'));
});
````
## [See It In a Live Application](https://awio.iljmp.com/5/drpdemogh)
## License
@ -179,7 +23,7 @@ for convenience. It is available under the [MIT license](http://www.opensource.o
The MIT License (MIT)
Copyright (c) 2012-2014 Dan Grossman
Copyright (c) 2012-2016 Dan Grossman
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

@ -2,7 +2,7 @@
"name": "bootstrap-daterangepicker",
"main": [
"daterangepicker.js",
"daterangepicker-bs3.css"
"daterangepicker.css"
],
"ignore": [
"**/.*",
@ -14,7 +14,7 @@
"moment.min.js"
],
"dependencies": {
"jquery": ">=1.10",
"moment": "~2.9.0"
"jquery": "1.9.1 - 3",
"moment": ">=2.9.0"
}
}

@ -1,303 +0,0 @@
/*!
* Stylesheet for the Date Range Picker, for use with Bootstrap 2.x
*
* Copyright 2013-2015 Dan Grossman ( http://www.dangrossman.info )
* Licensed under the MIT license. See http://www.opensource.org/licenses/mit-license.php
*
* Built for http://www.improvely.com
*/
.daterangepicker.dropdown-menu {
max-width: none;
z-index: 3000;
}
.daterangepicker.opensleft .ranges, .daterangepicker.opensleft .calendar {
float: left;
margin: 4px;
}
.daterangepicker.opensright .ranges, .daterangepicker.opensright .calendar,
.daterangepicker.openscenter .ranges, .daterangepicker.openscenter .calendar {
float: right;
margin: 4px;
}
.daterangepicker .ranges {
width: 160px;
text-align: left;
}
.daterangepicker .ranges .range_inputs>div {
float: left;
}
.daterangepicker .ranges .range_inputs>div:nth-child(2) {
padding-left: 11px;
}
.daterangepicker .calendar {
display: none;
max-width: 250px;
}
.daterangepicker.show-calendar .calendar {
display: block;
}
.daterangepicker .calendar.single .calendar-date {
border: none;
}
.daterangepicker .calendar th, .daterangepicker .calendar td {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
white-space: nowrap;
text-align: center;
}
.daterangepicker .daterangepicker_start_input label,
.daterangepicker .daterangepicker_end_input label {
color: #333;
font-size: 11px;
margin-bottom: 2px;
text-transform: uppercase;
text-shadow: 1px 1px 0 #fff;
}
.daterangepicker .ranges input {
font-size: 11px;
}
.daterangepicker .ranges ul {
list-style: none;
margin: 0;
padding: 0;
}
.daterangepicker .ranges li {
font-size: 13px;
background: #f5f5f5;
border: 1px solid #f5f5f5;
color: #08c;
padding: 3px 12px;
margin-bottom: 8px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
cursor: pointer;
}
.daterangepicker .ranges li.active, .daterangepicker .ranges li:hover {
background: #08c;
border: 1px solid #08c;
color: #fff;
}
.daterangepicker .calendar-date {
border: 1px solid #ddd;
padding: 4px;
border-radius: 4px;
background: #fff;
}
.daterangepicker .calendar-time {
text-align: center;
margin: 8px auto 0 auto;
line-height: 30px;
}
.daterangepicker {
position: absolute;
background: #fff;
top: 100px;
left: 20px;
padding: 4px;
margin-top: 1px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.daterangepicker.opensleft:before {
position: absolute;
top: -7px;
right: 9px;
display: inline-block;
border-right: 7px solid transparent;
border-bottom: 7px solid #ccc;
border-left: 7px solid transparent;
border-bottom-color: rgba(0, 0, 0, 0.2);
content: '';
}
.daterangepicker.opensleft:after {
position: absolute;
top: -6px;
right: 10px;
display: inline-block;
border-right: 6px solid transparent;
border-bottom: 6px solid #fff;
border-left: 6px solid transparent;
content: '';
}
.daterangepicker.openscenter:before {
position: absolute;
top: -7px;
left: 0;
right: 0;
width: 0;
margin-left: auto;
margin-right: auto;
display: inline-block;
border-right: 7px solid transparent;
border-bottom: 7px solid #ccc;
border-left: 7px solid transparent;
border-bottom-color: rgba(0, 0, 0, 0.2);
content: '';
}
.daterangepicker.openscenter:after {
position: absolute;
top: -6px;
left: 0;
right: 0;
width: 0;
margin-left: auto;
margin-right: auto;
display: inline-block;
border-right: 6px solid transparent;
border-bottom: 6px solid #fff;
border-left: 6px solid transparent;
content: '';
}
.daterangepicker.opensright:before {
position: absolute;
top: -7px;
left: 9px;
display: inline-block;
border-right: 7px solid transparent;
border-bottom: 7px solid #ccc;
border-left: 7px solid transparent;
border-bottom-color: rgba(0, 0, 0, 0.2);
content: '';
}
.daterangepicker.opensright:after {
position: absolute;
top: -6px;
left: 10px;
display: inline-block;
border-right: 6px solid transparent;
border-bottom: 6px solid #fff;
border-left: 6px solid transparent;
content: '';
}
.daterangepicker.dropup{
margin-top: -5px;
}
.daterangepicker.dropup:before{
top: initial;
bottom:-7px;
border-bottom: initial;
border-top: 7px solid #ccc;
}
.daterangepicker.dropup:after{
top: initial;
bottom:-6px;
border-bottom: initial;
border-top: 6px solid #fff;
}
.daterangepicker table {
width: 100%;
margin: 0;
}
.daterangepicker td, .daterangepicker th {
text-align: center;
width: 20px;
height: 20px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
cursor: pointer;
white-space: nowrap;
}
.daterangepicker td.off {
color: #999;
}
.daterangepicker td.disabled, .daterangepicker option.disabled {
color: #999;
}
.daterangepicker td.available:hover, .daterangepicker td.available.today, .daterangepicker th.available:hover {
background: #eee;
}
.daterangepicker td.in-range {
background: #ebf4f8;
-webkit-border-radius: 0;
-moz-border-radius: 0;
border-radius: 0;
}
.daterangepicker td.today.active, .daterangepicker td.active, .daterangepicker td.active:hover {
background-color: #006dcc;
background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
background-image: -o-linear-gradient(top, #0088cc, #0044cc);
background-image: linear-gradient(top, #0088cc, #0044cc);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
border-color: #0044cc #0044cc #002a80;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
color: #fff;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.daterangepicker td.week, .daterangepicker th.week {
font-size: 80%;
color: #ccc;
}
.daterangepicker select.monthselect, .daterangepicker select.yearselect {
font-size: 12px;
padding: 1px;
height: auto;
margin: 0;
cursor: default;
}
.daterangepicker select.monthselect {
margin-right: 2%;
width: 56%;
}
.daterangepicker select.yearselect {
width: 40%;
}
.daterangepicker select.hourselect, .daterangepicker select.minuteselect, .daterangepicker select.secondselect, .daterangepicker select.ampmselect {
width: 60px;
margin-bottom: 0;
}
.daterangepicker_start_input {
float: left;
}
.daterangepicker_end_input {
float: left;
padding-left: 11px
}
.daterangepicker th.month {
width: auto;
}

@ -1,335 +0,0 @@
/*!
* Stylesheet for the Date Range Picker, for use with Bootstrap 3.x
*
* Copyright 2013-2015 Dan Grossman ( http://www.dangrossman.info )
* Licensed under the MIT license. See http://www.opensource.org/licenses/mit-license.php
*
* Built for http://www.improvely.com
*/
.daterangepicker.dropdown-menu {
max-width: none;
z-index: 3000;
}
.daterangepicker.opensleft .ranges, .daterangepicker.opensleft .calendar {
float: left;
margin: 4px;
}
.daterangepicker.opensright .ranges, .daterangepicker.opensright .calendar,
.daterangepicker.openscenter .ranges, .daterangepicker.openscenter .calendar {
float: right;
margin: 4px;
}
.daterangepicker.single .ranges, .daterangepicker.single .calendar {
float: none;
}
.daterangepicker .ranges {
width: 160px;
text-align: left;
}
.daterangepicker .ranges .range_inputs>div {
float: left;
}
.daterangepicker .ranges .range_inputs>div:nth-child(2) {
padding-left: 11px;
}
.daterangepicker .calendar {
display: none;
max-width: 270px;
}
.daterangepicker.show-calendar .calendar {
display: block;
}
.daterangepicker .calendar.single .calendar-date {
border: none;
}
.daterangepicker .calendar th, .daterangepicker .calendar td {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
white-space: nowrap;
text-align: center;
min-width: 32px;
}
.daterangepicker .daterangepicker_start_input label,
.daterangepicker .daterangepicker_end_input label {
color: #333;
display: block;
font-size: 11px;
font-weight: normal;
height: 20px;
line-height: 20px;
margin-bottom: 2px;
text-shadow: #fff 1px 1px 0px;
text-transform: uppercase;
width: 74px;
}
.daterangepicker .ranges input {
font-size: 11px;
}
.daterangepicker .ranges .input-mini {
border: 1px solid #ccc;
border-radius: 4px;
color: #555;
display: block;
font-size: 11px;
height: 30px;
line-height: 30px;
vertical-align: middle;
margin: 0 0 10px 0;
padding: 0 6px;
width: 74px;
}
.daterangepicker .ranges ul {
list-style: none;
margin: 0;
padding: 0;
}
.daterangepicker .ranges li {
font-size: 13px;
background: #f5f5f5;
border: 1px solid #f5f5f5;
color: #08c;
padding: 3px 12px;
margin-bottom: 8px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
cursor: pointer;
}
.daterangepicker .ranges li.active, .daterangepicker .ranges li:hover {
background: #08c;
border: 1px solid #08c;
color: #fff;
}
.daterangepicker .calendar-date {
border: 1px solid #ddd;
padding: 4px;
border-radius: 4px;
background: #fff;
}
.daterangepicker .calendar-time {
text-align: center;
margin: 8px auto 0 auto;
line-height: 30px;
}
.daterangepicker {
position: absolute;
background: #fff;
top: 100px;
left: 20px;
padding: 4px;
margin-top: 1px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.daterangepicker.opensleft:before {
position: absolute;
top: -7px;
right: 9px;
display: inline-block;
border-right: 7px solid transparent;
border-bottom: 7px solid #ccc;
border-left: 7px solid transparent;
border-bottom-color: rgba(0, 0, 0, 0.2);
content: '';
}
.daterangepicker.opensleft:after {
position: absolute;
top: -6px;
right: 10px;
display: inline-block;
border-right: 6px solid transparent;
border-bottom: 6px solid #fff;
border-left: 6px solid transparent;
content: '';
}
.daterangepicker.openscenter:before {
position: absolute;
top: -7px;
left: 0;
right: 0;
width: 0;
margin-left: auto;
margin-right: auto;
display: inline-block;
border-right: 7px solid transparent;
border-bottom: 7px solid #ccc;
border-left: 7px solid transparent;
border-bottom-color: rgba(0, 0, 0, 0.2);
content: '';
}
.daterangepicker.openscenter:after {
position: absolute;
top: -6px;
left: 0;
right: 0;
width: 0;
margin-left: auto;
margin-right: auto;
display: inline-block;
border-right: 6px solid transparent;
border-bottom: 6px solid #fff;
border-left: 6px solid transparent;
content: '';
}
.daterangepicker.opensright:before {
position: absolute;
top: -7px;
left: 9px;
display: inline-block;
border-right: 7px solid transparent;
border-bottom: 7px solid #ccc;
border-left: 7px solid transparent;
border-bottom-color: rgba(0, 0, 0, 0.2);
content: '';
}
.daterangepicker.opensright:after {
position: absolute;
top: -6px;
left: 10px;
display: inline-block;
border-right: 6px solid transparent;
border-bottom: 6px solid #fff;
border-left: 6px solid transparent;
content: '';
}
.daterangepicker.dropup{
margin-top: -5px;
}
.daterangepicker.dropup:before{
top: initial;
bottom:-7px;
border-bottom: initial;
border-top: 7px solid #ccc;
}
.daterangepicker.dropup:after{
top: initial;
bottom:-6px;
border-bottom: initial;
border-top: 6px solid #fff;
}
.daterangepicker table {
width: 100%;
margin: 0;
}
.daterangepicker td, .daterangepicker th {
text-align: center;
width: 20px;
height: 20px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
cursor: pointer;
white-space: nowrap;
}
.daterangepicker td.off {
color: #999;
}
.daterangepicker td.disabled, .daterangepicker option.disabled {
color: #999;
}
.daterangepicker td.available:hover, .daterangepicker td.available.today, .daterangepicker th.available:hover {
background: #eee;
}
.daterangepicker td.in-range {
background: #ebf4f8;
-webkit-border-radius: 0;
-moz-border-radius: 0;
border-radius: 0;
}
.daterangepicker td.start-date {
-webkit-border-radius: 4px 0 0 4px;
-moz-border-radius: 4px 0 0 4px;
border-radius: 4px 0 0 4px;
}
.daterangepicker td.end-date {
-webkit-border-radius: 0 4px 4px 0;
-moz-border-radius: 0 4px 4px 0;
border-radius: 0 4px 4px 0;
}
.daterangepicker td.start-date.end-date {
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.daterangepicker td.today.active, .daterangepicker td.active, .daterangepicker td.active:hover {
background-color: #357ebd;
border-color: #3071a9;
color: #fff;
}
.daterangepicker td.week, .daterangepicker th.week {
font-size: 80%;
color: #ccc;
}
.daterangepicker select.monthselect, .daterangepicker select.yearselect {
font-size: 12px;
padding: 1px;
height: auto;
margin: 0;
cursor: default;
}
.daterangepicker select.monthselect {
margin-right: 2%;
width: 56%;
}
.daterangepicker select.yearselect {
width: 40%;
}
.daterangepicker select.hourselect, .daterangepicker select.minuteselect, .daterangepicker select.secondselect, .daterangepicker select.ampmselect {
width: 50px;
margin-bottom: 0;
}
.daterangepicker_start_input {
float: left;
}
.daterangepicker_end_input {
float: left;
padding-left: 11px
}
.daterangepicker th.month {
width: auto;
}

@ -1,272 +0,0 @@
<!DOCTYPE html>
<html dir="ltr" lang="en-US">
<head>
<meta charset="UTF-8" />
<title>A date range picker for Bootstrap</title>
<link href="http://netdna.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet">
<link href="http://netdna.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="all" href="daterangepicker-bs3.css" />
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script type="text/javascript" src="http://netdna.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<script type="text/javascript" src="moment.js"></script>
<script type="text/javascript" src="daterangepicker.js"></script>
</head>
<body>
<div class="container">
<div class="span12">
<h1>Usage Examples</h1>
<hr />
<h4>Basic Date Range Picker</h4>
<div class="well">
<form class="form-horizontal">
<fieldset>
<div class="control-group">
<div class="controls">
<div class="input-prepend input-group">
<span class="add-on input-group-addon"><i class="glyphicon glyphicon-calendar fa fa-calendar"></i></span><input type="text" style="width: 200px" name="reservation" id="reservation" class="form-control" value="03/18/2013 - 03/23/2013" />
</div>
</div>
</div>
</fieldset>
</form>
<script type="text/javascript">
$(document).ready(function() {
$('#reservation').daterangepicker(null, function(start, end, label) {
console.log(start.toISOString(), end.toISOString(), label);
});
});
</script>
</div>
<h4>Basic Single Date Picker</h4>
<div class="well">
<form class="form-horizontal">
<fieldset>
<div class="control-group">
<div class="controls">
<div class="input-prepend input-group">
<span class="add-on input-group-addon"><i class="glyphicon glyphicon-calendar fa fa-calendar"></i></span><input type="text" style="width: 200px" name="birthday" id="birthday" class="form-control" value="03/18/2013" />
</div>
</div>
</div>
</fieldset>
</form>
<script type="text/javascript">
$(document).ready(function() {
$('#birthday').daterangepicker({ singleDatePicker: true }, function(start, end, label) {
console.log(start.toISOString(), end.toISOString(), label);
});
});
</script>
</div>
<h4>Date Range &amp; Time Picker with 30 Minute Increments</h4>
<div class="well">
<form class="form-horizontal">
<fieldset>
<div class="control-group">
<label class="control-label" for="reservationtime">Choose your check-in and check-out times:</label>
<div class="controls">
<div class="input-prepend input-group">
<span class="add-on input-group-addon"><i class="glyphicon glyphicon-calendar fa fa-calendar"></i></span>
<input type="text" style="width: 400px" name="reservation" id="reservationtime" class="form-control" value="08/01/2013 1:00 PM - 08/01/2013 1:30 PM" class="span4"/>
</div>
</div>
</div>
</fieldset>
</form>
<script type="text/javascript">
$(document).ready(function() {
$('#reservationtime').daterangepicker({
timePicker: true,
timePickerIncrement: 30,
format: 'MM/DD/YYYY h:mm A'
}, function(start, end, label) {
console.log(start.toISOString(), end.toISOString(), label);
});
});
</script>
</div>
<h4>Options Usage</h4>
<div class="well" style="overflow: auto">
<button id="options1" class="btn btn-primary">Apply Option Set 1</button>
<button id="options2" class="btn btn-primary">Apply Option Set 2</button>
<button id="destroy" class="btn btn-primary">Remove DateRangePicker</button>
<div id="reportrange" class="pull-right" style="background: #fff; cursor: pointer; padding: 5px 10px; border: 1px solid #ccc">
<i class="glyphicon glyphicon-calendar fa fa-calendar"></i>
<span></span> <b class="caret"></b>
</div>
<script type="text/javascript">
$(document).ready(function() {
var cb = function(start, end, label) {
console.log(start.toISOString(), end.toISOString(), label);
$('#reportrange span').html(start.format('MMMM D, YYYY') + ' - ' + end.format('MMMM D, YYYY'));
//alert("Callback has fired: [" + start.format('MMMM D, YYYY') + " to " + end.format('MMMM D, YYYY') + ", label = " + label + "]");
};
var optionSet1 = {
startDate: moment().subtract(29, 'days'),
endDate: moment(),
minDate: '01/01/2012',
maxDate: '12/31/2015',
dateLimit: { days: 60 },
showDropdowns: true,
showWeekNumbers: true,
timePicker: false,
timePickerIncrement: 1,
timePicker12Hour: true,
ranges: {
'Today': [moment(), moment()],
'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
'Last 7 Days': [moment().subtract(6, 'days'), moment()],
'Last 30 Days': [moment().subtract(29, 'days'), moment()],
'This Month': [moment().startOf('month'), moment().endOf('month')],
'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
},
opens: 'left',
buttonClasses: ['btn btn-default'],
applyClass: 'btn-sm btn-primary',
cancelClass: 'btn-sm',
format: 'MM/DD/YYYY',
separator: ' to ',
locale: {
applyLabel: 'Submit',
cancelLabel: 'Clear',
fromLabel: 'From',
toLabel: 'To',
customRangeLabel: 'Custom',
daysOfWeek: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr','Sa'],
monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
firstDay: 1
}
};
var optionSet2 = {
startDate: moment().subtract(7, 'days'),
endDate: moment(),
opens: 'left',
ranges: {
'Today': [moment(), moment()],
'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
'Last 7 Days': [moment().subtract(6, 'days'), moment()],
'Last 30 Days': [moment().subtract(29, 'days'), moment()],
'This Month': [moment().startOf('month'), moment().endOf('month')],
'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
}
};
$('#reportrange span').html(moment().subtract(29, 'days').format('MMMM D, YYYY') + ' - ' + moment().format('MMMM D, YYYY'));
$('#reportrange').daterangepicker(optionSet1, cb);
$('#reportrange').on('show.daterangepicker', function() { console.log("show event fired"); });
$('#reportrange').on('hide.daterangepicker', function() { console.log("hide event fired"); });
$('#reportrange').on('apply.daterangepicker', function(ev, picker) {
console.log("apply event fired, start/end dates are "
+ picker.startDate.format('MMMM D, YYYY')
+ " to "
+ picker.endDate.format('MMMM D, YYYY')
);
});
$('#reportrange').on('cancel.daterangepicker', function(ev, picker) { console.log("cancel event fired"); });
$('#options1').click(function() {
$('#reportrange').data('daterangepicker').setOptions(optionSet1, cb);
});
$('#options2').click(function() {
$('#reportrange').data('daterangepicker').setOptions(optionSet2, cb);
});
$('#destroy').click(function() {
$('#reportrange').data('daterangepicker').remove();
});
});
</script>
</div>
<h4>Plays nicely with Bootstrap dropdowns</h4>
<div class="well">
<div class="dropdown" style="display: inline-block;">
<a data-toggle="dropdown" class="btn btn-primary" href="#">Regular bootstrap dropdown</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<li><a href="#">item</a></li>
</ul>
</div>
<div id="reportrange2" class="btn" style="display: inline-block; background: #fff; cursor: pointer; padding: 5px 10px; border: 1px solid #ccc">
<i class="glyphicon glyphicon-calendar fa fa-calendar"></i>
<span></span> <b class="caret"></b>
</div>
<script type="text/javascript">
$(document).ready(function() {
$('#reportrange2 span').html(moment().subtract(29, 'days').format('MMMM D, YYYY') + ' - ' + moment().format('MMMM D, YYYY'));
$('#reportrange2').daterangepicker({
opens: 'center'
});
});
</script>
</div>
<h4>And also can drop "up"</h4>
<div class="well">
<form class="form-horizontal">
<fieldset>
<div class="control-group">
<div class="controls">
<div class="input-prepend input-group">
<span class="add-on input-group-addon"><i class="glyphicon glyphicon-calendar fa fa-calendar"></i></span><input type="text" style="width: 200px" name="dropup" id="dropup" class="form-control" value="03/18/2013 - 03/23/2013" />
</div>
</div>
</div>
</fieldset>
</form>
<script type="text/javascript">
$(document).ready(function() {
$('#dropup').daterangepicker({
drops:'up'
});
});
</script>
</div>
</div>
</div>
</body>
</html>

@ -1,6 +1,6 @@
Package.describe({
name: 'dangrossman:bootstrap-daterangepicker',
version: '1.3.23',
version: '2.1.25',
summary: 'Date range picker component for Bootstrap',
git: 'https://github.com/dangrossman/bootstrap-daterangepicker',
documentation: 'README.md'
@ -9,10 +9,10 @@ Package.describe({
Package.onUse(function(api) {
api.versionsFrom('METEOR@0.9.0.1');
api.use('twbs:bootstrap@3.3.4', ["client"]);
api.use('twbs:bootstrap@3.3.4', ["client"], {weak: true});
api.use('momentjs:moment@2.10.3', ["client"]);
api.use('jquery@1.11.3_2', ["client"]);
api.addFiles('daterangepicker.js', ["client"]);
api.addFiles('daterangepicker-bs3.css', ["client"]);
api.addFiles('daterangepicker.css', ["client"]);
});

@ -1,10 +1,11 @@
{
"name": "bootstrap-daterangepicker",
"version": "1.3.23",
"version": "2.1.25",
"description": "Date range picker component for Bootstrap",
"main": "daterangepicker.js",
"style": "daterangepicker-bs3.css",
"style": "daterangepicker.css",
"scripts": {
"scss": "node-sass daterangepicker.scss > daterangepicker.css",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
@ -21,12 +22,11 @@
"url": "https://github.com/dangrossman/bootstrap-daterangepicker/issues"
},
"homepage": "https://github.com/dangrossman/bootstrap-daterangepicker",
"engines": {
"node": "0.10.32",
"nmp": "1.4.28"
},
"dependencies": {
"jquery": "^1.10",
"jquery": ">=1.10",
"moment": "^2.9.0"
},
"devDependencies": {
"node-sass": "^3.4.2"
}
}

@ -12,7 +12,7 @@
"fontawesome": "4.7.*",
"jquery": "2.2.0",
"jquery-ui": "1.11.*",
"bootstrap-daterangepicker": "1.3.*",
"bootstrap-daterangepicker": "2.1.*",
"ckeditor": "*",
"jquery-timeago": "1.4.*",
"mediaelement": "2.*",

@ -25,14 +25,18 @@ switch ($action) {
$certificatePathList[] = $certificate->html_file;
$pdfParams = array(
'orientation' => 'landscape',
'top' => 0,
'right' => 0,
'bottom' => 0,
'left' => 0
);
$orientation = api_get_configuration_value('certificate_pdf_orientation');
$pdfParams['orientation'] = 'landscape';
if (!empty($orientation)) {
$pdfParams['orientation'] = $orientation;
}
$pageFormat = $pdfParams['orientation'] === 'landscape' ? 'A4-L' : 'A4';
$userInfo = api_get_user_info($certificate->user_id);
$pdfName = api_replace_dangerous_char(get_lang('Certificate') . ' ' . $userInfo['username']);

9282
composer.lock generated

File diff suppressed because it is too large Load Diff

@ -387,6 +387,7 @@ if ($form->validate()) {
$reset_password = intval($user['reset_password']);
$hr_dept_id = isset($user['hr_dept_id']) ? intval($user['hr_dept_id']) : null;
$language = $user['language'];
$address = isset($user['address']) ? $user['address'] : null;
if ($user['radio_expiration_date'] == '1' && !$user_data['platform_admin']) {
$expiration_date = $user['expiration_date'];
@ -426,7 +427,7 @@ if ($form->validate()) {
null,
$send_mail,
$reset_password,
$user['address']
$address
);
if (isset($user['student_boss'])) {

@ -255,6 +255,7 @@ $tbl_session = Database:: get_main_table(TABLE_MAIN_SESSION);
$tbl_course = Database:: get_main_table(TABLE_MAIN_COURSE);
$tbl_user = Database:: get_main_table(TABLE_MAIN_USER);
$socialInformation = '';
/**
* Show social activity
@ -262,25 +263,32 @@ $tbl_user = Database:: get_main_table(TABLE_MAIN_USER);
if (api_get_setting('allow_social_tool') === 'true') {
$em = Database::getManager();
$userObject = $em->find('ChamiloUserBundle:User', $user['user_id']);
$header = ['Value' => 'CurrentData'];
$data = [];
// Calculate values
if (api_get_setting('allow_message_tool') === 'true') {
$messagesSent = \SocialManager::getCountMessagesSent($user['user_id']);
$messagesSent = SocialManager::getCountMessagesSent($user['user_id']);
$data[] = [get_lang('MessagesSent'), $messagesSent];
$messagesReceived = \SocialManager::getCountMessagesReceived($user['user_id']);
$messagesReceived = SocialManager::getCountMessagesReceived($user['user_id']);
$data[] = [get_lang('MessagesReceived'), $messagesReceived];
}
$wallMessagesPosted = \SocialManager::getCountWallPostedMessages($user['user_id']);
$wallMessagesPosted = SocialManager::getCountWallPostedMessages($user['user_id']);
$data[] = [get_lang('WallMessagesPosted'), $wallMessagesPosted];
$friends = SocialManager::getCountFriends($user['user_id']);
$data[] = [get_lang('Friends'), $friends];
$count = SocialManager::getCountInvitationSent($user['user_id']);
$data[] = [get_lang('InvitationSent'), $count];
$count = SocialManager::get_message_number_invitation_by_user_id($user['user_id']);
$data[] = [get_lang('InvitationReceived'), $count];
$socialInformation = Display::return_sortable_table(
$header,
'',
$data
);
}
/**

@ -1,47 +0,0 @@
<?php
/**
* Automatic cleanup procedure. Cleans the archive directory of anything
* older than 7 days
* @package chamilo.cron
* @author Yannick Warnier <yannick.warnier@beeznest.com>
*/
/**
* Initialization
*/
if (php_sapi_name() != 'cli') {
exit; //do not run from browser
}
$dir = dirname(__FILE__);
$a_dir = realpath($dir.'/../../archive/');
$list = scandir($a_dir);
// calculate 7 days
$t = time()-(86400*7);
foreach ($list as $item) {
if (substr($item,0,1) == '.') {
continue;
}
$stat = @stat($a_dir.'/'.$item);
if ($stat === false) {
error_log('Cron task cannot stat '.$a_dir.'/'.$item);
continue;
}
if ($stat['mtime'] > $t) { //if the file is older than one week, delete
recursive_delete($a_dir.'/'.$item);
}
}
/**
* Delete a file or recursively delete a directory
* @param string $str Path to file or directory
*/
function recursive_delete($str){
if (is_file($str)) {
return @unlink($str);
} elseif (is_dir($str)) {
$scan = glob(rtrim($str,'/').'/*');
foreach ($scan as $index=>$path) {
recursive_delete($path);
}
return @rmdir($str);
}
}

@ -133,9 +133,9 @@ if (!empty($attemptList)) {
$data['nmbrTries'] = $nmbrTries;
$data['done'] = 'done';
if (Session::has('hotspot_ordered')) {
if (Session::has("hotspot_ordered$questionId")) {
$tempHotspots = [];
$hotspotOrdered = Session::read('hotspot_ordered');
$hotspotOrdered = Session::read("hotspot_ordered$questionId");
foreach ($hotspotOrdered as $hotspotOrder) {
foreach ($data['hotspots'] as $hotspot) {
@ -149,7 +149,7 @@ if (Session::has('hotspot_ordered')) {
$data['hotspots'] = $tempHotspots;
Session::erase('hotspot_ordered');
Session::erase("hotspot_ordered$questionId");
}
header('Content-Type: application/json');

File diff suppressed because it is too large Load Diff

@ -38,12 +38,8 @@ class Agenda
$sessionId = 0
) {
// Table definitions
$this->tbl_global_agenda = Database::get_main_table(
TABLE_MAIN_SYSTEM_CALENDAR
);
$this->tbl_personal_agenda = Database::get_main_table(
TABLE_PERSONAL_AGENDA
);
$this->tbl_global_agenda = Database::get_main_table(TABLE_MAIN_SYSTEM_CALENDAR);
$this->tbl_personal_agenda = Database::get_main_table(TABLE_PERSONAL_AGENDA);
$this->tbl_course_agenda = Database::get_course_table(TABLE_AGENDA);
$this->table_repeat = Database::get_course_table(TABLE_AGENDA_REPEAT);
@ -142,7 +138,6 @@ class Agenda
public function setType($type)
{
$typeList = $this->getTypes();
if (in_array($type, $typeList)) {
$this->type = $type;
}
@ -738,7 +733,6 @@ class Agenda
}
$groupId = api_get_group_id();
$groupIid = 0;
if ($groupId) {
$groupInfo = GroupManager::get_group_properties($groupId);
@ -1118,9 +1112,7 @@ class Agenda
$course_id = null,
$groupId = null,
$user_id = 0,
$format = 'json',
$startLimit = 0,
$endLimit = 0
$format = 'json'
) {
switch ($this->type) {
case 'admin':
@ -1298,6 +1290,7 @@ class Agenda
*/
public function resizeEvent($id, $minute_delta)
{
$id = (int) $id;
$delta = intval($minute_delta);
$event = $this->get_event($id);
if (!empty($event)) {
@ -1305,21 +1298,21 @@ class Agenda
case 'personal':
$sql = "UPDATE $this->tbl_personal_agenda SET
enddate = DATE_ADD(enddate, INTERVAL $delta MINUTE)
WHERE id=".intval($id);
WHERE id = ".$id;
Database::query($sql);
break;
case 'course':
$sql = "UPDATE $this->tbl_course_agenda SET
end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
WHERE c_id = ".$this->course['real_id']." AND id=".intval(
$id
);
WHERE
c_id = ".$this->course['real_id']." AND
id = ".$id;
Database::query($sql);
break;
case 'admin':
$sql = "UPDATE $this->tbl_global_agenda SET
end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
WHERE id=".intval($id);
WHERE id = ".$id;
Database::query($sql);
break;
}
@ -1336,11 +1329,13 @@ class Agenda
*/
public function move_event($id, $minute_delta, $allDay)
{
$id = (int) $id;
$event = $this->get_event($id);
if (empty($event)) {
return false;
}
// we convert the hour delta into minutes and add the minute delta
$delta = intval($minute_delta);
$allDay = intval($allDay);
@ -1351,7 +1346,7 @@ class Agenda
$sql = "UPDATE $this->tbl_personal_agenda SET
all_day = $allDay, date = DATE_ADD(date, INTERVAL $delta MINUTE),
enddate = DATE_ADD(enddate, INTERVAL $delta MINUTE)
WHERE id=".intval($id);
WHERE id=".$id;
Database::query($sql);
break;
case 'course':
@ -1359,9 +1354,9 @@ class Agenda
all_day = $allDay,
start_date = DATE_ADD(start_date, INTERVAL $delta MINUTE),
end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
WHERE c_id = ".$this->course['real_id']." AND id=".intval(
$id
);
WHERE
c_id = ".$this->course['real_id']." AND
id=".$id;
Database::query($sql);
break;
case 'admin':
@ -1369,7 +1364,7 @@ class Agenda
all_day = $allDay,
start_date = DATE_ADD(start_date,INTERVAL $delta MINUTE),
end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
WHERE id=".intval($id);
WHERE id=".$id;
Database::query($sql);
break;
}
@ -1619,7 +1614,6 @@ class Agenda
);
}
}
}
/**
@ -1642,12 +1636,8 @@ class Agenda
$user_id = 0,
$color = ''
) {
$start = isset($start) && !empty($start) ? api_get_utc_datetime(
intval($start)
) : null;
$end = isset($end) && !empty($end) ? api_get_utc_datetime(
intval($end)
) : null;
$start = isset($start) && !empty($start) ? api_get_utc_datetime(intval($start)) : null;
$end = isset($end) && !empty($end) ? api_get_utc_datetime(intval($end)) : null;
if (empty($courseInfo)) {
return array();
@ -1781,8 +1771,7 @@ class Agenda
}
$visibilityCondition = " (ip.visibility IN ('1', '0')) AND ";
} else {
$where_condition = " ( (ip.to_user_id = ".api_get_user_id(
)." OR ip.to_user_id IS NULL) AND ip.to_group_id IS NULL) AND ";
$where_condition = " ( (ip.to_user_id = ".api_get_user_id()." OR ip.to_user_id IS NULL) AND ip.to_group_id IS NULL) AND ";
}
if (empty($session_id)) {
@ -1876,11 +1865,9 @@ class Agenda
get_lang('Attachment')
);
$user_filename = $attachment['filename'];
$url = api_get_path(
WEB_CODE_PATH
).'calendar/download.php?file='.$attachment['path'].'&course_id='.$course_id.'&'.api_get_cidreq(
);
$event['attachment'] .= $has_attachment.Display::url(
$url = api_get_path(WEB_CODE_PATH).'calendar/download.php?file='.$attachment['path'].'&course_id='.$course_id.'&'.api_get_cidreq();
$event['attachment'] .= $has_attachment.
Display::url(
$user_filename,
$url
).'<br />';
@ -2279,16 +2266,13 @@ class Agenda
*/
public function getForm($params = [])
{
$action = isset($params['action']) ? Security::remove_XSS(
$params['action']
) : null;
$action = isset($params['action']) ? Security::remove_XSS($params['action']) : null;
$id = isset($params['id']) ? intval($params['id']) : null;
if ($this->type == 'course') {
$url = api_get_self().'?'.api_get_cidreq(
).'&action='.$action.'&id='.$id.'&type='.$this->type;
$url = api_get_self().'?'.api_get_cidreq().'&action='.$action.'&id='.$id.'&type='.$this->type;
} else {
$url = api_get_self(
).'?action='.$action.'&id='.$id.'&type='.$this->type;
$url = api_get_self().'?action='.$action.'&id='.$id.'&type='.$this->type;
}
$form = new FormValidator(

@ -2901,9 +2901,9 @@ function api_is_allowed_to_edit(
$session_coach = false,
$check_student_view = true
) {
$my_session_id = api_get_session_id();
$sessionId = api_get_session_id();
$is_allowed_coach_to_edit = api_is_coach(null, null, $check_student_view);
$session_visibility = api_get_session_visibility($my_session_id);
$session_visibility = api_get_session_visibility($sessionId);
// Admins can edit anything.
if (api_is_platform_admin(false)) {
@ -2944,7 +2944,7 @@ function api_is_allowed_to_edit(
// Check if the student_view is enabled, and if so, if it is activated.
if (api_get_setting('student_view_enabled') == 'true') {
if (!empty($my_session_id)) {
if (!empty($sessionId)) {
// Check if session visibility is read only for coaches.
if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
$is_allowed_coach_to_edit = false;
@ -3010,8 +3010,7 @@ function api_is_coach_of_course_in_session($sessionId)
// Checking session visibility
$sessionCourseVisibility = api_get_session_visibility(
$sessionId,
$course['real_id'],
$ignore_visibility_for_admins
$course['real_id']
);
$courseIsVisible = !in_array(

@ -2,6 +2,7 @@
/* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Component\Utils\ChamiloApi;
use ChamiloSession as Session;
/**
* Code
@ -545,7 +546,6 @@ function return_breadcrumb($interbreadcrumb, $language_file, $nameTools)
$my_session_name = is_null($session_name) ? '' : '&nbsp;('.$session_name.')';
if (!empty($_course) && !isset($_GET['hide_course_breadcrumb'])) {
$navigation_item['url'] = $web_course_path . $_course['path'].'/index.php'.(!empty($session_id) ? '?id_session='.$session_id : '');
$_course['name'] = api_htmlentities($_course['name']);
$course_title = cut($_course['name'], MAX_LENGTH_BREADCRUMB);
@ -668,9 +668,23 @@ function return_breadcrumb($interbreadcrumb, $language_file, $nameTools)
/* Part 4 . Show the teacher view/student view button at the right of the breadcrumb */
$view_as_student_link = null;
if ($user_id && isset($course_id)) {
if ((api_is_course_admin() || api_is_platform_admin() || api_is_coach(null, null, false)) &&
api_get_setting('student_view_enabled') === 'true' && api_get_course_info()) {
if ((
api_is_course_admin() ||
api_is_platform_admin() ||
api_is_coach(null, null, false)
) &&
api_get_setting('student_view_enabled') === 'true' && api_get_course_info()
) {
$view_as_student_link = api_display_tool_view_option();
// Only show link if LP can be editable
/** @var learnpath $learnPath */
$learnPath = Session::read('oLP');
if (!empty($learnPath) && !empty($view_as_student_link)) {
if ((int)$learnPath->get_lp_session_id() != (int)api_get_session_id()) {
$view_as_student_link = '';
}
}
}
}
@ -706,7 +720,7 @@ function return_breadcrumb($interbreadcrumb, $language_file, $nameTools)
}
if (!empty($navigation_right)) {
foreach($navigation_right as $item) {
foreach ($navigation_right as $item) {
$extra_class = isset($item['class']) ? $item['class'] : null;
$lis.= Display::tag('li', $item['title'], array('class' => $extra_class.' pull-right'));
}
@ -715,7 +729,6 @@ function return_breadcrumb($interbreadcrumb, $language_file, $nameTools)
if (!empty($lis)) {
$html .= Display::tag('ul', $lis, array('class'=>'breadcrumb'));
}
}
return $html;
}

@ -2333,7 +2333,9 @@ class CourseManager
// Skills
$table = Database::get_main_table(TABLE_MAIN_SKILL_REL_USER);
$sql = "DELETE FROM $table WHERE course_id = $courseId";
$argumentation = Database::escape_string(sprintf(get_lang('SkillFromCourseXDeletedSinceThen'), $course['code']));
error_log($argumentation);
$sql = "UPDATE $table SET course_id = NULL, session_id = NULL, argumentation = '$argumentation' WHERE course_id = $courseId";
Database::query($sql);
// Delete the course from the database

@ -1186,7 +1186,7 @@ HTML;
';
if (!empty($answers_hotspot)) {
Session::write('hotspot_ordered', array_keys($answers_hotspot));
Session::write("hotspot_ordered$questionId", array_keys($answers_hotspot));
$countAnswers = 1;
foreach ($answers_hotspot as $value) {
$answerList .= "<li><p>{$countAnswers} - {$value}</p></li>";

@ -96,8 +96,7 @@ class DateRangePicker extends HTML_QuickForm_text
// timeFormat: 'hh:mm'
$js .= "<script>
$(function() {
$('#$id').daterangepicker({
format: '$format',
$('#$id').daterangepicker({
timePicker: $timePicker,
timePickerIncrement: 30,
timePicker12Hour: false,
@ -110,8 +109,10 @@ class DateRangePicker extends HTML_QuickForm_text
'".addslashes(get_lang('NextWeek'))."': [moment().weekday(8), moment().weekday(12)]
},
//showDropdowns : true,
separator: ' / ',
locale: {
separator: ' / ',
format: '$format',
applyLabel: '".addslashes(get_lang('Ok'))."',
cancelLabel: '".addslashes(get_lang('Cancel'))."',
fromLabel: '".addslashes(get_lang('From'))."',

@ -29,8 +29,8 @@ class SocialManager extends UserManager
public static function show_list_type_friends()
{
$friend_relation_list = array();
$tbl_my_friend_relation_type = Database :: get_main_table(TABLE_MAIN_USER_FRIEND_RELATION_TYPE);
$sql = 'SELECT id,title FROM '.$tbl_my_friend_relation_type.'
$table = Database :: get_main_table(TABLE_MAIN_USER_FRIEND_RELATION_TYPE);
$sql = 'SELECT id, title FROM '.$table.'
WHERE id<>6
ORDER BY id ASC';
$result = Database::query($sql);
@ -70,11 +70,13 @@ class SocialManager extends UserManager
*/
public static function get_relation_between_contacts($user_id, $user_friend)
{
$tbl_my_friend_relation_type = Database :: get_main_table(TABLE_MAIN_USER_FRIEND_RELATION_TYPE);
$tbl_my_friend = Database :: get_main_table(TABLE_MAIN_USER_REL_USER);
$sql = 'SELECT rt.id as id FROM '.$tbl_my_friend_relation_type.' rt
$table = Database :: get_main_table(TABLE_MAIN_USER_FRIEND_RELATION_TYPE);
$userRelUserTable = Database :: get_main_table(TABLE_MAIN_USER_REL_USER);
$sql = 'SELECT rt.id as id
FROM '.$table.' rt
WHERE rt.id = (
SELECT uf.relation_type FROM '.$tbl_my_friend.' uf
SELECT uf.relation_type
FROM '.$userRelUserTable.' uf
WHERE
user_id='.((int) $user_id).' AND
friend_user_id='.((int) $user_friend).' AND
@ -91,6 +93,35 @@ class SocialManager extends UserManager
}
}
/**
* Get count of friends from user
*
* @param int $userId
* @return int
*/
public static function getCountFriends($userId)
{
$tbl_my_friend = Database :: get_main_table(TABLE_MAIN_USER_REL_USER);
$userId = (int) $userId;
if (empty($userId)) {
return 0;
}
$sql = 'SELECT count(friend_user_id) count
FROM '.$tbl_my_friend.'
WHERE
relation_type NOT IN ('.USER_RELATION_TYPE_DELETED.', '.USER_RELATION_TYPE_RRHH.') AND
friend_user_id<>'.($userId).' AND
user_id='.($userId);
$res = Database::query($sql);
if (Database::num_rows($res)) {
$row = Database::fetch_array($res, 'ASSOC');
return (int) $row['count'];
}
return 0;
}
/**
* Gets friends id list
* @param int user id
@ -201,7 +232,6 @@ class SocialManager extends UserManager
$row_exist = Database::fetch_array($res_exist, 'ASSOC');
if ($row_exist['count'] == 0) {
$params = [
'user_sender_id' => $user_id,
'user_receiver_id' => $friend_id,
@ -301,15 +331,20 @@ class SocialManager extends UserManager
/**
* Get number of messages posted on own wall
* @param int $sender_id
* @param int $userId
* @return int
*/
public static function getCountWallPostedMessages($sender_id)
public static function getCountWallPostedMessages($userId)
{
if (empty($userId)) {
return 0;
}
$tbl_message = Database::get_main_table(TABLE_MESSAGE);
$sql = 'SELECT COUNT(*) FROM '.$tbl_message.'
$sql = 'SELECT COUNT(*)
FROM '.$tbl_message.'
WHERE
user_sender_id='.intval($sender_id).' AND
user_sender_id='.intval($userId).' AND
(msg_status = '.MESSAGE_STATUS_WALL.' OR
msg_status = '.MESSAGE_STATUS_WALL_POST.') AND
parent_id = 0';
@ -322,58 +357,102 @@ class SocialManager extends UserManager
/**
* Get invitation list received by user
* @author isaac flores paz
* @param int user id
* @param int $userId
*
* @return array
*/
public static function get_list_invitation_of_friends_by_user_id($user_id)
public static function get_list_invitation_of_friends_by_user_id($userId)
{
if (empty($userId)) {
return [];
}
$tbl_message = Database::get_main_table(TABLE_MESSAGE);
$sql = 'SELECT user_sender_id, send_date, title, content
FROM '.$tbl_message.'
WHERE
user_receiver_id = '.intval($user_id).' AND
user_receiver_id = '.intval($userId).' AND
msg_status = '.MESSAGE_STATUS_INVITATION_PENDING;
$res = Database::query($sql);
$list_friend_invitation = array();
$list = array();
while ($row = Database::fetch_array($res, 'ASSOC')) {
$list_friend_invitation[] = $row;
$list[] = $row;
}
return $list_friend_invitation;
return $list;
}
/**
* Get invitation list sent by user
* @author Julio Montoya <gugli100@gmail.com>
* @param int user id
* @param int $userId
*
* @return array()
*/
public static function get_list_invitation_sent_by_user_id($user_id)
public static function get_list_invitation_sent_by_user_id($userId)
{
$list_friend_invitation = array();
$tbl_message = Database::get_main_table(TABLE_MESSAGE);
if (empty($userId)) {
return [];
}
$table = Database::get_main_table(TABLE_MESSAGE);
$sql = 'SELECT user_receiver_id, send_date,title,content
FROM '.$tbl_message.'
FROM '.$table.'
WHERE
user_sender_id = '.intval($user_id).' AND
user_sender_id = '.intval($userId).' AND
msg_status = '.MESSAGE_STATUS_INVITATION_PENDING;
$res = Database::query($sql);
$list = array();
while ($row = Database::fetch_array($res, 'ASSOC')) {
$list_friend_invitation[$row['user_receiver_id']] = $row;
$list[$row['user_receiver_id']] = $row;
}
return $list_friend_invitation;
return $list;
}
/**
* Get count invitation sent by user
* @author Julio Montoya <gugli100@gmail.com>
* @param int $userId
*
* @return int
*/
public static function getCountInvitationSent($userId)
{
if (empty($userId)) {
return 0;
}
$table = Database::get_main_table(TABLE_MESSAGE);
$sql = 'SELECT count(user_receiver_id) count
FROM '.$table.'
WHERE
user_sender_id = '.intval($userId).' AND
msg_status = '.MESSAGE_STATUS_INVITATION_PENDING;
$res = Database::query($sql);
if (Database::num_rows($res)) {
$row = Database::fetch_array($res, 'ASSOC');
return (int) $row['count'];
}
return 0;
}
/**
* Accepts invitation
* @param int $user_send_id
* @param int $user_receiver_id
* @return bool
*
* @author isaac flores paz
* @author Julio Montoya <gugli100@gmail.com> Cleaning code
*/
public static function invitation_accepted($user_send_id, $user_receiver_id)
{
if (empty($user_send_id) || empty($user_receiver_id)) {
return false;
}
$tbl_message = Database::get_main_table(TABLE_MESSAGE);
$sql = "UPDATE $tbl_message
SET msg_status = ".MESSAGE_STATUS_INVITATION_ACCEPTED."
@ -382,17 +461,24 @@ class SocialManager extends UserManager
user_receiver_id=".((int) $user_receiver_id)." AND
msg_status = ".MESSAGE_STATUS_INVITATION_PENDING;
Database::query($sql);
return true;
}
/**
* Denies invitation
* @param int user sender id
* @param int user receiver id
* @return bool
*
* @author isaac flores paz
* @author Julio Montoya <gugli100@gmail.com> Cleaning code
*/
public static function invitation_denied($user_send_id, $user_receiver_id)
{
if (empty($user_send_id) || empty($user_receiver_id)) {
return false;
}
$tbl_message = Database::get_main_table(TABLE_MESSAGE);
$sql = 'DELETE FROM '.$tbl_message.'
WHERE
@ -400,6 +486,8 @@ class SocialManager extends UserManager
user_receiver_id='.((int) $user_receiver_id).' AND
msg_status = '.MESSAGE_STATUS_INVITATION_PENDING;
Database::query($sql);
return true;
}
/**
@ -420,8 +508,8 @@ class SocialManager extends UserManager
/**
* Get user's feeds
* @param int User ID
* @param int Limit of posts per feed
* @param int $user User ID
* @param int $limit Limit of posts per feed
* @return string HTML section with all feeds included
* @author Yannick Warnier
* @since Dokeos 1.8.6.1
@ -505,7 +593,6 @@ class SocialManager extends UserManager
return false;
} elseif (isset($userId) && !isset($subject)) {
if (isset($userId) && $userId > 0) {
$count = self::send_invitation_friend(
api_get_user_id(),
$userId,

@ -538,7 +538,6 @@ class Template
// Default CSS Bootstrap
$bowerCSSFiles = [
'bootstrap-daterangepicker/daterangepicker-bs3.css',
'fontawesome/css/font-awesome.min.css',
'jquery-ui/themes/smoothness/theme.css',
'jquery-ui/themes/smoothness/jquery-ui.min.css',
@ -546,6 +545,7 @@ class Template
'jqueryui-timepicker-addon/dist/jquery-ui-timepicker-addon.min.css',
'bootstrap/dist/css/bootstrap.min.css',
'jquery.scrollbar/jquery.scrollbar.css',
'bootstrap-daterangepicker/daterangepicker.css',
];
foreach ($bowerCSSFiles as $file) {

@ -17,6 +17,19 @@ use Chamilo\CoreBundle\Entity\Session;
*/
class Tracking
{
/**
* Get group reporting
* @param int $course_id
* @param int $sessionId
* @param int $group_id
* @param string $type
* @param int $start
* @param int $limit
* @param int $sidx
* @param string $sord
* @param array $where_condition
* @return array|null
*/
public static function get_group_reporting(
$course_id,
$sessionId = null,
@ -65,7 +78,6 @@ class Tracking
if (!empty($result)) {
foreach ($result as $group) {
$users = GroupManager::get_users($group['id'], true);
$time = 0;
$avg_student_score = 0;
$avg_student_progress = 0;
@ -141,7 +153,6 @@ class Tracking
$session_id = intval($session_id);
$origin = Security::remove_XSS($origin);
$list = learnpath :: get_flat_ordered_items_list($lp_id, 0, $courseInfo['real_id']);
$is_allowed_to_edit = api_is_allowed_to_edit(null, true);
$course_id = $courseInfo['real_id'];
$courseCode = $courseInfo['code'];
@ -162,7 +173,6 @@ class Tracking
Display::return_icon('view_less_stats.gif', get_lang('HideAllAttempts')),
api_get_self() . '?action=stats' . $url_suffix
);
$extend_all = 1;
} else {
$extend_all_link = Display::url(
@ -207,7 +217,6 @@ class Tracking
// Going through the items using the $items[] array instead of the database order ensures
// we get them in the same order as in the imsmanifest file, which is rather random when using
// the database table.
$TBL_LP_ITEM = Database :: get_course_table(TABLE_LP_ITEM);
$TBL_LP_ITEM_VIEW = Database :: get_course_table(TABLE_LP_ITEM_VIEW);
$TBL_LP_VIEW = Database :: get_course_table(TABLE_LP_VIEW);
@ -1232,7 +1241,6 @@ class Tracking
}
$sessions = SessionManager::get_sessions_followed_by_drh($userId);
} else {
$studentList = UserManager::getUsersFollowedByUser(
$userId,
STUDENT,
@ -1357,10 +1365,11 @@ class Tracking
/**
* Calculates the time spent on the platform by a user
* @param int|array User id
* @param string type of time filter: 'last_week' or 'custom'
* @param string start date date('Y-m-d H:i:s')
* @param string end date date('Y-m-d H:i:s')
* @return timestamp $nb_seconds
* @param string $timeFilter type of time filter: 'last_week' or 'custom'
* @param string $start_date start date date('Y-m-d H:i:s')
* @param string $end_date end date date('Y-m-d H:i:s')
*
* @return int $nb_seconds
*/
public static function get_time_spent_on_the_platform(
$userId,
@ -1394,7 +1403,7 @@ class Tracking
$newDate = new DateTime('-30 days', new DateTimeZone('UTC'));
$condition_time = " AND (login_date >= '{$newDate->format('Y-m-d H:i:s')}'";
$condition_time .= "AND logout_date <= '{$today->format('Y-m-d H:i:s')}') ";
break;
break;
case 'custom':
if (!empty($start_date) && !empty($end_date)) {
$start_date = Database::escape_string($start_date);
@ -1404,10 +1413,10 @@ class Tracking
break;
}
$sql = 'SELECT SUM(TIMESTAMPDIFF(SECOND, login_date, logout_date)) diff
$sql = 'SELECT SUM(TIMESTAMPDIFF(SECOND, login_date, logout_date)) diff
FROM '.$tbl_track_login.'
WHERE '.$userCondition.$condition_time;
$rs = Database::query($sql);
$rs = Database::query($sql);
$row = Database::fetch_array($rs, 'ASSOC');
$diff = $row['diff'];
@ -1429,19 +1438,18 @@ class Tracking
public static function get_time_spent_on_the_course($user_id, $courseId, $session_id = 0)
{
$courseId = intval($courseId);
$session_id = intval($session_id);
$tbl_track_course = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
if (is_array($user_id)) {
$user_id = array_map('intval', $user_id);
$condition_user = " AND user_id IN (".implode(',',$user_id).") ";
} else {
$user_id = intval($user_id);
$condition_user = " AND user_id = $user_id ";
}
$session_id = intval($session_id);
$tbl_track_course = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
if (is_array($user_id)) {
$user_id = array_map('intval', $user_id);
$condition_user = " AND user_id IN (".implode(',',$user_id).") ";
} else {
$user_id = intval($user_id);
$condition_user = " AND user_id = $user_id ";
}
$sql = "SELECT
SUM(UNIX_TIMESTAMP(logout_course_date) - UNIX_TIMESTAMP(login_course_date)) as nb_seconds
$sql = "SELECT
SUM(UNIX_TIMESTAMP(logout_course_date) - UNIX_TIMESTAMP(login_course_date)) as nb_seconds
FROM $tbl_track_course
WHERE UNIX_TIMESTAMP(logout_course_date) > UNIX_TIMESTAMP(login_course_date) ";
@ -1455,9 +1463,9 @@ class Tracking
$sql .= $condition_user;
$rs = Database::query($sql);
$row = Database::fetch_array($rs);
$row = Database::fetch_array($rs);
return $row['nb_seconds'];
return $row['nb_seconds'];
}
/**
@ -1468,25 +1476,25 @@ class Tracking
*/
public static function get_first_connection_date($student_id)
{
$tbl_track_login = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
$sql = 'SELECT login_date
FROM ' . $tbl_track_login . '
$tbl_track_login = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
$sql = 'SELECT login_date
FROM ' . $tbl_track_login . '
WHERE login_user_id = ' . intval($student_id) . '
ORDER BY login_date ASC
LIMIT 0,1';
$rs = Database::query($sql);
if (Database::num_rows($rs)>0) {
if ($first_login_date = Database::result($rs, 0, 0)) {
$rs = Database::query($sql);
if (Database::num_rows($rs)>0) {
if ($first_login_date = Database::result($rs, 0, 0)) {
return api_convert_and_format_date(
$first_login_date,
DATE_FORMAT_SHORT,
date_default_timezone_get()
);
}
}
}
}
return false;
return false;
}
/**
@ -1499,37 +1507,37 @@ class Tracking
*/
public static function get_last_connection_date($student_id, $warning_message = false, $return_timestamp = false)
{
$table = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
$sql = 'SELECT login_date
FROM ' . $table . '
$table = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
$sql = 'SELECT login_date
FROM ' . $table . '
WHERE login_user_id = ' . intval($student_id) . '
ORDER BY login_date
DESC LIMIT 0,1';
$rs = Database::query($sql);
if (Database::num_rows($rs) > 0) {
if ($last_login_date = Database::result($rs, 0, 0)) {
$last_login_date = api_get_local_time($last_login_date);
if ($return_timestamp) {
return api_strtotime($last_login_date,'UTC');
} else {
if (!$warning_message) {
return api_format_date($last_login_date, DATE_FORMAT_SHORT);
} else {
$timestamp = api_strtotime($last_login_date,'UTC');
$currentTimestamp = time();
$rs = Database::query($sql);
if (Database::num_rows($rs) > 0) {
if ($last_login_date = Database::result($rs, 0, 0)) {
$last_login_date = api_get_local_time($last_login_date);
if ($return_timestamp) {
return api_strtotime($last_login_date,'UTC');
} else {
if (!$warning_message) {
return api_format_date($last_login_date, DATE_FORMAT_SHORT);
} else {
$timestamp = api_strtotime($last_login_date,'UTC');
$currentTimestamp = time();
//If the last connection is > than 7 days, the text is red
//345600 = 7 days in seconds
if ($currentTimestamp - $timestamp > 604800) {
return '<span style="color: #F00;">' . api_format_date($last_login_date, DATE_FORMAT_SHORT) . '</span>';
} else {
return api_format_date($last_login_date, DATE_FORMAT_SHORT);
}
}
}
}
}
//If the last connection is > than 7 days, the text is red
//345600 = 7 days in seconds
if ($currentTimestamp - $timestamp > 604800) {
return '<span style="color: #F00;">' . api_format_date($last_login_date, DATE_FORMAT_SHORT) . '</span>';
} else {
return api_format_date($last_login_date, DATE_FORMAT_SHORT);
}
}
}
}
}
return false;
}
@ -1812,7 +1820,7 @@ class Tracking
}
// Compose a filter based on optional session id given
$condition_session = "";
$condition_session = '';
if (isset($session_id)) {
$session_id = intval($session_id);
$condition_session = " AND session_id = $session_id ";
@ -1866,7 +1874,6 @@ class Tracking
}
$count_quiz = Database::fetch_row(Database::query($sql));
$sql = "SELECT
SUM(exe_result/exe_weighting*100) as avg_score,
COUNT(*) as num_attempts
@ -4378,7 +4385,6 @@ class Tracking
$html = '';
// Course list
if ($show_courses) {
if (!empty($courses)) {
$html .= Display::page_subheader(
@ -4472,11 +4478,9 @@ class Tracking
$main_session_graph = '';
//Load graphics only when calling to an specific session
$session_graph = array();
$all_exercise_graph_name_list = array();
$my_results = array();
$all_exercise_graph_list = array();
$all_exercise_start_time = array();
foreach ($course_in_session as $my_session_id => $session_data) {
@ -4501,9 +4505,7 @@ class Tracking
$exercise_obj->read($exercise_data['id']);
//Exercise is not necessary to be visible to show results check the result_disable configuration instead
//$visible_return = $exercise_obj->is_visible();
if ($exercise_data['results_disabled'] == 0 || $exercise_data['results_disabled'] == 2) {
$best_average = intval(
ExerciseLib::get_best_average_score_by_exercise(
$exercise_data['id'],

@ -1463,7 +1463,7 @@ class UserManager
$user_table = Database :: get_main_table(TABLE_MAIN_USER);
$tblAccessUrlRelUser = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
$return_array = array();
$sql_query = "SELECT * FROM $user_table ";
$sql_query = "SELECT user.id FROM $user_table user ";
if (api_is_multiple_url_enabled()) {
$sql_query .= " INNER JOIN $tblAccessUrlRelUser auru ON auru.user_id = user.id ";
@ -1499,11 +1499,8 @@ class UserManager
$sql_result = Database::query($sql_query);
while ($result = Database::fetch_array($sql_result)) {
$result['complete_name'] = api_get_person_name(
$result['firstname'],
$result['lastname']
);
$return_array[] = $result;
$userInfo = api_get_user_info($result['id']);
$return_array[] = $userInfo;
}
return $return_array;

@ -282,4 +282,7 @@ $_configuration['system_stable'] = NEW_VERSION_STABLE;
// $_configuration['considered_working_time'] = 'work_time';
// During CSV special imports update users emails to x@example.com
// $_configuration['update_users_email_to_dummy_except_admins'] = false;
// Certification pdf export orientation
// $_configuration['certificate_pdf_orientation'] = 'landscape'; // It can be 'portrait' or 'landscape'

@ -7971,7 +7971,7 @@ $DocumentNumber = "Document ID";
$SocialData = "Social data";
$WallMessagesPosted = "Wall messages posted by him/herself";
$SeeAccesses = "See accesses";
$PriorityChangeFromXToY = "Priority change from %s to %s";
$StatusChangeFromXToY = "Status change from %s to %s";
$PriorityChangeFromXToY = "Priority changed from %s to %s";
$StatusChangeFromXToY = "Status changed from %s to %s";
$SkillFromCourseXDeletedSinceThen = "This skill was obtained through course %s which has been removed since then.";
?>

@ -7918,4 +7918,7 @@ $DocumentNumber = "ID du document";
$SocialData = "Données sociales";
$WallMessagesPosted = "Messages postés par lui/elle-même sur son mur";
$SeeAccesses = "Visualiser les accès";
$PriorityChangeFromXToY = "Priorité modifiée de %s à %s";
$StatusChangeFromXToY = "Statut modifié de %s à %s";
$SkillFromCourseXDeletedSinceThen = "Cette compétence a été obtenue au travers du cours %s qui a été éliminé depuis.";
?>

@ -7986,4 +7986,7 @@ $DocumentNumber = "ID de documento";
$SocialData = "Datos sociales";
$WallMessagesPosted = "Mensajes publicados en su muro (por el/ella)";
$SeeAccesses = "Ver accesos";
$PriorityChangeFromXToY = "Prioridad modificada de %s a %s";
$StatusChangeFromXToY = "Estado modificado de %s a %s";
$SkillFromCourseXDeletedSinceThen = "Esta competencia fue adquirida a través del curso %s que ha sido eliminado desde entonces.";
?>

@ -19,9 +19,35 @@ $this_section = SECTION_COURSES;
api_protect_course_script();
$isStudentView = isset($_REQUEST['isStudentView']) ? $_REQUEST['isStudentView'] : null;
$learnpath_id = isset($_REQUEST['lp_id']) ? intval($_REQUEST['lp_id']) : null;
$submit = isset($_POST['submit_button']) ? $_POST['submit_button'] : null;
$type = isset($_GET['type']) ? $_GET['type'] : null;
$action = isset($_GET['action']) ? $_GET['action'] : null;
$is_allowed_to_edit = api_is_allowed_to_edit(null, false);
$listUrl = api_get_path(WEB_CODE_PATH).'lp/lp_controller.php?action=view&lp_id='.$learnpath_id.'&'.api_get_cidreq().'&isStudentView=true';
if (!$is_allowed_to_edit) {
error_log('New LP - User not authorized in lp_add_item.php');
header("Location: $listUrl");
exit;
}
/** @var learnpath $learnPath */
$learnPath = Session::read('oLP');
if (empty($learnPath)) {
api_not_allowed();
}
if ((int)$learnPath->get_lp_session_id() != (int)api_get_session_id()) {
// You cannot edit an LP from a base course.
header("Location: $listUrl");
exit;
}
$htmlHeadXtra[] = '<script>'.
$learnPath->get_js_dropdown_array()."
function load_cbo(id) {
@ -62,22 +88,7 @@ $(function() {
});
</script>";
/* Constants and variables */
$isStudentView = isset($_REQUEST['isStudentView']) ? $_REQUEST['isStudentView'] : null;
$learnpath_id = isset($_REQUEST['lp_id']) ? intval($_REQUEST['lp_id']) : null;
$submit = isset($_POST['submit_button']) ? $_POST['submit_button'] : null;
$type = isset($_GET['type']) ? $_GET['type'] : null;
$action = isset($_GET['action']) ? $_GET['action'] : null;
if (!$is_allowed_to_edit) {
error_log('New LP - User not authorized in lp_add_item.php');
header('location:lp_controller.php?action=view&lp_id='.$learnpath_id);
exit;
}
/* SHOWING THE ADMIN TOOLS */
if (isset($_SESSION['gradebook'])) {
$gradebook = $_SESSION['gradebook'];
}

@ -533,7 +533,7 @@ $template->assign(
$template->assign('lp_author', $_SESSION['oLP']->get_author());
$template->assign('lp_mode', $_SESSION['oLP']->mode);
$template->assign('lp_title_scorm',$_SESSION['oLP']->name);
$template->assign('lp_title_scorm', $_SESSION['oLP']->name);
$template->assign(
'lp_html_toc',
$_SESSION['oLP']->get_html_toc($get_toc_list)

@ -42,16 +42,6 @@ $session_info = SessionManager::fetch($session_id);
$session_list = SessionManager::get_sessions_by_coach(api_get_user_id());
$course_list = SessionManager::get_course_list_by_session_id($session_id);
// Getting all sessions where I'm subscribed
/*$new_session_list = array();
if (!api_is_anonymous()) {
$new_session_list = UserManager::get_personal_session_course_list(api_get_user_id());
}
$user_course_list = array();
foreach ($new_session_list as $session_item) {
$user_course_list[] = $session_item['code'];
}*/
$userIsGeneralCoach = SessionManager::user_is_general_coach($userId, $session_id);
$user_course_list = array();
@ -71,60 +61,7 @@ if (empty($user_course_list)) {
}
$my_session_list = array();
$final_array = array();
/*
if (!empty($new_session_list)) {
foreach ($new_session_list as $item) {
$my_session_id = isset($item['id_session']) ? $item['id_session'] : null;
if (isset($my_session_id) && !in_array($my_session_id, $my_session_list) && $session_id == $my_session_id) {
$final_array[$my_session_id]['name'] = $item['session_name'];
//Get all courses by session where I'm subscribed
$my_course_list = UserManager::get_courses_list_by_session(api_get_user_id(), $my_session_id);
foreach ($my_course_list as $my_course) {
$course = array();
$course_info = api_get_course_info($my_course['code']);
// Getting all visible exercises from the current course
$exercise_list = ExerciseLib::get_all_exercises(
$course_info,
$my_session_id,
true,
null,
false,
1
);
$course['name'] = $course_info['name'];
$course['id'] = $course_info['real_id'];
if (!empty($exercise_list)) {
foreach ($exercise_list as $exercise_item) {
//Loading the exercise
$exercise = new Exercise($course_info['real_id']);
$exercise->read($exercise_item['id']);
$visible_return = $exercise->is_visible();
if ($visible_return['value'] != false) {
// Reading all Exercise results by user, exercise_id, code, and session.
$user_results = Event::getExerciseResultsByUser(
api_get_user_id(),
$exercise_item['id'],
$my_course['code'],
$my_session_id
);
$course['exercises'][$exercise_item['id']]['data']['exercise_data'] = $exercise;
$course['exercises'][$exercise_item['id']]['data']['results'] = $user_results;
}
}
$final_array[$my_session_id]['data'][$my_course['code']] = $course;
}
}
}
$my_session_list[] = $my_session_id;
}
}*/
$final_array = array();
$new_course_list = array();
if (!empty($course_list)) {
@ -283,7 +220,7 @@ $now = time();
foreach ($final_array as $session_data) {
$my_course_list = isset($session_data['data']) ? $session_data['data']: array();
if (!empty($my_course_list)) {
foreach ($my_course_list as $my_course_code=>$course_data) {
foreach ($my_course_list as $my_course_code => $course_data) {
$courseInfo = api_get_course_info($my_course_code);
if (isset($course_id) && !empty($course_id)) {
if ($course_id != $course_data['id']) {
@ -325,7 +262,9 @@ foreach ($final_array as $session_data) {
$exercise_result['exe_weighting']
);
$my_score = 0;
if(!empty($exercise_result['exe_weighting']) && intval($exercise_result['exe_weighting']) != 0) {
if (!empty($exercise_result['exe_weighting']) &&
intval($exercise_result['exe_weighting']) != 0
) {
$my_score = $exercise_result['exe_result']/$exercise_result['exe_weighting'];
}
$position = ExerciseLib::get_exercise_result_ranking(
@ -435,9 +374,10 @@ if ($session_info['show_description'] == 1) {
}
// All Learnpaths grid settings (First tab, first subtab)
$columns_courses = array(
get_lang('Title'), get_lang('NumberOfPublishedExercises'), get_lang('NumberOfPublishedLps')
get_lang('Title'),
get_lang('NumberOfPublishedExercises'),
get_lang('NumberOfPublishedLps'),
);
$column_model_courses = array(
array('name'=>'title', 'index'=>'title', 'width'=>'400px', 'align'=>'left', 'sortable'=>'true'),
@ -624,15 +564,16 @@ if (!api_is_anonymous()) {
false,
false
);
if (!empty($reportingTab)) {
$reportingTab .= '<br />'.Tracking::show_course_detail(
api_get_user_id(),
$courseCode,
$session_id
);
if (!empty($reportingTab)) {
$reportingTab .= '<br />';
$reportingTab .= Tracking::show_course_detail(
api_get_user_id(),
$courseCode,
$session_id
);
}
if (empty($reportingTab)) {
$reportingTab = Display::return_message(get_lang('NoDataAvailable'), 'warning');
$reportingTab = Display::return_message(get_lang('NoDataAvailable'), 'warning');
}
}
@ -648,24 +589,6 @@ if (!api_is_anonymous()) {
$headers[] = get_lang('MyStatistics');
}
// Sub headers
/*$sub_header = array(
get_lang('AllLearningPaths'),
get_lang('PerWeek'),
get_lang('ByCourse')
);
// Sub headers data
$lpTab = Display::tabs(
$sub_header,
array(
//Display::grid_html('list_default'),
Display::grid_html('list_week'),
//Display::grid_html('list_course')
),
'sub_tab'
);*/
$coursesTab = Display::grid_html('courses');
$starTab = Display::grid_html('list_default');
@ -696,7 +619,6 @@ echo Display::tabs(
Session::erase('_gid');
Session::erase('oLP');
Session::erase('lpobject');
api_remove_in_gradebook();
Display::display_footer();

@ -204,7 +204,7 @@ if (count($pending_invitations) > 0) {
$img = '<img class="img-responsive" src="'.$picture['file'].'" />';
$invitation['picture_uri'] = '<a href="group_view.php?id='.$invitation['id'].'">'.$img.'</a>';
$invitation['name'] = '<a href="group_view.php?id='.$invitation['id'].'">'.cut($invitation['name'],120,true).'</a>';
$invitation['description'] = cut($invitation['description'],220,true);
$invitation['description'] = cut($invitation['description'], 220, true);
$new_invitation[]=$invitation;
$waitingInvitation .= '<div class="panel-invitations"><div class="row">';
$waitingInvitation .= '<div class="col-md-3">'.$invitation['picture_uri'].'</div>';
@ -235,7 +235,7 @@ if (count($pending_invitations) > 0) {
$tpl = new Template(null);
SocialManager::setSocialUserBlock($tpl, api_get_user_id(), 'invitations');
$tpl->assign('social_menu_block', $social_menu_block);
$tpl->assign('social_invitations_block',$socialInvitationsBlock);
$tpl->assign('social_invitations_block', $socialInvitationsBlock);
$tpl->assign('content', $content);
$social_layout = $tpl->get_template('social/invitations.tpl');
$tpl->display($social_layout);

@ -40,8 +40,10 @@ $(document).ready(function() {
</script>
<section id="settings">
{% set columns = 2 %}
{% for block_item in blocks %}
{% if loop.index % 2 == 0 %}
{% if loop.first or loop.index0 is divisibleby(columns) %}
<div class="row">
{% endif %}
@ -86,7 +88,8 @@ $(document).ready(function() {
</div>
</div>
{% if loop.index % 2 == 0 %}
{% if loop.last or loop.index is divisibleby(columns) %}
</div>
{% endif %}
{% endfor %}

@ -321,8 +321,7 @@ function show_form_send_ticket()
);
if (api_is_platform_admin()) {
$form->addElement(
'SelectAjax',
$form->addSelectAjax(
'user_id',
get_lang('Assign'),
null,
@ -451,7 +450,7 @@ function save_ticket()
{
$content = $_POST['content'];
if ($_POST['phone'] != '') {
$content .= '<p style="color:red">&nbsp;' . get_lang('Phone') . ': ' . Security::remove_XSS($_POST['phone']). '</p>';
$content .= '<p style="color:red">&nbsp;' . get_lang('Phone') . ': ' . $_POST['phone']. '</p>';
}
$course_id = isset($_POST['course_id']) ? $_POST['course_id'] : '';
$sessionId = isset($_POST['session_id']) ? $_POST['session_id'] : '';
@ -460,7 +459,6 @@ function save_ticket()
$project_id = $_POST['project_id'];
$subject = $_POST['subject'];
$other_area = (int) $_POST['other_area'];
$email = $_POST['email'];
$personal_email = $_POST['personal_email'];
$source = $_POST['source_id'];
$user_id = isset($_POST['user_id']) ? $_POST['user_id'] : 0;
@ -474,7 +472,6 @@ function save_ticket()
$sessionId,
$project_id,
$other_area,
$email,
$subject,
$content,
$personal_email,

@ -49,19 +49,8 @@ $(document).ready(function() {
if(!confirm("' . get_lang('AreYouSure') . ' : ' . strtoupper(get_lang('No')) . '")){
return false;
}
});
$("#unassign").click(function () {
if (!confirm("' . get_lang('AreYouSureYouWantToUnassignTheTicket') . '")) {
return false;
}
});
$("#close").click(function () {
if (!confirm("' . get_lang('AreYouSureYouWantToCloseTheTicket') . '")) {
return false;
}
});
});
'.$disableReponseButtons.'
});
@ -195,29 +184,6 @@ if (isset($_POST['response'])) {
}
}
if (isset($_REQUEST['action'])) {
$action = $_REQUEST['action'];
switch ($action) {
case 'assign':
if (api_is_platform_admin() && isset($_GET['ticket_id'])) {
TicketManager::assign_ticket_user($_GET['ticket_id'], $_POST['admins']);
}
Display::addFlash(Display::return_message(get_lang('Updated')));
header("Location:" . api_get_self() . "?ticket_id=" . $ticket_id);
exit;
break;
case 'unassign':
if (api_is_platform_admin() && isset($_GET['ticket_id'])) {
TicketManager::assign_ticket_user($_GET['ticket_id'], 0);
}
Display::addFlash(Display::return_message(get_lang('Updated')));
header("Location:" . api_get_self() . "?ticket_id=" . $ticket_id);
exit;
break;
default:
break;
}
}
$title = 'Ticket #' . $ticket['ticket']['code'];
@ -236,32 +202,6 @@ if (!isset($_POST['compose'])) {
api_get_path(WEB_CODE_PATH) . 'ticket/tickets.php?project_id='.$projectId
);
echo '</div>';
$form_close_ticket = '';
if ($ticket['ticket']['status_id'] != TicketManager::STATUS_FORWARDED &&
$ticket['ticket']['status_id'] != TicketManager::STATUS_CLOSE &&
$isAdmin
) {
/*if (intval($ticket['ticket']['assigned_last_user']) == $user_id) {
if ($ticket['ticket']['status_id'] != TicketManager::STATUS_CLOSE) {
$form_close_ticket.= '<a href="' . api_get_self() . '?close=1&ticket_id=' . $ticket['ticket']['id'] . '" id="close" class="btn btn-danger" >';
$form_close_ticket.= get_lang('Close') . '</a>';
}
}*/
}
$img_assing = '';
if (empty($ticket['ticket']['assigned_last_user'])) {
if ($isAdmin) {
$img_assing = '<a href="#" id="assign" class="btn btn-success">'.get_lang('Assign').'</a>';
}
} else {
if ($isAdmin) {
$img_assing = '<a class="btn btn-warning" href="#" id="assign">
'.get_lang('ChangeAssign').'
</a>';
}
}
$bold = '';
if ($ticket['ticket']['status_id'] == TicketManager::STATUS_CLOSE) {
$bold = 'style = "font-weight: bold;"';
@ -280,7 +220,7 @@ if (!isset($_POST['compose'])) {
echo '<table width="100%" >
<tr>
<td colspan="3">
<h1>'.$title.' '.$form_close_ticket.'</h1>
<h1>'.$title.'</h1>
<h2>'.$ticket['ticket']['subject'].'</h2>
<p>
'.$senderData.' ' .
@ -424,7 +364,10 @@ if (!isset($_POST['compose'])) {
if (isset($_POST['assigned_last_user']) && !empty($_POST['assigned_last_user']) &&
$_POST['assigned_last_user'] != $oldUserId
) {
TicketManager::assign_ticket_user($ticket_id, $_POST['assigned_last_user'], false);
TicketManager::assignTicketToUser(
$ticket_id,
$_POST['assigned_last_user']
);
$oldUserName = '-';
if (!empty($oldUserId)) {
$oldUserInfo = api_get_user_info($oldUserId);
@ -493,7 +436,7 @@ if (!isset($_POST['compose'])) {
$messageToSend .= $content;
TicketManager::insert_message(
TicketManager::insertMessage(
$ticket_id,
$subject,
$messageToSend,
@ -503,6 +446,12 @@ if (!isset($_POST['compose'])) {
$message
);
TicketManager::sendNotification(
$ticket_id,
get_lang('TicketUpdated'),
$messageToSend
);
Display::addFlash(Display::return_message(get_lang('Saved')));
header("Location:" . api_get_self() . "?ticket_id=" . $ticket_id);
exit;
@ -548,26 +497,11 @@ function show_form_send_message($ticket)
)
);
$admins = UserManager::get_user_list_like(
array('status' => COURSEMANAGER),
array('username'),
true
);
$adminList = ['' => get_lang('Select')];
foreach ($admins as $admin) {
$adminList[$admin['user_id']] = $admin['complete_name'];
}
$form->addElement(
'select',
$form->addSelectAjax(
'assigned_last_user',
get_lang('Assign'),
$adminList,
array(
'id' => 'assigned_last_user',
'for' => 'assigned_last_user'
)
null,
['url' => api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_like']
);
$form->setDefaults(

@ -70,16 +70,6 @@ $action = isset($_GET['action']) ? $_GET['action'] : '';
$projectId = isset($_GET['project_id']) ? (int) $_GET['project_id'] : 0;
switch ($action) {
case 'assign':
if ($isAdmin && isset($_GET['ticket_id'])) {
TicketManager::assign_ticket_user($_GET['ticket_id'], $user_id);
}
break;
case 'unassign':
if ($isAdmin && isset($_GET['ticket_id'])) {
TicketManager::assign_ticket_user($_GET['ticket_id'], 0);
}
break;
case 'alert':
if (!$isAdmin && isset($_GET['ticket_id'])) {
TicketManager::send_alert($_GET['ticket_id'], $user_id);

@ -84,9 +84,16 @@ if (api_is_allowed_to_edit(null, true)) {
$courseId,
$isTutor
);
Display::addFlash(Display::return_message(get_lang('Updated')));
Display::addFlash(
Display::return_message(get_lang('Updated'))
);
} else {
Display::addFlash(Display::return_message(get_lang('InviteesCantBeTutors'), 'error'));
Display::addFlash(
Display::return_message(
get_lang('InviteesCantBeTutors'),
'error'
)
);
}
}
}
@ -428,9 +435,15 @@ if (api_is_allowed_to_edit(null, true)) {
$row = Database::fetch_array($result, 'ASSOC');
if ($row['user_id'] == $user_id || $row['user_id'] == "") {
CourseManager::unsubscribe_user($_GET['user_id'], $courseCode);
Display::addFlash(Display::return_message(get_lang('UserUnsubscribed')));
Display::addFlash(
Display::return_message(get_lang('UserUnsubscribed'))
);
} else {
Display::addFlash(Display::return_message(get_lang('ThisStudentIsSubscribeThroughASession')));
Display::addFlash(
Display::return_message(
get_lang('ThisStudentIsSubscribeThroughASession')
)
);
}
}
}
@ -456,7 +469,12 @@ Event::event_access_tool(TOOL_USER);
$default_column = 3;
$tableLabel = $type === STUDENT ? 'student' : 'teacher';
$table = new SortableTable($tableLabel.'_list', 'get_number_of_users', 'get_user_data', $default_column);
$table = new SortableTable(
$tableLabel.'_list',
'get_number_of_users',
'get_user_data',
$default_column
);
$parameters['keyword'] = isset($_GET['keyword']) ? Security::remove_XSS($_GET['keyword']) : null;
$parameters['sec_token'] = Security::get_token();
$parameters['id_session'] = api_get_session_id();
@ -489,14 +507,6 @@ $table->set_header($header_nr++, get_lang('LoginName'));
$indexList['groups'] = $header_nr;
$table->set_header($header_nr++, get_lang('GroupSingle'), false);
/*
if (api_is_allowed_to_edit(null, true) && api_get_setting('allow_user_course_subscription_by_course_admin') == 'true') {
} else {
$table->set_column_filter(0, 'hide_field');
}
*/
$hideFields = api_get_configuration_value('hide_user_field_from_list');
if (!empty($hideFields)) {
foreach ($hideFields as $fieldToHide) {
@ -537,7 +547,6 @@ if (api_is_allowed_to_edit(null, true)) {
if (isset($origin) && $origin == 'learnpath') {
Display::display_reduced_header();
} else {
if (isset($_GET['keyword']) && !empty($_GET['keyword'])) {
$interbreadcrumb[] = array(
"url" => "user.php?".api_get_cidreq(),
@ -551,9 +560,6 @@ if (isset($origin) && $origin == 'learnpath') {
Display::display_header($tool_name, "User");
}
/* Setting the permissions for this page */
$is_allowed_to_track = ($is_courseAdmin || $is_courseTutor) || api_is_platform_admin();
// Tool introduction
Display::display_introduction_section(TOOL_USER, 'left');
$actions = '';
@ -722,7 +728,8 @@ function get_number_of_users()
* @param $keyword
* @return bool
*/
function searchUserKeyword($firstname, $lastname, $username, $official_code, $keyword) {
function searchUserKeyword($firstname, $lastname, $username, $official_code, $keyword)
{
if (
api_strripos($firstname, $keyword) !== false ||
api_strripos($lastname, $keyword) !== false ||
@ -824,7 +831,8 @@ function get_user_data($from, $number_of_items, $column, $direction)
$o_course_user['lastname'],
$o_course_user['username'],
$o_course_user['official_code'],
$_GET['keyword'])
$_GET['keyword']
)
) || !isset($_GET['keyword']) || empty($_GET['keyword'])
) {
@ -961,7 +969,9 @@ function active_filter($active, $urlParams, $row)
*/
function modify_filter($user_id, $row, $data)
{
global $is_allowed_to_track, $charset;
global $charset;
$is_allowed_to_track = api_is_allowed_to_edit(true, true);
$user_id = $data[0];
$userInfo = api_get_user_info($user_id);
@ -1009,14 +1019,13 @@ function modify_filter($user_id, $row, $data)
).'&nbsp;';
}
}
// edit
if (api_get_setting('allow_user_course_subscription_by_course_admin') === 'true' or api_is_platform_admin()) {
// unregister
if ($user_id != $current_user_id || api_is_platform_admin()) {
$result .= '<a class="btn btn-small btn-danger" href="'.api_get_self().'?'.api_get_cidreq().'&type='.$type.'&unregister=yes&user_id='.$user_id.'" title="'.get_lang('Unreg').' " onclick="javascript:if(!confirm(\''.addslashes(api_htmlentities(get_lang('ConfirmYourChoice'),ENT_QUOTES,$charset)).'\')) return false;">'.
get_lang('Unreg').'</a>&nbsp;';
} else {
//$result .= Display::return_icon('unsubscribe_course_na.png', get_lang('Unreg'),'',ICON_SIZE_SMALL).'</a>&nbsp;';
}
}
} else {
@ -1028,10 +1037,6 @@ function modify_filter($user_id, $row, $data)
}
}
}
return $result;
}
function hide_field()
{
return null;
return $result;
}

@ -5290,24 +5290,25 @@ function getWorkCreatedByUser($user_id, $courseId, $sessionId)
$sessionId
);
$forumList = array();
$list = array();
if (!empty($items)) {
foreach ($items as $forum) {
foreach ($items as $work) {
$item = get_work_data_by_id(
$forum['ref'],
$work['ref'],
$courseId,
$sessionId
);
$forumList[] = array(
$item['title'],
api_get_local_time($forum['insert_date']),
api_get_local_time($forum['lastedit_date'])
);
if (!empty($item)) {
$list[] = array(
$item['title'],
api_get_local_time($work['insert_date']),
api_get_local_time($work['lastedit_date'])
);
}
}
}
return $forumList;
return $list;
}
/**

@ -162,9 +162,18 @@ class CourseArchiver
foreach ($course->resources[RESOURCE_ASSET] as $asset) {
$doc_dir = $backup_dir . $asset->path;
@mkdir(dirname($doc_dir), $perm_dirs, true);
if (file_exists($course->path . $asset->path)) {
copy($course->path . $asset->path, $doc_dir);
$assetPath = $course->path . $asset->path;
if (!file_exists($assetPath)) {
continue;
}
if (is_dir($course->path . $asset->path)) {
copyDirTo($course->path . $asset->path, $doc_dir);
continue;
}
copy($course->path . $asset->path, $doc_dir);
}
}
@ -185,6 +194,11 @@ class CourseArchiver
{
$backup_files = array();
$dirname = self::getBackupDir();
if (!file_exists($dirname)) {
$dirname = self::createBackupDir();
}
if ($dir = opendir($dirname)) {
while (($file = readdir($dir)) !== false) {
$file_parts = explode('_', $file);

@ -8,7 +8,7 @@ In order to run tests locally:
- user_id = 1
- Edit file tests/behat/behat.yml
An update your Chamilo URL.
Update with your Chamilo local URL.
- The main platform language must be in English.

@ -281,6 +281,9 @@ class FeatureContext extends MinkContext
*/
public function iFillInWysiwygOnFieldWith($locator, $value)
{
// Just in case wait that ckeditor is loaded
$this->getSession()->wait(2000);
$el = $this->getSession()->getPage()->findField($locator);
$fieldId = $el->getAttribute('id');
@ -322,7 +325,6 @@ class FeatureContext extends MinkContext
// See
// https://gist.github.com/blazarecki/2888851
/** @var \Behat\Mink\Driver\Selenium2Driver $driver Needed because no cross-driver way yet */
//$driver = $this->getSession()->getDriver();
$this->getSession()->getDriver()->getWebDriverSession()->accept_alert();
}
@ -407,4 +409,17 @@ class FeatureContext extends MinkContext
}
$select->selectOption($option);
}
/**
* Clicks link with specified id|title|alt|text
* Example: When I follow "Log In"
* Example: And I follow "Log In"
*
* @When /^(?:|I )focus "(?P<link>(?:[^"]|\\")*)"$/
*/
public function focus($input)
{
$input = $this->getSession()->getPage()->findField($input);
$input->focus();
}
}

@ -10,6 +10,19 @@ Feature: Course tools basic testing
And I am a "English" user
# This is executed just before each scenario below
Scenario: See the courses list
Given I am on "/main/admin/course_list.php"
Then I should see "Course list"
And I should not see "not authorized"
Scenario: See the course creation link on the admin page
Given I am on "/main/admin/index.php"
Then I should see "Create a course"
Scenario: Access the course creation page
Given I am on "/main/admin/course_add.php"
Then I should not see "not authorized"
Scenario: Create a course before testing
Given I am on "/main/admin/course_add.php"
When I fill in "title" with "TEMP"
@ -140,4 +153,13 @@ Feature: Course tools basic testing
And I am on "/main/course_info/maintenance.php"
Then I should not see an ".alert-danger" element
# Scenario: Enter to public password-protected course
# Given I have a public password-protected course named "PASSWORDPROTECTED" with password "123456"
# And I am not logged
# And I am on "/courses/PASSWORDPROTECTED/index.php"
# When I fill in "course_password" with "123456"
# And I press "submit"
# Then I should not see "The course password is incorrect"

@ -1,45 +0,0 @@
@administration
Feature: Courses management as admin
In order to add courses
As an administrator
I need to be able to create new courses from the admin page
Background:
Given I am a platform administrator
# This is executed just before each scenario below
Scenario: See the courses list
Given I am on "/main/admin/course_list.php"
Then I should see "Course list"
And I should not see "not authorized"
Scenario: See the course creation link on the admin page
Given I am on "/main/admin/index.php"
Then I should see "Create a course"
Scenario: Access the course creation page
Given I am on "/main/admin/course_add.php"
Then I should not see "not authorized"
Scenario: Access the course creation page
Given I am on "/main/admin/course_add.php"
When I fill in "title" with "TESTCOURSE1"
And I press "submit"
Then I should see "Course list"
Scenario: Search and delete a course
Given I am on "/main/admin/course_list.php"
And I fill in "course-search-keyword" with "TESTCOURSE1"
And I press "submit"
When I follow "Delete"
And I confirm the popup
Then I should see "Course list"
And I should not see "not be deleted"
# Scenario: Enter to public password-protected course
# Given I have a public password-protected course named "PASSWORDPROTECTED" with password "123456"
# And I am not logged
# And I am on "/courses/PASSWORDPROTECTED/index.php"
# When I fill in "course_password" with "123456"
# And I press "submit"
# Then I should not see "The course password is incorrect"

@ -1,17 +1,31 @@
#Feature: Agenda tool
# In order to use the Agenda tool
# The admin should be able to add an event
#
# Background:
# Given I am a platform administrator
#
# Scenario: Create a personal event
# Given I am on "/main/calendar/agenda.php?&action=add&type=personal"
# When I fill in the following:
# | title | Event 1 |
# Then I fill in ckeditor field "content" with "Description event"
# Then wait for the page to be loaded
#
# And I press "Add event"
# Then I should see "Event added"
#
Feature: Agenda tool
In order to use the Agenda tool
The admin should be able to add an event
Background:
Given I am a platform administrator
Scenario: Create a personal event
Given I am on "/main/calendar/agenda.php?action=add&type=personal"
When I fill in the following:
| title | Event 1 |
Then I fill in ckeditor field "content" with "Description event"
Then wait for the page to be loaded
And I focus "date_range"
And I fill in "date_range" with "2017-03-07 12:15 / 2017-03-07 12:15"
And I press "Add event"
Then I should see "Event added"
Scenario: Create an event inside course TEMP
Given I am on "/main/calendar/agenda.php?action=add&type=course&cidReq=TEMP"
When I fill in the following:
| title | Event in course |
Then I fill in ckeditor field "content" with "Description event"
# And I fill in select bootstrap input "users_to_send[]" with "Everyone" and select "Everyone"
Then wait for the page to be loaded
And I focus "date_range"
And I fill in "date_range" with "2017-03-07 12:15 / 2017-03-07 12:15"
And I press "Add event"
Then I should see "Event added"

@ -17,7 +17,7 @@ Feature: Forum tool
Scenario: Create a forum
Given I am on "/main/forum/index.php?action=add&content=forum&cidReq=TEMP"
When I fill in the following:
| forum_title | Forum Test |
| forum_title | Forum Test |
And I fill in ckeditor field "forum_comment" with "This is the first forum for test"
And I press "SubmitForum"
Then I should see "The forum has been added"
@ -26,8 +26,9 @@ Feature: Forum tool
Given I am on "/main/forum/index.php?cidReq=TEMP"
And I follow "Forum Test"
And I follow "Create thread"
And wait for the page to be loaded
When I fill in the following:
| post_title | Thread One |
| post_title | Thread One |
And I fill in ckeditor field "post_text" with "This is a the first thread in a forum for test"
And I press "SubmitPost"
Then I should see "The new thread has been added"

Loading…
Cancel
Save