Răsfoiți Sursa

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

Yannick Warnier 8 ani în urmă
părinte
comite
bda0b1623b
100 a modificat fișierele cu 804 adăugiri și 689 ștergeri
  1. 1 1
      app/Resources/public/assets/MathJax/.bower.json
  2. 5 5
      app/Resources/public/assets/blueimp-canvas-to-blob/.bower.json
  3. 1 1
      app/Resources/public/assets/blueimp-canvas-to-blob/js/canvas-to-blob.js
  4. 8 5
      app/Resources/public/assets/blueimp-canvas-to-blob/package.json
  5. 1 1
      app/Resources/public/assets/blueimp-canvas-to-blob/test/index.html
  6. 9 9
      app/Resources/public/assets/blueimp-canvas-to-blob/test/test.js
  7. 4 4
      app/Resources/public/assets/blueimp-load-image/.bower.json
  8. 12 6
      app/Resources/public/assets/blueimp-load-image/README.md
  9. 1 1
      app/Resources/public/assets/blueimp-load-image/index.html
  10. 87 74
      app/Resources/public/assets/blueimp-load-image/js/demo.js
  11. 1 1
      app/Resources/public/assets/blueimp-load-image/js/load-image-exif-map.js
  12. 1 1
      app/Resources/public/assets/blueimp-load-image/js/load-image-exif.js
  13. 19 3
      app/Resources/public/assets/blueimp-load-image/js/load-image-meta.js
  14. 15 5
      app/Resources/public/assets/blueimp-load-image/js/load-image-orientation.js
  15. 0 0
      app/Resources/public/assets/blueimp-load-image/js/load-image.all.min.js
  16. 0 0
      app/Resources/public/assets/blueimp-load-image/js/load-image.all.min.js.map
  17. 38 22
      app/Resources/public/assets/blueimp-load-image/js/load-image.js
  18. 9 6
      app/Resources/public/assets/blueimp-load-image/package.json
  19. 2 2
      app/Resources/public/assets/blueimp-load-image/test/index.html
  20. 187 166
      app/Resources/public/assets/blueimp-load-image/test/test.js
  21. 4 4
      app/Resources/public/assets/blueimp-tmpl/.bower.json
  22. 0 2
      app/Resources/public/assets/blueimp-tmpl/js/compile.js
  23. 1 1
      app/Resources/public/assets/blueimp-tmpl/js/demo.js
  24. 2 2
      app/Resources/public/assets/blueimp-tmpl/js/runtime.js
  25. 2 2
      app/Resources/public/assets/blueimp-tmpl/js/tmpl.js
  26. 1 1
      app/Resources/public/assets/blueimp-tmpl/js/tmpl.min.js
  27. 1 1
      app/Resources/public/assets/blueimp-tmpl/js/tmpl.min.js.map
  28. 8 6
      app/Resources/public/assets/blueimp-tmpl/package.json
  29. 1 1
      app/Resources/public/assets/blueimp-tmpl/test/index.html
  30. 26 26
      app/Resources/public/assets/blueimp-tmpl/test/test.js
  31. 1 1
      app/Resources/public/assets/bootstrap-daterangepicker/.bower.json
  32. 1 1
      app/Resources/public/assets/ckeditor/.bower.json
  33. 1 1
      app/Resources/public/assets/cropper/.bower.json
  34. 1 1
      app/Resources/public/assets/fontawesome/.bower.json
  35. 1 1
      app/Resources/public/assets/fullcalendar/.bower.json
  36. 1 1
      app/Resources/public/assets/image-map-resizer/.bower.json
  37. 1 1
      app/Resources/public/assets/jquery-timeago/.bower.json
  38. 1 1
      app/Resources/public/assets/jquery-ui/.bower.json
  39. 1 1
      app/Resources/public/assets/jquery.scrollbar/.bower.json
  40. 1 1
      app/Resources/public/assets/jqueryui-timepicker-addon/.bower.json
  41. 1 1
      app/Resources/public/assets/modernizr/.bower.json
  42. 1 1
      app/Resources/public/assets/moment/.bower.json
  43. 1 1
      app/Resources/public/assets/simpleWebRTC/.bower.json
  44. 2 1
      bower.json
  45. 5 0
      main/admin/settings.php
  46. 2 2
      main/admin/user_add.php
  47. 2 2
      main/admin/user_edit.php
  48. 1 1
      main/auth/inscription.php
  49. 2 2
      main/auth/profile.php
  50. 10 10
      main/calendar/agenda_js.php
  51. 2 2
      main/course_info/infocours.php
  52. 21 12
      main/document/document.php
  53. 5 6
      main/exercise/exercise.class.php
  54. 28 35
      main/exercise/exercise.php
  55. 2 2
      main/exercise/exercise_result.class.php
  56. 1 1
      main/gradebook/lib/gradebook_result.class.php
  57. 4 0
      main/group/group.php
  58. 13 6
      main/group/group_edit.php
  59. 3 2
      main/group/group_space.php
  60. 12 1
      main/inc/lib/api.lib.php
  61. 18 8
      main/inc/lib/groupmanager.lib.php
  62. 0 0
      main/inc/lib/javascript/qtip2/jquery.qtip.min.css
  63. 0 12
      main/inc/lib/javascript/qtip2/jquery.qtip.min.js
  64. 6 3
      main/inc/lib/nusoap/class.soap_server.php
  65. 6 6
      main/inc/lib/online.inc.php
  66. 4 1
      main/inc/lib/usermanager.lib.php
  67. 3 3
      main/lp/learnpath.class.php
  68. 1 1
      main/lp/lp_add_item.php
  69. 1 1
      main/lp/lp_edit_item.php
  70. 1 1
      main/mySpace/current_courses.php
  71. 2 2
      main/session/session_add.php
  72. 2 2
      main/session/session_edit.php
  73. 1 1
      main/survey/reporting.php
  74. 14 8
      main/survey/survey.lib.php
  75. 2 2
      main/template/default/agenda/month.tpl
  76. 1 1
      main/template/default/layout/footer.js.tpl
  77. 2 2
      main/template/default/layout/hot_course_item.tpl
  78. 14 14
      main/template/default/layout/layout_3_col.tpl
  79. 1 2
      main/template/default/layout/login_form.tpl
  80. 3 5
      main/template/default/layout/no_layout.tpl
  81. 2 2
      main/template/default/layout/page.tpl
  82. 3 3
      main/template/default/layout/page_header.tpl
  83. 0 3
      main/template/default/layout/welcome_to_course.tpl
  84. 0 1
      main/template/default/mail/content_registration_platform_to_admin.tpl
  85. 0 1
      main/template/default/sequence_resource/session_requirements.tpl
  86. 0 1
      main/template/default/session/about.tpl
  87. 0 4
      main/template/default/skill/badge.tpl
  88. 32 32
      main/template/default/skill/badge_create.tpl
  89. 27 23
      main/template/default/skill/profile.tpl
  90. 12 11
      main/template/default/skill/skill_info.tpl
  91. 0 2
      main/template/default/social/group_waiting_list.tpl
  92. 26 28
      main/template/default/social/home.tpl
  93. 0 1
      main/template/default/social/profile.tpl
  94. 19 20
      main/template/default/social/skills_block.tpl
  95. 13 14
      main/template/default/social/user_block.tpl
  96. 0 1
      main/template/default/user_portal/grid_courses_with_category.tpl
  97. 0 1
      main/template/default/user_portal/grid_courses_without_category.tpl
  98. 0 1
      main/template/default/user_portal/grid_session.tpl
  99. 0 2
      main/template/default/work/comments.tpl
  100. 13 6
      main/wiki/wiki.inc.php

+ 1 - 1
app/Resources/public/assets/MathJax/.bower.json

@@ -21,7 +21,7 @@
     "tag": "2.5.3",
     "commit": "ba9afeb5a743249acdea17540b48b14ebc95dbe4"
   },
-  "_source": "git://github.com/mathjax/MathJax.git",
+  "_source": "https://github.com/mathjax/MathJax.git",
   "_target": "2.5.*",
   "_originalSource": "MathJax"
 }

+ 5 - 5
app/Resources/public/assets/blueimp-canvas-to-blob/.bower.json

@@ -1,14 +1,14 @@
 {
   "name": "blueimp-canvas-to-blob",
   "homepage": "https://github.com/blueimp/JavaScript-Canvas-to-Blob",
-  "version": "3.3.0",
-  "_release": "3.3.0",
+  "version": "3.4.0",
+  "_release": "3.4.0",
   "_resolution": {
     "type": "version",
-    "tag": "v3.3.0",
-    "commit": "443806e20bf0cc6e5b812b0cf686f3109d791074"
+    "tag": "v3.4.0",
+    "commit": "ca0326180f984600aa25eab8a19c4be11b5f048c"
   },
-  "_source": "git://github.com/blueimp/JavaScript-Canvas-to-Blob.git",
+  "_source": "https://github.com/blueimp/JavaScript-Canvas-to-Blob.git",
   "_target": ">=2.1.1",
   "_originalSource": "blueimp-canvas-to-blob"
 }

+ 1 - 1
app/Resources/public/assets/blueimp-canvas-to-blob/js/canvas-to-blob.js

@@ -12,7 +12,7 @@
  * http://stackoverflow.com/q/4998908
  */
 
-/*global window, atob, Blob, ArrayBuffer, Uint8Array, define, module */
+/* global atob, Blob, define */
 
 ;(function (window) {
   'use strict'

+ 8 - 5
app/Resources/public/assets/blueimp-canvas-to-blob/package.json

@@ -1,6 +1,6 @@
 {
   "name": "blueimp-canvas-to-blob",
-  "version": "3.3.0",
+  "version": "3.4.0",
   "title": "JavaScript Canvas to Blob",
   "description": "Canvas to Blob is a polyfill for the standard JavaScript canvas.toBlob method. It can be used to create Blob objects from an HTML canvas element.",
   "keywords": [
@@ -22,12 +22,15 @@
   "license": "MIT",
   "main": "./js/canvas-to-blob.js",
   "devDependencies": {
-    "mocha-phantomjs": "4.0.1",
-    "standard": "6.0.7",
-    "uglify-js": "2.6.1"
+    "phantomjs-prebuilt": "2.1.13",
+    "mocha-phantomjs-core": "1.3.1",
+    "standard": "8.3.0",
+    "uglify-js": "2.7.3"
   },
   "scripts": {
-    "test": "standard js/*.js test/*.js && mocha-phantomjs test/index.html",
+    "lint": "standard js/*.js test/*.js",
+    "unit": "phantomjs node_modules/mocha-phantomjs-core/mocha-phantomjs-core.js test/index.html",
+    "test": "npm run lint && npm run unit",
     "build": "cd js && uglifyjs canvas-to-blob.js -c -m -o canvas-to-blob.min.js --source-map canvas-to-blob.min.js.map",
     "preversion": "npm test",
     "version": "npm run build && git add -A js",

+ 1 - 1
app/Resources/public/assets/blueimp-canvas-to-blob/test/index.html

@@ -24,7 +24,7 @@
 <body>
 <div id="mocha"></div>
 <script src="vendor/mocha.js"></script>
-<script src="vendor/expect.js"></script>
+<script src="vendor/chai.js"></script>
 <script>
 window.initMochaPhantomJS && initMochaPhantomJS();
 mocha.setup('bdd');

+ 9 - 9
app/Resources/public/assets/blueimp-canvas-to-blob/test/test.js

@@ -9,7 +9,7 @@
  * http://www.opensource.org/licenses/MIT
  */
 
-/*global window, describe, it, Blob */
+/* global describe, it, Blob */
 
 ;(function (expect) {
   'use strict'
@@ -26,7 +26,7 @@
       window.loadImage(blob, function (canvas) {
         canvas.toBlob(
           function (newBlob) {
-            expect(newBlob).to.be.a(Blob)
+            expect(newBlob).to.be.a.instanceOf(Blob)
             done()
           }
         )
@@ -37,7 +37,7 @@
       window.loadImage(blob, function (canvas) {
         canvas.toBlob(
           function (newBlob) {
-            expect(newBlob.type).to.be('image/png')
+            expect(newBlob.type).to.equal('image/png')
             done()
           },
           'image/png'
@@ -49,7 +49,7 @@
       window.loadImage(blob, function (canvas) {
         canvas.toBlob(
           function (newBlob) {
-            expect(newBlob.type).to.be('image/jpeg')
+            expect(newBlob.type).to.equal('image/jpeg')
             done()
           },
           'image/jpeg'
@@ -62,8 +62,8 @@
         canvas.toBlob(
           function (newBlob) {
             window.loadImage(newBlob, function (img) {
-              expect(img.width).to.be(canvas.width)
-              expect(img.height).to.be(canvas.height)
+              expect(img.width).to.equal(canvas.width)
+              expect(img.height).to.equal(canvas.height)
               done()
             })
           }
@@ -80,8 +80,8 @@
                   .getImageData(0, 0, canvas.width, canvas.height)
               var newCanvasData = newCanvas.getContext('2d')
                   .getImageData(0, 0, newCanvas.width, newCanvas.height)
-              expect(canvasData.width).to.be(newCanvasData.width)
-              expect(canvasData.height).to.be(newCanvasData.height)
+              expect(canvasData.width).to.equal(newCanvasData.width)
+              expect(canvasData.height).to.equal(newCanvasData.height)
               done()
             }, {canvas: true})
           }
@@ -89,4 +89,4 @@
       }, {canvas: true})
     })
   })
-}(this.expect))
+}(this.chai.expect))

+ 4 - 4
app/Resources/public/assets/blueimp-load-image/.bower.json

@@ -1,12 +1,12 @@
 {
   "name": "blueimp-load-image",
   "homepage": "https://github.com/blueimp/JavaScript-Load-Image",
-  "version": "2.6.2",
-  "_release": "2.6.2",
+  "version": "2.7.0",
+  "_release": "2.7.0",
   "_resolution": {
     "type": "version",
-    "tag": "v2.6.2",
-    "commit": "d6fdf1575c2f0376d29750a626d096f997e9572a"
+    "tag": "v2.7.0",
+    "commit": "8ee49d987e6951db1c4db6c5270abaa66e6b6659"
   },
   "_source": "https://github.com/blueimp/JavaScript-Load-Image.git",
   "_target": ">=1.13.0",

+ 12 - 6
app/Resources/public/assets/blueimp-load-image/README.md

@@ -194,9 +194,15 @@ Requires `canvas: true`.
 * **crop**: Crops the image to the maxWidth/maxHeight constraints if set to
 `true`.  
 Enabling the `crop` option also enables the `canvas` option.
-* **orientation**: Allows to transform the canvas coordinates according to the
-EXIF orientation specification.  
-Setting the `orientation` also enables the `canvas` option.
+* **orientation**: Transform the canvas according to the specified Exif
+orientation, which can be an `integer` in the range of `1` to `8` or the boolean
+value `true`.  
+When set to `true`, it will set the orientation value based on the EXIF data of
+the image, which will be parsed automatically if the exif library is available.  
+Setting the `orientation` also enables the `canvas` option.  
+Setting `orientation` to `true` alsoe enables the `meta` option.
+* **meta**: Automatically parses the image meta data if set to `true`.  
+The meta data is passed to the callback as second argument.
 * **canvas**: Returns the image as
 [canvas](https://developer.mozilla.org/en/HTML/Canvas) element if set to `true`.
 * **crossOrigin**: Sets the crossOrigin property on the img element for loading
@@ -266,9 +272,9 @@ Blob objects of resized images can be created via
 [canvas.toBlob()](https://github.com/blueimp/JavaScript-Canvas-to-Blob).
 
 ### Exif parser
-If you include the Load Image Exif Parser extension, the **parseMetaData**
-callback **data** contains the additional property **exif** if Exif data could
-be found in the given image.  
+If you include the Load Image Exif Parser extension, the argument passed to the
+callback for **parseMetaData** will contain the additional property **exif** if
+Exif data could be found in the given image.  
 The **exif** object stores the parsed Exif tags:
 
 ```js

+ 1 - 1
app/Resources/public/assets/blueimp-load-image/index.html

@@ -57,10 +57,10 @@ It also provides a method to parse image meta data to extract <a href="https://e
 </div>
 <br>
 <script src="js/load-image.js"></script>
-<script src="js/load-image-orientation.js"></script>
 <script src="js/load-image-meta.js"></script>
 <script src="js/load-image-exif.js"></script>
 <script src="js/load-image-exif-map.js"></script>
+<script src="js/load-image-orientation.js"></script>
 <!-- jQuery and Jcrop are not required by JavaScript Load Image, but included for the demo -->
 <script src="js/vendor/jquery.js"></script>
 <script src="js/vendor/jquery.Jcrop.js"></script>

+ 87 - 74
app/Resources/public/assets/blueimp-load-image/js/demo.js

@@ -9,7 +9,7 @@
  * http://www.opensource.org/licenses/MIT
  */
 
-/*global window, document, loadImage, HTMLCanvasElement, $ */
+/* global loadImage, HTMLCanvasElement, $ */
 
 $(function () {
   'use strict'
@@ -20,32 +20,7 @@ $(function () {
   var actionsNode = $('#actions')
   var currentFile
   var coordinates
-  function replaceResults (img) {
-    var content
-    if (!(img.src || img instanceof HTMLCanvasElement)) {
-      content = $('<span>Loading image file failed</span>')
-    } else {
-      content = $('<a target="_blank">').append(img)
-        .attr('download', currentFile.name)
-        .attr('href', img.src || img.toDataURL())
-    }
-    result.children().replaceWith(content)
-    if (img.getContext) {
-      actionsNode.show()
-    }
-  }
-  function displayImage (file, options) {
-    currentFile = file
-    if (!loadImage(
-        file,
-        replaceResults,
-        options
-      )) {
-      result.children().replaceWith(
-        $('<span>Your browser does not support the URL or FileReader API.</span>')
-      )
-    }
-  }
+
   function displayExifData (exif) {
     var thumbnail = exif.get('Thumbnail')
     var tags = exif.getAll()
@@ -70,6 +45,40 @@ $(function () {
     }
     exifNode.show()
   }
+
+  function updateResults (img, data) {
+    var content
+    if (!(img.src || img instanceof HTMLCanvasElement)) {
+      content = $('<span>Loading image file failed</span>')
+    } else {
+      content = $('<a target="_blank">').append(img)
+        .attr('download', currentFile.name)
+        .attr('href', img.src || img.toDataURL())
+    }
+    result.children().replaceWith(content)
+    if (img.getContext) {
+      actionsNode.show()
+    }
+    if (data && data.exif) {
+      displayExifData(data.exif)
+    }
+  }
+
+  function displayImage (file, options) {
+    currentFile = file
+    if (!loadImage(
+        file,
+        updateResults,
+        options
+      )) {
+      result.children().replaceWith(
+        $('<span>' +
+          'Your browser does not support the URL or FileReader API.' +
+          '</span>')
+      )
+    }
+  }
+
   function dropChangeHandler (e) {
     e.preventDefault()
     e = e.originalEvent
@@ -79,25 +88,23 @@ $(function () {
       maxWidth: result.width(),
       canvas: true,
       pixelRatio: window.devicePixelRatio,
-      downsamplingRatio: 0.5
+      downsamplingRatio: 0.5,
+      orientation: true
     }
     if (!file) {
       return
     }
     exifNode.hide()
     thumbNode.hide()
-    loadImage.parseMetaData(file, function (data) {
-      if (data.exif) {
-        options.orientation = data.exif.get('Orientation')
-        displayExifData(data.exif)
-      }
-      displayImage(file, options)
-    })
+    displayImage(file, options)
   }
+
   // Hide URL/FileReader API requirement message in capable browsers:
-  if (window.createObjectURL || window.URL || window.webkitURL || window.FileReader) {
+  if (window.createObjectURL || window.URL || window.webkitURL ||
+      window.FileReader) {
     result.children().hide()
   }
+
   $(document)
     .on('dragover', function (e) {
       e.preventDefault()
@@ -105,45 +112,51 @@ $(function () {
       e.dataTransfer.dropEffect = 'copy'
     })
     .on('drop', dropChangeHandler)
-  $('#file-input').on('change', dropChangeHandler)
-  $('#edit').on('click', function (event) {
-    event.preventDefault()
-    var imgNode = result.find('img, canvas')
-    var img = imgNode[0]
-    var pixelRatio = window.devicePixelRatio || 1
-    imgNode.Jcrop({
-      setSelect: [
-        40,
-        40,
-        (img.width / pixelRatio) - 40,
-        (img.height / pixelRatio) - 40
-      ],
-      onSelect: function (coords) {
-        coordinates = coords
-      },
-      onRelease: function () {
+
+  $('#file-input')
+    .on('change', dropChangeHandler)
+
+  $('#edit')
+    .on('click', function (event) {
+      event.preventDefault()
+      var imgNode = result.find('img, canvas')
+      var img = imgNode[0]
+      var pixelRatio = window.devicePixelRatio || 1
+      imgNode.Jcrop({
+        setSelect: [
+          40,
+          40,
+          (img.width / pixelRatio) - 40,
+          (img.height / pixelRatio) - 40
+        ],
+        onSelect: function (coords) {
+          coordinates = coords
+        },
+        onRelease: function () {
+          coordinates = null
+        }
+      }).parent().on('click', function (event) {
+        event.preventDefault()
+      })
+    })
+
+  $('#crop')
+    .on('click', function (event) {
+      event.preventDefault()
+      var img = result.find('img, canvas')[0]
+      var pixelRatio = window.devicePixelRatio || 1
+      if (img && coordinates) {
+        updateResults(loadImage.scale(img, {
+          left: coordinates.x * pixelRatio,
+          top: coordinates.y * pixelRatio,
+          sourceWidth: coordinates.w * pixelRatio,
+          sourceHeight: coordinates.h * pixelRatio,
+          minWidth: result.width(),
+          maxWidth: result.width(),
+          pixelRatio: pixelRatio,
+          downsamplingRatio: 0.5
+        }))
         coordinates = null
       }
-    }).parent().on('click', function (event) {
-      event.preventDefault()
     })
-  })
-  $('#crop').on('click', function (event) {
-    event.preventDefault()
-    var img = result.find('img, canvas')[0]
-    var pixelRatio = window.devicePixelRatio || 1
-    if (img && coordinates) {
-      replaceResults(loadImage.scale(img, {
-        left: coordinates.x * pixelRatio,
-        top: coordinates.y * pixelRatio,
-        sourceWidth: coordinates.w * pixelRatio,
-        sourceHeight: coordinates.h * pixelRatio,
-        minWidth: result.width(),
-        maxWidth: result.width(),
-        pixelRatio: pixelRatio,
-        downsamplingRatio: 0.5
-      }))
-      coordinates = null
-    }
-  })
 })

+ 1 - 1
app/Resources/public/assets/blueimp-load-image/js/load-image-exif-map.js

@@ -12,7 +12,7 @@
  * http://www.opensource.org/licenses/MIT
  */
 
-/*global define, module, require, window */
+/* global define */
 
 ;(function (factory) {
   'use strict'

+ 1 - 1
app/Resources/public/assets/blueimp-load-image/js/load-image-exif.js

@@ -9,7 +9,7 @@
  * http://www.opensource.org/licenses/MIT
  */
 
-/*global define, module, require, window, console */
+/* global define */
 
 ;(function (factory) {
   'use strict'

+ 19 - 3
app/Resources/public/assets/blueimp-load-image/js/load-image-meta.js

@@ -13,7 +13,7 @@
  * http://www.opensource.org/licenses/MIT
  */
 
-/*global define, module, require, window, DataView, Blob, Uint8Array, console */
+/* global define, Blob */
 
 ;(function (factory) {
   'use strict'
@@ -49,12 +49,12 @@
   // The options arguments accepts an object and supports the following properties:
   // * maxMetaDataSize: Defines the maximum number of bytes to parse.
   // * disableImageHead: Disables creating the imageHead property.
-  loadImage.parseMetaData = function (file, callback, options) {
+  loadImage.parseMetaData = function (file, callback, options, data) {
     options = options || {}
+    data = data || {}
     var that = this
     // 256 KiB should contain all EXIF/ICC/IPTC segments:
     var maxMetaDataSize = options.maxMetaDataSize || 262144
-    var data = {}
     var noMetaData = !(window.DataView && file && file.size >= 12 &&
                       file.type === 'image/jpeg' && loadImage.blobSlice)
     if (noMetaData || !loadImage.readFile(
@@ -140,4 +140,20 @@
       callback(data)
     }
   }
+
+  // Determines if meta data should be loaded automatically:
+  loadImage.hasMetaOption = function (options) {
+    return options.meta
+  }
+
+  var originalTransform = loadImage.transform
+  loadImage.transform = function (img, options, callback, file, data) {
+    if (loadImage.hasMetaOption(options || {})) {
+      loadImage.parseMetaData(file, function (data) {
+        originalTransform.call(loadImage, img, options, callback, file, data)
+      }, options, data)
+    } else {
+      originalTransform.apply(loadImage, arguments)
+    }
+  }
 }))

+ 15 - 5
app/Resources/public/assets/blueimp-load-image/js/load-image-orientation.js

@@ -9,7 +9,7 @@
  * http://www.opensource.org/licenses/MIT
  */
 
-/*global define, module, require, window */
+/* global define */
 
 ;(function (factory) {
   'use strict'
@@ -26,16 +26,22 @@
   'use strict'
 
   var originalHasCanvasOption = loadImage.hasCanvasOption
+  var originalHasMetaOption = loadImage.hasMetaOption
   var originalTransformCoordinates = loadImage.transformCoordinates
   var originalGetTransformedOptions = loadImage.getTransformedOptions
 
-  // This method is used to determine if the target image
-  // should be a canvas element:
+  // Determines if the target image should be a canvas element:
   loadImage.hasCanvasOption = function (options) {
     return !!options.orientation ||
       originalHasCanvasOption.call(loadImage, options)
   }
 
+  // Determines if meta data should be loaded automatically:
+  loadImage.hasMetaOption = function (options) {
+    return options.orientation === true ||
+      originalHasMetaOption.call(loadImage, options)
+  }
+
   // Transform image orientation based on
   // the given EXIF orientation option:
   loadImage.transformCoordinates = function (canvas, options) {
@@ -97,11 +103,14 @@
 
   // Transforms coordinate and dimension options
   // based on the given orientation option:
-  loadImage.getTransformedOptions = function (img, opts) {
+  loadImage.getTransformedOptions = function (img, opts, data) {
     var options = originalGetTransformedOptions.call(loadImage, img, opts)
     var orientation = options.orientation
     var newOptions
     var i
+    if (orientation === true && data && data.exif) {
+      orientation = data.exif.get('Orientation')
+    }
     if (!orientation || orientation > 8 || orientation === 1) {
       return options
     }
@@ -111,7 +120,8 @@
         newOptions[i] = options[i]
       }
     }
-    switch (options.orientation) {
+    newOptions.orientation = orientation
+    switch (orientation) {
       case 2:
         // horizontal flip
         newOptions.left = options.right

Fișier diff suprimat deoarece este prea mare
+ 0 - 0
app/Resources/public/assets/blueimp-load-image/js/load-image.all.min.js


Fișier diff suprimat deoarece este prea mare
+ 0 - 0
app/Resources/public/assets/blueimp-load-image/js/load-image.all.min.js.map


+ 38 - 22
app/Resources/public/assets/blueimp-load-image/js/load-image.js

@@ -9,7 +9,7 @@
  * http://www.opensource.org/licenses/MIT
  */
 
-/*global define, module, window, document, URL, webkitURL, FileReader */
+/* global define, URL, webkitURL, FileReader */
 
 ;(function ($) {
   'use strict'
@@ -17,26 +17,20 @@
   // Loads an image for a given File object.
   // Invokes the callback with an img or optional canvas
   // element (if supported by the browser) as parameter:
-  var loadImage = function (file, callback, options) {
+  function loadImage (file, callback, options) {
     var img = document.createElement('img')
     var url
-    var oUrl
-    img.onerror = callback
-    img.onload = function () {
-      if (oUrl && !(options && options.noRevoke)) {
-        loadImage.revokeObjectURL(oUrl)
-      }
-      if (callback) {
-        callback(loadImage.scale(img, options))
-      }
+    img.onerror = function (event) {
+      return loadImage.onerror(img, event, file, callback, options)
+    }
+    img.onload = function (event) {
+      return loadImage.onload(img, event, file, callback, options)
     }
     if (loadImage.isInstanceOf('Blob', file) ||
       // Files are also Blob instances, but some browsers
       // (Firefox 3.6) support the File API but not Blobs:
       loadImage.isInstanceOf('File', file)) {
-      url = oUrl = loadImage.createObjectURL(file)
-      // Store the file type for resize processing:
-      img._type = file.type
+      url = img._objectURL = loadImage.createObjectURL(file)
     } else if (typeof file === 'string') {
       url = file
       if (options && options.crossOrigin) {
@@ -53,10 +47,8 @@
       var target = e.target
       if (target && target.result) {
         img.src = target.result
-      } else {
-        if (callback) {
-          callback(e)
-        }
+      } else if (callback) {
+        callback(e)
       }
     })
   }
@@ -66,11 +58,36 @@
                 (window.URL && URL.revokeObjectURL && URL) ||
                 (window.webkitURL && webkitURL)
 
+  function revokeHelper (img, options) {
+    if (img._objectURL && !(options && options.noRevoke)) {
+      loadImage.revokeObjectURL(img._objectURL)
+      delete img._objectURL
+    }
+  }
+
   loadImage.isInstanceOf = function (type, obj) {
     // Cross-frame instanceof check
     return Object.prototype.toString.call(obj) === '[object ' + type + ']'
   }
 
+  loadImage.transform = function (img, options, callback, file, data) {
+    callback(loadImage.scale(img, options, data), data)
+  }
+
+  loadImage.onerror = function (img, event, file, callback, options) {
+    revokeHelper(img, options)
+    if (callback) {
+      callback.call(img, event)
+    }
+  }
+
+  loadImage.onload = function (img, event, file, callback, options) {
+    revokeHelper(img, options)
+    if (callback) {
+      loadImage.transform(img, options, callback, file, {})
+    }
+  }
+
   // Transform image coordinates, allows to override e.g.
   // the canvas orientation based on the orientation option,
   // gets canvas, options passed as arguments:
@@ -136,8 +153,7 @@
     return canvas
   }
 
-  // This method is used to determine if the target image
-  // should be a canvas element:
+  // Determines if the target image should be a canvas element:
   loadImage.hasCanvasOption = function (options) {
     return options.canvas || options.crop || !!options.aspectRatio
   }
@@ -147,7 +163,7 @@
   // Returns a canvas object if the browser supports canvas
   // and the hasCanvasOption method returns true or a canvas
   // object is passed as image, else the scaled image:
-  loadImage.scale = function (img, options) {
+  loadImage.scale = function (img, options, data) {
     options = options || {}
     var canvas = document.createElement('canvas')
     var useCanvas = img.getContext ||
@@ -188,7 +204,7 @@
       }
     }
     if (useCanvas) {
-      options = loadImage.getTransformedOptions(img, options)
+      options = loadImage.getTransformedOptions(img, options, data)
       sourceX = options.left || 0
       sourceY = options.top || 0
       if (options.sourceWidth) {

+ 9 - 6
app/Resources/public/assets/blueimp-load-image/package.json

@@ -1,6 +1,6 @@
 {
   "name": "blueimp-load-image",
-  "version": "2.6.2",
+  "version": "2.7.0",
   "main": "index.js",
   "title": "JavaScript Load Image",
   "description": "JavaScript Load Image is a library to load images provided as File or Blob objects or via URL. It returns an optionally scaled and/or cropped HTML img or canvas element. It also provides a method to parse image meta data to extract Exif tags and thumbnails and to restore the complete image header after resizing.",
@@ -31,13 +31,16 @@
     "url": "git://github.com/blueimp/JavaScript-Load-Image.git"
   },
   "devDependencies": {
-    "mocha-phantomjs": "4.0.1",
-    "standard": "6.0.7",
-    "uglify-js": "2.6.1"
+    "phantomjs-prebuilt": "2.1.13",
+    "mocha-phantomjs-core": "1.3.1",
+    "standard": "8.3.0",
+    "uglify-js": "2.7.3"
   },
   "scripts": {
-    "test": "standard *.js js/*.js test/*.js && mocha-phantomjs test/index.html",
-    "build": "cd js && uglifyjs load-image.js load-image-orientation.js load-image-meta.js load-image-exif.js load-image-exif-map.js -c -m -o load-image.all.min.js --source-map load-image.all.min.js.map",
+    "lint": "standard *.js js/*.js test/*.js",
+    "unit": "phantomjs node_modules/mocha-phantomjs-core/mocha-phantomjs-core.js test/index.html",
+    "test": "npm run lint && npm run unit",
+    "build": "cd js && uglifyjs load-image.js load-image-meta.js load-image-exif.js load-image-exif-map.js load-image-orientation.js -c -m -o load-image.all.min.js --source-map load-image.all.min.js.map",
     "preversion": "npm test",
     "version": "npm run build && git add -A js",
     "postversion": "git push --tags origin master master:gh-pages && npm publish"

+ 2 - 2
app/Resources/public/assets/blueimp-load-image/test/index.html

@@ -24,17 +24,17 @@
 <body>
 <div id="mocha"></div>
 <script src="vendor/mocha.js"></script>
-<script src="vendor/expect.js"></script>
+<script src="vendor/chai.js"></script>
 <script>
 window.initMochaPhantomJS && initMochaPhantomJS();
 mocha.setup('bdd');
 </script>
 <script src="vendor/canvas-to-blob.js"></script>
 <script src="../js/load-image.js"></script>
-<script src="../js/load-image-orientation.js"></script>
 <script src="../js/load-image-meta.js"></script>
 <script src="../js/load-image-exif.js"></script>
 <script src="../js/load-image-exif-map.js"></script>
+<script src="../js/load-image-orientation.js"></script>
 <script src="test.js"></script>
 <script>
 mocha.checkLeaks();

+ 187 - 166
app/Resources/public/assets/blueimp-load-image/test/test.js

@@ -9,7 +9,7 @@
  * http://www.opensource.org/licenses/MIT
  */
 
-/*global window, describe, it, Blob */
+/* global describe, it, Blob */
 
 ;(function (expect, loadImage) {
   'use strict'
@@ -21,7 +21,7 @@
                     'ovGITCqXzKbzCY1Kp9Sq9YrNarfcrvcLDovH5PKsAAA7'
   var imageUrlGIF = 'data:image/gif;base64,' + b64DataGIF
   var blobGIF = canCreateBlob && window.dataURLtoBlob(imageUrlGIF)
-  // 1x2px JPEG (color white, with the Exif orientation flag set to 6):
+  // 2x1px JPEG (color white, with the Exif orientation flag set to 6):
   var b64DataJPEG = '/9j/4AAQSkZJRgABAQEAYABgAAD/4QAiRXhpZgAASUkqAAgAAA' +
                     'ABABIBAwABAAAABgASAAAAAAD/2wBDAAEBAQEBAQEBAQEBAQEB' +
                     'AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ' +
@@ -59,43 +59,43 @@
       var img = loadImage(blobGIF, function () {
         return
       })
-      expect(img).to.be.an(Object)
+      expect(img).to.be.an.instanceOf(Object)
       expect(img.onload).to.be.a('function')
       expect(img.onerror).to.be.a('function')
     })
 
     it('Load image url', function (done) {
       expect(loadImage(imageUrlGIF, function (img) {
-        expect(img.width).to.be(80)
-        expect(img.height).to.be(60)
+        expect(img.width).to.equal(80)
+        expect(img.height).to.equal(60)
         done()
-      })).to.be.ok()
+      })).to.be.ok
     })
 
     it('Load image blob', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.width).to.be(80)
-        expect(img.height).to.be(60)
+        expect(img.width).to.equal(80)
+        expect(img.height).to.equal(60)
         done()
-      })).to.be.ok()
+      })).to.be.ok
     })
 
     it('Return image loading error to callback', function (done) {
       expect(loadImage('404', function (img) {
-        expect(img).to.be.a(window.Event)
-        expect(img.type).to.be('error')
+        expect(img).to.be.an.instanceOf(window.Event)
+        expect(img.type).to.equal('error')
         done()
-      })).to.be.ok()
+      })).to.be.ok
     })
 
     it('Keep object URL if noRevoke is true', function (done) {
       expect(loadImage(blobGIF, function (img) {
         loadImage(img.src, function (img2) {
-          expect(img.width).to.be(img2.width)
-          expect(img.height).to.be(img2.height)
+          expect(img.width).to.equal(img2.width)
+          expect(img.height).to.equal(img2.height)
           done()
         })
-      }, {noRevoke: true})).to.be.ok()
+      }, {noRevoke: true})).to.be.ok
     })
 
     it('Discard object URL if noRevoke is undefined or false', function (done) {
@@ -103,12 +103,12 @@
         loadImage(img.src, function (img2) {
           if (!window.callPhantom) {
             // revokeObjectUrl doesn't seem to have an effect in PhantomJS
-            expect(img2).to.be.a(window.Event)
-            expect(img2.type).to.be('error')
+            expect(img2).to.be.an.instanceOf(window.Event)
+            expect(img2.type).to.equal('error')
           }
           done()
         })
-      })).to.be.ok()
+      })).to.be.ok
     })
   })
 
@@ -116,146 +116,146 @@
     describe('max/min', function () {
       it('Scale to maxWidth', function (done) {
         expect(loadImage(blobGIF, function (img) {
-          expect(img.width).to.be(40)
-          expect(img.height).to.be(30)
+          expect(img.width).to.equal(40)
+          expect(img.height).to.equal(30)
           done()
-        }, {maxWidth: 40})).to.be.ok()
+        }, {maxWidth: 40})).to.be.ok
       })
 
       it('Scale to maxHeight', function (done) {
         expect(loadImage(blobGIF, function (img) {
-          expect(img.width).to.be(20)
-          expect(img.height).to.be(15)
+          expect(img.width).to.equal(20)
+          expect(img.height).to.equal(15)
           done()
-        }, {maxHeight: 15})).to.be.ok()
+        }, {maxHeight: 15})).to.be.ok
       })
 
       it('Scale to minWidth', function (done) {
         expect(loadImage(blobGIF, function (img) {
-          expect(img.width).to.be(160)
-          expect(img.height).to.be(120)
+          expect(img.width).to.equal(160)
+          expect(img.height).to.equal(120)
           done()
-        }, {minWidth: 160})).to.be.ok()
+        }, {minWidth: 160})).to.be.ok
       })
 
       it('Scale to minHeight', function (done) {
         expect(loadImage(blobGIF, function (img) {
-          expect(img.width).to.be(320)
-          expect(img.height).to.be(240)
+          expect(img.width).to.equal(320)
+          expect(img.height).to.equal(240)
           done()
-        }, {minHeight: 240})).to.be.ok()
+        }, {minHeight: 240})).to.be.ok
       })
 
       it('Scale to minWidth but respect maxWidth', function (done) {
         expect(loadImage(blobGIF, function (img) {
-          expect(img.width).to.be(160)
-          expect(img.height).to.be(120)
+          expect(img.width).to.equal(160)
+          expect(img.height).to.equal(120)
           done()
-        }, {minWidth: 240, maxWidth: 160})).to.be.ok()
+        }, {minWidth: 240, maxWidth: 160})).to.be.ok
       })
 
       it('Scale to minHeight but respect maxHeight', function (done) {
         expect(loadImage(blobGIF, function (img) {
-          expect(img.width).to.be(160)
-          expect(img.height).to.be(120)
+          expect(img.width).to.equal(160)
+          expect(img.height).to.equal(120)
           done()
-        }, {minHeight: 180, maxHeight: 120})).to.be.ok()
+        }, {minHeight: 180, maxHeight: 120})).to.be.ok
       })
 
       it('Scale to minWidth but respect maxHeight', function (done) {
         expect(loadImage(blobGIF, function (img) {
-          expect(img.width).to.be(160)
-          expect(img.height).to.be(120)
+          expect(img.width).to.equal(160)
+          expect(img.height).to.equal(120)
           done()
-        }, {minWidth: 240, maxHeight: 120})).to.be.ok()
+        }, {minWidth: 240, maxHeight: 120})).to.be.ok
       })
 
       it('Scale to minHeight but respect maxWidth', function (done) {
         expect(loadImage(blobGIF, function (img) {
-          expect(img.width).to.be(160)
-          expect(img.height).to.be(120)
+          expect(img.width).to.equal(160)
+          expect(img.height).to.equal(120)
           done()
-        }, {minHeight: 180, maxWidth: 160})).to.be.ok()
+        }, {minHeight: 180, maxWidth: 160})).to.be.ok
       })
 
       it('Scale up with the given pixelRatio', function (done) {
         expect(loadImage(blobGIF, function (img) {
-          expect(img.width).to.be(320)
-          expect(img.height).to.be(240)
-          expect(img.style.width).to.be('160px')
-          expect(img.style.height).to.be('120px')
+          expect(img.width).to.equal(320)
+          expect(img.height).to.equal(240)
+          expect(img.style.width).to.equal('160px')
+          expect(img.style.height).to.equal('120px')
           done()
-        }, {minWidth: 160, canvas: true, pixelRatio: 2})).to.be.ok()
+        }, {minWidth: 160, canvas: true, pixelRatio: 2})).to.be.ok
       })
 
       it('Scale down with the given pixelRatio', function (done) {
         expect(loadImage(blobGIF, function (img) {
-          expect(img.width).to.be(80)
-          expect(img.height).to.be(60)
-          expect(img.style.width).to.be('40px')
-          expect(img.style.height).to.be('30px')
+          expect(img.width).to.equal(80)
+          expect(img.height).to.equal(60)
+          expect(img.style.width).to.equal('40px')
+          expect(img.style.height).to.equal('30px')
           done()
-        }, {maxWidth: 40, canvas: true, pixelRatio: 2})).to.be.ok()
+        }, {maxWidth: 40, canvas: true, pixelRatio: 2})).to.be.ok
       })
 
       it('Scale down with the given downsamplingRatio', function (done) {
         expect(loadImage(blobGIF, function (img) {
-          expect(img.width).to.be(20)
-          expect(img.height).to.be(15)
+          expect(img.width).to.equal(20)
+          expect(img.height).to.equal(15)
           done()
-        }, {maxWidth: 20, canvas: true, downsamplingRatio: 0.5})).to.be.ok()
+        }, {maxWidth: 20, canvas: true, downsamplingRatio: 0.5})).to.be.ok
       })
 
       it('Ignore max settings if image dimensions are smaller', function (done) {
         expect(loadImage(blobGIF, function (img) {
-          expect(img.width).to.be(80)
-          expect(img.height).to.be(60)
+          expect(img.width).to.equal(80)
+          expect(img.height).to.equal(60)
           done()
-        }, {maxWidth: 160, maxHeight: 120})).to.be.ok()
+        }, {maxWidth: 160, maxHeight: 120})).to.be.ok
       })
 
       it('Ignore min settings if image dimensions are larger', function (done) {
         expect(loadImage(blobGIF, function (img) {
-          expect(img.width).to.be(80)
-          expect(img.height).to.be(60)
+          expect(img.width).to.equal(80)
+          expect(img.height).to.equal(60)
           done()
-        }, {minWidth: 40, minHeight: 30})).to.be.ok()
+        }, {minWidth: 40, minHeight: 30})).to.be.ok
       })
     })
 
     describe('contain', function () {
       it('Scale up to contain image in max dimensions', function (done) {
         expect(loadImage(blobGIF, function (img) {
-          expect(img.width).to.be(160)
-          expect(img.height).to.be(120)
+          expect(img.width).to.equal(160)
+          expect(img.height).to.equal(120)
           done()
-        }, {maxWidth: 160, maxHeight: 160, contain: true})).to.be.ok()
+        }, {maxWidth: 160, maxHeight: 160, contain: true})).to.be.ok
       })
 
       it('Scale down to contain image in max dimensions', function (done) {
         expect(loadImage(blobGIF, function (img) {
-          expect(img.width).to.be(40)
-          expect(img.height).to.be(30)
+          expect(img.width).to.equal(40)
+          expect(img.height).to.equal(30)
           done()
-        }, {maxWidth: 40, maxHeight: 40, contain: true})).to.be.ok()
+        }, {maxWidth: 40, maxHeight: 40, contain: true})).to.be.ok
       })
     })
 
     describe('cover', function () {
       it('Scale up to cover max dimensions with image dimensions', function (done) {
         expect(loadImage(blobGIF, function (img) {
-          expect(img.width).to.be(160)
-          expect(img.height).to.be(120)
+          expect(img.width).to.equal(160)
+          expect(img.height).to.equal(120)
           done()
-        }, {maxWidth: 120, maxHeight: 120, cover: true})).to.be.ok()
+        }, {maxWidth: 120, maxHeight: 120, cover: true})).to.be.ok
       })
 
       it('Scale down to cover max dimensions with image dimensions', function (done) {
         expect(loadImage(blobGIF, function (img) {
-          expect(img.width).to.be(40)
-          expect(img.height).to.be(30)
+          expect(img.width).to.equal(40)
+          expect(img.height).to.equal(30)
           done()
-        }, {maxWidth: 30, maxHeight: 30, cover: true})).to.be.ok()
+        }, {maxWidth: 30, maxHeight: 30, cover: true})).to.be.ok
       })
     })
   })
@@ -263,208 +263,219 @@
   describe('Cropping', function () {
     it('Crop to same values for maxWidth and maxHeight', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.width).to.be(40)
-        expect(img.height).to.be(40)
+        expect(img.width).to.equal(40)
+        expect(img.height).to.equal(40)
         done()
-      }, {maxWidth: 40, maxHeight: 40, crop: true})).to.be.ok()
+      }, {maxWidth: 40, maxHeight: 40, crop: true})).to.be.ok
     })
 
     it('Crop to different values for maxWidth and maxHeight', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.width).to.be(40)
-        expect(img.height).to.be(60)
+        expect(img.width).to.equal(40)
+        expect(img.height).to.equal(60)
         done()
-      }, {maxWidth: 40, maxHeight: 60, crop: true})).to.be.ok()
+      }, {maxWidth: 40, maxHeight: 60, crop: true})).to.be.ok
     })
 
     it('Crop using the given sourceWidth and sourceHeight dimensions', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.width).to.be(40)
-        expect(img.height).to.be(40)
+        expect(img.width).to.equal(40)
+        expect(img.height).to.equal(40)
         done()
-      }, {sourceWidth: 40, sourceHeight: 40, crop: true})).to.be.ok()
+      }, {sourceWidth: 40, sourceHeight: 40, crop: true})).to.be.ok
     })
 
     it('Crop using the given left and top coordinates', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.width).to.be(40)
-        expect(img.height).to.be(20)
+        expect(img.width).to.equal(40)
+        expect(img.height).to.equal(20)
         done()
-      }, {left: 40, top: 40, crop: true})).to.be.ok()
+      }, {left: 40, top: 40, crop: true})).to.be.ok
     })
 
     it('Crop using the given right and bottom coordinates', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.width).to.be(40)
-        expect(img.height).to.be(20)
+        expect(img.width).to.equal(40)
+        expect(img.height).to.equal(20)
         done()
-      }, {right: 40, bottom: 40, crop: true})).to.be.ok()
+      }, {right: 40, bottom: 40, crop: true})).to.be.ok
     })
 
     it('Crop using the given 2:1 aspectRatio', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.width).to.be(80)
-        expect(img.height).to.be(40)
+        expect(img.width).to.equal(80)
+        expect(img.height).to.equal(40)
         done()
-      }, {aspectRatio: 2})).to.be.ok()
+      }, {aspectRatio: 2})).to.be.ok
     })
 
     it('Crop using the given 2:3 aspectRatio', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.width).to.be(40)
-        expect(img.height).to.be(60)
+        expect(img.width).to.equal(40)
+        expect(img.height).to.equal(60)
         done()
-      }, {aspectRatio: 2 / 3})).to.be.ok()
+      }, {aspectRatio: 2 / 3})).to.be.ok
     })
 
     it('Crop using maxWidth/maxHeight with the given pixelRatio', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.width).to.be(80)
-        expect(img.height).to.be(80)
-        expect(img.style.width).to.be('40px')
-        expect(img.style.height).to.be('40px')
+        expect(img.width).to.equal(80)
+        expect(img.height).to.equal(80)
+        expect(img.style.width).to.equal('40px')
+        expect(img.style.height).to.equal('40px')
         done()
-      }, {maxWidth: 40, maxHeight: 40, crop: true, pixelRatio: 2})).to.be.ok()
+      }, {maxWidth: 40, maxHeight: 40, crop: true, pixelRatio: 2})).to.be.ok
     })
 
     it('Crop using sourceWidth/sourceHeight with the given pixelRatio', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.width).to.be(80)
-        expect(img.height).to.be(80)
-        expect(img.style.width).to.be('40px')
-        expect(img.style.height).to.be('40px')
+        expect(img.width).to.equal(80)
+        expect(img.height).to.equal(80)
+        expect(img.style.width).to.equal('40px')
+        expect(img.style.height).to.equal('40px')
         done()
-      }, {sourceWidth: 40, sourceHeight: 40, crop: true, pixelRatio: 2})).to.be.ok()
+      }, {sourceWidth: 40, sourceHeight: 40, crop: true, pixelRatio: 2})).to.be.ok
     })
   })
 
   describe('Orientation', function () {
     it('Should keep the orientation', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.width).to.be(80)
-        expect(img.height).to.be(60)
+        expect(img.width).to.equal(80)
+        expect(img.height).to.equal(60)
         done()
-      }, {orientation: 1})).to.be.ok()
+      }, {orientation: 1})).to.be.ok
     })
 
     it('Should rotate left', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.width).to.be(60)
-        expect(img.height).to.be(80)
+        expect(img.width).to.equal(60)
+        expect(img.height).to.equal(80)
         done()
-      }, {orientation: 8})).to.be.ok()
+      }, {orientation: 8})).to.be.ok
     })
 
     it('Should rotate right', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.width).to.be(60)
-        expect(img.height).to.be(80)
+        expect(img.width).to.equal(60)
+        expect(img.height).to.equal(80)
         done()
-      }, {orientation: 6})).to.be.ok()
+      }, {orientation: 6})).to.be.ok
     })
 
     it('Should adjust constraints to new coordinates', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.width).to.be(60)
-        expect(img.height).to.be(80)
+        expect(img.width).to.equal(60)
+        expect(img.height).to.equal(80)
         done()
-      }, {orientation: 6, maxWidth: 60, maxHeight: 80})).to.be.ok()
+      }, {orientation: 6, maxWidth: 60, maxHeight: 80})).to.be.ok
     })
 
     it('Should adjust left and top to new coordinates', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.width).to.be(30)
-        expect(img.height).to.be(60)
+        expect(img.width).to.equal(30)
+        expect(img.height).to.equal(60)
         done()
-      }, {orientation: 5, left: 30, top: 20})).to.be.ok()
+      }, {orientation: 5, left: 30, top: 20})).to.be.ok
     })
 
     it('Should adjust right and bottom to new coordinates', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.width).to.be(30)
-        expect(img.height).to.be(60)
+        expect(img.width).to.equal(30)
+        expect(img.height).to.equal(60)
         done()
-      }, {orientation: 5, right: 30, bottom: 20})).to.be.ok()
+      }, {orientation: 5, right: 30, bottom: 20})).to.be.ok
     })
 
     it('Should adjust left and bottom to new coordinates', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.width).to.be(30)
-        expect(img.height).to.be(60)
+        expect(img.width).to.equal(30)
+        expect(img.height).to.equal(60)
         done()
-      }, {orientation: 7, left: 30, bottom: 20})).to.be.ok()
+      }, {orientation: 7, left: 30, bottom: 20})).to.be.ok
     })
 
     it('Should adjust right and top to new coordinates', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.width).to.be(30)
-        expect(img.height).to.be(60)
+        expect(img.width).to.equal(30)
+        expect(img.height).to.equal(60)
         done()
-      }, {orientation: 7, right: 30, top: 20})).to.be.ok()
+      }, {orientation: 7, right: 30, top: 20})).to.be.ok
     })
 
     it('Should rotate left with the given pixelRatio', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.width).to.be(120)
-        expect(img.height).to.be(160)
-        expect(img.style.width).to.be('60px')
-        expect(img.style.height).to.be('80px')
+        expect(img.width).to.equal(120)
+        expect(img.height).to.equal(160)
+        expect(img.style.width).to.equal('60px')
+        expect(img.style.height).to.equal('80px')
         done()
-      }, {orientation: 8, pixelRatio: 2})).to.be.ok()
+      }, {orientation: 8, pixelRatio: 2})).to.be.ok
     })
 
     it('Should rotate right with the given pixelRatio', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.width).to.be(120)
-        expect(img.height).to.be(160)
-        expect(img.style.width).to.be('60px')
-        expect(img.style.height).to.be('80px')
+        expect(img.width).to.equal(120)
+        expect(img.height).to.equal(160)
+        expect(img.style.width).to.equal('60px')
+        expect(img.style.height).to.equal('80px')
         done()
-      }, {orientation: 6, pixelRatio: 2})).to.be.ok()
+      }, {orientation: 6, pixelRatio: 2})).to.be.ok
     })
 
     it('Should ignore too small orientation value', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.width).to.be(80)
-        expect(img.height).to.be(60)
+        expect(img.width).to.equal(80)
+        expect(img.height).to.equal(60)
         done()
-      }, {orientation: -1})).to.be.ok()
+      }, {orientation: -1})).to.be.ok
     })
 
     it('Should ignore too large orientation value', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.width).to.be(80)
-        expect(img.height).to.be(60)
+        expect(img.width).to.equal(80)
+        expect(img.height).to.equal(60)
         done()
-      }, {orientation: 9})).to.be.ok()
+      }, {orientation: 9})).to.be.ok
+    })
+
+    it('Should rotate right based on the exif orientation value', function (done) {
+      expect(loadImage(blobJPEG, function (img, data) {
+        expect(data).to.be.ok
+        expect(data.exif).to.be.ok
+        expect(data.exif.get('Orientation')).to.equal(6)
+        expect(img.width).to.equal(1)
+        expect(img.height).to.equal(2)
+        done()
+      }, {orientation: true})).to.be.ok
     })
   })
 
   describe('Canvas', function () {
     it('Return img element to callback if canvas is not true', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.getContext).to.not.be.ok()
-        expect(img.nodeName.toLowerCase()).to.be('img')
+        expect(img.getContext).to.not.be.ok
+        expect(img.nodeName.toLowerCase()).to.equal('img')
         done()
-      })).to.be.ok()
+      })).to.be.ok
     })
 
     it('Return canvas element to callback if canvas is true', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.getContext).to.be.ok()
-        expect(img.nodeName.toLowerCase()).to.be('canvas')
+        expect(img.getContext).to.be.ok
+        expect(img.nodeName.toLowerCase()).to.equal('canvas')
         done()
-      }, {canvas: true})).to.be.ok()
+      }, {canvas: true})).to.be.ok
     })
 
     it('Return scaled canvas element to callback', function (done) {
       expect(loadImage(blobGIF, function (img) {
-        expect(img.getContext).to.be.ok()
-        expect(img.nodeName.toLowerCase()).to.be('canvas')
-        expect(img.width).to.be(40)
-        expect(img.height).to.be(30)
+        expect(img.getContext).to.be.ok
+        expect(img.nodeName.toLowerCase()).to.equal('canvas')
+        expect(img.width).to.equal(40)
+        expect(img.height).to.equal(30)
         done()
-      }, {canvas: true, maxWidth: 40})).to.be.ok()
+      }, {canvas: true, maxWidth: 40})).to.be.ok
     })
 
     it('Accept a canvas element as parameter for loadImage.scale', function (done) {
@@ -472,39 +483,49 @@
         img = loadImage.scale(img, {
           maxWidth: 40
         })
-        expect(img.getContext).to.be.ok()
-        expect(img.nodeName.toLowerCase()).to.be('canvas')
-        expect(img.width).to.be(40)
-        expect(img.height).to.be(30)
+        expect(img.getContext).to.be.ok
+        expect(img.nodeName.toLowerCase()).to.equal('canvas')
+        expect(img.width).to.equal(40)
+        expect(img.height).to.equal(30)
         done()
-      }, {canvas: true})).to.be.ok()
+      }, {canvas: true})).to.be.ok
     })
   })
 
   describe('Metadata', function () {
     it('Should parse Exif information', function (done) {
       loadImage.parseMetaData(blobJPEG, function (data) {
-        expect(data.exif).to.be.ok()
-        expect(data.exif.get('Orientation')).to.be(6)
+        expect(data.exif).to.be.ok
+        expect(data.exif.get('Orientation')).to.equal(6)
         done()
       })
     })
 
     it('Should parse the complete image head', function (done) {
       loadImage.parseMetaData(blobJPEG, function (data) {
-        expect(data.imageHead).to.be.ok()
+        expect(data.imageHead).to.be.ok
         loadImage.parseMetaData(
           createBlob(data.imageHead, 'image/jpeg'),
           function (data) {
-            expect(data.exif).to.be.ok()
-            expect(data.exif.get('Orientation')).to.be(6)
+            expect(data.exif).to.be.ok
+            expect(data.exif.get('Orientation')).to.equal(6)
             done()
           }
         )
       })
     })
+
+    it('Should parse meta data automatically', function (done) {
+      expect(loadImage(blobJPEG, function (img, data) {
+        expect(data).to.be.ok
+        expect(data.imageHead).to.be.ok
+        expect(data.exif).to.be.ok
+        expect(data.exif.get('Orientation')).to.equal(6)
+        done()
+      }, {meta: true})).to.be.ok
+    })
   })
 }(
-  this.expect,
+  this.chai.expect,
   this.loadImage
 ))

+ 4 - 4
app/Resources/public/assets/blueimp-tmpl/.bower.json

@@ -1,12 +1,12 @@
 {
   "name": "blueimp-tmpl",
   "homepage": "https://github.com/blueimp/JavaScript-Templates",
-  "version": "3.4.0",
-  "_release": "3.4.0",
+  "version": "3.5.0",
+  "_release": "3.5.0",
   "_resolution": {
     "type": "version",
-    "tag": "v3.4.0",
-    "commit": "dcb7a7b44c733c5df0b6000e777bc6942646607e"
+    "tag": "v3.5.0",
+    "commit": "19dfc68580d036de22f1767ef8fde1a6da75b64b"
   },
   "_source": "https://github.com/blueimp/JavaScript-Templates.git",
   "_target": ">=2.5.4",

+ 0 - 2
app/Resources/public/assets/blueimp-tmpl/js/compile.js

@@ -10,8 +10,6 @@
  * http://www.opensource.org/licenses/MIT
  */
 
-/*global require, __dirname, process, console */
-
 ;(function () {
   'use strict'
   var path = require('path')

+ 1 - 1
app/Resources/public/assets/blueimp-tmpl/js/demo.js

@@ -9,7 +9,7 @@
  * http://www.opensource.org/licenses/MIT
  */
 
-/* global document, tmpl */
+/* global tmpl */
 
 ;(function () {
   'use strict'

+ 2 - 2
app/Resources/public/assets/blueimp-tmpl/js/runtime.js

@@ -9,7 +9,7 @@
  * http://www.opensource.org/licenses/MIT
  */
 
-/*global define, module */
+/* global define */
 
 ;(function ($) {
   'use strict'
@@ -20,7 +20,7 @@
     }
   }
   tmpl.cache = {}
-  tmpl.encReg = /[<>&"'\x00]/g
+  tmpl.encReg = /[<>&"'\x00]/g // eslint-disable-line no-control-regex
   tmpl.encMap = {
     '<': '&lt;',
     '>': '&gt;',

+ 2 - 2
app/Resources/public/assets/blueimp-tmpl/js/tmpl.js

@@ -12,7 +12,7 @@
  * http://ejohn.org/blog/javascript-micro-templating/
  */
 
-/*global document, define, module */
+/* global define */
 
 ;(function ($) {
   'use strict'
@@ -55,7 +55,7 @@
       return "_s+='"
     }
   }
-  tmpl.encReg = /[<>&"'\x00]/g
+  tmpl.encReg = /[<>&"'\x00]/g // eslint-disable-line no-control-regex
   tmpl.encMap = {
     '<': '&lt;',
     '>': '&gt;',

+ 1 - 1
app/Resources/public/assets/blueimp-tmpl/js/tmpl.min.js

@@ -1,2 +1,2 @@
-!function(e){"use strict";var n=function(e,t){var r=/[^\w\-\.:]/.test(e)?new Function(n.arg+",tmpl","var _e=tmpl.encode"+n.helper+",_s='"+e.replace(n.regexp,n.func)+"';return _s;"):n.cache[e]=n.cache[e]||n(n.load(e));return t?r(t,n):function(e){return r(e,n)}};n.cache={},n.load=function(e){return document.getElementById(e).innerHTML},n.regexp=/([\s'\\])(?!(?:[^{]|\{(?!%))*%\})|(?:\{%(=|#)([\s\S]+?)%\})|(\{%)|(%\})/g,n.func=function(e,n,t,r,c,u){return n?{"\n":"\\n","\r":"\\r","	":"\\t"," ":" "}[n]||"\\"+n:t?"="===t?"'+_e("+r+")+'":"'+("+r+"==null?'':"+r+")+'":c?"';":u?"_s+='":void 0},n.encReg=/[<>&"'\x00]/g,n.encMap={"<":"&lt;",">":"&gt;","&":"&amp;",'"':"&quot;","'":"&#39;"},n.encode=function(e){return(null==e?"":""+e).replace(n.encReg,function(e){return n.encMap[e]||""})},n.arg="o",n.helper=",print=function(s,e){_s+=e?(s==null?'':s):_e(s);},include=function(s,d){_s+=tmpl(s,d);}","function"==typeof define&&define.amd?define(function(){return n}):"object"==typeof module&&module.exports?module.exports=n:e.tmpl=n}(this);
+!function(e){"use strict";var n=function(e,t){var r=/[^\w\-\.:]/.test(e)?new Function(n.arg+",tmpl","var _e=tmpl.encode"+n.helper+",_s='"+e.replace(n.regexp,n.func)+"';return _s;"):n.cache[e]=n.cache[e]||n(n.load(e));return t?r(t,n):function(e){return r(e,n)}};n.cache={},n.load=function(e){return document.getElementById(e).innerHTML},n.regexp=/([\s'\\])(?!(?:[^{]|\{(?!%))*%\})|(?:\{%(=|#)([\s\S]+?)%\})|(\{%)|(%\})/g,n.func=function(e,n,t,r,c,u){return n?{"\n":"\\n","\r":"\\r","\t":"\\t"," ":" "}[n]||"\\"+n:t?"="===t?"'+_e("+r+")+'":"'+("+r+"==null?'':"+r+")+'":c?"';":u?"_s+='":void 0},n.encReg=/[<>&"'\x00]/g,n.encMap={"<":"&lt;",">":"&gt;","&":"&amp;",'"':"&quot;","'":"&#39;"},n.encode=function(e){return(null==e?"":""+e).replace(n.encReg,function(e){return n.encMap[e]||""})},n.arg="o",n.helper=",print=function(s,e){_s+=e?(s==null?'':s):_e(s);},include=function(s,d){_s+=tmpl(s,d);}","function"==typeof define&&define.amd?define(function(){return n}):"object"==typeof module&&module.exports?module.exports=n:e.tmpl=n}(this);
 //# sourceMappingURL=tmpl.min.js.map

+ 1 - 1
app/Resources/public/assets/blueimp-tmpl/js/tmpl.min.js.map

@@ -1 +1 @@
-{"version":3,"sources":["tmpl.js"],"names":["$","tmpl","str","data","f","test","Function","arg","helper","replace","regexp","func","cache","load","id","document","getElementById","innerHTML","s","p1","p2","p3","p4","p5","\n","\r","\t"," ","encReg","encMap","<",">","&","\"","'","encode","c","define","amd","module","exports","this"],"mappings":"CAgBE,SAAUA,GACV,YACA,IAAIC,GAAO,SAAUC,EAAKC,GACxB,GAAIC,GAAK,aAAaC,KAAKH,GAEvB,GAAII,UACJL,EAAKM,IAAM,QACX,qBAAuBN,EAAKO,OAAS,QACnCN,EAAIO,QAAQR,EAAKS,OAAQT,EAAKU,MAAQ,gBAJxCV,EAAKW,MAAMV,GAAOD,EAAKW,MAAMV,IAAQD,EAAKA,EAAKY,KAAKX,GAMxD,OAAOC,GAAOC,EAAED,EAAMF,GAAQ,SAAUE,GACtC,MAAOC,GAAED,EAAMF,IAGnBA,GAAKW,SACLX,EAAKY,KAAO,SAAUC,GACpB,MAAOC,UAASC,eAAeF,GAAIG,WAErChB,EAAKS,OAAS,2EACdT,EAAKU,KAAO,SAAUO,EAAGC,EAAIC,EAAIC,EAAIC,EAAIC,GACvC,MAAIJ,IAEAK,KAAM,MACNC,KAAM,MACNC,IAAM,MACNC,IAAK,KACLR,IAAO,KAAOA,EAEdC,EACS,MAAPA,EACK,QAAUC,EAAK,MAEjB,MAAQA,EAAK,aAAeA,EAAK,MAEtCC,EACK,KAELC,EACK,QADT,QAIFtB,EAAK2B,OAAS,eACd3B,EAAK4B,QACHC,IAAK,OACLC,IAAK,OACLC,IAAK,QACLC,IAAK,SACLC,IAAK,SAEPjC,EAAKkC,OAAS,SAAUjB,GACtB,OAAa,MAALA,EAAY,GAAK,GAAKA,GAAGT,QAC/BR,EAAK2B,OACL,SAAUQ,GACR,MAAOnC,GAAK4B,OAAOO,IAAM,MAI/BnC,EAAKM,IAAM,IACXN,EAAKO,OAAS,0FAEQ,kBAAX6B,SAAyBA,OAAOC,IACzCD,OAAO,WACL,MAAOpC,KAEkB,gBAAXsC,SAAuBA,OAAOC,QAC9CD,OAAOC,QAAUvC,EAEjBD,EAAEC,KAAOA,GAEXwC","file":"tmpl.min.js"}
+{"version":3,"sources":["tmpl.js"],"names":["$","tmpl","str","data","f","test","Function","arg","helper","replace","regexp","func","cache","load","id","document","getElementById","innerHTML","s","p1","p2","p3","p4","p5","\n","\r","\t"," ","encReg","encMap","<",">","&","\"","'","encode","c","define","amd","module","exports","this"],"mappings":"CAgBE,SAAUA,GACV,YACA,IAAIC,GAAO,SAAUC,EAAKC,GACxB,GAAIC,GAAK,aAAaC,KAAKH,GAEvB,GAAII,UACJL,EAAKM,IAAM,QACX,qBAAuBN,EAAKO,OAAS,QACnCN,EAAIO,QAAQR,EAAKS,OAAQT,EAAKU,MAAQ,gBAJxCV,EAAKW,MAAMV,GAAOD,EAAKW,MAAMV,IAAQD,EAAKA,EAAKY,KAAKX,GAMxD,OAAOC,GAAOC,EAAED,EAAMF,GAAQ,SAAUE,GACtC,MAAOC,GAAED,EAAMF,IAGnBA,GAAKW,SACLX,EAAKY,KAAO,SAAUC,GACpB,MAAOC,UAASC,eAAeF,GAAIG,WAErChB,EAAKS,OAAS,2EACdT,EAAKU,KAAO,SAAUO,EAAGC,EAAIC,EAAIC,EAAIC,EAAIC,GACvC,MAAIJ,IAEAK,KAAM,MACNC,KAAM,MACNC,KAAM,MACNC,IAAK,KACLR,IAAO,KAAOA,EAEdC,EACS,MAAPA,EACK,QAAUC,EAAK,MAEjB,MAAQA,EAAK,aAAeA,EAAK,MAEtCC,EACK,KAELC,EACK,QADT,QAIFtB,EAAK2B,OAAS,eACd3B,EAAK4B,QACHC,IAAK,OACLC,IAAK,OACLC,IAAK,QACLC,IAAK,SACLC,IAAK,SAEPjC,EAAKkC,OAAS,SAAUjB,GACtB,OAAa,MAALA,EAAY,GAAK,GAAKA,GAAGT,QAC/BR,EAAK2B,OACL,SAAUQ,GACR,MAAOnC,GAAK4B,OAAOO,IAAM,MAI/BnC,EAAKM,IAAM,IACXN,EAAKO,OAAS,0FAEQ,kBAAX6B,SAAyBA,OAAOC,IACzCD,OAAO,WACL,MAAOpC,KAEkB,gBAAXsC,SAAuBA,OAAOC,QAC9CD,OAAOC,QAAUvC,EAEjBD,EAAEC,KAAOA,GAEXwC","file":"tmpl.min.js"}

+ 8 - 6
app/Resources/public/assets/blueimp-tmpl/package.json

@@ -1,6 +1,6 @@
 {
   "name": "blueimp-tmpl",
-  "version": "3.4.0",
+  "version": "3.5.0",
   "title": "JavaScript Templates",
   "description": "1KB lightweight, fast & powerful JavaScript templating engine with zero dependencies. Compatible with server-side environments like Node.js, module loaders like RequireJS, Browserify or webpack and all web browsers.",
   "keywords": [
@@ -19,13 +19,15 @@
   },
   "license": "MIT",
   "devDependencies": {
-    "expect.js": "0.3.1",
-    "mocha": "2.3.4",
-    "standard": "6.0.7",
-    "uglify-js": "2.6.1"
+    "chai": "3.5.0",
+    "mocha": "3.1.0",
+    "standard": "8.3.0",
+    "uglify-js": "2.7.3"
   },
   "scripts": {
-    "test": "standard js/*.js test/*.js && mocha",
+    "lint": "standard js/*.js test/*.js",
+    "unit": "mocha",
+    "test": "npm run lint && npm run unit",
     "build": "cd js && uglifyjs tmpl.js -c -m -o tmpl.min.js --source-map tmpl.min.js.map",
     "preversion": "npm test",
     "version": "npm run build && git add -A js",

+ 1 - 1
app/Resources/public/assets/blueimp-tmpl/test/index.html

@@ -24,7 +24,7 @@
 <body>
 <div id="mocha"></div>
 <script src="vendor/mocha.js"></script>
-<script src="vendor/expect.js"></script>
+<script src="vendor/chai.js"></script>
 <script>
 mocha.setup('bdd');
 </script>

+ 26 - 26
app/Resources/public/assets/blueimp-tmpl/test/test.js

@@ -9,7 +9,7 @@
  * http://www.opensource.org/licenses/MIT
  */
 
-/*global beforeEach, afterEach, describe, it, require */
+/* global beforeEach, afterEach, describe, it */
 
 ;(function (context, expect, tmpl) {
   'use strict'
@@ -53,7 +53,7 @@
     it('String template', function () {
       expect(
         tmpl('{%=o.value%}', data)
-      ).to.be(
+      ).to.equal(
         'value'
       )
     })
@@ -61,7 +61,7 @@
     it('Load template by id', function () {
       expect(
         tmpl('template', data)
-      ).to.be(
+      ).to.equal(
         'value'
       )
     })
@@ -69,7 +69,7 @@
     it('Retun function when called without data parameter', function () {
       expect(
         tmpl('{%=o.value%}')(data)
-      ).to.be(
+      ).to.equal(
         'value'
       )
     })
@@ -86,7 +86,7 @@
     it('Escape HTML special characters with {%=o.prop%}', function () {
       expect(
         tmpl('{%=o.special%}', data)
-      ).to.be(
+      ).to.equal(
         '&lt;&gt;&amp;&quot;&#39;'
       )
     })
@@ -94,7 +94,7 @@
     it('Allow HTML special characters with {%#o.prop%}', function () {
       expect(
         tmpl('{%#o.special%}', data)
-      ).to.be(
+      ).to.equal(
         '<>&"\'\x00'
       )
     })
@@ -102,7 +102,7 @@
     it('Function call', function () {
       expect(
         tmpl('{%=o.func()%}', data)
-      ).to.be(
+      ).to.equal(
         'value'
       )
     })
@@ -110,7 +110,7 @@
     it('Dot notation', function () {
       expect(
         tmpl('{%=o.deep.value%}', data)
-      ).to.be(
+      ).to.equal(
         'value'
       )
     })
@@ -118,7 +118,7 @@
     it('Handle single quotes', function () {
       expect(
         tmpl('\'single quotes\'{%=": \'"%}', data)
-      ).to.be(
+      ).to.equal(
         "'single quotes': &#39;"
       )
     })
@@ -126,7 +126,7 @@
     it('Handle double quotes', function () {
       expect(
         tmpl('"double quotes"{%=": \\""%}', data)
-      ).to.be(
+      ).to.equal(
         '"double quotes": &quot;'
       )
     })
@@ -134,7 +134,7 @@
     it('Handle backslashes', function () {
       expect(
         tmpl('\\backslashes\\{%=": \\\\"%}', data)
-      ).to.be(
+      ).to.equal(
         '\\backslashes\\: \\'
       )
     })
@@ -148,7 +148,7 @@
           '{%=o.zeroValue%}',
           data
         )
-      ).to.be(
+      ).to.equal(
         'false0'
       )
     })
@@ -162,7 +162,7 @@
           '{%#o.zeroValue%}',
           data
         )
-      ).to.be(
+      ).to.equal(
         'false0'
       )
     })
@@ -173,7 +173,7 @@
           '\n\r\t{%=o.value%}  \n\r\t{%=o.value%}  ',
           data
         )
-      ).to.be(
+      ).to.equal(
         '\n\r\tvalue  \n\r\tvalue  '
       )
     })
@@ -183,7 +183,7 @@
     it('Escape HTML special characters with print(data)', function () {
       expect(
         tmpl('{% print(o.special); %}', data)
-      ).to.be(
+      ).to.equal(
         '&lt;&gt;&amp;&quot;&#39;'
       )
     })
@@ -191,7 +191,7 @@
     it('Allow HTML special characters with print(data, true)', function () {
       expect(
         tmpl('{% print(o.special, true); %}', data)
-      ).to.be(
+      ).to.equal(
         '<>&"\'\x00'
       )
     })
@@ -205,7 +205,7 @@
           '{% print(o.zeroValue); %}',
           data
         )
-      ).to.be(
+      ).to.equal(
         'false0'
       )
     })
@@ -219,7 +219,7 @@
           '{% print(o.zeroValue, true); %}',
           data
         )
-      ).to.be(
+      ).to.equal(
         'false0'
       )
     })
@@ -227,7 +227,7 @@
     it('Include template', function () {
       expect(
         tmpl('{% include("template", {value: "value"}); %}', data)
-      ).to.be(
+      ).to.equal(
         'value'
       )
     })
@@ -235,7 +235,7 @@
     it('If condition', function () {
       expect(
         tmpl('{% if (o.value) { %}true{% } else { %}false{% } %}', data)
-      ).to.be(
+      ).to.equal(
         'true'
       )
     })
@@ -246,7 +246,7 @@
           '{% if (o.undefinedValue) { %}false{% } else { %}true{% } %}',
           data
         )
-      ).to.be(
+      ).to.equal(
         'true'
       )
     })
@@ -258,7 +258,7 @@
           '{%=o.list[i]%}{% } %}',
           data
         )
-      ).to.be(
+      ).to.equal(
         '12345'
       )
     })
@@ -270,7 +270,7 @@
           'print(o.list[i]);} %}',
           data
         )
-      ).to.be(
+      ).to.equal(
         '12345'
       )
     })
@@ -282,7 +282,7 @@
           'include("template", {value: o.list[i]});} %}',
           data
         ).replace(/[\r\n]/g, '')
-      ).to.be(
+      ).to.equal(
         '12345'
       )
     })
@@ -293,13 +293,13 @@
           '{% if (o.list.length % 5 === 0) { %}5 list items{% } %}',
           data
         ).replace(/[\r\n]/g, '')
-      ).to.be(
+      ).to.equal(
         '5 list items'
       )
     })
   })
 }(
   this,
-  this.expect || require('expect.js'),
+  (this.chai || require('chai')).expect,
   this.tmpl || require('../js/tmpl')
 ))

+ 1 - 1
app/Resources/public/assets/bootstrap-daterangepicker/.bower.json

@@ -25,7 +25,7 @@
     "tag": "v1.3.23",
     "commit": "f000ab2a40a0e930c2913855b96a4e4d59c8920f"
   },
-  "_source": "git://github.com/dangrossman/bootstrap-daterangepicker.git",
+  "_source": "https://github.com/dangrossman/bootstrap-daterangepicker.git",
   "_target": "1.3.*",
   "_originalSource": "bootstrap-daterangepicker"
 }

+ 1 - 1
app/Resources/public/assets/ckeditor/.bower.json

@@ -21,7 +21,7 @@
   "_resolution": {
     "type": "version",
     "tag": "4.5.9",
-    "commit": "ba2580967f7409784921b4320e297522175e45bb"
+    "commit": "5de42515a5ca7015de75627ad8067f786d7fc425"
   },
   "_source": "https://github.com/AngelFQC/ckeditor-releases.git",
   "_target": "*",

+ 1 - 1
app/Resources/public/assets/cropper/.bower.json

@@ -57,7 +57,7 @@
     "tag": "v1.0.0",
     "commit": "c0805bc83c9270a0be4afdfbd02d517de7a4c970"
   },
-  "_source": "git://github.com/fengyuanchen/cropper.git",
+  "_source": "https://github.com/fengyuanchen/cropper.git",
   "_target": "1.0.*",
   "_originalSource": "cropper"
 }

+ 1 - 1
app/Resources/public/assets/fontawesome/.bower.json

@@ -30,7 +30,7 @@
     "tag": "v4.4.0",
     "commit": "f2cc73da12f0e6d828bc2daaa72bff457067bf39"
   },
-  "_source": "git://github.com/FortAwesome/Font-Awesome.git",
+  "_source": "https://github.com/FortAwesome/Font-Awesome.git",
   "_target": "4.4.*",
   "_originalSource": "fontawesome"
 }

+ 1 - 1
app/Resources/public/assets/fullcalendar/.bower.json

@@ -56,7 +56,7 @@
     "tag": "v2.3.2",
     "commit": "29fb42d6316bd2c293fbcaf699af4427f80abebb"
   },
-  "_source": "git://github.com/arshaw/fullcalendar.git",
+  "_source": "https://github.com/fullcalendar/fullcalendar.git",
   "_target": "2.3.2",
   "_originalSource": "fullcalendar"
 }

+ 1 - 1
app/Resources/public/assets/image-map-resizer/.bower.json

@@ -40,7 +40,7 @@
     "tag": "v0.5.4",
     "commit": "eef318b0892b5ecec2c95a9c2f7f06c420978cbe"
   },
-  "_source": "git://github.com/davidjbradshaw/image-map-resizer.git",
+  "_source": "https://github.com/davidjbradshaw/image-map-resizer.git",
   "_target": "0.5.*",
   "_originalSource": "image-map-resizer"
 }

+ 1 - 1
app/Resources/public/assets/jquery-timeago/.bower.json

@@ -17,7 +17,7 @@
     "tag": "v1.4.3",
     "commit": "5293dacee881e78b25bd4f699161fca81dff5205"
   },
-  "_source": "git://github.com/rmm5t/jquery-timeago.git",
+  "_source": "https://github.com/rmm5t/jquery-timeago.git",
   "_target": "1.4.*",
   "_originalSource": "jquery-timeago"
 }

+ 1 - 1
app/Resources/public/assets/jquery-ui/.bower.json

@@ -15,7 +15,7 @@
     "tag": "1.11.4",
     "commit": "c34f8dbf3ba57b3784b93f26119f436c0e8288e1"
   },
-  "_source": "git://github.com/components/jqueryui.git",
+  "_source": "https://github.com/components/jqueryui.git",
   "_target": "1.11.*",
   "_originalSource": "jquery-ui"
 }

+ 1 - 1
app/Resources/public/assets/jquery.scrollbar/.bower.json

@@ -21,7 +21,7 @@
     "tag": "0.2.10",
     "commit": "058c143d6623f8d39cd45becc1205b9aee325246"
   },
-  "_source": "git://github.com/gromo/jquery.scrollbar.git",
+  "_source": "https://github.com/gromo/jquery.scrollbar.git",
   "_target": "0.2.*",
   "_originalSource": "jquery.scrollbar"
 }

+ 1 - 1
app/Resources/public/assets/jqueryui-timepicker-addon/.bower.json

@@ -17,7 +17,7 @@
     "tag": "v1.5.5",
     "commit": "8498e17dc6c4b5aa21f3a2bbe8c20f3a461c3211"
   },
-  "_source": "git://github.com/trentrichardson/jQuery-Timepicker-Addon.git",
+  "_source": "https://github.com/trentrichardson/jQuery-Timepicker-Addon.git",
   "_target": "1.5.*",
   "_originalSource": "jqueryui-timepicker-addon"
 }

+ 1 - 1
app/Resources/public/assets/modernizr/.bower.json

@@ -8,7 +8,7 @@
     "tag": "v2.8.3",
     "commit": "d6bb30c0f12ebb3ddd01e90b0bf435e1c34e6f11"
   },
-  "_source": "git://github.com/Modernizr/Modernizr.git",
+  "_source": "https://github.com/Modernizr/Modernizr.git",
   "_target": "2.8.*",
   "_originalSource": "modernizr"
 }

+ 1 - 1
app/Resources/public/assets/moment/.bower.json

@@ -24,7 +24,7 @@
     "tag": "2.9.0",
     "commit": "8b35bc74c0e88c1a8c58ccb90117a9edc9f6a479"
   },
-  "_source": "git://github.com/moment/moment.git",
+  "_source": "https://github.com/moment/moment.git",
   "_target": "~2.9.0",
   "_originalSource": "moment"
 }

+ 1 - 1
app/Resources/public/assets/simpleWebRTC/.bower.json

@@ -8,7 +8,7 @@
     "tag": "v1.15.4",
     "commit": "6f84fbcd42bd6ab1af8134ef0c495e8a6c3175f7"
   },
-  "_source": "git://github.com/HenrikJoreteg/SimpleWebRTC.git",
+  "_source": "https://github.com/HenrikJoreteg/SimpleWebRTC.git",
   "_target": "1.15.*",
   "_originalSource": "simpleWebRTC"
 }

+ 2 - 1
bower.json

@@ -28,7 +28,8 @@
     "jquery.scrollbar": "0.2.*",
     "jquery-file-upload": "*",
     "pwstrength-bootstrap": "*",
-    "readmore-js": "2.1.0"
+    "readmore-js": "2.1.0",
+    "qtip2": "*"
   },
   "resolutions": {
     "jquery": "2.1.4"

+ 5 - 0
main/admin/settings.php

@@ -1,6 +1,8 @@
 <?php
 /* For licensing terms, see /license.txt */
 
+use ChamiloSession as Session;
+
 /**
  * With this tool you can easily adjust non critical configuration settings.
  * Non critical means that changing them will not result in a broken campus.
@@ -236,6 +238,9 @@ if (!empty($_GET['category']) &&
 
         foreach ($settings as $item) {
             $key = $item['variable'];
+            if ($key === 'prevent_multiple_simultaneous_login') {
+                Session::write('first_user_login', 1);
+            }
             if (in_array($key, $settings_to_avoid)) {
                 continue;
             }

+ 2 - 2
main/admin/user_add.php

@@ -42,8 +42,8 @@ if ($checkPass == 'true') {
     });
     </script>';
 }
-$htmlHeadXtra[] = '<link  href="'. api_get_path(WEB_PATH) .'web/assets/cropper/dist/cropper.min.css" rel="stylesheet">';
-$htmlHeadXtra[] = '<script src="'. api_get_path(WEB_PATH) .'web/assets/cropper/dist/cropper.min.js"></script>';
+$htmlHeadXtra[] = api_get_css_asset('cropper/dist/cropper.min.css');
+$htmlHeadXtra[] = api_get_asset('cropper/dist/cropper.min.js');
 $htmlHeadXtra[] = '
 <script>
 $("#status_select").ready(function() {

+ 2 - 2
main/admin/user_edit.php

@@ -70,8 +70,8 @@ function confirmation(name) {
 
 $userGeolocalization = api_get_setting('enable_profile_user_address_geolocalization') == 'true';
 
-$htmlHeadXtra[] = '<link  href="'. api_get_path(WEB_PATH) .'web/assets/cropper/dist/cropper.min.css" rel="stylesheet">';
-$htmlHeadXtra[] = '<script src="'. api_get_path(WEB_PATH) .'web/assets/cropper/dist/cropper.min.js"></script>';
+$htmlHeadXtra[] = api_get_css_asset('cropper/dist/cropper.min.css');
+$htmlHeadXtra[] = api_get_asset('cropper/dist/cropper.min.js');
 $htmlHeadXtra[] = '<script type="text/javascript" src="//maps.googleapis.com/maps/api/js?sensor=true" ></script>';
 
 $libpath = api_get_path(LIBRARY_PATH);

+ 1 - 1
main/auth/inscription.php

@@ -554,7 +554,7 @@ if (api_get_setting('allow_terms_conditions') == 'true') {
     if (!api_is_platform_admin()) {
         if (api_get_setting('show_terms_if_profile_completed') === 'true') {
             $userInfo = api_get_user_info();
-            if ($userInfo) {
+            if ($userInfo && $userInfo['status'] != ANONYMOUS) {
                 if ((int)$userInfo['profile_completed'] !== 1) {
                     api_not_allowed(true);
                 }

+ 2 - 2
main/auth/profile.php

@@ -31,8 +31,8 @@ if (!(isset($_user['user_id']) && $_user['user_id']) || api_is_anonymous($_user[
 $userGeolocalization = api_get_setting('enable_profile_user_address_geolocalization') == 'true';
 
 $htmlHeadXtra[] = api_get_password_checker_js('#username', '#password1');
-$htmlHeadXtra[] = '<link  href="'. api_get_path(WEB_PATH) .'web/assets/cropper/dist/cropper.min.css" rel="stylesheet">';
-$htmlHeadXtra[] = '<script src="'. api_get_path(WEB_PATH) .'web/assets/cropper/dist/cropper.min.js"></script>';
+$htmlHeadXtra[] = api_get_css_asset('cropper/dist/cropper.min.css');
+$htmlHeadXtra[] = api_get_asset('cropper/dist/cropper.min.js');
 $htmlHeadXtra[] = '<script type="text/javascript" src="//maps.googleapis.com/maps/api/js?sensor=true" ></script>';
 $htmlHeadXtra[] = '<script>
 $(document).ready(function() {

+ 10 - 10
main/calendar/agenda_js.php

@@ -21,11 +21,12 @@ $current_course_tool = TOOL_CALENDAR_EVENT;
 $this_section = SECTION_MYAGENDA;
 
 $htmlHeadXtra[] = api_get_jquery_libraries_js(array('jquery-ui', 'jquery-ui-i18n'));
-$htmlHeadXtra[] = api_get_js('qtip2/jquery.qtip.min.js');
+
+$htmlHeadXtra[] = api_get_asset('qtip2/jquery.qtip.min.js');
 $htmlHeadXtra[] = api_get_asset('fullcalendar/dist/fullcalendar.min.js');
 $htmlHeadXtra[] = api_get_asset('fullcalendar/dist/gcal.js');
-$htmlHeadXtra[] = api_get_css(api_get_path(WEB_PATH).'web/assets/fullcalendar/dist/fullcalendar.min.css');
-$htmlHeadXtra[] = api_get_css(api_get_path(WEB_LIBRARY_PATH).'javascript/qtip2/jquery.qtip.min.css');
+$htmlHeadXtra[] = api_get_css_asset('fullcalendar/dist/fullcalendar.min.css');
+$htmlHeadXtra[] = api_get_css_asset('qtip2/jquery.qtip.min.css');
 
 if (api_is_platform_admin() && ($type == 'admin' || $type == 'platform')) {
     $type = 'admin';
@@ -111,7 +112,6 @@ switch ($type) {
         break;
 }
 
-
 //Setting translations
 $day_short = api_get_week_days_short();
 $days = api_get_week_days_long();
@@ -208,7 +208,7 @@ $form = new FormValidator(
     array('id' => 'add_event_form')
 );
 
-$form->addElement('html', '<span id="calendar_course_info"></span><div id="visible_to_input">');
+$form->addHtml('<span id="calendar_course_info"></span><div id="visible_to_input">');
 
 $sendTo = $agenda->parseAgendaFilter($userId);
 $addOnlyItemsInSendTo = true;
@@ -218,11 +218,11 @@ if ($sendTo['everyone']) {
 }
 
 $agenda->showToForm($form, $sendTo, array(), $addOnlyItemsInSendTo);
-$form->addElement('html', '</div>');
+$form->addHtml('</div>');
 
-$form->addElement('html', '<div id="visible_to_read_only" style="display: none">');
+$form->addHtml('<div id="visible_to_read_only" style="display: none">');
 $form->addElement('label', get_lang('To'), '<div id="visible_to_read_only_users"></div>');
-$form->addElement('html', '</div>');
+$form->addHtml('</div>');
 
 $form->addElement('label', get_lang('Agenda'), '<div id ="color_calendar"></div>');
 $form->addElement('label', get_lang('Date'), '<span id="start_date"></span><span id="end_date"></span>');
@@ -239,9 +239,9 @@ $form->addHtmlEditor(
 );
 
 if ($agenda->type === 'course') {
-    $form->addElement('html', '<div id="add_as_announcement_div" style="display: none">');
+    $form->addHtml('<div id="add_as_announcement_div" style="display: none">');
     $form->addElement('checkbox', 'add_as_annonuncement', null, get_lang('AddAsAnnouncement'));
-    $form->addElement('html', '</div>');
+    $form->addHtml('</div>');
     $form->addElement('textarea', 'comment', get_lang('Comment'), array('id' => 'comment'));
 }
 

+ 2 - 2
main/course_info/infocours.php

@@ -46,8 +46,8 @@ if (!$is_allowedToEdit) {
     api_not_allowed(true);
 }
 
-$htmlHeadXtra[] = '<link  href="'. api_get_path(WEB_PATH) .'web/assets/cropper/dist/cropper.min.css" rel="stylesheet">';
-$htmlHeadXtra[] = '<script src="'. api_get_path(WEB_PATH) .'web/assets/cropper/dist/cropper.min.js"></script>';
+$htmlHeadXtra[] = api_get_css_asset('cropper/dist/cropper.min.css');
+$htmlHeadXtra[] = api_get_asset('cropper/dist/cropper.min.js');
 $show_delete_watermark_text_message = false;
 if (api_get_setting('pdf_export_watermark_by_course') == 'true') {
     if (isset($_GET['delete_watermark'])) {

+ 21 - 12
main/document/document.php

@@ -200,9 +200,7 @@ if (!empty($groupId)) {
 }
 
 // Actions.
-
 $document_id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : null;
-
 $currentUrl = api_get_self().'?'.api_get_cidreq().'&id='.$document_id;
 
 if (Portfolio::controller()->accept()) {
@@ -875,7 +873,10 @@ if ($is_certificate_mode) {
 // Interbreadcrumb for the current directory root path
 if (empty($document_data['parents'])) {
     if (isset($_GET['createdir'])) {
-        $interbreadcrumb[] = array('url' => $document_data['document_url'], 'name' => $document_data['title']);
+        $interbreadcrumb[] = array(
+            'url' => $document_data['document_url'],
+            'name' => $document_data['title'],
+        );
     } else {
         $interbreadcrumb[] = array('url' => '#', 'name' => $document_data['title']);
     }
@@ -892,7 +893,10 @@ if (empty($document_data['parents'])) {
         if (!isset($_GET['createdir']) && $document_sub_data['id'] == $document_data['id']) {
             $document_sub_data['document_url'] = '#';
         }
-        $interbreadcrumb[] = array('url' => $document_sub_data['document_url'], 'name' => $document_sub_data['title']);
+        $interbreadcrumb[] = array(
+            'url' => $document_sub_data['document_url'],
+            'name' => $document_sub_data['title'],
+        );
         $counter++;
     }
 }
@@ -907,7 +911,6 @@ $htmlHeadXtra[] = '<link rel="stylesheet" href="'.$js_path.'jquery-jplayer/skin/
 $htmlHeadXtra[] = '<script type="text/javascript" src="'.$js_path.'jquery-jplayer/jplayer/jquery.jplayer.min.js"></script>';
 $mediaplayer_path = api_get_path(WEB_LIBRARY_PATH).'mediaplayer/player.swf';
 
-
 $documentAndFolders = DocumentManager::get_all_document_data(
     $courseInfo,
     $curdirpath,
@@ -980,7 +983,7 @@ if ($groupId != 0) { // Add group name after for group documents
     $add_group_to_title = ' ('.$group_properties['name'].')';
 }
 
-$moveForm = null;
+$moveForm = '';
 
 /* 	MOVE FILE OR DIRECTORY */
 //Only teacher and all users into their group and each user into his/her shared folder
@@ -1512,6 +1515,7 @@ if (isset($_GET['curdirpath']) &&
         );
     }
 }
+
 /* 	GET ALL DOCUMENT DATA FOR CURDIRPATH */
 if (isset($_GET['keyword']) && !empty($_GET['keyword'])) {
     $documentAndFolders = DocumentManager::get_all_document_data(
@@ -1559,7 +1563,6 @@ if (!isset($folders) || $folders === false) {
 }
 $btngroup = array('class' => 'btn btn-default');
 
-
 /* GO TO PARENT DIRECTORY */
 $actionsLeft = '';
 
@@ -1676,6 +1679,7 @@ if ($is_allowed_to_edit ||
         );
     }
 }
+
 require 'document_slideshow.inc.php';
 if ($image_present && !isset($_GET['keyword'])) {
     $actionsLeft .= Display::url(
@@ -1764,7 +1768,6 @@ if (isset($documentAndFolders) && is_array($documentAndFolders)) {
 
             // Show the owner of the file only in groups
             $user_link = '';
-
             if (!empty($groupId)) {
                 if (!empty($document_data['insert_user_id'])) {
                     $user_info = api_get_user_info($document_data['insert_user_id']);
@@ -1774,7 +1777,12 @@ if (isset($documentAndFolders) && is_array($documentAndFolders)) {
             }
 
             // Icons (clickable)
-            $row[] = DocumentManager::create_document_link($document_data, true, $count, $is_visible);
+            $row[] = DocumentManager::create_document_link(
+                $document_data,
+                true,
+                $count,
+                $is_visible
+            );
 
             $path_info = pathinfo($document_data['path']);
 
@@ -1811,9 +1819,11 @@ if (isset($documentAndFolders) && is_array($documentAndFolders)) {
             // Admins get an edit column
             if ($is_allowed_to_edit ||
                 $groupMemberWithEditRights ||
-                DocumentManager::is_my_shared_folder(api_get_user_id(), $curdirpath, $sessionId)
+                DocumentManager::is_my_shared_folder(api_get_user_id(), $curdirpath, $sessionId) ||
+                $document_data['insert_user_id'] == api_get_user_id()
             ) {
                 $is_template = isset($document_data['is_template']) ? $document_data['is_template'] : false;
+
                 // If readonly, check if it the owner of the file or if the user is an admin
                 if ($document_data['insert_user_id'] == api_get_user_id() || api_is_platform_admin()) {
                     $edit_icons = DocumentManager::build_edit_icons(
@@ -1887,7 +1897,6 @@ if (!is_null($documentAndFolders)) {
     }
 }
 
-
 if (api_is_platform_admin()) {
     if (api_get_configuration_value('document_manage_deleted_files')) {
         $actionsLeft .= Display::url(
@@ -1997,7 +2006,7 @@ if ($is_allowed_to_edit
 // TODO: Currently only delete action -> take only DELETE permission into account
 
 if (count($documentAndFolders) > 1) {
-    if ($is_allowed_to_edit || $group_member_with_upload_rights) {
+    if ($is_allowed_to_edit || $groupMemberWithEditRights) {
         $form_actions = array();
         $form_action['set_invisible'] = get_lang('SetInvisible');
         $form_action['set_visible'] = get_lang('SetVisible');

+ 5 - 6
main/exercise/exercise.class.php

@@ -134,7 +134,8 @@ class Exercise
 
             return false;
         }
-        $sql = "SELECT * FROM $TBL_EXERCISES WHERE c_id = ".$this->course_id." AND id = ".$id;
+        $sql = "SELECT * FROM $TBL_EXERCISES 
+                WHERE c_id = ".$this->course_id." AND id = ".$id;
         $result = Database::query($sql);
 
         // if the exercise has been found
@@ -194,12 +195,10 @@ class Exercise
                 $this->start_time = $object->start_time;
             }
 
-            //control time
+            // Control time
             $this->expired_time = $object->expired_time;
 
-            //Checking if question_order is correctly set
-
-            //$this->questionList     = $this->selectQuestionList(true);
+            // Checking if question_order is correctly set
             if ($parseQuestionList) {
                 $this->setQuestionList();
             }
@@ -3980,7 +3979,7 @@ class Exercise
 
                             if ($show_result) {
                                 if ($showTotalScoreAndUserChoicesInLastAttempt === false) {
-                                    $user_answer = '';
+                                    $s_answer_label = '';
                                 }
                                 echo '<tr>';
                                 echo '<td>' . $s_answer_label . '</td>';

+ 28 - 35
main/exercise/exercise.php

@@ -1,6 +1,8 @@
 <?php
 /* For licensing terms, see /license.txt */
 
+use ChamiloSession as Session;
+
 /**
  * 	Exercise list: This script shows the list of exercises for administrators and students.
  * 	@package chamilo.exercise
@@ -11,8 +13,6 @@
  * Modified by hubert.borderiou (question category)
  */
 
-use \ChamiloSession as Session;
-
 // including the global library
 require_once '../inc/global.inc.php';
 $current_course_tool = TOOL_QUIZ;
@@ -20,14 +20,11 @@ $current_course_tool = TOOL_QUIZ;
 // Setting the tabs
 $this_section = SECTION_COURSES;
 
-$htmlHeadXtra[] = api_get_js('qtip2/jquery.qtip.min.js');
-$htmlHeadXtra[] = api_get_css(api_get_path(WEB_LIBRARY_PATH).'javascript/qtip2/jquery.qtip.min.css');
+$htmlHeadXtra[] = api_get_asset('qtip2/jquery.qtip.min.js');
+$htmlHeadXtra[] = api_get_css_asset('qtip2/jquery.qtip.min.css');
 
 // Access control
 api_protect_course_script(true);
-
-// including additional libraries
-
 require_once 'hotpotatoes.lib.php';
 
 /* 	Constants and variables */
@@ -78,7 +75,7 @@ $origin = isset($_REQUEST['origin']) ? Security::remove_XSS($_REQUEST['origin'])
 $choice = isset($_REQUEST['choice']) ? Security::remove_XSS($_REQUEST['choice']) : null;
 
 $hpchoice = isset($_REQUEST['hpchoice']) ? Security::remove_XSS($_REQUEST['hpchoice']) : null;
-$exerciseId = isset($_REQUEST['exerciseId']) ? Security::remove_XSS($_REQUEST['exerciseId']) : null;
+$exerciseId = isset($_REQUEST['exerciseId']) ? (int) $_REQUEST['exerciseId'] : null;
 $file = isset($_REQUEST['file']) ? Database::escape_string($_REQUEST['file']) : null;
 
 $learnpath_id = isset($_REQUEST['learnpath_id']) ? intval($_REQUEST['learnpath_id']) : null;
@@ -389,7 +386,8 @@ $condition_session = api_get_session_condition($session_id, true, true);
 
 // Only for administrators
 if ($is_allowedToEdit) {
-    $total_sql = "SELECT count(iid) as count FROM $TBL_EXERCISES
+    $total_sql = "SELECT count(iid) as count 
+                  FROM $TBL_EXERCISES
                   WHERE c_id = $courseId AND active<>'-1' $condition_session ";
     $sql = "SELECT * FROM $TBL_EXERCISES
             WHERE c_id = $courseId AND active<>'-1' $condition_session
@@ -397,7 +395,8 @@ if ($is_allowedToEdit) {
             LIMIT ".$from.",".$limit;
 } else {
     // Only for students
-    $total_sql = "SELECT count(iid) as count FROM $TBL_EXERCISES
+    $total_sql = "SELECT count(iid) as count 
+                  FROM $TBL_EXERCISES
                   WHERE c_id = $courseId AND active = '1' $condition_session ";
     $sql = "SELECT * FROM $TBL_EXERCISES
             WHERE c_id = $courseId AND
@@ -500,15 +499,14 @@ $i = 1;
 $online_icon = Display::return_icon('online.png', get_lang('Visible'), array('width' => '12px'));
 $offline_icon = Display::return_icon('offline.png', get_lang('Invisible'), array('width' => '12px'));
 
-$exercise_list = array();
-$exercise_obj = new Exercise();
+$exerciseList = array();
 $list_ordered = null;
 
 while ($row = Database :: fetch_array($result, 'ASSOC')) {
-    $exercise_list[$row['iid']] = $row;
+    $exerciseList[$row['iid']] = $row;
 }
 
-if (!empty($exercise_list) &&
+if (!empty($exerciseList) &&
     api_get_setting('exercise_invisible_in_session') === 'true'
 ) {
     if (!empty($sessionId)) {
@@ -523,7 +521,7 @@ if (!empty($exercise_list) &&
 
         if ($changeDefaultVisibility) {
             // Check exercise
-            foreach ($exercise_list as $exercise) {
+            foreach ($exerciseList as $exercise) {
                 if ($exercise['session_id'] == 0) {
                     $visibilityInfo = api_get_item_property_info(
                         $courseInfo,
@@ -557,38 +555,34 @@ if (!empty($exercise_list) &&
 if (isset($list_ordered) && !empty($list_ordered)) {
     $new_question_list = array();
     foreach ($list_ordered as $exercise_id) {
-        if (isset($exercise_list[$exercise_id])) {
-            $new_question_list[] = $exercise_list[$exercise_id];
+        if (isset($exerciseList[$exercise_id])) {
+            $new_question_list[] = $exerciseList[$exercise_id];
         }
     }
-    $exercise_list = $new_question_list;
+    $exerciseList = $new_question_list;
 }
 
 $tableRows = [];
 
 /*  Listing exercises  */
-if (!empty($exercise_list)) {
+if (!empty($exerciseList)) {
     if ($origin != 'learnpath') {
         //avoid sending empty parameters
         $myorigin = (empty($origin) ? '' : '&origin='.$origin);
         $mylpid = (empty($learnpath_id) ? '' : '&learnpath_id='.$learnpath_id);
         $mylpitemid = (empty($learnpath_item_id) ? '' : '&learnpath_item_id='.$learnpath_item_id);
-
-        // $token = Security::get_token(); // has been moved above
-
         $i = 1;
-
-        foreach ($exercise_list as $row) {
+        foreach ($exerciseList as $row) {
             $my_exercise_id = $row['id'];
 
-            $exercise_obj = new Exercise();
-            $exercise_obj->read($my_exercise_id);
+            $exercise = new Exercise();
+            $exercise->read($my_exercise_id, false);
 
-            if (empty($exercise_obj->id)) {
+            if (empty($exercise->id)) {
                 continue;
             }
 
-            $locked = $exercise_obj->is_gradebook_locked;
+            $locked = $exercise->is_gradebook_locked;
             $i++;
             //validacion when belongs to a session
             $session_img = api_get_session_image($row['session_id'], $userInfo['status']);
@@ -642,7 +636,7 @@ if (!empty($exercise_list)) {
                 }
             }
 
-            $cut_title = $exercise_obj->getCutTitle();
+            $cut_title = $exercise->getCutTitle();
             $alt_title = '';
             if ($cut_title != $row['title']) {
                 $alt_title = ' title = "'.$row['title'].'" ';
@@ -651,7 +645,7 @@ if (!empty($exercise_list)) {
             // Teacher only
             if ($is_allowedToEdit) {
                 $lp_blocked = null;
-                if ($exercise_obj->exercise_was_added_in_lp == true) {
+                if ($exercise->exercise_was_added_in_lp == true) {
                     $lp_blocked = Display::div(
                         get_lang('AddedToLPCannotBeAccessed'),
                         array('class' => 'lp_content_type_label')
@@ -668,7 +662,7 @@ if (!empty($exercise_list)) {
                 if (!empty($sessionId)) {
                     $setting = api_get_configuration_value('show_hidden_exercise_added_to_lp');
                     if ($setting) {
-                        if ($exercise_obj->exercise_was_added_in_lp == false) {
+                        if ($exercise->exercise_was_added_in_lp == false) {
                             if ($visibility == 0) {
                                 continue;
                             }
@@ -771,7 +765,7 @@ if (!empty($exercise_list)) {
 
                     // Visible / invisible
                     // Check if this exercise was added in a LP
-                    if ($exercise_obj->exercise_was_added_in_lp == true) {
+                    if ($exercise->exercise_was_added_in_lp == true) {
                         $actions .= Display::return_icon('invisible.png', get_lang('AddedToLPCannotBeAccessed'), '', ICON_SIZE_SMALL);
                     } else {
                         if ($row['active'] == 0 || $visibility == 0) {
@@ -788,7 +782,7 @@ if (!empty($exercise_list)) {
                     $actions = Display::return_icon('edit_na.png', get_lang('ExerciseEditionNotAvailableInSession'));
 
                     // Check if this exercise was added in a LP
-                    if ($exercise_obj->exercise_was_added_in_lp == true) {
+                    if ($exercise->exercise_was_added_in_lp == true) {
                         $actions .= Display::return_icon('invisible.png', get_lang('AddedToLPCannotBeAccessed'), '', ICON_SIZE_SMALL);
                     } else {
 
@@ -1151,14 +1145,13 @@ if (isset($attribute['path']) && is_array($attribute['path'])) {
 
                     $item .= Display::tag('td', $actions, array('class' => 'td_actions'));
                 }
-
                 $tableRows[] = Display::tag('tr', $item);
             }
         }
     }
 }
 
-if (empty($exercise_list) && $hotpotatoes_exist == false) {
+if (empty($exerciseList) && $hotpotatoes_exist == false) {
     if ($is_allowedToEdit && $origin != 'learnpath') {
         echo '<div id="no-data-view">';
         echo '<h3>'.get_lang('Quiz').'</h3>';

+ 2 - 2
main/exercise/exercise_result.class.php

@@ -408,9 +408,9 @@ class ExerciseResult
     ) {
         global $charset;
         $this->getExercisesReporting($document_path, $user_id, $export_filter, $exercise_id, $hotpotato_name);
-        $filename = 'exercise_results_'.api_get_local_time().'.xls';
+        $filename = 'exercise_results_'.api_get_local_time().'.xlsx';
         if (!empty($user_id)) {
-            $filename = 'exercise_results_user_'.$user_id.'_'.api_get_local_time().'.xls';
+            $filename = 'exercise_results_user_'.$user_id.'_'.api_get_local_time().'.xlsx';
         }
 
         $spreadsheet = new PHPExcel();

+ 1 - 1
main/gradebook/lib/gradebook_result.class.php

@@ -79,7 +79,7 @@ class GradeBookResult
      */
     public function exportCompleteReportXLS($data)
     {
-        $filename = 'gradebook-results-'.api_get_local_time().'.xls';
+        $filename = 'gradebook-results-'.api_get_local_time().'.xlsx';
 
         $spreadsheet = new PHPExcel();
         $spreadsheet->setActiveSheetIndex(0);

+ 4 - 0
main/group/group.php

@@ -77,6 +77,10 @@ if (isset($_GET['action']) && $is_allowed_in_course) {
                 Display::addFlash(Display::return_message(get_lang('GroupNowMember')));
                 header("Location: $currentUrl");
                 exit;
+            } else {
+                Display::addFlash(Display::return_message(get_lang('Error')));
+                header("Location: $currentUrl");
+                exit;
             }
             break;
         case 'self_unreg':

+ 13 - 6
main/group/group_edit.php

@@ -104,7 +104,7 @@ function check_group_members($value)
         return true;
     }
     if (isset($value['max_member']) && isset($value['group_members']) && $value['max_member'] < count($value['group_members'])) {
-        return array ('group_members' => get_lang('GroupTooMuchMembers'));
+        return array('group_members' => get_lang('GroupTooMuchMembers'));
     }
     return true;
 }
@@ -157,7 +157,7 @@ $group_tutors_element = $form->addElement(
 );
 
 // Group members
-$group_member_list = GroupManager :: get_subscribed_users($current_group['iid']);
+$group_member_list = GroupManager::get_subscribed_users($current_group['iid']);
 
 $selected_users = array ();
 foreach ($group_member_list as $index => $user) {
@@ -172,7 +172,14 @@ foreach ($complete_user_list as $index => $user) {
      }
 }
 
-$group_members_element = $form->addElement('advmultiselect', 'group_members', get_lang('GroupMembers'), $possible_users, 'style="width: 280px;"');
+$group_members_element = $form->addElement(
+    'advmultiselect',
+    'group_members',
+    get_lang('GroupMembers'),
+    $possible_users,
+    'style="width: 280px;"'
+);
+
 $form->addFormRule('check_group_members');
 
 // Members per group
@@ -306,7 +313,7 @@ if ($form->validate()) {
     } else {
         $max_member = $values['max_member'];
     }
-    $self_registration_allowed   = isset($values['self_registration_allowed']) ? 1 : 0;
+    $self_registration_allowed = isset($values['self_registration_allowed']) ? 1 : 0;
     $self_unregistration_allowed = isset($values['self_unregistration_allowed']) ? 1 : 0;
 
     GroupManager::set_group_properties(
@@ -369,9 +376,9 @@ if (!empty($_GET['keyword']) && !empty($_GET['submit'])) {
     echo '<br/>'.get_lang('SearchResultsFor').' <span style="font-style: italic ;"> '.$keyword_name.' </span><br>';
 }
 
-Display :: display_header($nameTools, 'Group');
+Display::display_header($nameTools, 'Group');
 
 $form->setDefaults($defaults);
 $form->display();
 
-Display :: display_footer();
+Display::display_footer();

+ 3 - 2
main/group/group_space.php

@@ -345,6 +345,7 @@ $my_gidreq = isset($_GET['gidReq']) ? Security::remove_XSS($_GET['gidReq']) : ''
 $parameters = array('cidReq' => $my_cidreq, 'origin'=> $my_origin, 'gidReq' => $my_gidreq);
 $table->set_additional_parameters($parameters);
 $table->set_header(0, '');
+
 if (api_is_western_name_order()) {
     $table->set_header(1, get_lang('FirstName'));
     $table->set_header(2, get_lang('LastName'));
@@ -363,8 +364,8 @@ if (api_get_setting('show_email_addresses') == 'true') {
     }
 }
 //the order of these calls is important
-$table->set_column_filter(1, 'user_name_filter');
-$table->set_column_filter(2, 'user_name_filter');
+//$table->set_column_filter(1, 'user_name_filter');
+//$table->set_column_filter(2, 'user_name_filter');
 $table->set_column_filter(0, 'user_icon_filter');
 $table->display();
 

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

@@ -6367,11 +6367,22 @@ function api_get_js($file) {
 
 /**
  * Returns the <script> HTML tag
+ * @return string
  */
-function api_get_asset($file) {
+function api_get_asset($file)
+{
     return '<script type="text/javascript" src="'.api_get_path(WEB_PATH).'web/assets/'.$file.'"></script>'."\n";
 }
 
+/**
+ * Returns the <script> HTML tag
+ * @return string
+ */
+function api_get_css_asset($file, $media = 'screen')
+{
+    return '<link href="'.api_get_path(WEB_PATH).'web/assets/'.$file.'" rel="stylesheet" media="'.$media.'" type="text/css" />'."\n";
+}
+
 /**
  * Returns the <link> HTML tag
  * @param string $file

+ 18 - 8
main/inc/lib/groupmanager.lib.php

@@ -1386,13 +1386,18 @@ class GroupManager
         $table_group = Database :: get_course_table(TABLE_GROUP);
         $group_id = intval($group_id);
         if (isset($group_id)) {
-            $sql = "SELECT  self_registration_allowed
+            $sql = "SELECT status, self_registration_allowed
                     FROM $table_group
                     WHERE c_id = $course_id AND iid = $group_id";
-            $db_result = Database::query($sql);
-            $db_object = Database::fetch_object($db_result);
+            $result = Database::query($sql);
+            $group = Database::fetch_object($result);
+
+            if ($group->status == 0 || $group->self_registration_allowed != 1) {
+
+                return false;
+            }
 
-            return $db_object->self_registration_allowed == 1 && self :: can_user_subscribe($user_id, $group_id);
+            return self::can_user_subscribe($user_id, $group_id);
         } else {
             return false;
         }
@@ -1413,13 +1418,18 @@ class GroupManager
         $group_id = intval($group_id);
         $course_id = api_get_course_int_id();
 
-        $sql = "SELECT self_unregistration_allowed
+        $sql = "SELECT status, self_unregistration_allowed
                 FROM $table_group
                 WHERE c_id = $course_id AND iid = $group_id";
-        $db_result = Database::query($sql);
-        $db_object = Database::fetch_object($db_result);
+        $result = Database::query($sql);
+        $group = Database::fetch_object($result);
+
+        if ($group->status == 0 || $group->self_unregistration_allowed != 1) {
+
+            return false;
+        }
 
-        return $db_object->self_unregistration_allowed == 1 && self :: is_subscribed($user_id, $group_id);
+        return self::is_subscribed($user_id, $group_id);
     }
 
     /**

Fișier diff suprimat deoarece este prea mare
+ 0 - 0
main/inc/lib/javascript/qtip2/jquery.qtip.min.css


Fișier diff suprimat deoarece este prea mare
+ 0 - 12
main/inc/lib/javascript/qtip2/jquery.qtip.min.js


+ 6 - 3
main/inc/lib/nusoap/class.soap_server.php

@@ -211,11 +211,13 @@ class nusoap_server extends nusoap_base
 			$this->debug("In nusoap_server, WSDL is specified");
 			if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
 				$this->wsdl = $wsdl;
+                $this->wsdl->soap_defencoding = $this->soap_defencoding;
 				$this->externalWSDLURL = $this->wsdl->wsdl;
 				$this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
 			} else {
 				$this->debug('Create wsdl from ' . $wsdl);
 				$this->wsdl = new wsdl($wsdl);
+                $this->wsdl->soap_defencoding = $this->soap_defencoding;
 				$this->externalWSDLURL = $wsdl;
 			}
 			$this->appendDebug($this->wsdl->getDebug());
@@ -282,7 +284,7 @@ class nusoap_server extends nusoap_base
               }
 			} elseif ($this->wsdl) {
 				$this->debug("In service, serialize WSDL");
-				header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
+                header("Content-Type: text/xml; charset=".$this->soap_defencoding."\r\n");
 				print $this->wsdl->serialize($this->debug_flag);
 				if ($this->debug_flag) {
 					$this->debug('wsdl:');
@@ -291,7 +293,7 @@ class nusoap_server extends nusoap_base
 				}
 			} else {
 				$this->debug("In service, there is no WSDL");
-				header("Content-Type: text/html; charset=ISO-8859-1\r\n");
+                header("Content-Type: text/html; charset=".$this->soap_defencoding."\r\n");
 				print "This service does not provide WSDL";
 			}
 		} elseif ($this->wsdl) {
@@ -1090,7 +1092,8 @@ class nusoap_server extends nusoap_base
             $schemaTargetNamespace = $namespace;
         }
 
-		$this->wsdl = new wsdl;
+        $this->wsdl = new wsdl();
+        $this->wsdl->soap_defencoding = $this->soap_defencoding;
 		$this->wsdl->serviceName = $serviceName;
         $this->wsdl->endpoint = $endpoint;
 		$this->wsdl->namespaces['tns'] = $namespace;

+ 6 - 6
main/inc/lib/online.inc.php

@@ -3,7 +3,6 @@
 
 use ChamiloSession as Session;
 
-
 /**
 *	Code library for showing Who is online
 *
@@ -60,11 +59,11 @@ function preventMultipleLogin($userId)
     $userId = intval($userId);
     if (api_get_setting('prevent_multiple_simultaneous_login') === 'true') {
         if (!empty($userId) && !api_is_anonymous()) {
-
             $isFirstLogin = Session::read('first_user_login');
             if (empty($isFirstLogin)) {
                 $sql = "SELECT login_id FROM $table
-                        WHERE login_user_id = " . $userId . " LIMIT 1";
+                        WHERE login_user_id = $userId 
+                        LIMIT 1";
 
                 $result = Database::query($sql);
                 $loginData = array();
@@ -184,13 +183,14 @@ function user_is_online($user_id)
     $access_url_id = api_get_current_access_url_id();
     $time_limit = api_get_setting('time_limit_whosonline');
 
-    $online_time = time() - $time_limit*60;
+    $online_time = time() - $time_limit * 60;
     $limit_date = api_get_utc_datetime($online_time);
     $user_id = intval($user_id);
 
-    $query = " SELECT login_user_id,login_date
+    $query = " SELECT login_user_id, login_date
                FROM $track_online_table track
-               INNER JOIN $table_user u ON (u.id=track.login_user_id)
+               INNER JOIN $table_user u 
+               ON (u.id=track.login_user_id)
                WHERE
                     track.access_url_id =  $access_url_id AND
                     login_date >= '".$limit_date."'  AND

+ 4 - 1
main/inc/lib/usermanager.lib.php

@@ -5340,7 +5340,10 @@ EOF;
     public static function getUserProfileLink($userInfo)
     {
         if (isset($userInfo) && isset($userInfo['user_id'])) {
-            return Display::url($userInfo['complete_name'], $userInfo['profile_url']);
+            return Display::url(
+                $userInfo['complete_name_with_username'],
+                $userInfo['profile_url']
+            );
         } else {
             return get_lang('Anonymous');
         }

+ 3 - 3
main/lp/learnpath.class.php

@@ -8949,7 +8949,7 @@ class learnpath
                     link_category.category_title as category_title
                 FROM $tbl_link as link
                 LEFT JOIN $linkCategoryTable as link_category
-                ON link.category_id = link_category.id
+                ON (link.category_id = link_category.id AND link.c_id = link_category.c_id)
                 WHERE link.c_id = ".$course_id." $condition_session
                 ORDER BY link_category.category_title ASC, link.title ASC";
         $links = Database::query($sql);
@@ -11155,8 +11155,8 @@ EOD;
         $lpItemId = [];
 
         $typeListNotToVerify = self::getChapterTypes();
-	    
-	// Using get_toc() function instead $this->items because returns the correct order of the items  
+
+	// Using get_toc() function instead $this->items because returns the correct order of the items
         foreach ($this->get_toc() as $item) {
             if (!in_array($item['type'], $typeListNotToVerify)) {
                 $lpItemId[] = $item['id'];

+ 1 - 1
main/lp/lp_add_item.php

@@ -209,7 +209,7 @@ $(document).on( 'shown.bs.tab', 'a[data-toggle="tab"]', function (e) {
 /* DISPLAY SECTION */
 
 echo $learnPath->build_action_menu();
-echo '<div class="row" style="overflow:hidden">';
+echo '<div class="row">';
 echo '<div id="lp_sidebar" class="col-md-4">';
 echo $learnPath->return_new_tree(null, true);
 

+ 1 - 1
main/lp/lp_edit_item.php

@@ -161,7 +161,7 @@ $(document).ready(function() {
 
 echo $_SESSION['oLP']->build_action_menu();
 
-echo '<div class="row" style="overflow:hidden">';
+echo '<div class="row">';
 echo '<div id="lp_sidebar" class="col-md-4">';
 $path_item = isset($_GET['path_item']) ? $_GET['path_item'] : 0;
 $path_item = Database::escape_string($path_item);

+ 1 - 1
main/mySpace/current_courses.php

@@ -9,7 +9,7 @@ $cidReset = true;
 require_once '../inc/global.inc.php';
 $this_section = SECTION_TRACKING;
 
-$filename = 'reporting.xls';
+$filename = 'reporting.xlsx';
 
 if (!api_is_allowed_to_create_course()) {
 	api_not_allowed(true);

+ 2 - 2
main/session/session_add.php

@@ -23,8 +23,8 @@ $formSent = 0;
 $errorMsg = '';
 
 // Crop picture plugin for session images
-$htmlHeadXtra[] = '<link  href="'. api_get_path(WEB_PATH) .'web/assets/cropper/dist/cropper.min.css" rel="stylesheet">';
-$htmlHeadXtra[] = '<script src="'. api_get_path(WEB_PATH) .'web/assets/cropper/dist/cropper.min.js"></script>';
+$htmlHeadXtra[] = api_get_css_asset('cropper/dist/cropper.min.css');
+$htmlHeadXtra[] = api_get_asset('cropper/dist/cropper.min.js');
 
 $interbreadcrumb[] = array(
     'url' => 'session_list.php',

+ 2 - 2
main/session/session_edit.php

@@ -15,8 +15,8 @@ $this_section = SECTION_PLATFORM_ADMIN;
 $formSent = 0;
 
 // Crop picture plugin for session images
-$htmlHeadXtra[] = '<link  href="'. api_get_path(WEB_PATH) .'web/assets/cropper/dist/cropper.min.css" rel="stylesheet">';
-$htmlHeadXtra[] = '<script src="'. api_get_path(WEB_PATH) .'web/assets/cropper/dist/cropper.min.js"></script>';
+$htmlHeadXtra[] = api_get_css_asset('cropper/dist/cropper.min.css');
+$htmlHeadXtra[] = api_get_asset('cropper/dist/cropper.min.js');
 
 // Database Table Definitions
 $tbl_user = Database::get_main_table(TABLE_MAIN_USER);

+ 1 - 1
main/survey/reporting.php

@@ -25,7 +25,7 @@ $survey_data = SurveyManager::get_survey($survey_id);
 if (isset($_POST['export_report']) && $_POST['export_report']) {
     switch ($_POST['export_format']) {
         case 'xls':
-            $filename = 'survey_results_'.$survey_id.'.xls';
+            $filename = 'survey_results_'.$survey_id.'.xlsx';
             $data = SurveyUtil::export_complete_report_xls(
                 $survey_data,
                 $filename,

+ 14 - 8
main/survey/survey.lib.php

@@ -2502,6 +2502,7 @@ class SurveyUtil
         $table_survey_answer = Database :: get_course_table(TABLE_SURVEY_ANSWER);
 
         $surveyId = isset($_GET['survey_id']) ? intval($_GET['survey_id']) : 0;
+        $action = isset($_GET['action']) ? Security::remove_XSS($_GET['action']) : '';
 
         // Actions bar
         echo '<div class="actions">';
@@ -2514,16 +2515,16 @@ class SurveyUtil
         echo '</div>';
 
         // The form
-        echo '<form id="form1a" name="form1a" method="post" action="'.api_get_self().'?action='.Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&'.api_get_cidreq().'">';
+        echo '<form id="form1a" name="form1a" method="post" action="'.api_get_self().'?action='.$action.'&survey_id='.$surveyId.'&'.api_get_cidreq().'">';
         echo '<input type="hidden" name="export_report" value="export_report">';
         echo '<input type="hidden" name="export_format" value="csv">';
         echo '</form>';
-        echo '<form id="form1b" name="form1b" method="post" action="'.api_get_self().'?action='.Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&'.api_get_cidreq().'">';
+        echo '<form id="form1b" name="form1b" method="post" action="'.api_get_self().'?action='.$action.'&survey_id='.$surveyId.'&'.api_get_cidreq().'">';
         echo '<input type="hidden" name="export_report" value="export_report">';
         echo '<input type="hidden" name="export_format" value="xls">';
         echo '</form>';
 
-        echo '<form id="form2" name="form2" method="post" action="'.api_get_self().'?action='.Security::remove_XSS($_GET['action']).'&survey_id='.$surveyId.'&'.api_get_cidreq().'">';
+        echo '<form id="form2" name="form2" method="post" action="'.api_get_self().'?action='.$action.'&survey_id='.$surveyId.'&'.api_get_cidreq().'">';
 
         // The table
         echo '<br /><table class="data_table" border="1">';
@@ -2557,14 +2558,17 @@ class SurveyUtil
 
         $course_id = api_get_course_int_id();
         $sql = "SELECT q.question_id, q.type, q.survey_question, count(o.question_option_id) as number_of_options
-				FROM $table_survey_question q LEFT JOIN $table_survey_question_option o
+				FROM $table_survey_question q 
+				LEFT JOIN $table_survey_question_option o
 				ON q.question_id = o.question_id
-				WHERE q.survey_id = '".$surveyId."' AND
-				q.c_id = $course_id AND
-				o.c_id = $course_id
+				WHERE 
+				    q.survey_id = '".$surveyId."' AND
+				    q.c_id = $course_id AND
+				    o.c_id = $course_id
 				GROUP BY q.question_id
 				ORDER BY q.sort ASC";
         $result = Database::query($sql);
+        $questions = [];
         while ($row = Database::fetch_array($result)) {
             // We show the questions if
             // 1. there is no question filter and the export button has not been clicked
@@ -2620,7 +2624,9 @@ class SurveyUtil
 				ORDER BY sq.sort ASC, sqo.sort ASC";
         $result = Database::query($sql);
 
-        $display_percentage_header = 1;	// in order to display only once the cell option (and not 100 times)
+        $display_percentage_header = 1;
+        $possible_answers = [];
+        // in order to display only once the cell option (and not 100 times)
         while ($row = Database::fetch_array($result)) {
             // We show the options if
             // 1. there is no question filter and the export button has not been clicked

+ 2 - 2
main/template/default/agenda/month.tpl

@@ -235,13 +235,13 @@ $(document).ready(function() {
                     comment = event.comment;
                 }
 
-				/*element.qtip({
+				element.qtip({
                     hide: {
                         delay: 2000
                     },
 		            content: event.description + ' ' + comment,
 		            position: { at:'top left' , my:'bottom left'}
-		        });*/
+		        });
 			}
 	    },
 		eventClick: function(calEvent, jsEvent, view) {

+ 1 - 1
main/template/default/layout/footer.js.tpl

@@ -60,7 +60,7 @@
         });
 
         // Adv multi-select search input.
-        $('.select_class_filter').on('focus', function () {
+        $('.select_class_filter').each( function () {
             var inputId = $(this).attr('id');
             inputId = inputId.replace('-filter', '');
             $("#" + inputId).filterByText($("#" + inputId + "-filter"));

+ 2 - 2
main/template/default/layout/hot_course_item.tpl

@@ -22,7 +22,7 @@
                                             {{ teacher.firstname }} {{ teacher.lastname }}
                                         </a>
                                      </h5>
-                                </div>       
+                                </div>
                             {% endif %}
                         {% endfor %}
                         </div>
@@ -31,7 +31,7 @@
                 </div>
                 <div class="description">
                     <h4 class="title">
-                            <a title="{{ item.title}}" href="{{ item.course_public_url }}">{{ item.title}}</a>
+                        <a title="{{ item.title}}" href="{{ item.course_public_url }}">{{ item.title}}</a>
                     </h4>
                     <div class="ranking">
                         {{ item.rating_html }}

+ 14 - 14
main/template/default/layout/layout_3_col.tpl

@@ -1,21 +1,21 @@
 {% extends template ~ "/layout/page.tpl" %}
 {% block body %}
 <div id="maincontent" class="maincontent">
-    {{ plugin_courses_block}}
-    {{ home_page_block}}
-    {{ message}}
-    {{ content}}
-    {{ announcements_block}}
+    {{ plugin_courses_block }}
+    {{ home_page_block }}
+    {{ message }}
+    {{ content }}
+    {{ announcements_block }}
 </div>
 <div id="menu-wrapper">
-    {{ login_block}}
-    {{ profile_block}}
-    {{ account_block}}
-    {{ teacher_block}}
-    {{ notice_block}}
-    {{ navigation_course_links}}
-    {{ plugin_courses_right_block}}
-    {{ search_block}}
-    {{ classes_block}}
+    {{ login_block }}
+    {{ profile_block }}
+    {{ account_block }}
+    {{ teacher_block }}
+    {{ notice_block }}
+    {{ navigation_course_links }}
+    {{ plugin_courses_right_block }}
+    {{ search_block }}
+    {{ classes_block }}
 </div>
 {% endblock %}

+ 1 - 2
main/template/default/layout/login_form.tpl

@@ -3,7 +3,7 @@
     <div id="login_block" class="panel panel-default">
         <div class="panel-body">
         {{ login_language_form }}
-        
+
         {% if plugin_login_top is not null %}
             <div id="plugin_login_top">
                 {{ plugin_login_top }}
@@ -11,7 +11,6 @@
         {% endif %}
 
         {{ login_failed }}
-
         {{ login_form }}
 
         {% if "allow_lostpassword" | get_setting == 'true' or "allow_registration" | get_setting == 'true' %}

+ 3 - 5
main/template/default/layout/no_layout.tpl

@@ -8,10 +8,8 @@
 </head>
 <body dir="{{text_direction}}" class="{{section_name}}">
 <section id="content-scorm">
-    
-        {% block body %}
-            {{ content }}
-        {% endblock %}
-    
+{% block body %}
+    {{ content }}
+{% endblock %}
 </body>
 </html>

+ 2 - 2
main/template/default/layout/page.tpl

@@ -6,7 +6,7 @@
 <html lang="{{ document_language }}" class="no-js"> <!--<![endif]-->
 <head>
 {% block head %}
-    {% include template ~ "/layout/head.tpl" %}
+{% include template ~ "/layout/head.tpl" %}
 {% endblock %}
 </head>
 <body dir="{{ text_direction }}" class="{{ section_name }} {{ login_class }}">
@@ -46,7 +46,7 @@
             {% block breadcrumb %}
                 {{ breadcrumb }}
             {% endblock %}
-            
+
             {% block body %}
                 {{ content }}
             {% endblock %}

+ 3 - 3
main/template/default/layout/page_header.tpl

@@ -2,9 +2,9 @@
     {{ help_content }}
     {{ bug_notification }}
 </div>
-    {% block topbar %}
-        {% include template ~ "/layout/topbar.tpl" %}
-    {% endblock %}
+{% block topbar %}
+    {% include template ~ "/layout/topbar.tpl" %}
+{% endblock %}
 <div class="extra-header">{{ header_extra_content }}</div>
 <header id="header-section">
 <section>

+ 0 - 3
main/template/default/layout/welcome_to_course.tpl

@@ -6,15 +6,12 @@
 {% else %}
 
     {% if "allow_students_to_browse_courses"|get_setting  == 'true' %}
-        
         {{ "GoAheadAndBrowseOurCourseCatalogXOnceRegisteredYouWillSeeTheCourseHereX"|get_lang|format(course_catalog_link, course_list_link) }}
-        
         <a class="btn btn-primary btn-large" href="{{ course_catalog_url }}">
             {{ "CourseCatalog"|get_lang }}
         </a>
     {% else %}
         {{ "PleaseAllowUsALittleTimeToSubscribeYouToOneOfOurCourses"|get_lang }}
     {% endif %}
-
 {% endif %}
 </div>

+ 0 - 1
main/template/default/mail/content_registration_platform_to_admin.tpl

@@ -11,7 +11,6 @@
 </div>
 
 <p>{{ 'YouCanAssignATutorInThisLinkX'|get_lang | format(link)}} </p>
-
 <p>{{ 'SignatureFormula'|get_lang }}</p>
 <p>{{ _admin.name }}, {{ _admin.surname }}<br>
     {{ 'Manager'|get_lang }} {{ _s.site_name }}<br>

+ 0 - 1
main/template/default/sequence_resource/session_requirements.tpl

@@ -2,7 +2,6 @@
 
 {% for item in sequences %}
     <h4>{{ item.name }}</h4>
-
     <div id="parents">
         {% for session in item.requirements %}
             <div class="parent">

+ 0 - 1
main/template/default/session/about.tpl

@@ -2,7 +2,6 @@
     <div class="row">
         <div class="col-xs-12">
             <p><em class="fa fa-clock-o"></em> <em>{{ session_date.display }}</em></p>
-
             {% if show_tutor %}
                 <p>
                     <em class="fa fa-user"></em> {{ 'SessionGeneralCoach'|get_lang }}: <em>{{ session.generalCoach.getCompleteName() }}</em>

+ 0 - 4
main/template/default/skill/badge.tpl

@@ -30,14 +30,10 @@
                 <h3 class="sub-title">{{ 'OpenBadgesActionCall' | get_lang }}</h3>
                 <div class="block-content">
                     <div class="block-title">{{ 'IssuerDetails' | get_lang }}</div>
-
                     <p>{{ 'Name' | get_lang }} : {{ _s.institution }}</p>
                     <p>{{ 'URL' | get_lang }} : {{ _p.web }}</p>
-
                     <div class="block-title">{{ 'BackpackDetails' | get_lang }}</div>
-
                     <p>{{ 'URL' | get_lang }} : {{ backpack }}</p>
-
                     <p>{{ 'TheBadgesWillBeSentToThatBackpack' | get_lang }}</p>
 
                 </div>

+ 32 - 32
main/template/default/skill/badge_create.tpl

@@ -1,44 +1,44 @@
 <script>
-    (function () {
-        var designer = null;
-        $(document).on('ready', function () {
-            $('.help-badges').tooltip();
-            $('.help-badges-img').tooltip();
-        });
-
-        $(document).on('ready', function () {
-            $('#btn-open-designer').on('click', function (e) {
-                e.preventDefault();
+(function () {
+    var designer = null;
+    $(document).on('ready', function () {
+        $('.help-badges').tooltip();
+        $('.help-badges-img').tooltip();
+    });
 
-                var designerUrl = 'https://www.openbadges.me/designer.html?origin={{ _p.web }}';
-                designerUrl = designerUrl + '&email={{ platformAdminEmail }}';
-                designerUrl = designerUrl + '&close=true';
-                designerUrl = designerUrl + '&hidePublish=true';
+    $(document).on('ready', function () {
+        $('#btn-open-designer').on('click', function (e) {
+            e.preventDefault();
 
-                var windowOptions = 'width=1200,height=680,location=0,menubar=0,status=0,toolbar=0';
-                designer = window.open(designerUrl, '', windowOptions);
-            });
+            var designerUrl = 'https://www.openbadges.me/designer.html?origin={{ _p.web }}';
+            designerUrl = designerUrl + '&email={{ platformAdminEmail }}';
+            designerUrl = designerUrl + '&close=true';
+            designerUrl = designerUrl + '&hidePublish=true';
 
-            $('#image').on('change', function () {
-                var self = this;
+            var windowOptions = 'width=1200,height=680,location=0,menubar=0,status=0,toolbar=0';
+            designer = window.open(designerUrl, '', windowOptions);
+        });
 
-                if (self.files.length > 0) {
-                    var image = self.files[0];
+        $('#image').on('change', function () {
+            var self = this;
 
-                    if (!image.type.match(/image.*/)) {
-                        return;
-                    }
+            if (self.files.length > 0) {
+                var image = self.files[0];
 
-                    var fileReader = new FileReader();
-                    fileReader.onload = function (e) {
-                        $('#badge-preview').attr('src', e.target.result);
-                        $('#badge-container').removeClass('hide');
-                    };
-                    fileReader.readAsDataURL(image);
+                if (!image.type.match(/image.*/)) {
+                    return;
                 }
-            });
+
+                var fileReader = new FileReader();
+                fileReader.onload = function (e) {
+                    $('#badge-preview').attr('src', e.target.result);
+                    $('#badge-container').removeClass('hide');
+                };
+                fileReader.readAsDataURL(image);
+            }
         });
-    })();
+    });
+})();
 </script>
 <div class="col-md-12">
 

+ 27 - 23
main/template/default/skill/profile.tpl

@@ -1,28 +1,30 @@
 {% if search_skill_list is not null %}
     <div class="skills-skills">
         <h3>{{"Skills"|get_lang}}</h3>
-        <ul class="holder">             
-            {% for search_skill_id in search_skill_list %}        
+        <ul class="holder">
+            {% for search_skill_id in search_skill_list %}
                 <li class="bit-box">
                     {{ skill_list[search_skill_id].name}}
                     <a class="closebutton" href="?a=remove_skill&id={{search_skill_id}}"></a>
-                </li>        
+                </li>
             {% endfor %}
         </ul>
-        <a id="add_profile" class="btn btn-default" href="#"><em class="fa fa-floppy-o"></em> {{"SaveThisSearch"|get_lang}}</a>
+        <a id="add_profile" class="btn btn-default" href="#">
+            <em class="fa fa-floppy-o"></em> {{"SaveThisSearch"|get_lang}}
+        </a>
     </div>
 {% endif %}
 
-{% if profiles is not null %}    
+{% if profiles is not null %}
     <div class="skills-profiles">
         <h3>{{"SkillProfiles"|get_lang}}</h3>
         <ul class="holder">
-            {%for profile in profiles %}        
+            {%for profile in profiles %}
                 <li class="bit-box">
                     <a href="?a=load_profile&id={{profile.id}}">{{profile.name}}</a>
-                </li>        
+                </li>
             {% endfor %}
-        </ul>    
+        </ul>
     </div>
 {% endif %}
 
@@ -37,7 +39,7 @@
                         {% if (total_search_skills - count) == 1 %}
                             {{ "MissingOneStepToMatch"|get_lang }}
                         {% else %}
-                            {{ "MissingXStepsToMatch"|get_lang | format(total_search_skills - count)}}                        
+                            {{ "MissingXStepsToMatch"|get_lang | format(total_search_skills - count)}}
                         {% endif %}
                     {% endif %}
                 </h4>
@@ -51,14 +53,16 @@
                     <div class="panel panel-default">
                         <div class="panel-body">
                             <div class="avatar-user">
-                                <img  class="img-circle" width="100" src="{{ user.user.avatar }}" class="center-block">
+                                <img class="img-circle" width="100" src="{{ user.user.avatar }}" class="center-block">
                             </div>
-                            <p class="text-center"><em class="fa fa-user"></em> 
+                            <p class="text-center"><em class="fa fa-user"></em>
                                 <a href="{{ _p.web_main }}social/profile.php?u={{ user['user'].user_id }}" target="_blank">
                                     {{ user['user'].complete_name_with_username }}
                                 </a>
                             </p>
-                            <p class="text-center"><em class="fa fa-graduation-cap"></em> {{ "AchievedSkills"|get_lang }} {{ user.total_found_skills }} / {{ total_search_skills }}</p>
+                            <p class="text-center">
+                                <em class="fa fa-graduation-cap"></em> {{ "AchievedSkills"|get_lang }} {{ user.total_found_skills }} / {{ total_search_skills }}
+                            </p>
                         </div>
                         <ul class="list-group">
                             {% for skill_data in user.skills %}
@@ -78,7 +82,7 @@
                             {% endfor %}
                         </ul>
                     </div>
-                    </div>    
+                    </div>
                 </div>
             {% endfor %}
         </div>
@@ -89,21 +93,21 @@
     {% endif %}
 {% endif %}
 </div>
-<div id="dialog-form" style="display:none;">    
-    <form id="save_profile_form" class="form-horizontal" name="form">       
+<div id="dialog-form" style="display:none;">
+    <form id="save_profile_form" class="form-horizontal" name="form">
         <fieldset>
-            <div class="control-group">            
-                <label class="control-label" for="name">{{"Name"|get_lang}}</label>            
+            <div class="control-group">
+                <label class="control-label" for="name">{{"Name"|get_lang}}</label>
                 <div class="controls">
-                    <input type="text" name="name" id="name" size="40" />             
+                    <input type="text" name="name" id="name" size="40" />
                 </div>
-            </div>        
-            <div class="control-group">            
-                <label class="control-label" for="name">{{"Description"|get_lang}}</label>            
+            </div>
+            <div class="control-group">
+                <label class="control-label" for="name">{{"Description"|get_lang}}</label>
                 <div class="controls">
                     <textarea name="description" id="description" class="span2"  rows="7"></textarea>
                 </div>
-            </div>  
+            </div>
         </fieldset>
-    </form>    
+    </form>
 </div>

+ 12 - 11
main/template/default/skill/skill_info.tpl

@@ -1,15 +1,16 @@
 <p>{{ "ToGetToLearnXYouWillNeedToTakeOneOfTheFollowingCourses" | get_lang | format( "<em>" ~ skill.name ~ "</em>") }}</p>
-
 <ul>
-    {% for course in courses %}
-        <li>
-            <a href="#" class="course_description_popup" rel="{{ course.code }}">{{ "SkillXWithCourseX" | get_lang | format(skill.name, course.title) }}</a>
-        </li>
-    {% endfor %}
+{% for course in courses %}
+    <li>
+        <a href="#" class="course_description_popup" rel="{{ course.code }}">
+            {{ "SkillXWithCourseX" | get_lang | format(skill.name, course.title) }}
+        </a>
+    </li>
+{% endfor %}
 
-    {% for session in sessions %}
-        <li>
-            {{ "SkillXWithCourseX" | get_lang | format(skill.name, session.name) }}
-        </li>
-    {% endfor %}
+{% for session in sessions %}
+    <li>
+        {{ "SkillXWithCourseX" | get_lang | format(skill.name, session.name) }}
+    </li>
+{% endfor %}
 </ul>

+ 0 - 2
main/template/default/social/group_waiting_list.tpl

@@ -29,9 +29,7 @@
                     </div>
                 </div>
             </div>
-
             {% endfor %}
-
         </div>
         <div id="display_response_id" class="col-md-5"></div>
         {{ social_auto_extend_link }}

+ 26 - 28
main/template/default/social/home.tpl

@@ -4,7 +4,6 @@
     <div class="row">
         <div class="col-md-3">
             {{ social_avatar_block }}
-
             <div class="social-network-menu">
             {{ social_menu_block }}
             </div>
@@ -19,7 +18,7 @@
             {{ social_auto_extend_link }}
         </div>
         <div class="col-md-3">
-        <!-- Block chat list -->    
+            <!-- Block chat list -->
             <div class="chat-friends">
                 <div class="panel-group" id="blocklistFriends" role="tablist" aria-multiselectable="true">
                     <div class="panel panel-default">
@@ -38,34 +37,33 @@
                     </div>
                 </div>
             </div>
-       
-         <!-- Block session list -->
-        {% if sessionList != null %}
-        <div class="panel-group" id="session-block" role="tablist" aria-multiselectable="true">
-            <div class="panel panel-default">
-                <div class="panel-heading" role="tab" id="headingOne">
-                    <h4 class="panel-title">
-                        <a role="button" data-toggle="collapse" data-parent="#session-block" href="#sessionList" aria-expanded="true" aria-controls="sessionList">
-                           {{ "MySessions" | get_lang }}
-                        </a>
-                    </h4>
-                </div>
-                <div id="sessionList" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne">
-                    <div class="panel-body">
-                        <ul class="list-group">
-                            {% for session in sessionList %}
-                            <li id="session_{{ session.id }}" class="list-group-item" style="min-height:65px;">
-                                <img class="img-session" src="{{ session.image }}"/>
-                                <span class="title">{{ session.name }}</span>
-                            </li>
-                            {% endfor %}
-                        </ul>
+
+            <!-- Block session list -->
+            {% if sessionList != null %}
+            <div class="panel-group" id="session-block" role="tablist" aria-multiselectable="true">
+                <div class="panel panel-default">
+                    <div class="panel-heading" role="tab" id="headingOne">
+                        <h4 class="panel-title">
+                            <a role="button" data-toggle="collapse" data-parent="#session-block" href="#sessionList" aria-expanded="true" aria-controls="sessionList">
+                               {{ "MySessions" | get_lang }}
+                            </a>
+                        </h4>
+                    </div>
+                    <div id="sessionList" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne">
+                        <div class="panel-body">
+                            <ul class="list-group">
+                                {% for session in sessionList %}
+                                <li id="session_{{ session.id }}" class="list-group-item" style="min-height:65px;">
+                                    <img class="img-session" src="{{ session.image }}"/>
+                                    <span class="title">{{ session.name }}</span>
+                                </li>
+                                {% endfor %}
+                            </ul>
+                        </div>
                     </div>
                 </div>
-            </div>
-         </div>
-         {% endif %}
-         
+             </div>
+             {% endif %}
         </div>
     </div>
 {% endblock %}

+ 0 - 1
main/template/default/social/profile.tpl

@@ -91,7 +91,6 @@
             </div>
          </div>
         {% endif %}
-
         {{ invitations }}
         {{ social_rss_block }}
         {{ social_right_information }}

+ 19 - 20
main/template/default/social/skills_block.tpl

@@ -1,3 +1,8 @@
+<script>
+jQuery(document).ready(function(){
+    jQuery('.scrollbar-inner').scrollbar();
+});
+</script>
 <div class="panel-group" id="skill-block" role="tablist" aria-multiselectable="true">
     <div class="panel panel-default">
         <div class="panel-heading" role="tab" id="headingOne">
@@ -25,29 +30,23 @@
                 </div>
             </h4>
         </div>
-        <script type="text/javascript">
-            jQuery(document).ready(function(){
-            jQuery('.scrollbar-inner').scrollbar();
-        });
-                        </script>
         <div id="skillList" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne">
             <div class="panel-body">
                 {% if skills %}
-
-                <div class="scrollbar-inner badges-sidebar">
-                    <ul class="list-unstyled list-badges">
-                        {% for skill in skills %}
-                            <li class="thumbnail">
-                                <a href="{{ _p.web }}skill/{{ skill.id }}/user/{{ user_id }}" target="_blank">
-                                    <img title="{{ skill.name }}" class="img-responsive" src="{{ skill.icon ? skill.web_icon_thumb_path : 'badges-default.png'|icon(64) }}" width="64" height="64" alt="{{ skill.name }}">
-                                    <div class="caption">
-                                        <p class="text-center">{{ skill.name }}</p>
-                                    </div>
-                                </a>
-                            </li>
-                        {% endfor %}
-                    </ul>
-                </div>
+                    <div class="scrollbar-inner badges-sidebar">
+                        <ul class="list-unstyled list-badges">
+                            {% for skill in skills %}
+                                <li class="thumbnail">
+                                    <a href="{{ _p.web }}skill/{{ skill.id }}/user/{{ user_id }}" target="_blank">
+                                        <img title="{{ skill.name }}" class="img-responsive" src="{{ skill.icon ? skill.web_icon_thumb_path : 'badges-default.png'|icon(64) }}" width="64" height="64" alt="{{ skill.name }}">
+                                        <div class="caption">
+                                            <p class="text-center">{{ skill.name }}</p>
+                                        </div>
+                                    </a>
+                                </li>
+                            {% endfor %}
+                        </ul>
+                    </div>
                 {% else %}
                     <p>{{ 'WithoutAchievedSkills'|get_lang }}</p>
                     <p>

+ 13 - 14
main/template/default/social/user_block.tpl

@@ -57,21 +57,21 @@
                                 </li>
                             {% endif %}
                         {% endif %}
-                    {% if chat_enabled == 1 %}
-                        {% if user.user_is_online_in_chat != 0 %}
-                            {% if user_relation == user_relation_type_friend %}
-                                <li class="item">
-                                    <a onclick="javascript:chatWith('{{ user.id }}', '{{ user.complete_name }}', '{{ user.user_is_online }}','{{ user.avatar_small }}')" href="javascript:void(0);">
-                                        <img src="{{ "online.png" | icon }}" alt="{{ "Online" | get_lang }}">
-                                        {{ "Chat" | get_lang }} ({{ "Online" | get_lang }})
-                                    </a>
-                                </li>
-                            {# else #}
-                                {# <img src="{{ "offline.png" | icon }}" alt="{{ "Online" | get_lang }}"> #}
-                                {# {{ "Chat" | get_lang }} ({{ "Offline" | get_lang }}) #}
+                        {% if chat_enabled == 1 %}
+                            {% if user.user_is_online_in_chat != 0 %}
+                                {% if user_relation == user_relation_type_friend %}
+                                    <li class="item">
+                                        <a onclick="javascript:chatWith('{{ user.id }}', '{{ user.complete_name }}', '{{ user.user_is_online }}','{{ user.avatar_small }}')" href="javascript:void(0);">
+                                            <img src="{{ "online.png" | icon }}" alt="{{ "Online" | get_lang }}">
+                                            {{ "Chat" | get_lang }} ({{ "Online" | get_lang }})
+                                        </a>
+                                    </li>
+                                {# else #}
+                                    {# <img src="{{ "offline.png" | icon }}" alt="{{ "Online" | get_lang }}"> #}
+                                    {# {{ "Chat" | get_lang }} ({{ "Offline" | get_lang }}) #}
+                                {% endif %}
                             {% endif %}
                         {% endif %}
-                    {% endif %}
 
                     {% if not profile_edition_link is empty %}
                     <li class="item">
@@ -80,7 +80,6 @@
                         </a>
                     </li>
                     {% endif %}
-
                     </ul>
                 </div>
             </div>

+ 0 - 1
main/template/default/user_portal/grid_courses_with_category.tpl

@@ -64,7 +64,6 @@
                                         {% endif %}
                                     </h4>
                                     <div class="notifications">{{ item.notifications }}</div>
-
                                 </div>
                             </div>
                         </div>

+ 0 - 1
main/template/default/user_portal/grid_courses_without_category.tpl

@@ -61,7 +61,6 @@
                                 {% endif %}
                             </h4>
                             <div class="notifications">{{ item.notifications }}</div>
-
                         </div>
                     </div>
                 </div>

+ 0 - 1
main/template/default/user_portal/grid_session.tpl

@@ -85,7 +85,6 @@
                                         {% endif %}
                                     </h4>
                                     <div class="notifications">{{ item.notifications }}</div>
-
                                 </div>
                             </div>
                         </div>

+ 0 - 2
main/template/default/work/comments.tpl

@@ -1,5 +1,3 @@
-{# "UpdatedBy"|get_lang|format(comment.username) #}
-
 <hr>
 <h3>
     {{ 'Comments' | get_lang }}

+ 13 - 6
main/wiki/wiki.inc.php

@@ -528,13 +528,20 @@ class Wiki
                 WHERE c_id = $course_id AND $groupFilter $conditionSession
                 ORDER BY id DESC";
 
-        $sql = "DELETE FROM $tbl_wiki_conf
-                WHERE c_id = $course_id AND page_id IN ($sql)";
-        Database::query($sql);
+        $result = Database::query($sql);
+        $pageList = Database::store_result($result);
+        if ($pageList) {
+            foreach ($pageList as $pageData) {
+                $pageId = $pageData['page_id'];
+                $sql = "DELETE FROM $tbl_wiki_conf
+                        WHERE c_id = $course_id AND page_id = $pageId";
+                Database::query($sql);
 
-        $sql = "DELETE FROM $tbl_wiki_discuss
-                WHERE c_id = $course_id AND publication_id IN ($sql)";
-        Database::query($sql);
+                $sql = "DELETE FROM $tbl_wiki_discuss
+                        WHERE c_id = $course_id AND publication_id = $pageId";
+                Database::query($sql);
+            }
+        }
 
         $sql = "DELETE FROM $tbl_wiki_mailcue
                 WHERE c_id = $course_id AND $groupFilter $conditionSession ";

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff