Browse Source

Solve conflicts when merging - refs #5637

Imanol Losada 10 years ago
parent
commit
b3100a633c
100 changed files with 3959 additions and 1378 deletions
  1. 4 0
      .gitattributes
  2. 14 0
      CONTRIBUTING.md
  3. 2 1
      composer.json
  4. 843 0
      composer.lock
  5. 2 2
      custompages/index-unlogged.php
  6. 8 1
      custompages/language.php
  7. 1 3
      custompages/lostpassword.php
  8. 11 2
      documentation/changelog.html
  9. 4 2
      documentation/credits.html
  10. 24 0
      documentation/dependencies.html
  11. 13 5
      documentation/installation_guide.html
  12. 4 3
      documentation/installation_guide_es_ES.html
  13. 68 0
      documentation/optimization.html
  14. 3 5
      index.php
  15. 1 0
      main/admin/access_url_add_courses_to_url.php
  16. 3 3
      main/admin/access_url_add_users_to_url.php
  17. 10 10
      main/admin/access_url_check_user_session.php
  18. 5 4
      main/admin/access_url_edit.php
  19. 1 1
      main/admin/access_url_edit_course_category_to_url.php
  20. 7 13
      main/admin/access_url_edit_courses_to_url.php
  21. 2 2
      main/admin/access_url_edit_users_to_url.php
  22. 5 4
      main/admin/access_urls.php
  23. 1 1
      main/admin/add_courses_to_session.php
  24. 1 2
      main/admin/add_courses_to_usergroup.php
  25. 65 70
      main/admin/add_many_session_to_category.php
  26. 1 2
      main/admin/add_sessions_to_promotion.php
  27. 19 24
      main/admin/add_sessions_to_usergroup.php
  28. 3 3
      main/admin/add_students_to_session.php
  29. 0 4
      main/admin/add_users_to_group.php
  30. 95 34
      main/admin/add_users_to_session.php
  31. 38 3
      main/admin/add_users_to_usergroup.php
  32. 2 2
      main/admin/archive_cleanup.php
  33. 3 4
      main/admin/configure_extensions.php
  34. 152 142
      main/admin/configure_homepage.php
  35. 4 0
      main/admin/configure_plugin.php
  36. 11 8
      main/admin/course_edit.php
  37. 11 10
      main/admin/course_export.php
  38. 35 26
      main/admin/course_import.php
  39. 10 2
      main/admin/course_information.php
  40. 3 3
      main/admin/course_list.php
  41. 1 0
      main/admin/course_request_accepted.php
  42. 3 3
      main/admin/course_request_rejected.php
  43. 3 5
      main/admin/course_user_import.php
  44. 234 0
      main/admin/course_user_import_by_email.php
  45. 0 1
      main/admin/dashboard_add_courses_to_user.php
  46. 0 1
      main/admin/dashboard_add_users_to_user.php
  47. 2 2
      main/admin/example_session.csv
  48. 22 12
      main/admin/group_add.php
  49. 1 1
      main/admin/group_list.php
  50. 5 6
      main/admin/inactive_user_list.php
  51. 18 3
      main/admin/index.php
  52. 4 25
      main/admin/languages.php
  53. 33 33
      main/admin/promotions.php
  54. 48 29
      main/admin/resume_session.php
  55. 15 10
      main/admin/session_add.php
  56. 2 2
      main/admin/session_category_add.php
  57. 49 33
      main/admin/session_category_edit.php
  58. 8 17
      main/admin/session_category_list.php
  59. 13 11
      main/admin/session_course_edit.php
  60. 10 21
      main/admin/session_course_user_list.php
  61. 16 6
      main/admin/session_edit.php
  62. 50 47
      main/admin/session_import.php
  63. 8 7
      main/admin/session_list.php
  64. 97 0
      main/admin/session_user_edit.php
  65. 2 2
      main/admin/session_user_import.php
  66. 15 8
      main/admin/settings.lib.php
  67. 3 3
      main/admin/settings.php
  68. 1 2
      main/admin/statistics/index.php
  69. 1 1
      main/admin/sub_language.class.php
  70. 78 39
      main/admin/subscribe_user2course.php
  71. 1 1
      main/admin/system_announcements.php
  72. 4 4
      main/admin/user_add.php
  73. 23 24
      main/admin/user_edit.php
  74. 1 1
      main/admin/user_export.php
  75. 103 42
      main/admin/user_import.php
  76. 292 113
      main/admin/user_information.php
  77. 8 2
      main/admin/user_list.php
  78. 2 4
      main/admin/user_move_stats.php
  79. 492 0
      main/admin/user_update_import.php
  80. 14 11
      main/admin/usergroup_import.php
  81. 12 6
      main/admin/usergroups.php
  82. 10 1
      main/announcements/announcement_email.class.php
  83. 8 4
      main/announcements/announcements.inc.php
  84. 80 50
      main/announcements/announcements.php
  85. 6 13
      main/attendance/attendance_controller.php
  86. 0 1
      main/attendance/index.php
  87. 76 78
      main/auth/courses.php
  88. 321 35
      main/auth/courses_controller.php
  89. 2 3
      main/auth/gotocourse.php
  90. 44 44
      main/auth/inscription.php
  91. 23 42
      main/auth/lostPassword.php
  92. 7 7
      main/auth/my_progress.php
  93. 9 12
      main/auth/profile.php
  94. 109 53
      main/calendar/agenda.lib.php
  95. 1 4
      main/calendar/agenda.php
  96. 10 9
      main/chat/chat.php
  97. 28 25
      main/chat/chat_chat.php
  98. 7 21
      main/chat/chat_functions.lib.php
  99. 13 12
      main/chat/chat_hidden.php
  100. 22 25
      main/chat/chat_message.php

+ 4 - 0
.gitattributes

@@ -0,0 +1,4 @@
+.gitattributes export-ignore
+.gitignore export-ignore
+.travis.yml export-ignore
+/tests export-ignore

+ 14 - 0
CONTRIBUTING.md

@@ -0,0 +1,14 @@
+Contributing
+------------
+
+Chamilo LMS is a free software, community-driven project.
+
+If you'd like to contribute, please read the following document:
+
+* [Coding conventions][1]: The main conventions document
+* [PSR-1][2]: PSR-1 are standard conventions rules we use as a base (conversion of old code still in progress)
+* [PSR-2][3]: PSR-2 are more detailed standard conventions rules we use as base (conversion of old code still in progress)
+
+[1]: https://support.chamilo.org/projects/chamilo-18/wiki/Coding_conventions
+[2]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md
+[3]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md

+ 2 - 1
composer.json

@@ -2,6 +2,7 @@
     "require": {
         "php-ffmpeg/php-ffmpeg": "0.3.x-dev@dev",
         "sabre/vobject": "~3.1",
-        "toin0u/digitalocean": "~1.4"
+        "toin0u/digitalocean": "~1.4",
+        "twig/twig": "1.*"
     }
 }

+ 843 - 0
composer.lock

@@ -0,0 +1,843 @@
+{
+    "_readme": [
+        "This file locks the dependencies of your project to a known state",
+        "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
+        "This file is @generated automatically"
+    ],
+    "hash": "65894a3b6a22df32a403b1e0d6a7b742",
+    "packages": [
+        {
+            "name": "alchemy/binary-driver",
+            "version": "1.5.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/alchemy-fr/BinaryDriver.git",
+                "reference": "b32c03d4b56ce29f783051eac55887adae654b41"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/alchemy-fr/BinaryDriver/zipball/b32c03d4b56ce29f783051eac55887adae654b41",
+                "reference": "b32c03d4b56ce29f783051eac55887adae654b41",
+                "shasum": ""
+            },
+            "require": {
+                "evenement/evenement": "~1.0",
+                "monolog/monolog": "~1.3",
+                "php": ">=5.3.3",
+                "psr/log": "~1.0",
+                "symfony/process": "~2.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~3.7"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "Alchemy": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Romain Neutron",
+                    "email": "imprec@gmail.com",
+                    "homepage": "http://www.lickmychip.com/"
+                },
+                {
+                    "name": "Nicolas Le Goff",
+                    "email": "legoff.n@gmail.com"
+                },
+                {
+                    "name": "Phraseanet Team",
+                    "email": "info@alchemy.fr",
+                    "homepage": "http://www.phraseanet.com/"
+                }
+            ],
+            "description": "A set of tools to build binary drivers",
+            "keywords": [
+                "binary",
+                "driver"
+            ],
+            "time": "2013-06-21 15:51:20"
+        },
+        {
+            "name": "doctrine/cache",
+            "version": "v1.3.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/doctrine/cache.git",
+                "reference": "cf483685798a72c93bf4206e3dd6358ea07d64e7"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/doctrine/cache/zipball/cf483685798a72c93bf4206e3dd6358ea07d64e7",
+                "reference": "cf483685798a72c93bf4206e3dd6358ea07d64e7",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.2"
+            },
+            "conflict": {
+                "doctrine/common": ">2.2,<2.4"
+            },
+            "require-dev": {
+                "phpunit/phpunit": ">=3.7",
+                "satooshi/php-coveralls": "~0.6"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.4.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Doctrine\\Common\\Cache\\": "lib/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Roman Borschel",
+                    "email": "roman@code-factory.org"
+                },
+                {
+                    "name": "Benjamin Eberlei",
+                    "email": "kontakt@beberlei.de"
+                },
+                {
+                    "name": "Guilherme Blanco",
+                    "email": "guilhermeblanco@gmail.com"
+                },
+                {
+                    "name": "Jonathan Wage",
+                    "email": "jonwage@gmail.com"
+                },
+                {
+                    "name": "Johannes Schmitt",
+                    "email": "schmittjoh@gmail.com"
+                }
+            ],
+            "description": "Caching library offering an object-oriented API for many cache backends",
+            "homepage": "http://www.doctrine-project.org",
+            "keywords": [
+                "cache",
+                "caching"
+            ],
+            "time": "2014-09-17 14:24:04"
+        },
+        {
+            "name": "evenement/evenement",
+            "version": "v1.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/igorw/evenement.git",
+                "reference": "fa966683e7df3e5dd5929d984a44abfbd6bafe8d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/igorw/evenement/zipball/fa966683e7df3e5dd5929d984a44abfbd6bafe8d",
+                "reference": "fa966683e7df3e5dd5929d984a44abfbd6bafe8d",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "Evenement": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Igor Wiedler",
+                    "email": "igor@wiedler.ch",
+                    "homepage": "http://wiedler.ch/igor/"
+                }
+            ],
+            "description": "Événement is a very simple event dispatching library for PHP 5.3",
+            "keywords": [
+                "event-dispatcher"
+            ],
+            "time": "2012-05-30 15:01:08"
+        },
+        {
+            "name": "monolog/monolog",
+            "version": "1.11.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/Seldaek/monolog.git",
+                "reference": "ec3961874c43840e96da3a8a1ed20d8c73d7e5aa"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/Seldaek/monolog/zipball/ec3961874c43840e96da3a8a1ed20d8c73d7e5aa",
+                "reference": "ec3961874c43840e96da3a8a1ed20d8c73d7e5aa",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0",
+                "psr/log": "~1.0"
+            },
+            "provide": {
+                "psr/log-implementation": "1.0.0"
+            },
+            "require-dev": {
+                "aws/aws-sdk-php": "~2.4, >2.4.8",
+                "doctrine/couchdb": "~1.0@dev",
+                "graylog2/gelf-php": "~1.0",
+                "phpunit/phpunit": "~3.7.0",
+                "raven/raven": "~0.5",
+                "ruflin/elastica": "0.90.*",
+                "videlalvaro/php-amqplib": "~2.4"
+            },
+            "suggest": {
+                "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
+                "doctrine/couchdb": "Allow sending log messages to a CouchDB server",
+                "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
+                "ext-mongo": "Allow sending log messages to a MongoDB server",
+                "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
+                "raven/raven": "Allow sending log messages to a Sentry server",
+                "rollbar/rollbar": "Allow sending log messages to Rollbar",
+                "ruflin/elastica": "Allow sending log messages to an Elastic Search server",
+                "videlalvaro/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.11.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Monolog\\": "src/Monolog"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jordi Boggiano",
+                    "email": "j.boggiano@seld.be",
+                    "homepage": "http://seld.be"
+                }
+            ],
+            "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
+            "homepage": "http://github.com/Seldaek/monolog",
+            "keywords": [
+                "log",
+                "logging",
+                "psr-3"
+            ],
+            "time": "2014-09-30 13:30:58"
+        },
+        {
+            "name": "neutron/temporary-filesystem",
+            "version": "2.1.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/romainneutron/Temporary-Filesystem.git",
+                "reference": "6b21fa99fd452efea16b9a7adb7304ccfff854d0"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/romainneutron/Temporary-Filesystem/zipball/6b21fa99fd452efea16b9a7adb7304ccfff854d0",
+                "reference": "6b21fa99fd452efea16b9a7adb7304ccfff854d0",
+                "shasum": ""
+            },
+            "require": {
+                "symfony/filesystem": "~2.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~3.7"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "Neutron": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Romain Neutron",
+                    "email": "imprec@gmail.com",
+                    "homepage": "http://www.lickmychip.com/"
+                }
+            ],
+            "description": "Symfony filesystem extension to handle temporary files",
+            "time": "2013-10-10 10:58:09"
+        },
+        {
+            "name": "php-ffmpeg/php-ffmpeg",
+            "version": "0.3.x-dev",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/PHP-FFMpeg/PHP-FFMpeg.git",
+                "reference": "185fb5c33da594db7ffbf3f89d48e9841bc666a0"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/PHP-FFMpeg/PHP-FFMpeg/zipball/185fb5c33da594db7ffbf3f89d48e9841bc666a0",
+                "reference": "185fb5c33da594db7ffbf3f89d48e9841bc666a0",
+                "shasum": ""
+            },
+            "require": {
+                "alchemy/binary-driver": "~1.5",
+                "doctrine/cache": "~1.0",
+                "evenement/evenement": "~1.0",
+                "neutron/temporary-filesystem": "~2.1, >=2.1.1",
+                "php": ">=5.3.3"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~3.7",
+                "sami/sami": "~1.0",
+                "silex/silex": "~1.0"
+            },
+            "suggest": {
+                "php-ffmpeg/extras": "A compilation of common audio & video drivers for PHP-FFMpeg"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "0.4-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "FFMpeg": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Romain Neutron",
+                    "email": "imprec@gmail.com",
+                    "homepage": "http://www.lickmychip.com/"
+                },
+                {
+                    "name": "Phraseanet Team",
+                    "email": "info@alchemy.fr",
+                    "homepage": "http://www.phraseanet.com/"
+                }
+            ],
+            "description": "FFMpeg PHP, an Object Oriented library to communicate with AVconv / ffmpeg",
+            "keywords": [
+                "audio",
+                "audio processing",
+                "avconv",
+                "avprobe",
+                "ffmpeg",
+                "ffprobe",
+                "video",
+                "video processing"
+            ],
+            "time": "2013-10-21 12:13:46"
+        },
+        {
+            "name": "psr/log",
+            "version": "1.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/log.git",
+                "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b",
+                "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b",
+                "shasum": ""
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "Psr\\Log\\": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "http://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for logging libraries",
+            "keywords": [
+                "log",
+                "psr",
+                "psr-3"
+            ],
+            "time": "2012-12-21 11:40:51"
+        },
+        {
+            "name": "sabre/vobject",
+            "version": "3.3.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/fruux/sabre-vobject.git",
+                "reference": "de508f160e811c09b5e651909eb20b9e058a043c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/fruux/sabre-vobject/zipball/de508f160e811c09b5e651909eb20b9e058a043c",
+                "reference": "de508f160e811c09b5e651909eb20b9e058a043c",
+                "shasum": ""
+            },
+            "require": {
+                "ext-mbstring": "*",
+                "php": ">=5.3.1"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "*",
+                "squizlabs/php_codesniffer": "*"
+            },
+            "bin": [
+                "bin/vobject",
+                "bin/generate_vcards"
+            ],
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.2.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Sabre\\VObject\\": "lib/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Evert Pot",
+                    "email": "me@evertpot.com",
+                    "homepage": "http://evertpot.com/",
+                    "role": "Developer"
+                },
+                {
+                    "name": "Dominik Tobschall",
+                    "email": "dominik@fruux.com",
+                    "homepage": "http://tobschall.de/",
+                    "role": "Developer"
+                }
+            ],
+            "description": "The VObject library for PHP allows you to easily parse and manipulate iCalendar and vCard objects",
+            "homepage": "http://sabre.io/vobject/",
+            "keywords": [
+                "VObject",
+                "iCalendar",
+                "jCal",
+                "jCard",
+                "vCard"
+            ],
+            "time": "2014-10-09 15:59:25"
+        },
+        {
+            "name": "symfony/console",
+            "version": "v2.5.5",
+            "target-dir": "Symfony/Component/Console",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/Console.git",
+                "reference": "ca053eaa031c93afb68a71e4eb1f4168dfd4a661"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/Console/zipball/ca053eaa031c93afb68a71e4eb1f4168dfd4a661",
+                "reference": "ca053eaa031c93afb68a71e4eb1f4168dfd4a661",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "require-dev": {
+                "psr/log": "~1.0",
+                "symfony/event-dispatcher": "~2.1"
+            },
+            "suggest": {
+                "psr/log": "For using the console logger",
+                "symfony/event-dispatcher": ""
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.5-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Symfony\\Component\\Console\\": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Symfony Community",
+                    "homepage": "http://symfony.com/contributors"
+                },
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                }
+            ],
+            "description": "Symfony Console Component",
+            "homepage": "http://symfony.com",
+            "time": "2014-09-25 09:53:56"
+        },
+        {
+            "name": "symfony/filesystem",
+            "version": "v2.5.5",
+            "target-dir": "Symfony/Component/Filesystem",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/Filesystem.git",
+                "reference": "4e62fab0060a826561c78b665925b37c870c45f5"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/Filesystem/zipball/4e62fab0060a826561c78b665925b37c870c45f5",
+                "reference": "4e62fab0060a826561c78b665925b37c870c45f5",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.5-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Symfony\\Component\\Filesystem\\": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Symfony Community",
+                    "homepage": "http://symfony.com/contributors"
+                },
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                }
+            ],
+            "description": "Symfony Filesystem Component",
+            "homepage": "http://symfony.com",
+            "time": "2014-09-22 09:14:18"
+        },
+        {
+            "name": "symfony/process",
+            "version": "v2.5.5",
+            "target-dir": "Symfony/Component/Process",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/Process.git",
+                "reference": "8a1ec96c4e519cee0fb971ea48a1eb7369dda54b"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/Process/zipball/8a1ec96c4e519cee0fb971ea48a1eb7369dda54b",
+                "reference": "8a1ec96c4e519cee0fb971ea48a1eb7369dda54b",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.5-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Symfony\\Component\\Process\\": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Symfony Community",
+                    "homepage": "http://symfony.com/contributors"
+                },
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                }
+            ],
+            "description": "Symfony Process Component",
+            "homepage": "http://symfony.com",
+            "time": "2014-09-23 05:25:11"
+        },
+        {
+            "name": "symfony/yaml",
+            "version": "v2.5.5",
+            "target-dir": "Symfony/Component/Yaml",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/Yaml.git",
+                "reference": "b1dbc53593b98c2d694ebf383660ac9134d30b96"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/Yaml/zipball/b1dbc53593b98c2d694ebf383660ac9134d30b96",
+                "reference": "b1dbc53593b98c2d694ebf383660ac9134d30b96",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.5-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Symfony\\Component\\Yaml\\": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Symfony Community",
+                    "homepage": "http://symfony.com/contributors"
+                },
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                }
+            ],
+            "description": "Symfony Yaml Component",
+            "homepage": "http://symfony.com",
+            "time": "2014-09-22 09:14:18"
+        },
+        {
+            "name": "toin0u/digitalocean",
+            "version": "1.4.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/toin0u/DigitalOcean.git",
+                "reference": "fb460785207fa4029217eef489508b9ed6c61b00"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/toin0u/DigitalOcean/zipball/fb460785207fa4029217eef489508b9ed6c61b00",
+                "reference": "fb460785207fa4029217eef489508b9ed6c61b00",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0",
+                "symfony/console": "~2.3",
+                "symfony/yaml": "~2.3",
+                "toin0u/http-adapter": "~1.0"
+            },
+            "require-dev": {
+                "satooshi/php-coveralls": "~0.6"
+            },
+            "bin": [
+                "digitalocean"
+            ],
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.4-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "DigitalOcean": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Antoine Corcy",
+                    "email": "contact@sbin.dk",
+                    "homepage": "http://sbin.dk",
+                    "role": "Developer"
+                }
+            ],
+            "description": "DigitalOcean API PHP 5.3+ library",
+            "homepage": "https://github.com/toin0u/DigitalOcean",
+            "keywords": [
+                "Cloud Hosting",
+                "SSD",
+                "api",
+                "digitalocean",
+                "vps"
+            ],
+            "time": "2014-01-14 22:20:56"
+        },
+        {
+            "name": "toin0u/http-adapter",
+            "version": "1.0.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/toin0u/HttpAdapter.git",
+                "reference": "29253948d446bc3afc29897ac67b4cd01f56cd10"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/toin0u/HttpAdapter/zipball/29253948d446bc3afc29897ac67b4cd01f56cd10",
+                "reference": "29253948d446bc3afc29897ac67b4cd01f56cd10",
+                "shasum": ""
+            },
+            "require": {
+                "ext-curl": "*",
+                "php": ">=5.3.0"
+            },
+            "require-dev": {
+                "guzzle/guzzle": "@stable",
+                "kriswallsmith/buzz": "@stable",
+                "satooshi/php-coveralls": "~0.6",
+                "zendframework/zendframework": "~2.1"
+            },
+            "suggest": {
+                "guzzle/guzzle": "Enabling Guzzle allows you to use the GuzzleHttpAdapter",
+                "kriswallsmith/buzz": "Enabling Buzz allows you to use the BuzzHttpAdapter",
+                "zendframework/zendframework": "Enabling Zend Http allows you to use the ZendHttpAdapter"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "HttpAdapter": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Antoine Corcy",
+                    "email": "contact@sbin.dk",
+                    "homepage": "http://sbin.dk",
+                    "role": "Developer"
+                }
+            ],
+            "description": "HttpAdapter PHP 5.3+ library",
+            "homepage": "https://github.com/toin0u/HttpAdapter",
+            "keywords": [
+                "adapter",
+                "http"
+            ],
+            "time": "2013-05-26 18:18:11"
+        },
+        {
+            "name": "twig/twig",
+            "version": "v1.16.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/fabpot/Twig.git",
+                "reference": "7c4c01dcf578523cfcddf383641a4f12790270ec"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/fabpot/Twig/zipball/7c4c01dcf578523cfcddf383641a4f12790270ec",
+                "reference": "7c4c01dcf578523cfcddf383641a4f12790270ec",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.2.4"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.16-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Twig_": "lib/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com",
+                    "homepage": "http://fabien.potencier.org",
+                    "role": "Lead Developer"
+                },
+                {
+                    "name": "Armin Ronacher",
+                    "email": "armin.ronacher@active-4.com",
+                    "role": "Project Founder"
+                },
+                {
+                    "name": "Twig Team",
+                    "homepage": "https://github.com/fabpot/Twig/graphs/contributors",
+                    "role": "Contributors"
+                }
+            ],
+            "description": "Twig, the flexible, fast, and secure template language for PHP",
+            "homepage": "http://twig.sensiolabs.org",
+            "keywords": [
+                "templating"
+            ],
+            "time": "2014-10-10 14:09:53"
+        }
+    ],
+    "packages-dev": [],
+    "aliases": [],
+    "minimum-stability": "stable",
+    "stability-flags": {
+        "php-ffmpeg/php-ffmpeg": 20
+    },
+    "prefer-stable": false,
+    "platform": [],
+    "platform-dev": []
+}

+ 2 - 2
custompages/index-unlogged.php

@@ -102,12 +102,12 @@ $rootWeb = api_get_path('WEB_PATH');
 			<div id="links">
 
                 <?php if (api_get_setting('allow_registration') === 'true') { ?>
-                <a href="<?php echo api_get_path(WEB_PATH); ?>main/auth/inscription.php">
+                <a href="<?php echo api_get_path(WEB_PATH); ?>main/auth/inscription.php?language=<?php echo api_get_interface_language(); ?>">
                     <?php echo custompages_get_lang('langReg')?>
                 </a><br />
                 <?php } ?>
 
-                <a href="<?php echo api_get_path(WEB_PATH); ?>main/auth/lostPassword.php">
+                <a href="<?php echo api_get_path(WEB_PATH); ?>main/auth/lostPassword.php?language=<?php echo api_get_interface_language(); ?>">
                     <?php echo custompages_get_lang('langLostPassword')?>
                 </a>
 			</div>

+ 8 - 1
custompages/language.php

@@ -51,7 +51,14 @@ if (isset($_REQUEST['language']) && !empty($_REQUEST['language']) && in_array($_
 if (isset($_REQUEST['lang']) && !empty($_REQUEST['lang']) && in_array($_REQUEST['lang'], $available_langs)) {
 	$lang_match = $chamilo_langs[$_REQUEST['lang']];
 }
-$_user['language'] = $lang_match;
+global $_configuration;
+$defaultLanguage = api_get_interface_language();
+if (isset($_configuration['auto_detect_language_custom_pages']) &&
+    $_configuration['auto_detect_language_custom_pages'] == true
+) {
+    $defaultLanguage = $lang_match;
+}
+$_user['language'] = $defaultLanguage;
 
 $_SESSION['user_language_choice'] = $lang_match;
 

+ 1 - 3
custompages/lostpassword.php

@@ -52,10 +52,8 @@ require_once('language.php');
 		}?>
 			<form id="lostpassword-form" class="form" action="lostPassword.php" method="post">
 				<div>
-        <label for="user">*<?php echo custompages_get_lang('UserName');?></label>
+                    <label for="user">*<?php echo custompages_get_lang('LoginOrEmailAddress');?></label>
 					<input name="user" type="text" /><br />
-          <label for="email">*<?php echo custompages_get_lang('Email');?></label>
-					<input name="email" type="text" /><br />
 				</div>
 			</form>
 			<div id="lostpassword-form-submit" class="form-submit" onclick="document.forms['lostpassword-form'].submit();">

+ 11 - 2
documentation/changelog.html

@@ -44,9 +44,18 @@
 <p><i>Note: most #wxyz references are issue numbers you can find in <a href="http://support.chamilo.org/projects/chamilo-18/issues" target="_blank">our public bug tracking system</a>. Some references marked BT#xyz are developments made externally for BeezNest customers and integrated into Chamilo. The details of these tasks cannot be seen for confidentiality reasons, but the code change is public and can be reviewed by anyone.</i></p>
 <p>&nbsp;</p>
 
-<h1>Chamilo 1.9.8.3 - 21st of July, 2014</h1>
+<h1>Chamilo 1.9.10 - 30th of October, 2014</h1>
 <h3>Release notes - summary</h3>
-<p>Chamilo 1.9.8.3 is a small patch version with a few minor bugfixes and a new packaging. This will be packaged and promoted as 1.9.8, but the folder inside the 1.9.8 will be called 1.9.8.3, with a few changes to this changelog file and a few fixes throughout the code (as such, you can just overwrite previous files to upgrade from 1.9.8, 1.9.8.1 or 1.9.8.2 to 1.9.8.3).</p>
+<p>Chamilo 1.9.10 is a patch version with a few minor bugfixes and a new packaging. This will be packaged and promoted as 1.9.8, but the folder inside the 1.9.8 will be called 1.9.10, with a few changes to this changelog file and a few fixes throughout the code (as such, you can just overwrite previous files to upgrade from 1.9.8, 1.9.8.1 or 1.9.8.2 to 1.9.10).</p>
+<h3>Release name</h3>
+<p><a href="http://es.wikipedia.org/wiki/Departamento_de_Huánuco">Huánuco</a> is a small city in the Peruvian Andes, Northeast of Lima. This is a special version in memory of our cherished development team member César Perales, who passed away on July 22nd, 2014, at age 27. César contributed mostly "in the shadow" to Chamilo LMS, allowing the rest of the team to contribute more actively. He was a vibrant young man. He will be missed. César lived in calle Huánuco, in La Molina, Lima, Peru, where other team members bid him their last farewell for his last, eternal trip.</p>
+
+<h3>Possibly breaking changes</h3>
+<p>Two changes have been made to the forum tool code, which might make some of your forums disappear and require a direct database intervention.<br />
+First case: If you use forums with sessions and have placed a session forum inside a base-course forum category, the forum category will now no longer appear in any session, and as such, the session forums contained in that category will disappear. You can easily fix that by checking the c_forum_forum table for any record with session_id != 0 that points to a forum category that has session_id == 0. This is related to issue #7264.<br />
+Second case: if you use group forums and have had issues with posts appearing twice, then this release will fix this bug, but might also make some forum posts disappear. Although we could not reproduce the error, you should be able to fix it by changing the group_id column inside the c_forum_thread table. This is related to issue #7267<br />
+This is an exceptional event in the history of Chamilo, and we believe it should only affect very few portals, but we prefer to take precautionnary measures and warn you upfront.<br />
+</p>
 
 <h3>New Features</h3>
 <ul>

+ 4 - 2
documentation/credits.html

@@ -683,7 +683,7 @@ Note that we are infinitely grateful to our translators, having made the spread
   <li>Gaëtan Frenoy, for efficient and well-coded updates to Drupal module and the integration with Drupal Ubercart in 1.9.8</li>
   <li>Francis Gonzales Tello, for a first draft of the OpenMeetings plugin for 1.9.8</li>
   <li>Maxim Solodovnik, for his help in the development of the OpenMeetings plugin for 1.9.8 - see https://issues.apache.org/jira/browse/OPENMEETINGS-802</li>
-  <li>Hector Lacherre, Alan Garcia, Genesis Lopez and Kenny Rodas, for their work extending Chamilo at USIL and letting us share the advance (notably for exercises tool and the tickets plugin) in 1.8 and 1.9</li>
+  <li>Hector Lacherre, Alan García, Genesis Lopez and Kenny Rodas, for their work extending Chamilo at USIL and letting us share the advance (notably for exercises tool and the tickets plugin) in 1.8 and 1.9</li>
   <li>Adolfo Igualada Martínez, for changes to the glossary to PDF export for subdir installs in 1.9.8 (#6929)</li>
   <li>Kevin Levron, for several contributions to Chamilo LMS 1.9.*</li>
   <li>Cesar Perales, for several contributions to Chamilo LMS 1.9.*</li>
@@ -700,11 +700,13 @@ These institutions and companies have either contributed to a better free Chamil
 <ul>
   <li>Académie d'Aix-Marseilles, France</li>
   <li>ACTA VZW, Belgium</li>
+  <li>agence-codecouleurs.fr, France</li>
   <li>APA e-Learning, Spain</li>
   <li>BeezNest Belgium, Brussels, Belgium</li>
   <li>BeezNest Latino, Lima, Peru</li>
   <li>Commission Scolaire des Hautes-Rivières, project TIC-FP, Canada</li>
   <li>Contidos Dixitais, Lugo, Spain</li>
+  <li>Costengineering.eu, The Netherlands</li>
   <li>Encora/HBO5, Antwerp, Belgium</li>
   <li>EPSU, Genève, Switzerland</li>
   <li>ESIAJ, Namur, Belgium</li>
@@ -714,7 +716,7 @@ These institutions and companies have either contributed to a better free Chamil
   <li>Imag'in, Nouméa, New Caledony</li>
   <li>IPYS, Lima, Peru</li>
   <li>Ministerio de Educación, Peru</li>
-  <li>NoSoloRed, Spain</li> 
+  <li>NoSoloRed, Spain</li>
   <li>Ricoh, Panama</li>
   <li>Rimac Seguros, Peru</li>
   <li>Universidad San Ignacio de Loyola, Lima, Peru</li>

+ 24 - 0
documentation/dependencies.html

@@ -102,6 +102,30 @@ We recommend using HTML5-compatible technology.
   <li>xajax </li>
   <li>jQuery</li>
 </ul>
+<h2>Extra features dependencies - server-side</h2>
+Chamilo LMS is a very complex software suite, and some of its components wil
+only work when some specific server-side libraries are installed. The names of
+the libraries below are taken from a Debian/Ubuntu installation, so you might
+need to adapt these if you are installing on Windows, Mac or another Linux
+distribution.<br />
+Please note that, as for the rest of free software, we are NOT giving or
+implying any warranty of any kind that this will work on your system, even on
+the intended Debian/Ubuntu systems. You should take your own precautions to
+ensure all components are installed by an expert in the field.<br />
+  <ul>
+    <li>Chamilo Rapid (ex Oogie(TM))</li>
+      <ul>
+        <li>libreoffice</li>
+      </ul>
+    <li>Audio recording</li>
+      <ul>
+        <li>libav-tools</li>
+      </ul>
+    <li>BigBlueButton videoconference</li>
+      <ul>
+        <li>bigbluebutton</li>
+      </ul>
+  </ul>
 </div>
 <hr />
     <a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-xhtml10-blue" alt="Valid XHTML 1.0 Transitional" style="margin: 1em; float: right;" height="31" width="88" /></a>

+ 13 - 5
documentation/installation_guide.html

@@ -796,13 +796,21 @@ Provider</a> for) include a full review of the full-text search feature.
 <h2><a name="11._Chamilo_rapid_ppt_conversion"></a>Chamilo Rapid - PPT conversion system</h2>
 <p>
 <em>Note</em>: This step will require a dedicated server or a virtual dedicated server as the packages involved are not available on most shared hosting solutions.<br />
-On Debian or Ubuntu 11.10 and superior, install LibreOffice.org v3 and start it as a headless server:
+On Debian or Ubuntu 11.10 and superior, install LibreOffice v3 (or v4) and start it as a headless server:
 <pre>
-sudo apt-get install libreoffice
-sudo soffice -accept="socket,host=127.0.0.1,port=2002,tcpNoDelay=1;urp;" -headless -nodefault -nofirststartwizard -nolockcheck -nologo -norestore &amp;
+sudo apt-get install libreoffice screen
+sudo screen
+su - www-data
+soffice --accept="socket,host=127.0.0.1,port=2002,tcpNoDelay=1;urp;" --headless --nodefault --nofirststartwizard --nolockcheck --nologo --norestore
+CTRL+a, CTRL+d
 </pre>
-Then go to your administration page -&gt; <i>Chamilo Rapid</i> and set the host to "localhost" and the port to "2002". Save. Go to your course, learning path tool and see the new icon appeared. Import your PPT. This should work.
-<em>Note</em>: Sometimes, this doesn't work out so easily. You can probably ask for the assistance of any system administrator around with a bit of Java and PHP experience, or you can always ask one of the Chamilo's Official Providers for assistance (ask for a guaranteed commercial contract).
+Please note that this will effectively launch LibreOffice in a "headless" mode (thanks to the --headless option), in a "headless" terminal (thanks to screen). You can later get back into your "headless" terminal by launching:
+<pre>
+sudo screen -r
+</pre>
+You can then go to your administration page -&gt; <i>Chamilo Rapid</i> and set the host to "localhost" and the port to "2002". Save. Go to your course, learning path tool and see the new icon appeared. Import your PPT. This should work.
+<em>Note</em>: Sometimes, this doesn't work out so easily. You can probably ask for the assistance of any system administrator around with a bit of Java and PHP experience, or you can always ask one of the Chamilo's Official Providers for assistance (ask for a guaranteed commercial contract). The above is *not* meant for production servers with a high load. You should get a real system administrator to look at it and develop init scripts, in a way that makes monitoring and relaunching feasable. If any sysadmin wants to contribute this, feel free to contribute it to Chamilo: send us an e-mail at info@chamilo.org.
+<em>Note</em>: If you use LibreOffice 4, please note that version 4.2 (available in Ubuntu 14.04) has demonstrated to be more successfull at converting documents than version 4.1, which tended to crash when sending a document for conversion.
 </p>
 
 <hr style="width: 100%; height: 2px;" />

+ 4 - 3
documentation/installation_guide_es_ES.html

@@ -729,14 +729,15 @@ Nota: Este paso requiere un servidor dedicado o un servidor dedicado virtual ya
 En Debian o Ubuntu 11.10 y superior, instale LibreOffice.org v3 e iniciarlo como un servidor en segundo plano:
 <pre>
 sudo apt-get install libreoffice
-sudo soffice -accept="socket,host=127.0.0.1,port=2002,tcpNoDelay=1;urp;" -headless -nodefault -nofirststartwizard -nolockcheck -nologo -norestore &amp;
+sudo soffice --accept="socket,host=127.0.0.1,port=2002,tcpNoDelay=1;urp;" --headless --nodefault --nofirststartwizard --nolockcheck --nologo --norestore &amp;
 </pre>
 </p>
 <p>
-A continuación, vaya a la página de administración -&gt; Chamilo Rapid y establecer el host a "localhost" y el puerto a "2002". Guarde los cambios. Vaya a su curso, en la pantalla de herramientas de aprendizaje y verá que apareció un nuevo icono. Importar tu PPT. Esto debería funcionar.
+A continuación, vaya a la página de administración -&gt; Chamilo Rapid y establecer el host a "localhost" y el puerto a "2002". Guarde los cambios. Vaya a su curso, en la pantalla de herramientas de aprendizaje y verá que apareció un nuevo icono. Importar tu PPT. Esto debería funcionar. Otra possibilidad es lanzar soffice desde una instancia de "screen", sin el &amp; al final.
 </p>
 <p>
-Nota: A veces, esto no se resuelve tan fácilmente. Usted probablemente tenga que solicitar la asistencia de algún administrador de sistemas con un poco de experiencia en  Java y PHP, o siempre podrá preguntar a uno de los proveedores oficiales de Chamilo para asistirle (pregunte por un contrato comercial garantizado).
+<em>Nota</em>: A veces, esto no se resuelve tan fácilmente. Usted probablemente tenga que solicitar la asistencia de algún administrador de sistemas con un poco de experiencia en  Java y PHP, o siempre podrá preguntar a uno de los proveedores oficiales de Chamilo para asistirle (pregunte por un contrato comercial garantizado).
+<em>Nota</em>: Si usa la versión 4 de LibreOffice, es importante notar que la versión 4.2 (disponible en Ubuntu 14.04) ha mostrado resultados considerablemente más exitosos al momento de convertir documentos que la versión 4.1 (disponible en Ubuntu 13.10), la cual tiene tendencia a colgarse durante las conversiones.
 </p>
 
 <hr style="width: 100%; height: 2px;" />

+ 68 - 0
documentation/optimization.html

@@ -50,6 +50,7 @@
   <li><a href="#8.Avoid-non-fixed-values">Avoiding non-fixed values</a></li>
   <li><a href="#9.xsendfile">Speeding file downloads with mod_xsendfile</a></li>
   <li><a href="#10.igbinary">IGBinary for faster courses backups and better sessions</a></li>
+  <li><a href="#11.permissions-check">Removing files download permissions check</a></li>
 </ol>
 
 <h2><a name="1.Using-XCache"></a>1. Using xCache or APC</h2>
@@ -245,6 +246,38 @@ If you use php5-memcached (different set of functions than php5-memcache!), then
             ...
         }
 </pre>
+Finally, the Free Campus of Chamilo has a very specific case of slow query: the courses catalog! Because there might be more than 30,000 courses in there, getting the number of "Connections last month" can be a desastrous query in terms of performances. This is why you should try to cache the results as well.<br />
+Obviously, as we are speaking about showing the number of visits this month, it doesn't really matter if the number doesn't refresh for an hour or so...<br />
+Locate the main/inc/lib/course_category.lib.php file, open it and go to the browseCoursesInCategory() function.<br />
+Locate the $count_connections_last_month = Tracking::get_course_connections_count(...) call, and wrap in into something like this:
+<pre>
+    $xc = method_exists('Memcached', 'add');
+    if ($xc) {
+        // Make sure the server is available
+        $xm = new Memcached;
+        $xm->addServer('localhost', 11211);
+        // The following concatenates the name of the database + the id of the
+        // access url to make it a unique variable prefix for the variables to
+        // be stored
+        $xs = $_configuration['main_database'].'_'.$_configuration['access_url'].'_';
+    }
+    $result = Database::query($sql);
+    $courses = array();
+    while ($row = Database::fetch_array($result)) {
+        $row['registration_code'] = !empty($row['registration_code']);
+        $count_users = CourseManager::get_users_count_in_course($row['code']);
+        if ($xc) {
+            if ($xm->get($xs.'cccount_'.$row['code'])) {
+                $number = $xm->get($xs.'cccount_'.$row['code']);
+            } else {
+                $count_connections_last_month = Tracking::get_course_connections_count($row['code'], 0, api_get_utc_datetime(time() - (30 * 86400)));
+                $xm->set($xs.'cccount_'.$row['code'], $count_connections_last_month, 3600);
+            }
+        } else {
+            $count_connections_last_month = Tracking::get_course_connections_count($row['code'], 0, api_get_utc_datetime(time() - (30 * 86400)));
+        }
+   ...
+</pre>
 <hr />
 <h2><a name="2.Slow-queries"></a>2. Slow queries</h2>
 Enable slow_queries in /etc/mysqld/my.cnf, restart MySQL then follow using sudo tail -f /var/log/mysql/mysql-slow.log
@@ -369,6 +402,41 @@ Done! Now your downloads should go substantially faster. This is still a feature
 <p>
 <a href="http://pecl.php.net/package/igbinary">IGBinary</a> is a small PECL library that replaces the PHP serializer. It uses less space (so less memory for serialized objects) and is particularly efficient with memory-based storages (like Memcached). Use it for course backups (see <a href="https://support.chamilo.org/issues/4443">issue 4443</a>) or <a href="http://www.neanderthal-technology.com/2011/11/ubuntu-10-install-php-memcached-with-igbinary-support/">to boost sessions management</a>.
 </p>
+<h2><a name="#11.permissions-check"></a>Removing files download permissions check</h2>
+<p>
+This measure is not cumulative with mod_xsendfile explained above. It is not *recommended* either, as it removes an important security layer.<br />
+<br />
+In Chamilo, for security and tracking purposes, all downloaded files pass through PHP scripts that check whether the user has access to the file given his/her current permissions. This process requires important database accesses and processing, which might terminally affect your server's performance. In particular, this can have a huge effect if having hundreds of simultaneous users accessing learning paths pages composed of local resources.<br /><br />
+The logic behind this verification is that, whatever resources that needs to be downloaded/viewed that come from the /courses/ directory, the /courses/.htaccess file with get in the middle and redirect these accesses to a PHP script (usually called download.php but there are more than one depending on the type of resource).<br /><br />
+If you want to speed up files accesses and you don't really care about whom can see your files, then an option is to simply remove this redirection to download.php and let Apache treat the file on its own.<br /><br />
+Furthermore, using a PHP script for the download (unless you have special rules) will usually prevent static content caching, which will multiply downloads and use large amount of additional bandwidth.<br /><br />
+Typically, the .htaccess will look like this (with additional comments):<br />
+<pre>
+<IfModule mod_rewrite.c>
+RewriteEngine On
+RewriteBase /courses/
+RewriteCond %{REQUEST_URI} !^/main/
+RewriteRule ([^/]+)/document/(.*)&(.*)$ $1/document/$2///$3 [N]
+RewriteRule ([^/]+)/scorm/(.*)$ /main/document/download_scorm.php?doc_url=/$2&cDir=$1 [QSA,L]
+RewriteRule ([^/]+)/document/(.*)$ /main/document/download.php?doc_url=/$2&cDir=$1 [QSA,L]
+RewriteRule ([^/]+)/work/(.*)$ /main/work/download.php?file=work/$2&cDir=$1 [QSA,L]
+</IfModule>
+</pre><br />
+The idea is to remove the "scorm" line, so you are left with:
+<pre>
+<IfModule mod_rewrite.c>
+RewriteEngine On
+RewriteBase /courses/
+RewriteCond %{REQUEST_URI} !^/main/
+RewriteRule ([^/]+)/document/(.*)&(.*)$ $1/document/$2///$3 [N]
+RewriteRule ([^/]+)/document/(.*)$ /main/document/download.php?doc_url=/$2&cDir=$1 [QSA,L]
+RewriteRule ([^/]+)/work/(.*)$ /main/work/download.php?file=work/$2&cDir=$1 [QSA,L]
+</IfModule>
+</pre><br />
+This is easy, doesn't require a server reload and you should see the results pretty quickly. As mentioned above, if security of your content is an issue, though, you should avoid using this technique.
+</p>
+<p>
+</p>
 <hr />
 <h2>Authors</h2>
 <ul>

+ 3 - 5
index.php

@@ -5,9 +5,7 @@
  * @package chamilo.main
  */
 
-
 use \ChamiloSession as Session;
-
 define('CHAMILO_HOMEPAGE', true);
 
 $language_file = array('courses', 'index', 'userInfo');
@@ -20,6 +18,9 @@ require_once 'main/inc/global.inc.php';
 require_once api_get_path(LIBRARY_PATH).'userportal.lib.php';
 require_once 'main/chat/chat_functions.lib.php';
 
+// Set cookie for check if client browser are cookies enabled
+setcookie('TestCookie', 'cookies_yes', time()+3600*24*31*12);
+
 // The section (for the tabs).
 $this_section = SECTION_CAMPUS;
 
@@ -42,9 +43,6 @@ $htmlHeadXtra[] ='
     });
 </script>';
 
-//set cookie for check if client browser are cookies enabled
-setcookie('TestCookie', 'cookies_yes', time()+3600*24*31*12);
-
 $controller = new IndexManager($header_title);
 
 //Actions

+ 1 - 0
main/admin/access_url_add_courses_to_url.php

@@ -17,6 +17,7 @@ require_once api_get_path(LIBRARY_PATH).'urlmanager.lib.php';
 $this_section=SECTION_PLATFORM_ADMIN;
 
 api_protect_global_admin_script();
+
 if (!api_get_multiple_access_url()) {
     header('Location: index.php');
     exit;

+ 3 - 3
main/admin/access_url_add_users_to_url.php

@@ -12,13 +12,13 @@
 $language_file = 'admin';
 $cidReset = true;
 require_once '../inc/global.inc.php';
-$this_section=SECTION_PLATFORM_ADMIN;
+$this_section = SECTION_PLATFORM_ADMIN;
 
 require_once api_get_path(LIBRARY_PATH).'urlmanager.lib.php';
 api_protect_global_admin_script();
 if (!api_get_multiple_access_url()) {
-    header('Location: index.php');
-    exit;
+	header('Location: index.php');
+	exit;
 }
 
 $form_sent = 0;

+ 10 - 10
main/admin/access_url_check_user_session.php

@@ -34,14 +34,14 @@ $url_id                             = api_get_current_access_url_id();
 $action = $_GET['action'];
 
 switch($action) {
-    case 'add_user_to_url':        
+    case 'add_user_to_url':
         $user_id = $_REQUEST['user_id'];
         $result = UrlManager::add_user_to_url($user_id, $url_id);
         $user_info = api_get_user_info($user_id);
         if ($result) {
             $message = Display::return_message(get_lang('UserAdded').' '.api_get_person_name($user_info['firstname'], $user_info['lastname']), 'confirm');
         }
-        break;    
+        break;
 }
 
 Display::display_header($tool_name);
@@ -69,7 +69,7 @@ if ($show_users_with_problems) {
 foreach($session_list  as $session_item) {
     $session_id = $session_item['id'];
     $html .= '<h3>'.$session_item['name'].'</h3>';
-    
+
     $access_where = "(access_url_id = $url_id OR access_url_id is null )";
     if ($show_users_with_problems) {
         $access_where = "(access_url_id is null)";
@@ -85,24 +85,24 @@ foreach($session_list  as $session_item) {
 
     $result = Database::query($sql);
     $users  = Database::store_result($result);
-    
+
     if (!empty($users)) {
-        $html .= '<table class="data_table"><tr><th>'.get_lang('User').'<th>'.get_lang('Actions').'</th></tr>';   
-    
+        $html .= '<table class="data_table"><tr><th>'.get_lang('User').'<th>'.get_lang('Actions').'</th></tr>';
+
         foreach ($users as $user) {
             $user_link = '';
             if (!empty($user['user_id'])) {
-                $user_link = '<a href="'.api_get_path(WEB_CODE_PATH).'admin/user_information.php?user_id='.intval($user['user_id']).'">'.api_htmlentities(api_get_person_name($user['firstname'], $user['lastname']),ENT_QUOTES,$charset).' ('.$user['username'].')</a>';
+                $user_link = '<a href="'.api_get_path(WEB_CODE_PATH).'admin/user_information.php?user_id='.intval($user['user_id']).'">'.Security::remove_XSS(api_get_person_name($user['firstname'], $user['lastname'])).' ('.$user['username'].')</a>';
             }
 
             $link_to_add_user_in_url = '';
 
             if ($multiple_url_is_on) {
-                if ($user['access_url_id'] != $url_id) {            
+                if ($user['access_url_id'] != $url_id) {
                     $user_link .= ' '.Display::return_icon('warning.png', get_lang('UserNotAddedInURL'), array(), ICON_SIZE_MEDIUM);
-                    $add = Display::return_icon('add.png', get_lang('AddUsersToURL'), array(), ICON_SIZE_MEDIUM);                    
+                    $add = Display::return_icon('add.png', get_lang('AddUsersToURL'), array(), ICON_SIZE_MEDIUM);
                     $link_to_add_user_in_url = '<a href="'.api_get_self().'?'.Security::remove_XSS($_SERVER['QUERY_STRING']).'&action=add_user_to_url&id_session='.$id_session.'&user_id='.$user['user_id'].'">'.$add.'</a>';
-                }                
+                }
             }
             $html .= '<tr>
                     <td>

+ 5 - 4
main/admin/access_url_edit.php

@@ -111,8 +111,8 @@ $form->addRule('url', '', 'maxlength',254);
 $form->addElement('textarea','description',get_lang('Description'));
 
 //the first url with id = 1 will be always active
-if ($_GET['url_id'] != 1) {
-	$form->addElement('checkbox','active', null, get_lang('Active'));
+if (isset($_GET['url_id']) && $_GET['url_id'] != 1) {
+    $form->addElement('checkbox','active', null, get_lang('Active'));
 }
 
 $defaults['url']='http://';
@@ -132,14 +132,15 @@ if (isset($_GET['url_id'])) {
 	$submit_name = get_lang('AddUrl');
 }
 
-if (!$_configuration['multiple_access_urls']) {
-	header('Location: index.php');
+if (!api_is_multiple_url_enabled()) {
+    header('Location: index.php');
     exit;
 }
 
 $tool_name = get_lang('AddUrl');
 $interbreadcrumb[] = array ("url" => 'index.php', "name" => get_lang('PlatformAdmin'));
 $interbreadcrumb[] = array ("url" => 'access_urls.php', "name" => get_lang('MultipleAccessURLs'));
+
 Display :: display_header($tool_name);
 
 if (isset ($_GET['action'])) {

+ 1 - 1
main/admin/access_url_edit_course_category_to_url.php

@@ -184,7 +184,7 @@ if (!empty($errorMsg)) {
 <table border="0" cellpadding="5" cellspacing="0" width="100%">
 <!-- Users -->
 <tr>
-  <td align="center"><b><?php echo get_lang('CourseCategoryInPlatform') ?></b>
+  <td align="center"><b><?php echo get_lang('CourseCategoryInPlatform') ?> :</b>
   </td>
   <td></td>
   <td align="center"><b><?php printf(get_lang('CourseCategoryListInX'),$url_selected); ?></b></td>

+ 7 - 13
main/admin/access_url_edit_courses_to_url.php

@@ -46,14 +46,13 @@ if(isset($_REQUEST['add_type']) && $_REQUEST['add_type']!='') {
 }
 
 $access_url_id=1;
-if(isset($_REQUEST['access_url_id']) && $_REQUEST['access_url_id']!=''){
+if (isset($_REQUEST['access_url_id']) && $_REQUEST['access_url_id']!='') {
 	$access_url_id = Security::remove_XSS($_REQUEST['access_url_id']);
 }
 
 $xajax -> processRequests();
 $htmlHeadXtra[] = $xajax->getJavascript('../inc/lib/xajax/');
-$htmlHeadXtra[] = '
-<script type="text/javascript">
+$htmlHeadXtra[] = '<script>
 function add_user_to_url(code, content) {
 
 	document.getElementById("course_to_add").value = "";
@@ -67,7 +66,7 @@ function add_user_to_url(code, content) {
 }
 
 function send() {
-	if (document.formulaire.access_url_id.value!=0) {
+	if (document.formulaire.access_url_id.value != 0) {
 		document.formulaire.form_sent.value=0;
 		document.formulaire.add_type.value=\''.$add_type.'\';
 		document.formulaire.submit();
@@ -93,16 +92,16 @@ if (isset($_POST['form_sent']) && $_POST['form_sent']) {
 	$form_sent=$_POST['form_sent'];
 	$course_list=$_POST['course_list'];
 
-	if(!is_array($course_list)) {
+	if (!is_array($course_list)) {
 		$course_list=array();
 	}
 
-	if($form_sent == 1) {
+	if ($form_sent == 1) {
 		if ($access_url_id==0) {
 			header('Location: access_url_edit_users_to_url.php?action=show_message&message='.get_lang('SelectURL'));
 		}
 		elseif(is_array($course_list) ) {
-			UrlManager::update_urls_rel_course($course_list,$access_url_id);
+			UrlManager::update_urls_rel_course($course_list, $access_url_id);
 			header('Location: access_urls.php?action=show_message&message='.get_lang('CoursesWereEdited'));
 		}
 	}
@@ -196,6 +195,7 @@ $url_list = UrlManager::get_url_data();
 if(!empty($errorMsg)) {
 	Display::display_normal_message($errorMsg); //main API
 }
+
 ?>
 
 <table border="0" cellpadding="5" cellspacing="0" width="100%">
@@ -318,11 +318,6 @@ function valide(){
 	var options = document.getElementById('destination_users').options;
 	for (i = 0 ; i<options.length ; i++)
 		options[i].selected = true;
-	/*
-	var options = document.getElementById('destination_classes').options;
-	for (i = 0 ; i<options.length ; i++)
-		options[i].selected = true;
-		*/
 	document.forms.formulaire.submit();
 }
 
@@ -362,7 +357,6 @@ function makepost(select){
 
 	return ret;
 }
--->
 </script>
 <?php
 Display::display_footer();

+ 2 - 2
main/admin/access_url_edit_users_to_url.php

@@ -24,6 +24,7 @@ $this_section = SECTION_PLATFORM_ADMIN;
 
 // Access restrictions
 api_protect_global_admin_script();
+
 if (!api_get_multiple_access_url()) {
     header('Location: index.php');
     exit;
@@ -52,8 +53,7 @@ if (isset($_REQUEST['access_url_id']) && $_REQUEST['access_url_id'] != '') {
 
 $xajax->processRequests();
 $htmlHeadXtra[] = $xajax->getJavascript('../inc/lib/xajax/');
-$htmlHeadXtra[] = '
-<script type="text/javascript">
+$htmlHeadXtra[] = '<script>
 function add_user_to_url(code, content) {
 	document.getElementById("user_to_add").value = "";
 	document.getElementById("ajax_list_users").innerHTML = "";

+ 5 - 4
main/admin/access_urls.php

@@ -1,10 +1,11 @@
 <?php
 /* For licensing terms, see /license.txt */
 /**
-*	@package chamilo.admin
-*	@author Julio Montoya <gugli100@gmail.com>
-*/
-
+ * Frontend script for multiple access urls
+ * @package chamilo.admin
+ * @author Julio Montoya <gugli100@gmail.com>
+ * @author Yannick Warnier <yannick.warnier@beeznest.com>
+ */
 // name of the language file that needs to be included
 $language_file = 'admin';
 $cidReset = true;

+ 1 - 1
main/admin/add_courses_to_session.php

@@ -56,7 +56,7 @@ function add_course_to_session(code, content) {
 	document.getElementById("ajax_list_courses_single").innerHTML = "";
 	destination = document.getElementById("destination");
 	for (i=0;i<destination.length;i++) {
-		if(destination.options[i].text == content) {
+		if (destination.options[i].text == content) {
             return false;
 		}
 	}

+ 1 - 2
main/admin/add_courses_to_usergroup.php

@@ -39,8 +39,7 @@ if (isset($_REQUEST['add_type']) && $_REQUEST['add_type']!=''){
 $add = isset($_GET['add']) ? Security::remove_XSS($_GET['add']) : null;
 
 $htmlHeadXtra[] = $xajax->getJavascript('../inc/lib/xajax/');
-$htmlHeadXtra[] = '
-<script>
+$htmlHeadXtra[] = '<script>
 function add_user_to_session (code, content) {
     document.getElementById("user_to_add").value = "";
     document.getElementById("ajax_list_users_single").innerHTML = "";

+ 65 - 70
main/admin/add_many_session_to_category.php

@@ -15,7 +15,7 @@ require_once api_get_path(LIBRARY_PATH).'add_many_session_to_category_functions.
 require_once api_get_path(LIBRARY_PATH).'sessionmanager.lib.php';
 
 $xajax = new xajax();
-$xajax -> registerFunction ('search_courses');
+$xajax->registerFunction('search_courses');
 
 // setting the section (for the tabs)
 $this_section = SECTION_PLATFORM_ADMIN;
@@ -36,12 +36,12 @@ $tbl_session_rel_course				= Database::get_main_table(TABLE_MAIN_SESSION_COURSE)
 $tbl_course							= Database::get_main_table(TABLE_MAIN_COURSE);
 
 // setting the name of the tool
-$tool_name= get_lang('SubscribeSessionsToCategory');
-$id_session=intval($_GET['id_session']);
+$tool_name = get_lang('SubscribeSessionsToCategory');
+$id_session = isset($_GET['id_session']) ? intval($_GET['id_session']) : null;
 
 $add_type = 'multiple';
-if(isset($_GET['add_type']) && $_GET['add_type']!=''){
-	$add_type = Security::remove_XSS($_REQUEST['add_type']);
+if (isset($_GET['add_type']) && $_GET['add_type'] != '') {
+    $add_type = Security::remove_XSS($_REQUEST['add_type']);
 }
 
 if (!api_is_platform_admin() && !api_is_session_admin()) {
@@ -71,7 +71,6 @@ function add_course_to_session (code, content) {
 }
 function send() {
 	if (document.formulaire.CategorySessionId.value!=0) {
-		//alert(document.formulaire.CategorySessionId.value);
 		document.formulaire.formSent.value=0;
 		document.formulaire.submit();
 	}
@@ -87,54 +86,59 @@ function remove_item(origin)
 }
 </script>';
 
-$formSent=0;
-$errorMsg = $firstLetterCourse = $firstLetterSession='';
-$CourseList=$SessionList=array();
-$courses=$sessions=array();
-$Categoryid = intval($_POST['CategorySessionId']);
-
-if ($_POST['formSent']) {
-	$formSent=$_POST['formSent'];
-	$SessionCategoryList = $_POST['SessionCategoryList'];
-
-	if($Categoryid != 0 && count($SessionCategoryList)>0 ){
-		$session_id = join(',', $SessionCategoryList);
-		$sql = "UPDATE $tbl_session SET session_category_id = $Categoryid WHERE id in ($session_id) ";
-		Database::query($sql);
-		//header('Location: session_list.php?id_category='.$Categoryid);
-		header('Location: add_many_session_to_category.php?id_category='.$Categoryid.'&msg=ok');
-		exit;
-	} else {
-		header('Location: add_many_session_to_category.php?msg=error');
-		exit;
-	}
+$formSent = 0;
+$errorMsg = $firstLetterCourse = $firstLetterSession = '';
+$CourseList = $SessionList = array();
+$courses = $sessions = array();
+$categoryId = isset($_POST['CategorySessionId']) ? intval($_POST['CategorySessionId']) : null;
+
+if (isset($_POST['formSent']) && $_POST['formSent']) {
+    $formSent = $_POST['formSent'];
+    $sessionCategoryList = $_POST['SessionCategoryList'];
+
+
+    if ($categoryId != 0 && count($sessionCategoryList) > 0) {
+        // Removing all
+        $sql = "UPDATE $tbl_session SET session_category_id = '' WHERE session_category_id = $categoryId";
+        Database::query($sql);
+        // Adding new
+        $sessionCategoryList = array_map('intval', $sessionCategoryList);
+        $session_id = join(',', $sessionCategoryList);
+
+        $sql = "UPDATE $tbl_session SET session_category_id = $categoryId WHERE id in ($session_id) ";
+        Database::query($sql);
+        header('Location: add_many_session_to_category.php?id_category=' . $categoryId . '&msg=ok');
+        exit;
+    } else {
+        header('Location: add_many_session_to_category.php?msg=error');
+        exit;
+    }
 }
 
 if (isset($_GET['id_category'])) {
-	$Categoryid = intval($_GET['id_category']);
+    $categoryId = intval($_GET['id_category']);
 }
 
-if(isset($_GET['msg']) && $_GET['msg']=='error'){
-	$errorMsg = get_lang('MsgErrorSessionCategory');
+if (isset($_GET['msg']) && $_GET['msg'] == 'error') {
+    $errorMsg = get_lang('MsgErrorSessionCategory');
 }
 
-if(isset($_GET['msg']) && $_GET['msg']=='ok'){
-	$OkMsg = get_lang('SessionCategoryUpdate');
+if (isset($_GET['msg']) && $_GET['msg'] == 'ok') {
+    $OkMsg = get_lang('SessionCategoryUpdate');
 }
 
+$page = isset($_GET['page']) ? Security::remove_XSS($_GET['page']) : null;
 
-// display the dokeos header
 Display::display_header($tool_name);
 
-
-$where ='';
+$where = '';
 $rows_category_session = array();
-if((isset($_POST['CategorySessionId']) && $_POST['formSent'] == 0) || isset($_GET['id_category']) ) {
-	
-	$where = 'WHERE session_category_id !='.$Categoryid;
-	$sql = 'SELECT id, name  FROM '.$tbl_session .' WHERE session_category_id ='.$Categoryid.' ORDER BY name';
-	$result=Database::query($sql);
-	$rows_category_session = Database::store_result($result);
+if ((isset($_POST['CategorySessionId']) && $_POST['formSent'] == 0) || isset($_GET['id_category'])) {
+
+    $where = 'WHERE session_category_id !=' . $categoryId;
+    $sql = 'SELECT id, name  FROM ' . $tbl_session . ' WHERE session_category_id =' . $categoryId . ' ORDER BY name';
+    $result = Database::query($sql);
+    $rows_category_session = Database::store_result($result);
 }
 
 $rows_session_category = SessionManager::get_all_session_category();
@@ -150,26 +154,30 @@ if (api_get_multiple_access_url()) {
     $sql = "SELECT s.id, s.name  FROM $tbl_session s INNER JOIN $table_access_url_rel_session u ON s.id = u.session_id $where AND u.access_url_id = $access_url_id ORDER BY name";
 } else {
     $sql = "SELECT id, name  FROM $tbl_session $where ORDER BY name";
-} 
+}
 $result=Database::query($sql);
 $rows_session = Database::store_result($result);
 ?>
-<form name="formulaire" method="post" action="<?php echo api_get_self(); ?>?page=<?php echo Security::remove_XSS($_GET['page']); if(!empty($_GET['add'])) echo '&add=true' ; ?>" style="margin:0px;" <?php if($ajax_search){echo ' onsubmit="valide();"';}?>>
-    <?php echo '<legend>'.$tool_name.'</legend>'; ?>
-<input type="hidden" name="formSent" value="1" />
-<?php
-if(!empty($errorMsg)) {
-	Display::display_error_message($errorMsg); //main API
-}
+<form name="formulaire" method="post"
+      action="<?php echo api_get_self(); ?>?page=<?php echo $page;
+      if (!empty($_GET['add'])) {
+          echo '&add=true';
+      } ?>" style="margin:0px;">
+    <?php echo '<legend>' . $tool_name . '</legend>'; ?>
+    <input type="hidden" name="formSent" value="1"/>
+    <?php
+    if (!empty($errorMsg)) {
+        Display::display_error_message($errorMsg); //main API
+    }
 
 if(!empty($OkMsg)) {
 	Display::display_confirmation_message($OkMsg); //main API
 }
 
-/* 
- * 
- * The a/b/c Filter is not a priority 
- *  
+/*
+ *
+ * The a/b/c Filter is not a priority
+ *
  * <td width="45%" align="center">
  <?php echo get_lang('FirstLetterCourse'); ?> :
      <select name="firstLetterCourse" onchange = "xajax_search_courses(this.value,'multiple')">
@@ -187,14 +195,14 @@ if(!empty($OkMsg)) {
 <tr>
 	<td align="left"></td>
 	<td align="left"></td>
-	<td  align="center"> 
+	<td  align="center">
 	<b><?php echo get_lang('SessionCategoryName') ?> :</b><br />
 	<select name="CategorySessionId" style="width: 320px;" onchange="javascript:send();" >
 		<option value="0" ></option>
 		<?php
 		if (!empty($rows_session_category)) {
     		foreach($rows_session_category as $category) {
-    			if($category['id'] == $Categoryid)
+    			if($category['id'] == $categoryId)
       				echo '<option value="'.$category['id'].'" selected>'.$category['name'].'</option>';
       			else
       				echo '<option value="'.$category['id'].'">'.$category['name'].'</option>';
@@ -227,19 +235,9 @@ if(!empty($OkMsg)) {
 <?php unset($nosessionCourses); ?>
   </td>
   <td width="10%" valign="middle" align="center">
-  <?php
-  if ($ajax_search) {
-  ?>
-  	<button class="arrowl" type="button" onclick="remove_item(document.getElementById('destination'))"></button>
-  <?php
-  } else {
-  ?>
   	<button class="arrowr" type="button" onclick="moveItem(document.getElementById('origin'), document.getElementById('destination'))" onclick="moveItem(document.getElementById('origin'), document.getElementById('destination'))"></button>
 	<br /><br />
 	<button class="arrowl" type="button" onclick="moveItem(document.getElementById('destination'), document.getElementById('origin'))" onclick="moveItem(document.getElementById('destination'), document.getElementById('origin'))"></button>
-  <?php
-  }
-  ?>
 	<br /><br /><br /><br /><br /><br />
 	<?php
 		echo '<button class="save" type="button" value="" onclick="valide()" >'.get_lang('SubscribeSessionsToCategory').'</button>';
@@ -257,7 +255,6 @@ if(!empty($OkMsg)) {
 
 </form>
 <script type="text/javascript">
-<!--
 function moveItem(origin , destination) {
 	for(var i = 0 ; i<origin.options.length ; i++) {
 		if(origin.options[i].selected) {
@@ -301,9 +298,7 @@ function valide(){
 
 	document.forms.formulaire.submit();
 }
--->
-
 </script>
 <?php
-/*		FOOTER	*/
-Display::display_footer();
+
+Display::display_footer();

+ 1 - 2
main/admin/add_sessions_to_promotion.php

@@ -38,8 +38,7 @@ if (isset($_REQUEST['add_type']) && $_REQUEST['add_type']!=''){
 }
 
 $htmlHeadXtra[] = $xajax->getJavascript('../inc/lib/xajax/');
-$htmlHeadXtra[] = '
-<script>
+$htmlHeadXtra[] = '<script>
 function add_user_to_session (code, content) {
 
     document.getElementById("user_to_add").value = "";

+ 19 - 24
main/admin/add_sessions_to_usergroup.php

@@ -41,8 +41,7 @@ if(isset($_REQUEST['add_type']) && $_REQUEST['add_type']!=''){
 }
 
 $htmlHeadXtra[] = $xajax->getJavascript('../inc/lib/xajax/');
-$htmlHeadXtra[] = '
-<script type="text/javascript">
+$htmlHeadXtra[] = '<script>
 function add_user_to_session (code, content) {
 
     document.getElementById("user_to_add").value = "";
@@ -80,9 +79,9 @@ function display_advanced_search () {
 }
 
 function validate_filter() {
-        document.formulaire.add_type.value = \''.$add_type.'\';
-        document.formulaire.form_sent.value=0;
-        document.formulaire.submit();
+    document.formulaire.add_type.value = \''.$add_type.'\';
+    document.formulaire.form_sent.value=0;
+    document.formulaire.submit();
 }
 </script>';
 
@@ -92,9 +91,9 @@ $errorMsg   = '';
 $sessions=array();
 $usergroup = new UserGroup();
 $id = intval($_GET['id']);
-if($_POST['form_sent']) {
-    $form_sent          = $_POST['form_sent'];    
-    $elements_posted    = $_POST['elements_in_name'];     
+if (isset($_POST['form_sent']) && $_POST['form_sent']) {
+    $form_sent          = $_POST['form_sent'];
+    $elements_posted    = $_POST['elements_in_name'];
     if (!is_array($elements_posted)) {
         $elements_posted = array();
     }
@@ -102,7 +101,7 @@ if($_POST['form_sent']) {
         //added a parameter to send emails when registering a user        
         $usergroup->subscribe_sessions_to_usergroup($id, $elements_posted);
         header('Location: usergroups.php');
-        exit;        
+        exit;
     }
 }
 $data               = $usergroup->get($id);
@@ -113,9 +112,9 @@ $session_list       = SessionManager::get_sessions_list(array(), array('name'));
 $elements_not_in = $elements_in= array();
 
 if (!empty($session_list)) {
-    foreach($session_list as $session) {        
-        if (in_array($session['id'], $session_list_in)) {            
-            $elements_in[$session['id']] = $session['name'];             
+    foreach($session_list as $session) {
+        if (in_array($session['id'], $session_list_in)) {
+            $elements_in[$session['id']] = $session['name'];
         } else {
             $elements_not_in[$session['id']] = $session['name'];
         }
@@ -130,7 +129,7 @@ function search_sessions($needle,$type) {
     global $tbl_user,$elements_in;
     $xajax_response = new XajaxResponse();
     $return = '';
-    if (isset($needle) && !empty($type)) {
+    if (!empty($needle) && !empty($type)) {
 
         // xajax send utf8 datas... datas in db can be non-utf8 datas
         $charset = api_get_system_encoding();
@@ -147,11 +146,10 @@ function search_sessions($needle,$type) {
                 ' LIMIT 11';*/
         } else if ($type == 'searchbox') {
             $session_list = SessionManager::get_sessions_list(array('s.name LIKE' => "%$needle%"));
-        }
-        else {
+        } else {
             $session_list = SessionManager::get_sessions_list(array('s.name LIKE' => "$needle%"));
         }
-        $i=0;        
+        $i=0;
         if ($type=='single') {
             /*
             while ($user = Database :: fetch_array($rs)) {
@@ -166,9 +164,9 @@ function search_sessions($needle,$type) {
             $xajax_response -> addAssign('ajax_list_users_single','innerHTML',api_utf8_encode($return));*/
         } else {
             $return .= '<select id="elements_not_in" name="elements_not_in_name[]" multiple="multiple" size="15" style="width:360px;">';
-            
-            foreach ($session_list as $row ) {         
-                if (!in_array($row['id'], array_keys($elements_in))) {       
+
+            foreach ($session_list as $row ) {
+                if (!in_array($row['id'], array_keys($elements_in))) {
                     $return .= '<option value="'.$row['id'].'">'.$row['name'].'</option>';
                 }
             }
@@ -270,10 +268,10 @@ if(!empty($errorMsg)) {
         <input type="text" id="user_to_add" onkeyup="xajax_search_users(this.value,'single')" />
         <div id="ajax_list_users_single"></div>
         <?php
-      } else {               
+      } else {
       ?>
       <div id="ajax_list_multiple">
-        <?php echo Display::select('elements_not_in_name',$elements_not_in, '',array('style'=>'width:360px', 'multiple'=>'multiple','id'=>'elements_not_in','size'=>'15px'),false); ?> 
+        <?php echo Display::select('elements_not_in_name',$elements_not_in, '',array('style'=>'width:360px', 'multiple'=>'multiple','id'=>'elements_not_in','size'=>'15px'),false); ?>
       </div>
     <?php
       }
@@ -360,7 +358,6 @@ function valide(){
     document.forms.formulaire.submit();
 }
 
-
 function loadUsersInSelect(select){
 
     var xhr_object = null;
@@ -372,7 +369,6 @@ function loadUsersInSelect(select){
     else  // XMLHttpRequest non supporté par le navigateur
     alert("Votre navigateur ne supporte pas les objets XMLHTTPRequest...");
 
-    //xhr_object.open("GET", "loadUsersInSelect.ajax.php?id_session=<?php echo $id_session ?>&letter="+select.options[select.selectedIndex].text, false);
     xhr_object.open("POST", "loadUsersInSelect.ajax.php");
 
     xhr_object.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
@@ -400,7 +396,6 @@ function makepost(select){
 
     return ret;
 }
--->
 </script>
 <?php
 Display::display_footer();

+ 3 - 3
main/admin/add_students_to_session.php

@@ -35,7 +35,7 @@ $form_sent  = 0;
 $errorMsg   = '';
 $users = $sessions = array();
 
-$id = intval($_GET['id']);
+$id = isset($_GET['id']) ? intval($_GET['id']) : null;
 $htmlResult = null;
 
 if (isset($_POST['form_sent']) && $_POST['form_sent']) {
@@ -80,7 +80,7 @@ echo Display::input('hidden', 'form_sent', '1');
                      'sessions[]',
                      $sessionList,
                      '',
-                     array('style'=>'width:360px', 'multiple'=>'multiple', 'id'=>'sessions', 'size'=>'15px'),
+                     array('style'=>'width:100%', 'multiple'=>'multiple', 'id'=>'sessions', 'size'=>'15px'),
                      false
                  );
                 ?>
@@ -93,7 +93,7 @@ echo Display::input('hidden', 'form_sent', '1');
                     'sessions_destination[]',
                     $sessionList,
                     '',
-                    array('style'=>'width:360px', 'id'=>'courses', 'size'=>'15px'),
+                    array('style'=>'width:100%', 'id'=>'courses', 'size'=>'15px'),
                     false
                 );
                 ?>

+ 0 - 4
main/admin/add_users_to_group.php

@@ -182,10 +182,6 @@ $htmlHeadXtra[] = $xajax->getJavascript('../inc/lib/xajax/');
 $htmlHeadXtra[] = '
 <script>
 function add_user (code, content) {
-
-	// document.getElementById("user_to_add").value = "";
-	//document.getElementById("ajax_list_users_single").innerHTML = "";
-
 	destination = document.getElementById("destination_users");
 	for (i=0;i<destination.length;i++) {
 		if (destination.options[i].text == content) {

+ 95 - 34
main/admin/add_users_to_session.php

@@ -32,14 +32,13 @@ $interbreadcrumb[] = array('url' => 'session_list.php','name' => get_lang('Sessi
 $interbreadcrumb[] = array('url' => "resume_session.php?id_session=".$id_session,"name" => get_lang('SessionOverview'));
 
 // Database Table Definitions
-$tbl_session						= Database::get_main_table(TABLE_MAIN_SESSION);
-$tbl_course							= Database::get_main_table(TABLE_MAIN_COURSE);
-$tbl_user							= Database::get_main_table(TABLE_MAIN_USER);
-$tbl_session_rel_user				= Database::get_main_table(TABLE_MAIN_SESSION_USER);
+$tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
+$tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
+$tbl_user = Database::get_main_table(TABLE_MAIN_USER);
+$tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
 
 // setting the name of the tool
 $tool_name = get_lang('SubscribeUsersToSession');
-
 $add_type = 'unique';
 
 if (isset($_REQUEST['add_type']) && $_REQUEST['add_type']!='') {
@@ -48,7 +47,7 @@ if (isset($_REQUEST['add_type']) && $_REQUEST['add_type']!='') {
 
 $page = isset($_GET['page']) ? Security::remove_XSS($_GET['page']) : null;
 
-//checking for extra field with filter on
+// Checking for extra field with filter on
 
 $extra_field_list = UserManager::get_extra_fields();
 
@@ -57,20 +56,25 @@ if (is_array($extra_field_list)) {
     foreach ($extra_field_list as $extra_field) {
         //if is enabled to filter and is a "<select>" field type
         if ($extra_field[8]==1 && $extra_field[2]==4) {
-            $new_field_list[] = array('name'=> $extra_field[3], 'variable'=>$extra_field[1], 'data'=> $extra_field[9]);
+            $new_field_list[] = array(
+                'name'=> $extra_field[3],
+                'variable'=>$extra_field[1],
+                'data'=> $extra_field[9]
+            );
         }
     }
 }
 
 function search_users($needle, $type)
 {
-    global $tbl_user,$tbl_session_rel_user,$id_session;
+    global $tbl_user, $tbl_session_rel_user, $id_session;
+
     $xajax_response = new XajaxResponse();
     $return = '';
 
     if (!empty($needle) && !empty($type)) {
 
-        //normal behaviour
+        // Normal behaviour
         if ($type == 'any_session' && $needle == 'false') {
             $type = 'multiple';
             $needle = '';
@@ -82,9 +86,20 @@ function search_users($needle, $type)
         $needle = api_convert_encoding($needle, $charset, 'utf-8');
 
         $order_clause = api_sort_by_first_name() ? ' ORDER BY firstname, lastname, username' : ' ORDER BY lastname, firstname, username';
+
+
+        $showOfficialCode = false;
+        global $_configuration;
+        if (isset($_configuration['order_user_list_by_official_code']) &&
+            $_configuration['order_user_list_by_official_code']
+        ) {
+            $showOfficialCode = true;
+            $order_clause = ' ORDER BY official_code, firstname, lastname, username';
+        }
+
         $cond_user_id = '';
 
-        //Only for single & multiple
+        // Only for single & multiple
         if (in_array($type, array('single','multiple')))
         if (!empty($id_session)) {
             $id_session = intval($id_session);
@@ -108,10 +123,14 @@ function search_users($needle, $type)
                 // search users where username or firstname or lastname begins likes $needle
                 $sql = 'SELECT user.user_id, username, lastname, firstname, official_code
                         FROM '.$tbl_user.' user
-                        WHERE (username LIKE "'.$needle.'%" OR firstname LIKE "'.$needle.'%"
-                            OR lastname LIKE "'.$needle.'%") AND user.status<>6 AND user.status<>'.DRH.''.
-                            $order_clause.
-                            ' LIMIT 11';
+                        WHERE
+                            (
+                                username LIKE "'.$needle.'%" OR
+                                firstname LIKE "'.$needle.'%" OR
+                                lastname LIKE "'.$needle.'%"
+                            ) AND user.status<>6 AND user.status<>'.DRH.''.
+                        $order_clause.'
+                        LIMIT 11';
                 break;
             case 'multiple':
                 $sql = 'SELECT user.user_id, username, lastname, firstname, official_code
@@ -123,8 +142,10 @@ function search_users($needle, $type)
                 $sql = 'SELECT DISTINCT user.user_id, username, lastname, firstname, official_code
                         FROM '.$tbl_user.' user
                         LEFT OUTER JOIN '.$tbl_session_rel_user.' s ON (s.id_user = user.user_id)
-                        WHERE   s.id_user IS null AND user.status<>'.DRH.' AND
-                                user.status<>6 '.$cond_user_id.
+                        WHERE
+                            s.id_user IS null AND
+                            user.status<>'.DRH.' AND
+                            user.status<>6 '.$cond_user_id.
                         $order_clause;
                 break;
         }
@@ -138,21 +159,26 @@ function search_users($needle, $type)
                         $sql = 'SELECT user.user_id, username, lastname, firstname, official_code
                         FROM '.$tbl_user.' user
                         INNER JOIN '.$tbl_user_rel_access_url.' url_user ON (url_user.user_id=user.user_id)
-                        WHERE access_url_id = '.$access_url_id.'  AND (username LIKE "'.$needle.'%"
-                        OR firstname LIKE "'.$needle.'%"
-                        OR lastname LIKE "'.$needle.'%") AND user.status<>6 AND user.status<>'.DRH.' '.
+                        WHERE
+                            access_url_id = '.$access_url_id.' AND
+                            (
+                                username LIKE "'.$needle.'%" OR
+                                firstname LIKE "'.$needle.'%" OR
+                                lastname LIKE "'.$needle.'%"
+                            ) AND user.status<>6 AND user.status<>'.DRH.' '.
                         $order_clause.
                         ' LIMIT 11';
                         break;
                     case 'multiple':
-                        $sql = 'SELECT user.user_id, username, lastname, firstname , official_code
-                        FROM '.$tbl_user.' user
-                        INNER JOIN '.$tbl_user_rel_access_url.' url_user ON (url_user.user_id=user.user_id)
-                        WHERE access_url_id = '.$access_url_id.' AND
-                            '.(api_sort_by_first_name() ? 'firstname' : 'lastname').' LIKE "'.$needle.'%" AND
-                                user.status<>'.DRH.' AND
-                                user.status<>6 '.$cond_user_id.
-                        $order_clause;
+                        $sql = 'SELECT user.user_id, username, lastname, firstname, official_code
+                                FROM '.$tbl_user.' user
+                                INNER JOIN '.$tbl_user_rel_access_url.' url_user ON (url_user.user_id=user.user_id)
+                                WHERE
+                                    access_url_id = '.$access_url_id.' AND
+                                    '.(api_sort_by_first_name() ? 'firstname' : 'lastname').' LIKE "'.$needle.'%" AND
+                                    user.status<>'.DRH.' AND
+                                    user.status<>6 '.$cond_user_id.
+                                $order_clause;
                         break;
                     case 'any_session' :
                         $sql = 'SELECT DISTINCT user.user_id, username, lastname, firstname, official_code
@@ -164,7 +190,7 @@ function search_users($needle, $type)
                                 s.id_user IS null AND
                                 user.status<>'.DRH.' AND
                                 user.status<>6 '.$cond_user_id.
-                        $order_clause;
+                            $order_clause;
                         break;
                 }
             }
@@ -177,6 +203,11 @@ function search_users($needle, $type)
                 $i++;
                 if ($i<=10) {
                     $person_name = api_get_person_name($user['firstname'], $user['lastname']).' ('.$user['username'].') '.$user['official_code'];
+                    if ($showOfficialCode) {
+                        $officialCode = !empty($user['official_code']) ? $user['official_code'].' - ' : '? - ';
+                        $person_name = $officialCode.api_get_person_name($user['firstname'], $user['lastname']).' ('.$user['username'].')';
+                    }
+
                     $return .= '<a href="javascript: void(0);" onclick="javascript: add_user_to_session(\''.$user['user_id'].'\',\''.$person_name.' '.'\')">'.$person_name.' </a><br />';
                 } else {
                     $return .= '...<br />';
@@ -188,7 +219,13 @@ function search_users($needle, $type)
             global $nosessionUsersList;
             $return .= '<select id="origin_users" name="nosessionUsersList[]" multiple="multiple" size="15" style="width:360px;">';
             while ($user = Database :: fetch_array($rs)) {
+
                 $person_name = api_get_person_name($user['firstname'], $user['lastname']).' ('.$user['username'].') '.$user['official_code'];
+                if ($showOfficialCode) {
+                    $officialCode = !empty($user['official_code']) ? $user['official_code'].' - ' : '? - ';
+                    $person_name = $officialCode.api_get_person_name($user['firstname'], $user['lastname']).' ('.$user['username'].')';
+                }
+
 	            $return .= '<option value="'.$user['user_id'].'">'.$person_name.' </option>';
 			}
 			$return .= '</select>';
@@ -275,17 +312,28 @@ $session_info = SessionManager::fetch($id_session);
 Display::display_header($tool_name);
 
 $nosessionUsersList = $sessionUsersList = array();
-
+$where_filter = null;
 $ajax_search = $add_type == 'unique' ? true : false;
 
 $order_clause = api_sort_by_first_name() ? ' ORDER BY firstname, lastname, username' : ' ORDER BY lastname, firstname, username';
+
+$showOfficialCode = false;
+global $_configuration;
+if (isset($_configuration['order_user_list_by_official_code']) &&
+    $_configuration['order_user_list_by_official_code']
+) {
+    $showOfficialCode = true;
+    $order_clause = ' ORDER BY official_code, firstname, lastname, username';
+}
+
 if ($ajax_search) {
     $sql = "SELECT user_id, lastname, firstname, username, id_session, official_code
             FROM $tbl_user u
             INNER JOIN $tbl_session_rel_user
                 ON $tbl_session_rel_user.id_user = u.user_id AND $tbl_session_rel_user.relation_type<>".SESSION_RELATION_TYPE_RRHH."
                 AND $tbl_session_rel_user.id_session = ".intval($id_session)."
-            WHERE u.status<>".DRH." AND u.status<>6 $order_clause";
+            WHERE u.status<>".DRH." AND u.status<>6
+            $order_clause";
 
     if (api_is_multiple_url_enabled()) {
         $tbl_user_rel_access_url= Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
@@ -296,7 +344,7 @@ if ($ajax_search) {
             INNER JOIN $tbl_session_rel_user
                 ON $tbl_session_rel_user.id_user = u.user_id AND $tbl_session_rel_user.relation_type<>".SESSION_RELATION_TYPE_RRHH."
                 AND $tbl_session_rel_user.id_session = ".intval($id_session)."
-                INNER JOIN $tbl_user_rel_access_url url_user ON (url_user.user_id=u.user_id)
+            INNER JOIN $tbl_user_rel_access_url url_user ON (url_user.user_id=u.user_id)
             WHERE access_url_id = $access_url_id AND u.status<>".DRH." AND u.status<>6
             $order_clause";
         }
@@ -337,7 +385,6 @@ if ($ajax_search) {
             $final_result = $extra_field_result[0];
         }
 
-        $where_filter ='';
         if (api_is_multiple_url_enabled()) {
             if (is_array($final_result) && count($final_result)>0) {
                 $where_filter = " AND u.user_id IN  ('".implode("','",$final_result)."') ";
@@ -532,7 +579,14 @@ if (!empty($errorMsg)) {
               foreach ($nosessionUsersList as $uid => $enreg) {
               ?>
                   <option value="<?php echo $uid; ?>" <?php if(in_array($uid,$UserList)) echo 'selected="selected"'; ?>>
-                      <?php echo api_get_person_name($enreg['fn'], $enreg['ln']).' ('.$enreg['un'].') '.$enreg['official_code']; ?>
+                      <?php
+                      $personName = api_get_person_name($enreg['fn'], $enreg['ln']).' ('.$enreg['un'].') '.$enreg['official_code'];
+                      if ($showOfficialCode) {
+                          $officialCode = !empty($enreg['official_code']) ? $enreg['official_code'].' - ' : '? - ';
+                          $personName = $officialCode.api_get_person_name($enreg['fn'], $enreg['ln']).' ('.$enreg['un'].')';
+                      }
+                      echo $personName;
+                      ?>
                   </option>
               <?php
               }
@@ -586,7 +640,14 @@ if (!empty($errorMsg)) {
         foreach ($sessionUsersList as $enreg) {
         ?>
             <option value="<?php echo $enreg['user_id']; ?>">
-                <?php echo api_get_person_name($enreg['firstname'], $enreg['lastname']).' ('.$enreg['username'].') '.$enreg['official_code']; ?>
+            <?php
+                $personName = api_get_person_name($enreg['firstname'], $enreg['lastname']).' ('.$enreg['username'].') '.$enreg['official_code'];
+                if ($showOfficialCode) {
+                    $officialCode = !empty($enreg['official_code']) ? $enreg['official_code'].' - ' : '? - ';
+                    $personName = $officialCode.api_get_person_name($enreg['firstname'], $enreg['lastname']).' ('.$enreg['username'].')';
+                }
+                echo $personName;
+            ?>
             </option>
         <?php
         }

+ 38 - 3
main/admin/add_users_to_usergroup.php

@@ -209,6 +209,13 @@ if (api_is_western_name_order()) {
     $order = array('firstname');
 }
 
+global $_configuration;
+if (isset($_configuration['order_user_list_by_official_code']) &&
+    $_configuration['order_user_list_by_official_code']
+) {
+    $order = array('official_code', 'lastname');
+}
+
 $conditions = array();
 
 if (!empty($first_letter_user)) {
@@ -242,10 +249,22 @@ if (!empty($complete_user_list)) {
         }
 
         if (in_array($item['user_id'], $list_in)) {
+            $officialCode = !empty($item['official_code']) ? ' - '.$item['official_code'] : null;
             $person_name = api_get_person_name(
                 $item['firstname'],
                 $item['lastname']
-            ).' ('.$item['username'].') '.$item['official_code'];
+            ).' ('.$item['username'].') '.$officialCode;
+
+            if (isset($_configuration['order_user_list_by_official_code']) &&
+                $_configuration['order_user_list_by_official_code']
+            ) {
+                $officialCode = !empty($item['official_code']) ? $item['official_code'].' - ' : '? - ';
+                $person_name = $officialCode.api_get_person_name(
+                        $item['firstname'],
+                        $item['lastname']
+                    ).' ('.$item['username'].') ';
+            }
+
             $elements_in[$item['user_id']] = $person_name;
         }
     }
@@ -273,11 +292,27 @@ if (!empty($user_list)) {
                 continue;
             }
         }
-        if ($item['status'] == 6 ) continue; //avoid anonymous users
+
+        // Avoid anonymous users
+        if ($item['status'] == 6) {
+            continue;
+        }
+        $officialCode = !empty($item['official_code']) ? ' - '.$item['official_code'] : null;
         $person_name = api_get_person_name(
             $item['firstname'],
             $item['lastname']
-        ).' ('.$item['username'].') '.$item['official_code'];
+        ).' ('.$item['username'].') '.$officialCode;
+
+        if (isset($_configuration['order_user_list_by_official_code']) &&
+            $_configuration['order_user_list_by_official_code']
+        ) {
+            $officialCode = !empty($item['official_code']) ? $item['official_code'].' - ' : '? - ';
+            $person_name = $officialCode.api_get_person_name(
+                    $item['firstname'],
+                    $item['lastname']
+                ).' ('.$item['username'].') ';
+        }
+
         if (in_array($item['user_id'], $list_in)) {
             //$elements_in[$item['user_id']] = $person_name;
         } else {

+ 2 - 2
main/admin/archive_cleanup.php

@@ -19,7 +19,7 @@ $this_section = SECTION_PLATFORM_ADMIN;
 api_protect_admin_script(true);
 
 // setting breadcrumbs
-$interbreadcrumb[]=array('url' => 'index.php','name' => get_lang('PlatformAdmin'));
+$interbreadcrumb[] = array('url' => 'index.php','name' => get_lang('PlatformAdmin'));
 
 $form = new FormValidator('archive_cleanup_form');
 $form->addElement('style_submit_button','proceed', get_lang('ArchiveDirCleanupProceedButton'),'class="save"');
@@ -63,4 +63,4 @@ if (!empty($message)) {
     echo $message;
 }
 $form->display();
-Display::display_footer();
+Display::display_footer();

+ 3 - 4
main/admin/configure_extensions.php

@@ -26,7 +26,7 @@ if (isset($_POST['activeExtension'])) {
 					WHERE variable="service_visio"
 					AND subkey="active"';
 			$rs = Database::query($sql);
-			if(Database::affected_rows()>0) {
+			if (Database::affected_rows($rs)>0) {
 				// select all the courses and insert the tool inside
 				$sql = 'SELECT id FROM '.Database::get_main_table(TABLE_MAIN_COURSE);
 				$rs = Database::query($sql);
@@ -105,7 +105,7 @@ if (isset($_POST['activeExtension'])) {
 
 			$rs = Database::query($sql);
 
-			if(Database::affected_rows()>0){
+			if (Database::affected_rows($rs)>0){
 				$message = get_lang('ServiceActivated');
 			}
 
@@ -441,8 +441,7 @@ Display::display_header($nameTool);
 	</div>
 	*/
     /*
-	
-    
+   
 	<!-- SEARCH -->
 	<div id="main_search">
 		<div id="extension_header_search" class="accordion_header">

+ 152 - 142
main/admin/configure_homepage.php

@@ -15,34 +15,35 @@
  */
 function home_tabs($file_logged_in)
 {
-	$file_logged_out = str_replace('_logged_in','', $file_logged_in);
-
-	//variables initialization
-	$data_logged_out = array();
-	$data_logged_in  = array();
-
-	//we read the file with all links
-	$file = file($file_logged_in);
-	foreach ($file as $line) {
-		//not logged user only sees public links
-		if (!preg_match('/::private/',$line)) {
-			$data_logged_out[] = $line;
-		}
-		//logged user only sees all links
-		$data_logged_in[] = $line;
-	}
-	//tabs file for logged out users
-	$fp = fopen($file_logged_out, 'w');
-	fputs($fp, implode("\n", $data_logged_out));
-	fclose($fp);
-	//tabs file for logged in users
-	$fp = fopen($file_logged_in, 'w');
-	fputs($fp, implode("\n", $data_logged_in));
-	fclose($fp);
+    $post = strpos($file_logged_in, "_logged_in");
+    if ($post !== false) {
+        $file_logged_out = str_replace('_logged_in','', $file_logged_in);
+        //variables initialization
+        $data_logged_out = array();
+        $data_logged_in  = array();
+
+        //we read the file with all links
+        $file = file($file_logged_in);
+        foreach ($file as $line) {
+            $line = str_replace("\n", '',$line);
+            //not logged user only sees public links
+            if (!preg_match('/::private/',$line)) {
+                $data_logged_out[] = $line;
+            }
+            //logged user only sees all links
+            $data_logged_in[] = $line;
+        }
+        //tabs file for logged out users
+        $fp = fopen($file_logged_out, 'w');
+        fputs($fp, implode("\n", $data_logged_out));
+        fclose($fp);
+        //tabs file for logged in users
+        $fp = fopen($file_logged_in, 'w');
+        fputs($fp, implode("\n", $data_logged_in));
+        fclose($fp);
+    }
 }
-/**
- * Code
- */
+
 $language_file = array('index','admin', 'accessibility');
 $cidReset = true;
 require_once '../inc/global.inc.php';
@@ -228,20 +229,20 @@ if (!empty($action)) {
 						$fp = fopen($homep.$topf.'_'.$lang.$ext, 'w');
 						fputs($fp, $home_top);
 						fclose($fp);
-            
-                foreach ($_languages['name'] as $key => $value) {
-                    $lang_name = $_languages['folder'][$key];
-                    if (isset($_POST[$lang_name])) {
-                        if (file_exists($homep.$topf.'_'.$lang_name.$ext)) {
-                            if (is_writable($homep.$topf.'_'.$lang_name.$ext)) {
-                                $fp = fopen($homep.$topf.'_'.$lang_name.$ext, 'w');
-                                fputs($fp, $home_top);
-                                fclose($fp);
+
+                    foreach ($_languages['name'] as $key => $value) {
+                        $lang_name = $_languages['folder'][$key];
+                        if (isset($_POST[$lang_name])) {
+                            if (file_exists($homep.$topf.'_'.$lang_name.$ext)) {
+                                if (is_writable($homep.$topf.'_'.$lang_name.$ext)) {
+                                    $fp = fopen($homep.$topf.'_'.$lang_name.$ext, 'w');
+                                    fputs($fp, $home_top);
+                                    fclose($fp);
+                                }
                             }
                         }
                     }
-                }
-            
+
 					} else {
 						$errorMsg = get_lang('HomePageFilesNotWritable');
 					}
@@ -250,19 +251,18 @@ if (!empty($action)) {
 					$fp = fopen($homep.$topf.'_'.$lang.$ext, 'w');
 					fputs($fp, $home_top);
 					fclose($fp);
-         
-              foreach ($_languages['name'] as $key => $value) {
-                  $lang_name = $_languages['folder'][$key];
-                  if (isset($_POST[$lang_name])) {
-                      if (file_exists($homep.$topf.'_'.$lang_name.$ext)) {
-                          $fp = fopen($homep.$topf.'_'.$lang_name.$ext, 'w');
-                          fputs($fp, $home_top);
-                          fclose($fp);
-    
-                      }
-                  }
-              }  
-       }
+
+                    foreach ($_languages['name'] as $key => $value) {
+                        $lang_name = $_languages['folder'][$key];
+                        if (isset($_POST[$lang_name])) {
+                            if (file_exists($homep.$topf.'_'.$lang_name.$ext)) {
+                                $fp = fopen($homep.$topf.'_'.$lang_name.$ext, 'w');
+                                fputs($fp, $home_top);
+                                fclose($fp);
+                            }
+                        }
+                    }
+                }
 
                 if (EventsMail::check_if_using_class('portal_homepage_edited')) {
                     EventsDispatcher::events('portal_homepage_edited',array('about_user' => api_get_user_id()));
@@ -283,34 +283,32 @@ if (!empty($action)) {
 						if ($errorMsg == '') {
 							fputs($fp, "<b>$notice_title</b><br />\n$notice_text");
 
-                  foreach ($_languages['name'] as $key => $value) {
-                      $lang_name = $_languages['folder'][$key];
-                      if (isset($_POST[$lang_name])) {
-                          if (file_exists($homep.$noticef.'_'.$lang_name.$ext)) {
-                              if (is_writable($homep.$noticef.'_'.$lang_name.$ext)) {
-                                  $fp = fopen($homep.$noticef.'_'.$lang_name.$ext, 'w');
-                                  fputs($fp, "<b>$notice_title</b><br />\n$notice_text");
-                                  fclose($fp);
-                              }
-                          }
-                      }
-                  }
-                                         
-						} else {
+                            foreach ($_languages['name'] as $key => $value) {
+                                $lang_name = $_languages['folder'][$key];
+                                if (isset($_POST[$lang_name])) {
+                                    if (file_exists($homep.$noticef.'_'.$lang_name.$ext)) {
+                                        if (is_writable($homep.$noticef.'_'.$lang_name.$ext)) {
+                                            $fp = fopen($homep.$noticef.'_'.$lang_name.$ext, 'w');
+                                            fputs($fp, "<b>$notice_title</b><br />\n$notice_text");
+                                            fclose($fp);
+                                        }
+                                    }
+                                }
+                            }
+                        } else {
 							fputs($fp, '');
-             
-                  foreach ($_languages['name'] as $key => $value) {
-                      $lang_name = $_languages['folder'][$key];
-                      if (isset($_POST[$lang_name])) {
-                          if (file_exists($homep.$noticef.'_'.$lang_name.$ext)) {
-                              $fp1 = fopen($homep.$noticef.'_'.$lang_name.$ext, 'w');
-                              fputs($fp1, '');
-                              fclose($fp1);
-
-                          }
-                      }
-                   }
-            }
+
+                            foreach ($_languages['name'] as $key => $value) {
+                                $lang_name = $_languages['folder'][$key];
+                                if (isset($_POST[$lang_name])) {
+                                    if (file_exists($homep.$noticef.'_'.$lang_name.$ext)) {
+                                        $fp1 = fopen($homep.$noticef.'_'.$lang_name.$ext, 'w');
+                                        fputs($fp1, '');
+                                        fclose($fp1);
+                                    }
+                                }
+                            }
+                        }
 						fclose($fp);
 					} else {
 						$errorMsg .= "<br/>\n".get_lang('HomePageFilesNotWritable');
@@ -395,6 +393,7 @@ if (!empty($action)) {
 					$link_url='http://'.$link_url;
 				}
 				$menuf = ($action == 'insert_tabs' || $action == 'edit_tabs')? $mtloggedin : $menuf;
+
 				if (!is_writable($homep.$menuf.'_'.$lang.$ext)) {
 					$errorMsg = get_lang('HomePageFilesNotWritable');
 				} elseif (empty($link_name)) {
@@ -404,6 +403,7 @@ if (!empty($action)) {
 					if ($action == 'insert_link' || $action == 'insert_tabs' || empty($filename) || strstr($filename, '/') || !strstr($filename, '.html')) {
 						$filename = replace_dangerous_char($link_name, 'strict').'.html';
 					}
+
 					// "home_" prefix for links are renamed to "user_" prefix (to avoid name clash with existing home page files)
 					if (!empty($filename)) {
 						$filename = str_replace('home_', 'user_', $filename);
@@ -476,8 +476,6 @@ if (!empty($action)) {
 								break;
 							}
 						}
-
-
 						$home_menu[$insert_where + 1] = '<li '.$class_add_in_tab.'><a href="'.$link_url.'" target="'.($target_blank ? '_blank' : '_self').'"><span>'.$link_name.'</span></a></li>';
 					} else {
 						// If the request is about a link edition, change the link
@@ -492,17 +490,17 @@ if (!empty($action)) {
 							fputs($fp, $home_menu);
 							home_tabs($homep.$menuf.'_'.$lang.$ext);
 							fclose($fp);
-              
-                  foreach ($_languages['name'] as $key => $value) {
-                      $lang_name = $_languages['folder'][$key];
-                      if (isset($_POST[$lang_name])) {
-                          $fp = fopen($homep.$menuf.'_'.$lang_name.$ext, 'w');
-                          fputs($fp, $home_menu);
-                          home_tabs($homep.$menuf.'_'.$lang_name.$ext);
-                          fclose($fp);
-                      }
-                   }
-              
+
+                            foreach ($_languages['name'] as $key => $value) {
+                                $lang_name = $_languages['folder'][$key];
+                                if (isset($_POST[$lang_name])) {
+                                    $fp = fopen($homep.$menuf.'_'.$lang_name.$ext, 'w');
+                                    fputs($fp, $home_menu);
+                                    home_tabs($homep.$menuf.'_'.$lang_name.$ext);
+                                    fclose($fp);
+                                }
+                            }
+
 							if (file_exists($homep.$menuf.$ext)) {
 								if (is_writable($homep.$menuf.$ext)) {
 									$fpo = fopen($homep.$menuf.$ext, 'w');
@@ -520,17 +518,17 @@ if (!empty($action)) {
 						fputs($fp, $home_menu);
 						home_tabs($homep.$menuf.'_'.$lang.$ext);
 						fclose($fp);
-            
-                foreach ($_languages['name'] as $key => $value) {
-                    $lang_name = $_languages['folder'][$key];
-                    if (isset($_POST[$lang_name])) {
-                        $fp = fopen($homep.$menuf.'_'.$lang_name.$ext, 'w');
-                        fputs($fp, $home_menu);
-                        home_tabs($homep.$menuf.'_'.$lang_name.$ext);
-                        fclose($fp);
+
+                        foreach ($_languages['name'] as $key => $value) {
+                            $lang_name = $_languages['folder'][$key];
+                            if (isset($_POST[$lang_name])) {
+                                $fp = fopen($homep.$menuf.'_'.$lang_name.$ext, 'w');
+                                fputs($fp, $home_menu);
+                                home_tabs($homep.$menuf.'_'.$lang_name.$ext);
+                                fclose($fp);
+                            }
+                        }
                     }
-                }  
-          }
 				}
                 event_system(LOG_HOMEPAGE_CHANGED, $action, cut($link_name.':'.$link_url, 254), api_get_utc_datetime(), api_get_user_id());
 				break;
@@ -679,6 +677,13 @@ if (!empty($action)) {
 				} else {
 					$errorMsg = get_lang('HomePageFilesNotReadable');
 				}
+
+                if (empty($home_menu)) {
+                    if (file_exists($homep.$menutabs.'_'.$lang.$ext)) {
+                        $home_menu = @file($homep.$menutabs.'_'.$lang.$ext);
+                    }
+                }
+
 				if (empty($home_menu)) {
 					$home_menu = array();
 				}
@@ -828,8 +833,9 @@ switch ($action) {
         $default['link_name'] = $link_name;
     	}
 		$default['link_url'] = empty($link_url) ? 'http://' : api_htmlentities($link_url, ENT_QUOTES);
-		$form->addElement('text', 'link_url', array(get_lang('LinkURL'), get_lang('Optional').'<br />'.get_lang('GlobalLinkUseDoubleColumnPrivateToShowPrivately')), array('size' => '30', 'maxlength' => '100', 'style' => 'width: 350px;'));
-
+        $linkUrlComment = ($action == 'insert_tabs') ? get_lang('Optional').'<br />'.get_lang('GlobalLinkUseDoubleColumnPrivateToShowPrivately') : '';
+        $form->addElement('text', 'link_url', array(get_lang('LinkURL'), $linkUrlComment), array('size' => '30', 'maxlength' => '100', 'style' => 'width: 350px;'));
+        
         $options = array('-1' => get_lang('FirstPlace'));
 
 		$selected = '';
@@ -876,21 +882,21 @@ switch ($action) {
                     $form->add_html_editor('link_html', get_lang('Content'), false, false, array('ToolbarSet' => 'PortalHomePage', 'Width' => '100%', 'Height' => '400'));
                 }
             }
-      $form->addElement('checkbox', 'all_langs', null, get_lang('ApplyAllLanguages'), array('id' => 'all_langs'));
-      $form->addElement('html','<table id="table_langs" style="margin-left:159px;"><tr>');
-      $i = 0;
-      foreach ($_languages['name'] as $key => $value) {
-         $i++;  
-         $lang_name = $_languages['folder'][$key];
-         $html_langs = '<td width="300">';
-         $html_langs .= '<label><input type="checkbox" id="lang" name="'.$lang_name.'" />&nbsp;'.$lang_name.'<label/>';
-         $html_langs .= '</td>';
-         if ($i%5 == 0) {
-             $html_langs .= '</tr><tr>';
-         }
-         $form->addElement('html', $html_langs);
-      }
-      $form->addElement('html','</tr></table><br/>');  
+            $form->addElement('checkbox', 'all_langs', null, get_lang('ApplyAllLanguages'), array('id' => 'all_langs'));
+            $form->addElement('html','<table id="table_langs" style="margin-left:159px;"><tr>');
+            $i = 0;
+            foreach ($_languages['name'] as $key => $value) {
+                $i++;
+                $lang_name = $_languages['folder'][$key];
+                $html_langs = '<td width="300">';
+                $html_langs .= '<label><input type="checkbox" id="lang" name="'.$lang_name.'" />&nbsp;'.$lang_name.'<label/>';
+                $html_langs .= '</td>';
+                if ($i%5 == 0) {
+                $html_langs .= '</tr><tr>';
+                }
+                $form->addElement('html', $html_langs);
+            }
+            $form->addElement('html','</tr></table><br/>');
       		$form->addElement('style_submit_button', null, get_lang('Save'), 'class="save"');
 		}
 
@@ -922,7 +928,7 @@ switch ($action) {
 		$renderer->setRequiredNoteTemplate('');
 		$form->addElement('hidden', 'formSent', '1');
 
-		if ($action == 'edit_news'){
+		if ($action == 'edit_news') {
 			$_languages = api_get_languages();
 			$html = '<tr><td>'.get_lang('ChooseNewsLanguage').' : ';
 			$html .= '<select name="news_languages">';
@@ -949,24 +955,23 @@ switch ($action) {
 			$default[$name] = str_replace('{rel_path}', api_get_path(REL_PATH), $open);
 			$form->add_html_editor($name, '', true, false, array('ToolbarSet' => 'PortalHomePage', 'Width' => '100%', 'Height' => '400'));
 		}
-    $form->addElement('checkbox', 'all_langs', null, get_lang('ApplyAllLanguages'),array('id' => 'all_langs'));
-    $form->addElement('html','<table id="table_langs" style="margin-left:5px;"><tr>');
-    $i = 0;
-    foreach ($_languages['name'] as $key => $value) {
-          $i++;  
-          $lang_name = $_languages['folder'][$key];
-          if (file_exists($homep.$topf.'_'.$lang_name.$ext)) {
-              $html_langs = '<td width="300">';
-              $html_langs .= '<label><input type="checkbox" id="lang" name="'.$lang_name.'" />&nbsp;'.$lang_name.'<label/>';
-              $html_langs .= '</td>';
-              if($i%5 == 0) {
-                $html_langs .= '</tr><tr>';
-              }
-              $form->addElement('html', $html_langs);
-             
-          }
-      }
-      $form->addElement('html','</tr></table><br/>');  
+        $form->addElement('checkbox', 'all_langs', null, get_lang('ApplyAllLanguages'),array('id' => 'all_langs'));
+        $form->addElement('html','<table id="table_langs" style="margin-left:5px;"><tr>');
+        $i = 0;
+        foreach ($_languages['name'] as $key => $value) {
+            $i++;
+            $lang_name = $_languages['folder'][$key];
+            if (file_exists($homep.$topf.'_'.$lang_name.$ext)) {
+                $html_langs = '<td width="300">';
+                $html_langs .= '<label><input type="checkbox" id="lang" name="'.$lang_name.'" />&nbsp;'.$lang_name.'<label/>';
+                $html_langs .= '</td>';
+                if($i%5 == 0) {
+                    $html_langs .= '</tr><tr>';
+                }
+                $form->addElement('html', $html_langs);
+            }
+        }
+        $form->addElement('html','</tr></table><br/>');
 		$form->addElement('style_submit_button', null, get_lang('Save'), 'class="save"');
 		$form->setDefaults($default);
 		$form->display();
@@ -1000,7 +1005,7 @@ switch ($action) {
 			</tr>
 			<tr>
 			<?php
-            
+
 			$access_url_id = 1;
 			// we only show the category options for the main chamilo installation
 			if (api_is_multiple_url_enabled()) {
@@ -1055,14 +1060,23 @@ switch ($action) {
 			// Add new page
 
 			$home_menu = '';
+
             if (file_exists($homep.$mtloggedin.'_'.$lang.$ext)) {
                 $home_menu = @file($homep.$mtloggedin.'_'.$lang.$ext);
             } else {
                 $home_menu = @file($homep.$mtloggedin.$ext);
             }
+
+            if (empty($home_menu)) {
+                if (file_exists($homep.$menutabs.'_'.$lang.$ext)) {
+                    $home_menu = @file($homep.$menutabs.'_'.$lang.$ext);
+                }
+            }
+
             if (empty($home_menu)) {
                 $home_menu = array();
             }
+
             if (!empty($home_menu)) {
                 $home_menu = implode("\n", $home_menu);
                 $home_menu = api_to_system_encoding($home_menu, api_detect_encoding(strip_tags($home_menu)));
@@ -1133,12 +1147,9 @@ switch ($action) {
             echo '</div>';
             ?>
             </div>
-
-
            	<div class="well sidebar-nav">
                 <a href="<?php echo api_get_self(); ?>?action=insert_link"><?php Display::display_icon('addd.gif', get_lang('InsertLink')); ?></a>
                 <a href="<?php echo api_get_self(); ?>?action=insert_link"><?php echo get_lang('InsertLink'); ?></a>
-
     			<h4><?php echo api_ucfirst(get_lang('General')); ?></h4>
     				<ul class="menulist">
     				<?php
@@ -1169,7 +1180,6 @@ switch ($action) {
     				?>
     				</ul>
 			     </div>
-
 		  </td>
 		</tr>
 		</table>

+ 4 - 0
main/admin/configure_plugin.php

@@ -69,6 +69,10 @@ if (isset($form)) {
                 1
             );
         }
+        if (isset($values['show_main_menu_tab'])) {
+            $objPlugin = $plugin_info['plugin_class']::create();
+            $objPlugin->manageTab($values['show_main_menu_tab']);
+        }
         $message = Display::return_message(get_lang('Updated'), 'success');
     }
 }

+ 11 - 8
main/admin/course_edit.php

@@ -251,8 +251,6 @@ $form->setDefaults($course);
 // Validate form
 if ($form->validate()) {
     $course = $form->getSubmitValues();
-
-    $dbName = $_POST['dbName'];
     $course_code = $course['code'];
     $visual_code = $course['visual_code'];
     $visual_code = generate_course_code($visual_code);
@@ -286,8 +284,8 @@ if ($form->validate()) {
         }
     }
 
-	$tutor_id = $course['tutor_name'];
-	$tutor_name = $platform_teachers[$tutor_id];
+	$tutor_id = isset($course['tutor_name']) ? $course['tutor_name'] : null;
+	$tutor_name = isset($platform_teachers[$tutor_id]) ? $platform_teachers[$tutor_id] : null;
 	$teachers = $course['group']['course_teachers'];
 
 	$title = $course['title'];
@@ -350,9 +348,15 @@ if ($form->validate()) {
         $sessionCoaches = $course['session_coaches'];
         if (!empty($sessionCoaches)) {
             foreach ($sessionCoaches as $sessionId => $teacherInfo) {
-                $coachesToSubscribe = $teacherInfo['coaches_by_session'];
-                SessionManager::updateCoaches($sessionId, $course['code'], $coachesToSubscribe, true);
-
+                $coachesToSubscribe = isset($teacherInfo['coaches_by_session']) ? $teacherInfo['coaches_by_session'] : null;
+                if (!empty($coachesToSubscribe)) {
+                    SessionManager::updateCoaches(
+                        $sessionId,
+                        $course['code'],
+                        $coachesToSubscribe,
+                        true
+                    );
+                }
             }
         }
     }
@@ -367,7 +371,6 @@ if ($form->validate()) {
 				user_course_cat='0'";
 	Database::query($sql);
 
-
     if (array_key_exists('add_teachers_to_sessions_courses', $course_info)) {
         $sql = "UPDATE $course_table SET add_teachers_to_sessions_courses = '$addTeacherToSessionCourses'
                 WHERE id = ".$course_info['real_id'];

+ 11 - 10
main/admin/course_export.php

@@ -25,9 +25,10 @@ $archivePath = api_get_path(SYS_ARCHIVE_PATH);
 $archiveURL = api_get_path(WEB_CODE_PATH).'course_info/download.php?archive=';
 
 $course_list = CourseManager::get_courses_list();
+$formSent = null;
 
-if ($_POST['formSent']) {
-	$formSent	=$_POST['formSent'];
+if (isset($_POST['formSent']) && $_POST['formSent']) {
+	$formSent = $_POST['formSent'];
 	$select_type=intval($_POST['select_type']);
 	$file_type = 'csv';
 	$courses = $selected_courses = array();
@@ -92,20 +93,20 @@ if (!empty($msg)) {
 
 <form method="post" action="<?php echo api_get_self(); ?>" style="margin:0px;">
     <input type="hidden" name="formSent" value="1">
-    <legend><?php echo $tool_name; ?></legend>    
+    <legend><?php echo $tool_name; ?></legend>
 <?php if (!empty($course_list)) { ?>
-<div class="control-group">    
-    
+<div class="control-group">
+
     <div class="controls">
-        <label class="radio" for="all-courses">            
+        <label class="radio" for="all-courses">
         <input id="all-courses" class="checkbox" type="radio" value="1" name="select_type" <?php if(!$formSent || ($formSent && $select_type == 1)) echo 'checked="checked"'; ?> onclick="javascript: if(this.checked){document.getElementById('div-course-list').style.display='none';}"/>
             <?php echo get_lang('ExportAllCoursesList')?>
-        </label>        
-        
+        </label>
+
         <label class="radio" for="select-courses">
             <input id="select-courses" class="checkbox" type="radio" value="2" name="select_type" <?php if($formSent && $select_type == 2) echo 'checked="checked"'; ?> onclick="javascript: if(this.checked){document.getElementById('div-course-list').style.display='block';}"/>
             <?php echo get_lang('ExportSelectedCoursesFromCoursesList')?>
-        </label>        
+        </label>
     </div>
 </div>
 <div id="div-course-list" style="<?php echo (!$formSent || ($formSent && $select_type == 1))?'display:none':'display:block';?>">
@@ -133,4 +134,4 @@ if (!empty($msg)) {
 <?php } else { echo get_lang('ThereAreNotCreatedCourses'); }?>
 </form>
 <?php
-Display :: display_footer();
+Display :: display_footer();

+ 35 - 26
main/admin/course_import.php

@@ -53,10 +53,10 @@ function validate_data($courses)
                     $course['error'] = get_lang('UnknownTeacher').' ('.$teacher.')';
                     $errors[] = $course;
                 } else {
-                    if ($teacherInfo['status'] != COURSEMANAGER) {
+                    /*if ($teacherInfo['status'] != COURSEMANAGER) {
                         $course['error'] = get_lang('UserIsNotATeacher').' ('.$teacher.')';
                         $errors[] = $course;
-                    }
+                    }*/
                 }
             }
         }
@@ -72,20 +72,27 @@ function validate_data($courses)
             }
         }
     }
+
     return $errors;
 }
 
+/**
+ * @param array $teachers
+ *
+ * @return array
+ */
 function getTeacherListInArray($teachers)
 {
     if (!empty($teachers)) {
         return explode('|', $teachers);
     }
+
     return array();
 }
 
 /**
  * Saves imported data.
- * @param array   List of courses
+ * @param array $courses List of courses
  */
 function save_data($courses)
 {
@@ -113,16 +120,23 @@ function save_data($courses)
         $params['course_language']  = $course_language;
         $params['user_id']          = $creatorId;
 
-        $course_info = CourseManager::create_course($params);
+        $addMeAsTeacher = isset($_POST['add_me_as_teacher']) ? $_POST['add_me_as_teacher'] : false;
+        $params['add_user_as_teacher'] = $addMeAsTeacher;
 
-        if (!empty($course_info)) {
+        $courseInfo = CourseManager::create_course($params);
+
+        if (!empty($courseInfo)) {
             if (!empty($teacherList)) {
                 foreach ($teacherList as $teacher) {
-                    CourseManager::add_user_to_course($teacher['user_id'], $course_info['code'], COURSEMANAGER);
+                    CourseManager::add_user_to_course(
+                        $teacher['user_id'],
+                        $courseInfo['code'],
+                        COURSEMANAGER
+                    );
                 }
             }
-            $msg .= '<a href="'.api_get_path(WEB_COURSE_PATH).$course_info['directory'].'/">
-                    '.$course_info['title'].'</a> '.get_lang('Created').'<br />';
+            $msg .= '<a href="'.api_get_path(WEB_COURSE_PATH).$courseInfo['directory'].'/">
+                    '.$courseInfo['title'].'</a> '.get_lang('Created').'<br />';
         }
     }
 
@@ -155,7 +169,7 @@ require_once api_get_path(LIBRARY_PATH).'fileManage.lib.php';
 require_once api_get_path(LIBRARY_PATH).'import.lib.php';
 $defined_auth_sources[] = PLATFORM_AUTH_SOURCE;
 
-if (is_array($extAuthSource)) {
+if (isset($extAuthSource) && is_array($extAuthSource)) {
     $defined_auth_sources = array_merge($defined_auth_sources, array_keys($extAuthSource));
 }
 
@@ -166,7 +180,7 @@ $interbreadcrumb[] = array('url' => 'index.php', 'name' => get_lang('PlatformAdm
 set_time_limit(0);
 Display :: display_header($tool_name);
 
-if ($_POST['formSent']) {
+if (isset($_POST['formSent']) && $_POST['formSent']) {
     if (empty($_FILES['import_file']['tmp_name'])) {
         $error_message = get_lang('UplUploadFailed');
         Display :: display_error_message($error_message, false);
@@ -187,7 +201,7 @@ if ($_POST['formSent']) {
     }
 }
 
-if (count($errors) != 0) {
+if (isset($errors) && count($errors) != 0) {
     $error_message = '<ul>';
     foreach ($errors as $index => $error_course) {
         $error_message .= '<li>'.get_lang('Line').' '.$error_course['line'].': <strong>'.$error_course['error'].'</strong>: ';
@@ -197,22 +211,17 @@ if (count($errors) != 0) {
     $error_message .= '</ul>';
     Display :: display_error_message($error_message, false);
 }
+
+$form = new FormValidator('import', 'post', api_get_self(), null, array('enctype' => 'multipart/form-data'));
+$form->add_header($tool_name);
+$form->addElement('file', 'import_file', get_lang('ImportCSVFileLocation'));
+$form->addElement('checkbox', 'add_me_as_teacher', null, get_lang('AddMeAsTeacherInCourses'));
+$form->addElement('button', 'save', get_lang('Import'));
+$form->addElement('hidden', 'formSent', 1);
+//$form->setDefaults(array('add_me_as_teacher' => 0));
+$form->display();
+
 ?>
-<form method="post" action="<?php echo api_get_self(); ?>" enctype="multipart/form-data" style="margin: 0px;">
-<legend><?php echo $tool_name; ?></legend>
-<div class="control-group">
-    <label><?php echo get_lang('ImportCSVFileLocation'); ?></label>
-    <div class="control">
-        <input type="file" name="import_file"/>
-    </div>
-</div>
-<div class="control-group">
-    <div class="control">
-        <button type="submit" class="save" value="<?php echo get_lang('Import'); ?>"><?php echo get_lang('Import'); ?></button>
-    </div>
-</div>
-<input type="hidden" name="formSent" value="1"/>
-</form>
 <div style="clear: both;"></div>
 <p><?php echo get_lang('CSVMustLookLike').' ('.get_lang('MandatoryFields').')'; ?> :</p>
 

+ 10 - 2
main/admin/course_information.php

@@ -110,8 +110,16 @@ $table->display();
 echo Display::page_header(get_lang('Users'));
 $table_course_user     = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
 $table_user            = Database :: get_main_table(TABLE_MAIN_USER);
-$sql                   = "SELECT *,cu.status as course_status FROM $table_course_user cu, $table_user u WHERE cu.user_id = u.user_id AND cu.course_code = '".$code."' AND cu.relation_type <> ".COURSE_RELATION_TYPE_RRHH." ";
-$res                   = Database::query($sql);
+$sql = "SELECT *,cu.status as course_status 
+        FROM $table_course_user cu, $table_user u";
+if (api_is_multiple_url_enabled()) {
+    $sql .= " INNER JOIN ".Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER)." url_rel_user
+        ON u.user_id = url_rel_user.user_id
+        AND url_rel_user.access_url_id = ".intval(api_get_current_access_url_id());
+}
+$sql .= " WHERE cu.user_id = u.user_id AND cu.course_code = '".$code."'
+        AND cu.relation_type <> ".COURSE_RELATION_TYPE_RRHH;
+$res = Database::query($sql);
 $is_western_name_order = api_is_western_name_order();
 if (Database::num_rows($res) > 0) {
     $users = array();

+ 3 - 3
main/admin/course_list.php

@@ -222,7 +222,7 @@ if (isset ($_POST['action'])) {
             $course_codes = $_POST['course'];
             if (count($course_codes) > 0) {
                 foreach ($course_codes as $course_code) {
-                    CourseManager :: delete_course($course_code);
+                    CourseManager::delete_course($course_code);
                     $obj_cat = new Category();
                     $obj_cat->update_category_delete($course_code);
                 }
@@ -298,8 +298,8 @@ if (isset ($_GET['search']) && $_GET['search'] == 'advanced') {
                 break;
         }
     }
-    if (isset ($_GET['delete_course'])) {
-        CourseManager :: delete_course($_GET['delete_course']);
+    if (isset($_GET['delete_course'])) {
+        CourseManager::delete_course($_GET['delete_course']);
         $obj_cat = new Category();
         $obj_cat->update_category_delete($_GET['delete_course']);
 

+ 1 - 0
main/admin/course_request_accepted.php

@@ -100,6 +100,7 @@ function get_number_of_requests() {
 function get_request_data($from, $number_of_items, $column, $direction) {
     $keyword = Database::escape_string(trim($_GET['keyword']));
     $course_request_table = Database :: get_main_table(TABLE_MAIN_COURSE_REQUEST);
+
     $sql = "SELECT id AS col0,
                    code AS col1,
                    title AS col2,

+ 3 - 3
main/admin/course_request_rejected.php

@@ -48,9 +48,9 @@ $keyword = Database::escape_string(trim($_GET['keyword']));
 
 if ($course_validation_feature) {
 
-/**
- * Acceptance and creation of the requested course.
- */
+    /**
+     * Acceptance and creation of the requested course.
+     */
     if (!empty($accept_course_request)) {
         $course_request_code = CourseRequestManager::get_course_request_code($accept_course_request);
         $course_id = CourseRequestManager::accept_course_request($accept_course_request);

+ 3 - 5
main/admin/course_user_import.php

@@ -95,15 +95,13 @@ function save_data($users_courses)
         if ($_POST['subscribe']) {
             foreach ($to_subscribe as $course_code) {
                 if (CourseManager :: course_exists($course_code)) {
-                    CourseManager::add_user_to_course($user_id, $course_code, $csv_subscriptions[$course_code]);
-                    $course_info = CourseManager::get_course_information($course_code);
-                    $inserted_in_course[$course_code] = $course_info['title'];
-
-                    CourseManager::add_user_to_course(
+                    CourseManager::subscribe_user(
                         $user_id,
                         $course_code,
                         $csv_subscriptions[$course_code]
                     );
+                    $course_info = CourseManager::get_course_information($course_code);
+                    $inserted_in_course[$course_code] = $course_info['title'];
                     $inserted_in_course[$course_info['code']] = $course_info['title'];
                 }
             }

+ 234 - 0
main/admin/course_user_import_by_email.php

@@ -0,0 +1,234 @@
+<?php
+/* For licensing terms, see /license.txt */
+exit;
+/**
+ * This tool allows platform admins to update course-user relations by uploading
+ * a CSV file
+ * @package chamilo.admin
+ */
+/**
+ * Validates the imported data.
+ */
+function validate_data($users_courses)
+{
+    $errors = array();
+    $coursecodes = array();
+    foreach ($users_courses as $index => $user_course) {
+        $user_course['line'] = $index + 1;
+        // 1. Check whether mandatory fields are set.
+        $mandatory_fields = array('Email', 'CourseCode', 'Status');
+        foreach ($mandatory_fields as $key => $field) {
+            if (!isset($user_course[$field]) || strlen($user_course[$field]) == 0) {
+                $user_course['error'] = get_lang($field.'Mandatory');
+                $errors[]             = $user_course;
+            }
+        }
+
+        // 2. Check whether coursecode exists.
+        if (isset ($user_course['CourseCode']) && strlen($user_course['CourseCode']) != 0) {
+            // 2.1 Check whethher code has been allready used by this CVS-file.
+            if (!isset($coursecodes[$user_course['CourseCode']])) {
+                // 2.1.1 Check whether course with this code exists in the system.
+                $course_table = Database :: get_main_table(TABLE_MAIN_COURSE);
+                $sql = "SELECT * FROM $course_table
+                        WHERE code = '".Database::escape_string($user_course['CourseCode'])."'";
+                $res = Database::query($sql);
+                if (Database::num_rows($res) == 0) {
+                    $user_course['error'] = get_lang('CodeDoesNotExists');
+                    $errors[]             = $user_course;
+                } else {
+                    $coursecodes[$user_course['CourseCode']] = 1;
+                }
+            }
+        }
+
+        // 3. Check whether Email exists.
+        if (isset ($user_course['Email']) && strlen($user_course['Email']) !=
+            0) {
+            $user = api_get_user_info_from_email($user_course['Email']);
+            if (empty($user)) {
+                $user_course['error'] = get_lang('UnknownUser');
+                $errors[]             = $user_course;
+            }
+        }
+
+        // 4. Check whether status is valid.
+        if (isset ($user_course['Status']) && strlen($user_course['Status']) != 0) {
+            if ($user_course['Status'] != COURSEMANAGER && $user_course['Status'] != STUDENT) {
+                $user_course['error'] = get_lang('UnknownStatus');
+                $errors[]             = $user_course;
+            }
+        }
+    }
+
+    return $errors;
+}
+
+/**
+ * Saves imported data.
+ */
+function save_data($users_courses)
+{
+    $user_table = Database::get_main_table(TABLE_MAIN_USER);
+    $course_user_table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
+    $csv_data = array();
+    $inserted_in_course = array();
+
+    foreach ($users_courses as $user_course) {
+        $csv_data[$user_course['Email']][$user_course['CourseCode']] =
+            $user_course['Status'];
+    }
+
+    foreach ($csv_data as $email => $csv_subscriptions) {
+        $sql = "SELECT * FROM $user_table u
+                WHERE u.email = '".Database::escape_string($email)."' LIMIT 1";
+        $res = Database::query($sql);
+        $obj = Database::fetch_object($res);
+        $user_id = $obj->user_id;
+        $sql = "SELECT * FROM $course_user_table cu
+                WHERE cu.user_id = $user_id AND cu.relation_type <> ".COURSE_RELATION_TYPE_RRHH." ";
+        $res = Database::query($sql);
+        $db_subscriptions = array();
+        while ($obj = Database::fetch_object($res)) {
+            $db_subscriptions[$obj->course_code] = $obj->status;
+        }
+
+        $to_subscribe   = array_diff(array_keys($csv_subscriptions), array_keys($db_subscriptions));
+        $to_unsubscribe = array_diff(array_keys($db_subscriptions), array_keys($csv_subscriptions));
+
+        if ($_POST['subscribe']) {
+            foreach ($to_subscribe as $course_code) {
+                if (CourseManager :: course_exists($course_code)) {
+                    $course_info = CourseManager::get_course_information($course_code);
+                    $inserted_in_course[$course_code] = $course_info['title'];
+
+                    CourseManager::subscribe_user(
+                        $user_id,
+                        $course_code,
+                        $csv_subscriptions[$course_code]
+                    );
+                    $inserted_in_course[$course_info['code']] = $course_info['title'];
+                }
+            }
+        }
+
+        if ($_POST['unsubscribe']) {
+            foreach ($to_unsubscribe as $course_code) {
+                if (CourseManager :: course_exists($course_code)) {
+                    CourseManager::unsubscribe_user($user_id, $course_code);
+                    $course_info = CourseManager::get_course_information($course_code);
+                    CourseManager::unsubscribe_user($user_id, $course_code);
+                    $inserted_in_course[$course_info['code']] = $course_info['title'];
+                }
+            }
+        }
+    }
+
+    return $inserted_in_course;
+}
+
+/**
+ * Reads CSV-file.
+ * @param string $file Path to the CSV-file
+ * @return array All course-information read from the file
+ */
+function parse_csv_data($file)
+{
+    $courses = Import :: csv_to_array($file);
+    return $courses;
+}
+
+// Language files that should be included,
+$language_file = array('admin', 'registration');
+$cidReset = true;
+
+include '../inc/global.inc.php';
+
+// Setting the section (for the tabs).
+$this_section = SECTION_PLATFORM_ADMIN;
+
+// Protecting the admin section.
+api_protect_admin_script();
+
+// Including additional libraries.
+require_once api_get_path(LIBRARY_PATH).'fileManage.lib.php';
+require_once api_get_path(LIBRARY_PATH).'import.lib.php';
+
+$tool_name = get_lang('AddUsersToACourse').' CSV';
+
+$interbreadcrumb[] = array('url' => 'index.php', 'name' => get_lang('PlatformAdmin'));
+
+set_time_limit(0);
+
+// Creating the form.
+$form = new FormValidator('course_user_import');
+$form->addElement('header', '', $tool_name);
+$form->addElement('file', 'import_file', get_lang('ImportFileLocation'));
+$form->addElement('checkbox', 'subscribe', get_lang('Action'), get_lang('SubscribeUserIfNotAllreadySubscribed'));
+$form->addElement('checkbox', 'unsubscribe', '', get_lang('UnsubscribeUserIfSubscriptionIsNotInFile'));
+$form->addElement('style_submit_button', 'submit', get_lang('Import'), 'class="save"');
+$form->setDefaults(array('subscribe' => '1', 'unsubscribe' => 1));
+$errors = array();
+
+if ($form->validate()) {
+    $users_courses = parse_csv_data($_FILES['import_file']['tmp_name']);
+    $errors = validate_data($users_courses);
+    if (count($errors) == 0) {
+        $inserted_in_course = save_data($users_courses);
+        // Build the alert message in case there were visual codes subscribed to.
+        if ($_POST['subscribe']) {
+            $warn = get_lang('UsersSubscribedToBecauseVisualCode').': ';
+        } else {
+            $warn = get_lang('UsersUnsubscribedFromBecauseVisualCode').': ';
+        }
+
+        if (!empty($inserted_in_course)) {
+            $warn = $warn.' '.get_lang('FileImported');
+            // The users have been inserted in more than one course.
+            foreach ($inserted_in_course as $code => $info) {
+                $warn .= ' '.$info.' ('.$code.') ';
+            }
+        } else {
+            $warn = get_lang('ErrorsWhenImportingFile');
+        }
+
+        Security::clear_token();
+        $tok = Security::get_token();
+        header('Location: user_list.php?action=show_message&warn='.urlencode($warn).'&sec_token='.$tok);
+        exit();
+    }
+}
+
+// Displaying the header.
+Display :: display_header($tool_name);
+
+if (count($errors) != 0) {
+    $error_message = '<ul>';
+    foreach ($errors as $index => $error_course) {
+        $error_message .= '<li>'.get_lang('Line').' '.$error_course['line'].': <strong>'.$error_course['error'].'</strong>: ';
+        $error_message .= $error_course['Code'].' '.$error_course['Title'];
+        $error_message .= '</li>';
+    }
+    $error_message .= '</ul>';
+    Display :: display_error_message($error_message, false);
+}
+
+// Displaying the form.
+$form->display();
+?>
+<p><?php echo get_lang('CSVMustLookLike').' ('.get_lang('MandatoryFields').')'; ?> :</p>
+<blockquote>
+<pre>
+<b>Email</b>;<b>CourseCode</b>;<b>Status</b>
+example1@example.org;course01;<?php echo COURSEMANAGER; ?>
+
+example2@example.org;course01;<?php echo STUDENT; ?>
+</pre>
+<?php
+echo COURSEMANAGER.': '.get_lang('Teacher').'<br />';
+echo STUDENT.': '.get_lang('Student').'<br />';
+?>
+</blockquote>
+<?php
+
+Display :: display_footer();

+ 0 - 1
main/admin/dashboard_add_courses_to_user.php

@@ -17,7 +17,6 @@ require_once '../inc/lib/xajax/xajax.inc.php';
 
 global $_configuration;
 
-// create an ajax object
 $xajax = new xajax();
 $xajax->registerFunction('search_courses');
 

+ 0 - 1
main/admin/dashboard_add_users_to_user.php

@@ -11,7 +11,6 @@ $language_file = 'admin';
 // resetting the course id
 $cidReset = true;
 
-// including some necessary dokeos files
 require_once '../inc/global.inc.php';
 require_once '../inc/lib/xajax/xajax.inc.php';
 

+ 2 - 2
main/admin/example_session.csv

@@ -1,3 +1,3 @@
 SessionName;Coach;DateStart;DateEnd;Users;Courses
-Session1;jmontoya;2008/08/08;2012/12/12;username1|username2;course1[coach1][username1,username2]|course2[coach1][username1,username2]
-Session2;jmontoya;2008/08/08;2012/12/12;username1|username2;course1[coach1][username1,username2]|course2[coach1][username1,username2]
+Session1;jmontoya;2008/08/08;2020/12/12;username1|username2;course1[coach1][username1,username2]|course2[coach1][username1,username2]
+Session2;jmontoya;2008/08/08;2020/12/12;username1|username2;course1[coach1][username1,username2]|course2[coach1][username1,username2]

+ 22 - 12
main/admin/group_add.php

@@ -5,7 +5,7 @@
 */
 
 // Language files that should be included
-$language_file = array('admin', 'registration','userInfo');
+$language_file = array('admin', 'registration', 'userInfo');
 
 $cidReset = true;
 
@@ -36,10 +36,10 @@ function text_longitud(){
 
 // Database table definitions
 if (!empty($_GET['message'])) {
-	$message = urldecode($_GET['message']);
+    $message = urldecode($_GET['message']);
 }
 
-$interbreadcrumb[] = array ('url' => 'index.php', 'name' => get_lang('PlatformAdmin'));
+$interbreadcrumb[] = array('url' => 'index.php', 'name' => get_lang('PlatformAdmin'));
 $tool_name = get_lang('AddGroups');
 
 // Create the form
@@ -47,25 +47,35 @@ $form = new FormValidator('group_add');
 $form->addElement('header', $tool_name);
 
 // name
-$form->addElement('text', 'name', get_lang('Name'), array('size'=>60, 'maxlength'=>120));
+$form->addElement('text', 'name', get_lang('Name'), array('size' => 60, 'maxlength' => 120));
 $form->applyFilter('name', 'html_filter');
 $form->applyFilter('name', 'trim');
 $form->addRule('name', get_lang('ThisFieldIsRequired'), 'required');
 
 // Description
-$form->addElement('textarea', 'description', get_lang('Description'), array('rows'=>3, 'cols'=>58, 'onKeyDown' => "text_longitud()", 'onKeyUp' => "text_longitud()"));
+$form->addElement(
+    'textarea',
+    'description',
+    get_lang('Description'),
+    array('rows' => 3, 'cols' => 58, 'onKeyDown' => "text_longitud()", 'onKeyUp' => "text_longitud()")
+);
 $form->applyFilter('description', 'html_filter');
 $form->applyFilter('description', 'trim');
 
 // url
-$form->addElement('text', 'url', get_lang('URL'), array('size'=>35));
+$form->addElement('text', 'url', get_lang('URL'), array('size' => 35));
 $form->applyFilter('url', 'html_filter');
 $form->applyFilter('url', 'trim');
 
 // Picture
 $form->addElement('file', 'picture', get_lang('AddPicture'));
-$allowed_picture_types = array ('jpg', 'jpeg', 'png', 'gif');
-$form->addRule('picture', get_lang('OnlyImagesAllowed').' ('.implode(',', $allowed_picture_types).')', 'filetype', $allowed_picture_types);
+$allowed_picture_types = array('jpg', 'jpeg', 'png', 'gif');
+$form->addRule(
+    'picture',
+    get_lang('OnlyImagesAllowed').' ('.implode(',', $allowed_picture_types).')',
+    'filetype',
+    $allowed_picture_types
+);
 
 //Group Parentship
 $groups = array();
@@ -77,8 +87,8 @@ $form->addElement('select', 'parent_group', get_lang('GroupParentship'), $groups
 
 // Status
 $status = array();
-$status[GROUP_PERMISSION_OPEN] 		= get_lang('Open');
-$status[GROUP_PERMISSION_CLOSED]	= get_lang('Closed');
+$status[GROUP_PERMISSION_OPEN] = get_lang('Open');
+$status[GROUP_PERMISSION_CLOSED] = get_lang('Closed');
 
 $form->addElement('select', 'visibility', get_lang('GroupPermissions'), $status);
 
@@ -153,8 +163,8 @@ if( $form->validate()) {
 // Display form
 Display::display_header($tool_name);
 //api_display_tool_title($tool_name);
-if(!empty($message)){
-	Display::display_normal_message(stripslashes($message));
+if (!empty($message)) {
+    Display::display_normal_message(stripslashes($message));
 }
 $form->display();
 

+ 1 - 1
main/admin/group_list.php

@@ -397,4 +397,4 @@ if (isset($_GET['search']) && $_GET['search'] == 'advanced') {
         $table->set_form_actions(array('delete' => get_lang('DeleteFromPlatform')));
     $table->display();
 }
-Display :: display_footer();
+Display :: display_footer();

+ 5 - 6
main/admin/inactive_user_list.php

@@ -2,9 +2,9 @@
 /* For licensing terms, see /license.txt */
 /**
     @author Andre Boivin base code
-	@author Julio Montoya fixing lot of little details  
+	@author Julio Montoya fixing lot of little details
 	@todo this script is not ready for a production use that's why I'm commenting the function delete_inactive_student
-	
+
 *	@package chamilo.admin
 *	script pour effacer les user inactif depuis x temps
 */
@@ -34,12 +34,11 @@ Display :: display_header($tool_name, "");
 //On sélectionne les user élèves
 $sql = "SELECT user_id FROM ".$table_user." user WHERE user.status= '5' ORDER by lastname " ;
 $result = Database::query($sql);
-	
-while($row = Database::fetch_array($result)) {   
+
+while($row = Database::fetch_array($result)) {
     $user_id = $row['user_id'];
     //  pour chaque élève, on trouve la dernière connexion
     //$last_connection_date = UserManager:: delete_inactive_student($user_id, 2, true);
 }
-    
-/*  		FOOTER    */
+
 Display :: display_footer();

+ 18 - 3
main/admin/index.php

@@ -62,6 +62,7 @@ $blocks = array();
 
 $blocks['users']['icon']  = Display::return_icon('members.gif', get_lang('Users'), array(), ICON_SIZE_SMALL, false);
 $blocks['users']['label'] = api_ucfirst(get_lang('Users'));
+$blocks['users']['class'] = 'block-admin-users';
 
 if (api_is_platform_admin()) {
 	$search_form = ' <form method="get" class="form-search" action="user_list.php">
@@ -74,6 +75,7 @@ if (api_is_platform_admin()) {
 		array('url'=>'user_add.php', 	'label' => get_lang('AddUsers')),
 		array('url'=>'user_export.php', 'label' => get_lang('ExportUserListXMLCSV')),
 		array('url'=>'user_import.php', 'label' => get_lang('ImportUserListXMLCSV')),
+               array('url'=>'user_update_import.php', 'label' => get_lang('EditUserListCSV')),
 	);
 
 	if (api_get_setting('allow_social_tool') == 'true') {
@@ -101,6 +103,7 @@ if (api_is_platform_admin()) {
 	/* Courses */
 	$blocks['courses']['icon']  = Display::return_icon('course.gif', get_lang('Courses'), array(), ICON_SIZE_MEDIUM, false);
 	$blocks['courses']['label'] = api_ucfirst(get_lang('Courses'));
+    $blocks['courses']['class'] = 'block-admin-courses';
 
 	$search_form = ' <form method="get" class="form-search" action="course_list.php">
 							<input class="span3" type="text" name="keyword" value="">
@@ -139,6 +142,8 @@ if (api_is_platform_admin()) {
     /* Platform */
     $blocks['platform']['icon']  = Display::return_icon('platform.png', get_lang('Platform'), array(), ICON_SIZE_MEDIUM, false);
     $blocks['platform']['label'] = api_ucfirst(get_lang('Platform'));
+    $blocks['platform']['class'] = 'block-admin-platform';
+
 
     $search_form = ' <form method="get" action="settings.php" class="form-search">
 							<input class="span3" type="text" name="search_field" value="" >
@@ -184,6 +189,8 @@ if (api_is_platform_admin()) {
 /* Sessions */
 $blocks['sessions']['icon']  = Display::return_icon('session.png', get_lang('Sessions'), array(), ICON_SIZE_SMALL, false);
 $blocks['sessions']['label'] = api_ucfirst(get_lang('Sessions'));
+$blocks['sessions']['class'] = 'block-admin-sessions';
+
 
 $search_form = ' <form method="GET" class="form-search" action="session_list.php">
                     <input class="span3" type="text" name="keyword" value="">
@@ -218,8 +225,10 @@ if (api_is_platform_admin()) {
 
 	$blocks['settings']['icon']  = Display::return_icon('settings.png', get_lang('System'), array(), ICON_SIZE_SMALL, false);
 	$blocks['settings']['label'] = api_ucfirst(get_lang('System'));
+    $blocks['settings']['class'] = 'block-admin-settings';
 
-	$items = array();
+
+    $items = array();
 	$items[] = array('url'=>'special_exports.php', 	'label' => get_lang('SpecialExports'));
 	if (!empty($_configuration['db_admin_path'])) {
 		$items[] = array('url'=>$_configuration['db_admin_path'], 	'label' => get_lang('AdminDatabases').' ('.get_lang('DBManagementOnlyForServerAdmin').') ');
@@ -253,6 +262,8 @@ if (api_is_platform_admin()) {
 	/*
 	$blocks['extensions']['icon']  = Display::return_icon('visio_meeting.gif', get_lang('ConfigureExtensions'), array(), ICON_SIZE_SMALL, false);
 	$blocks['extensions']['label'] = api_ucfirst(get_lang('ConfigureExtensions'));
+	$blocks['extensions']['class'] = 'block-admin-extensions';
+
 
 	$items = array();
 	$items[] = array('url'=>'configure_extensions.php?display=visio', 	'label' => get_lang('Visioconf'));
@@ -268,6 +279,8 @@ if (api_is_platform_admin()) {
     if (api_get_setting('allow_skills_tool') == 'true') {
         $blocks['skills']['icon']  = Display::return_icon('logo.png', get_lang('Skills'), array(), ICON_SIZE_SMALL, false);
         $blocks['skills']['label'] = get_lang('Skills');
+        $blocks['skills']['class'] = 'block-admin-skills';
+
 
         $items = array();
         //$items[] = array('url'=>'skills.php',           'label' => get_lang('SkillsTree'));
@@ -285,8 +298,10 @@ if (api_is_platform_admin()) {
 
 	$blocks['chamilo']['icon']  = Display::return_icon('logo.png', 'Chamilo.org', array(), ICON_SIZE_SMALL, false);
 	$blocks['chamilo']['label'] = 'Chamilo.org';
+    $blocks['chamilo']['class'] = 'block-admin-chamilo';
 
-	$items = array();
+
+    $items = array();
 	$items[] = array('url'=>'http://www.chamilo.org/', 	'label' => get_lang('ChamiloHomepage'));
 	$items[] = array('url'=>'http://www.chamilo.org/forum', 	'label' => get_lang('ChamiloForum'));
 
@@ -313,7 +328,7 @@ if (api_is_platform_admin()) {
 	$blocks['version_check']['extra'] = '<div class="admin-block-version"></div>';
     $blocks['version_check']['search_form'] = null;
     $blocks['version_check']['items'] = null;
-    //$blocks['version_check']['class'] = '';
+    $blocks['version_check']['class'] = 'block-admin-version_check';
 
 }
 $admin_ajax_url = api_get_path(WEB_AJAX_PATH).'admin.ajax.php';

+ 4 - 25
main/admin/languages.php

@@ -28,6 +28,7 @@ require_once 'sub_language.class.php';
 $this_section = SECTION_PLATFORM_ADMIN;
 
 api_protect_admin_script();
+$action = isset($_GET['action']) ? $_GET['action'] : null;
 
 //Ajax request
 if (isset($_POST['sent_http_request'])) {
@@ -50,7 +51,6 @@ if (isset($_POST['sent_http_request'])) {
     exit;
 }
 
-
 $htmlHeadXtra[] = '<script>
  $(document).ready(function() {
 
@@ -124,13 +124,6 @@ $htmlHeadXtra[] = '<script>
 $tbl_admin_languages = Database :: get_main_table(TABLE_MAIN_LANGUAGE);
 $tbl_settings_current = Database :: get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
 
-/*
-  ==============================================================================
-  STORING THE CHANGES
-  ==============================================================================
- */
-$action = isset($_GET['action']) ? $_GET['action'] : null;
-
 // we change the availability
 if ($action == 'makeunavailable') {
     if (isset($_GET['id']) && $_GET['id'] == strval(intval($_GET['id']))) {
@@ -186,11 +179,6 @@ if (isset($_POST['Submit']) && $_POST['Submit']) {
     }
 }
 
-/*
-  ==============================================================================
-  MAIN CODE
-  ==============================================================================
- */
 // setting the name of the tool
 $tool_name = get_lang('PlatformLanguages');
 
@@ -221,12 +209,6 @@ $sql_select_lang = "SELECT * FROM $tbl_settings_current WHERE  category='Languag
 $result_select_lang = Database::query($sql_select_lang);
 $row_lang = Database::fetch_array($result_select_lang);
 
-/*
-  --------------------------------------
-  DISPLAY THE TABLE
-  --------------------------------------
-*/
-
 // the table data
 $language_data = array();
 while ($row = Database::fetch_array($result_select)) {
@@ -278,6 +260,9 @@ while ($row = Database::fetch_array($result_select)) {
             $allow_add_term_sub_language = "&nbsp;<a href='sub_language.php?action=registersublanguage&id=" . Security::remove_XSS($all_information_of_sub_language['parent_id']) . "&sub_language_id=" . Security::remove_XSS($row['id']) . "'>" . Display::return_icon('2rightarrow.gif', get_lang('AddWordForTheSubLanguage'), array('width' => ICON_SIZE_SMALL, 'height' => ICON_SIZE_SMALL)) . "</a>";
             $allow_delete_sub_language = "&nbsp;<a href='sub_language_add.php?action=deletesublanguage&id=" . Security::remove_XSS($all_information_of_sub_language['parent_id']) . "&sub_language_id=" . Security::remove_XSS($row['id']) . "'>" . Display::return_icon('delete.png', get_lang('DeleteSubLanguage'), array('width' => ICON_SIZE_SMALL, 'height' => ICON_SIZE_SMALL)) . "</a>";
         }
+    } else {
+        $allow_use_sub_language = '';
+        $allow_add_term_sub_language = '';
     }
 
     if ($row['english_name'] == $row_lang['selected_value']) {
@@ -306,10 +291,4 @@ $table->set_form_actions($form_actions);
 echo '<div id="id_content_message">&nbsp;</div>';
 $table->display();
 
-/*
-  ==============================================================================
-  FOOTER
-  ==============================================================================
- */
 Display :: display_footer();
-?>

+ 33 - 33
main/admin/promotions.php

@@ -25,13 +25,13 @@ $interbreadcrumb[] = array('url' => 'career_dashboard.php','name' => get_lang('C
 $action = isset($_GET['action']) ? $_GET['action'] : null;
 
 $check = Security::check_token('request');
-$token = Security::get_token();    
+$token = Security::get_token();
 
 if ($action == 'add') {
     $interbreadcrumb[]=array('url' => 'promotions.php','name' => get_lang('Promotions'));
     $interbreadcrumb[]=array('url' => '#','name' => get_lang('Add'));
 } elseif ($action == 'edit') {
-    $interbreadcrumb[]=array('url' => 'promotions.php','name' => get_lang('Promotions'));    
+    $interbreadcrumb[]=array('url' => 'promotions.php','name' => get_lang('Promotions'));
     $interbreadcrumb[]=array('url' => '#','name' => get_lang('Edit'));
 } else {
     $interbreadcrumb[]=array('url' => '#','name' => get_lang('Promotions'));
@@ -43,7 +43,7 @@ Display::display_header($tool_name);
 // Tool name
 if (isset($_GET['action']) && $_GET['action'] == 'add') {
     $tool = 'Add';
-    $interbreadcrumb[] = array ('url' => api_get_self(), 'name' => get_lang('Promotion'));    
+    $interbreadcrumb[] = array ('url' => api_get_self(), 'name' => get_lang('Promotion'));
 }
 if (isset($_GET['action']) && $_GET['action'] == 'edit') {
     $tool = 'Modify';
@@ -54,31 +54,31 @@ $url            = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_promotions';
 //The order is important you need to check the model.ajax.php the $column variable
 $columns        = array(get_lang('Name'),get_lang('Career'),get_lang('Description'),get_lang('Actions'));
 $column_model   = array(
-                        array('name'=>'name',           'index'=>'name',        'width'=>'180',   'align'=>'left'),
-                        array('name'=>'career',         'index'=>'career',      'width'=>'100',  'align'=>'left'),
-                        array('name'=>'description',    'index'=>'description', 'width'=>'500',  'align'=>'left','sortable'=>'false'),
-                        array('name'=>'actions',        'index'=>'actions',     'width'=>'100',  'align'=>'left','formatter'=>'action_formatter','sortable'=>'false'),
-                       );                        
+    array('name'=>'name',           'index'=>'name',        'width'=>'180',   'align'=>'left'),
+    array('name'=>'career',         'index'=>'career',      'width'=>'100',  'align'=>'left'),
+    array('name'=>'description',    'index'=>'description', 'width'=>'500',  'align'=>'left','sortable'=>'false'),
+    array('name'=>'actions',        'index'=>'actions',     'width'=>'100',  'align'=>'left','formatter'=>'action_formatter','sortable'=>'false'),
+);
 $extra_params['autowidth'] = 'true'; //use the width of the parent
 //$extra_params['editurl'] = $url; //use the width of the parent
 
 $extra_params['height'] = 'auto'; //use the width of the parent
 //With this function we can add actions to the jgrid
 $action_links = 'function action_formatter (cellvalue, options, rowObject) {
-                    return \'<a href="add_sessions_to_promotion.php?id=\'+options.rowId+\'">'.Display::return_icon('session_to_promotion.png',get_lang('SubscribeSessionsToPromotions'),'',ICON_SIZE_SMALL).'</a>'.
-                    '&nbsp;<a href="?action=edit&id=\'+options.rowId+\'">'.Display::return_icon('edit.png',get_lang('Edit'),'',ICON_SIZE_SMALL).'</a>'.
-					'&nbsp;<a onclick="javascript:if(!confirm('."\'".addslashes(api_htmlentities(get_lang("ConfirmYourChoice"),ENT_QUOTES))."\'".')) return false;"  href="?sec_token='.$token.'&action=copy&id=\'+options.rowId+\'">'.Display::return_icon('copy.png',get_lang('Copy'),'',ICON_SIZE_SMALL).'</a>'.
-                    '&nbsp;<a onclick="javascript:if(!confirm('."\'".addslashes(api_htmlentities(get_lang("ConfirmYourChoice"),ENT_QUOTES))."\'".')) return false;"  href="?sec_token='.$token.'&action=delete&id=\'+options.rowId+\'">'.Display::return_icon('delete.png',get_lang('Delete'),'',ICON_SIZE_SMALL).'</a> \'; 
-                 }';
+    return \'<a href="add_sessions_to_promotion.php?id=\'+options.rowId+\'">'.Display::return_icon('session_to_promotion.png',get_lang('SubscribeSessionsToPromotions'),'',ICON_SIZE_SMALL).'</a>'.
+    '&nbsp;<a href="?action=edit&id=\'+options.rowId+\'">'.Display::return_icon('edit.png',get_lang('Edit'),'',ICON_SIZE_SMALL).'</a>'.
+    '&nbsp;<a onclick="javascript:if(!confirm('."\'".addslashes(api_htmlentities(get_lang("ConfirmYourChoice"),ENT_QUOTES))."\'".')) return false;"  href="?sec_token='.$token.'&action=copy&id=\'+options.rowId+\'">'.Display::return_icon('copy.png',get_lang('Copy'),'',ICON_SIZE_SMALL).'</a>'.
+    '&nbsp;<a onclick="javascript:if(!confirm('."\'".addslashes(api_htmlentities(get_lang("ConfirmYourChoice"),ENT_QUOTES))."\'".')) return false;"  href="?sec_token='.$token.'&action=delete&id=\'+options.rowId+\'">'.Display::return_icon('delete.png',get_lang('Delete'),'',ICON_SIZE_SMALL).'</a> \'; 
+}';
 
 ?>
 <script>
-$(function() { 
-    <?php 
-         echo Display::grid_js('promotions',  $url,$columns,$column_model,$extra_params,array(), $action_links, true);       
+$(function() {
+    <?php
+         echo Display::grid_js('promotions',  $url,$columns,$column_model,$extra_params,array(), $action_links, true);
     ?>
 });
-</script>   
+</script>
 <?php
 $promotion = new Promotion();
 
@@ -99,22 +99,22 @@ switch ($action) {
         }
 
         $url  = api_get_self().'?action='.Security::remove_XSS($_GET['action']);
-        $form = $promotion->return_form($url, 'add');    
+        $form = $promotion->return_form($url, 'add');
 
         // The validation or display
-        if ($form->validate()) {            
+        if ($form->validate()) {
             if ($check) {
-                $values = $form->exportValues();       
-                $res    = $promotion->save($values);            
+                $values = $form->exportValues();
+                $res    = $promotion->save($values);
                 if ($res) {
                     Display::display_confirmation_message(get_lang('ItemAdded'));
                 }
-            }            
+            }
             $promotion->display();
         } else {
-            echo '<div class="actions">';        
+            echo '<div class="actions">';
             echo Display::url(Display::return_icon('back.png',get_lang('Back'),'',ICON_SIZE_MEDIUM), api_get_self());
-            echo '</div>';            
+            echo '</div>';
             $form->addElement('hidden', 'sec_token');
             $form->setConstants(array('sec_token' => $token));
             $form->display();
@@ -122,13 +122,13 @@ switch ($action) {
         break;
     case 'edit':
         //Editing 
-        $url  = api_get_self().'?action='.Security::remove_XSS($_GET['action']).'&id='.intval($_GET['id']);    
+        $url  = api_get_self().'?action='.Security::remove_XSS($_GET['action']).'&id='.intval($_GET['id']);
         $form = $promotion->return_form($url, 'edit');
 
         // The validation or display
-        if ($form->validate()) {            
+        if ($form->validate()) {
             if ($check) {
-                $values = $form->exportValues();                    
+                $values = $form->exportValues();
                 $res    = $promotion->update($values);
                 $promotion->update_all_sessions_status_by_promotion_id($values['id'], $values['status']);  
                 if ($res) {
@@ -137,15 +137,15 @@ switch ($action) {
             }            
             $promotion->display();
         } else {
-            echo '<div class="actions">';        
+            echo '<div class="actions">';
             echo Display::url(Display::return_icon('back.png',get_lang('Back'),'',ICON_SIZE_MEDIUM), api_get_self());
-            echo '</div>';            
+            echo '</div>';
             $form->addElement('hidden', 'sec_token');
             $form->setConstants(array('sec_token' => $token));
             $form->display();
         }
         break;
-    case 'delete':        
+    case 'delete':
         if ($check) {
             // Action handling: deleting an obj
             $res = $promotion->delete($_GET['id']);
@@ -153,17 +153,17 @@ switch ($action) {
                 Display::display_confirmation_message(get_lang('ItemDeleted'));
             }
         }
-        $promotion->display();        
+        $promotion->display();
         break;
     case 'copy':
         if (api_get_session_id() != 0 && !api_is_allowed_to_session_edit(false, true)) {
             api_not_allowed();
         }
         if ($check) {
-            $res = $promotion->copy($_GET['id'], null, true);    
+            $res = $promotion->copy($_GET['id'], null, true);
             if ($res) {
                 Display::display_confirmation_message(get_lang('ItemCopied').' - '.get_lang('ExerciseAndLPsAreInvisibleInTheNewCourse'));
-            }            
+            }
         }
         $promotion->display();
         break;

+ 48 - 29
main/admin/resume_session.php

@@ -96,39 +96,31 @@ switch ($action) {
         }
         break;
     case 'delete':
-        $idChecked = $_GET['idChecked'];
+        // Delete course from session.
+        $idChecked = isset($_GET['idChecked']) ? $_GET['idChecked'] : null;
         if (is_array($idChecked)) {
-            $my_temp = array();
-            foreach ($idChecked as $id){
-                $my_temp[]= Database::escape_string($id);// forcing the escape_string
+            $usersToDelete = array();
+            foreach ($idChecked as $courseCode) {
+                // forcing the escape_string
+                $courseInfo = api_get_course_info($courseCode);
+                SessionManager::unsubscribe_course_from_session(
+                    $id_session,
+                    $courseInfo['real_id']
+                );
             }
-            $idChecked = $my_temp;
-
-            $idChecked="'".implode("','",$idChecked)."'";
-
-            Database::query("DELETE FROM $tbl_session_rel_course WHERE id_session='$id_session' AND course_code IN($idChecked)");
-            $nbr_affected_rows=Database::affected_rows();
-
-            Database::query("DELETE FROM $tbl_session_rel_course_rel_user WHERE id_session='$id_session' AND course_code IN($idChecked)");
-            Database::query("UPDATE $tbl_session SET nbr_courses=nbr_courses-$nbr_affected_rows WHERE id='$id_session'");
         }
 
-        if (!empty($_GET['class'])){
+        if (!empty($_GET['class'])) {
             Database::query("DELETE FROM $tbl_session_rel_class WHERE session_id='$id_session' AND class_id=".Database::escape_string($_GET['class']));
             $nbr_affected_rows=Database::affected_rows();
             Database::query("UPDATE $tbl_session SET nbr_classes=nbr_classes-$nbr_affected_rows WHERE id='$id_session'");
         }
 
         if (!empty($_GET['user'])) {
-            Database::query("DELETE FROM $tbl_session_rel_user WHERE relation_type<>".SESSION_RELATION_TYPE_RRHH." AND id_session='$id_session' AND id_user=".intval($_GET['user']));
-            $nbr_affected_rows=Database::affected_rows();
-
-            Database::query("UPDATE $tbl_session SET nbr_users=nbr_users-$nbr_affected_rows WHERE id='$id_session'");
-
-            Database::query("DELETE FROM $tbl_session_rel_course_rel_user WHERE id_session='$id_session' AND id_user=".intval($_GET['user']));
-            $nbr_affected_rows=Database::affected_rows();
-
-            Database::query("UPDATE $tbl_session_rel_course SET nbr_users=nbr_users-$nbr_affected_rows WHERE id_session='$id_session'");
+            SessionManager::unsubscribe_user_from_session(
+                $id_session,
+                $_GET['user']
+            );
         }
         break;
 }
@@ -230,11 +222,23 @@ if ($multiple_url_is_on) {
     echo '</td>';
     echo '<td>';
     $url_list = UrlManager::get_access_url_from_session($id_session);
-    foreach($url_list as $url_data) {
+    foreach ($url_list as $url_data) {
         echo $url_data['url'].'<br />';
     }
     echo '</td></tr>';
 }
+
+if (SessionManager::durationPerUserIsEnabled()) {
+    $sessionInfo = api_get_session_info($id_session);
+    echo '<tr><td>';
+    echo get_lang('Duration');
+    echo '</td>';
+    echo '<td>';
+    echo $sessionInfo['duration'].' ';
+    echo get_lang('Days');
+    echo '</td></tr>';
+
+}
 ?>
 </table>
 <br />
@@ -387,11 +391,8 @@ $url .= Display::url(
     "session_user_import.php?id_session=$id_session"
 );
 echo Display::page_subheader(get_lang('UserList').$url);
-
 ?>
-
 <!--List of users -->
-
 <table class="data_table">
     <tr>
         <th>
@@ -444,15 +445,28 @@ if ($session['nbr_users']==0) {
                 $link_to_add_user_in_url = '<a href="resume_session.php?action=add_user_to_url&id_session='.$id_session.'&user_id='.$user['user_id'].'">'.$add.'</a>';
             }
         }
+
+        $editUrl = null;
+        if (SessionManager::durationPerUserIsEnabled()) {
+            if (isset($sessionInfo['duration']) && !empty($sessionInfo['duration'])) {
+                $editUrl = api_get_path(WEB_CODE_PATH) . 'admin/session_user_edit.php?session_id=' . $id_session . '&user_id=' . $user['user_id'];
+                $editUrl = Display::url(
+                    Display::return_icon('agenda.png', get_lang('SessionDurationEdit')),
+                    $editUrl
+                );
+            }
+        }
 		echo '<tr>
-                <td width="90%">
+                <td width="80%">
                     '.$user_link.'
                 </td>
                 <td>
+                    '.$editUrl.'
                     <a href="../mySpace/myStudents.php?student='.$user['user_id'].''.$orig_param.'">'.Display::return_icon('statistics.gif', get_lang('Reporting')).'</a>&nbsp;
                     <a href="session_course_user.php?id_user='.$user['user_id'].'&id_session='.$id_session.'">'.Display::return_icon('course.gif', get_lang('BlockCoursesForThisUser')).'</a>&nbsp;
                     <a href="'.api_get_self().'?id_session='.$id_session.'&action=delete&user='.$user['user_id'].'" onclick="javascript:if(!confirm(\''.get_lang('ConfirmYourChoice').'\')) return false;">'.Display::return_icon('delete.png', get_lang('Delete')).'</a>
                     '.$link_to_add_user_in_url.'
+
                 </td>
                 </tr>';
 	}
@@ -460,11 +474,16 @@ if ($session['nbr_users']==0) {
 ?>
 </table>
 <?php
-// footer
+
 Display :: display_footer();
 
 /*
  ALTER TABLE session_rel_course ADD COLUMN position int;
  ALTER TABLE session_rel_course ADD COLUMN category varchar(255);
+
+ https://task.beeznest.com/issues/8317:
+
+ ALTER TABLE session ADD COLUMN duration int;
+ ALTER TABLE session_rel_user ADD COLUMN duration int;
  *
 */

+ 15 - 10
main/admin/session_add.php

@@ -95,7 +95,7 @@ function fill_coach_field (username) {
 </script>';
 
 
-if ($_POST['formSent']) {
+if (isset($_POST['formSent']) && $_POST['formSent']) {
 	$formSent = 1;
     $name = $_POST['name'];
     $year_start = $_POST['year_start'];
@@ -145,8 +145,14 @@ if ($_POST['formSent']) {
 	}
 }
 
-$nb_days_acess_before = 0;
-$nb_days_acess_after = 0;
+global $_configuration;
+$defaultBeforeDays = isset($_configuration['session_days_before_coach_access']) ?
+    $_configuration['session_days_before_coach_access'] : 0;
+$defaultAfterDays = isset($_configuration['session_days_after_coach_access'])
+    ? $_configuration['session_days_after_coach_access'] : 0;
+
+$nb_days_acess_before = $defaultBeforeDays;
+$nb_days_acess_after = $defaultAfterDays;
 
 $thisYear=date('Y');
 $thisMonth=date('m');
@@ -221,9 +227,6 @@ $Categories = SessionManager::get_all_session_category();
 ?>
         </div>
     </div>
-
-
-
     <div class="control-group">
         <label class="control-label">
             <?php echo get_lang('SessionCategory') ?>
@@ -388,7 +391,6 @@ for ($i=$thisYear-5;$i <= ($thisYear+5);$i++) {
   </select>
   /
   <select name="year_end">
-
 <?php
 for ($i=$thisYear-5;$i <= ($thisYear+5);$i++) {
 ?>
@@ -401,13 +403,16 @@ for ($i=$thisYear-5;$i <= ($thisYear+5);$i++) {
     <?php echo get_lang('SessionVisibility') ?>
     <select name="session_visibility" style="width:250px;">
         <?php
-        $visibility_list = array(SESSION_VISIBLE_READ_ONLY=>get_lang('SessionReadOnly'), SESSION_VISIBLE=>get_lang('SessionAccessible'), SESSION_INVISIBLE=>api_ucfirst(get_lang('SessionNotAccessible')));
+        $visibility_list = array(
+            SESSION_VISIBLE_READ_ONLY => get_lang('SessionReadOnly'),
+            SESSION_VISIBLE => get_lang('SessionAccessible'),
+            SESSION_INVISIBLE => api_ucfirst(get_lang('SessionNotAccessible'))
+        );
         foreach($visibility_list as $key=>$item): ?>
-        <option value="<?php echo $key; ?>" <?php if($item == $visibility_id) echo 'selected="selected"'; ?>><?php echo $item; ?></option>
+        <option value="<?php echo $key; ?>"><?php echo $item; ?></option>
         <?php endforeach; ?>
     </select>
      </div>
-
         </div>
     </div>
 

+ 2 - 2
main/admin/session_category_add.php

@@ -31,7 +31,7 @@ $interbreadcrumb[]=array('url' => "session_category_list.php","name" => get_lang
 $tbl_user		= Database::get_main_table(TABLE_MAIN_USER);
 $tbl_session	= Database::get_main_table(TABLE_MAIN_SESSION);
 
-if ($_POST['formSent']) {
+if (isset($_POST['formSent']) && $_POST['formSent']) {
 	$formSent=1;
 	$name= $_POST['name'];
 	$year_start= $_POST['year_start'];
@@ -233,4 +233,4 @@ function setDisable(select) {
 </script>
 <?php
 Display::display_footer();
-?>
+

+ 49 - 33
main/admin/session_category_edit.php

@@ -4,27 +4,31 @@
  * Edition script for sessions categories
  * @package chamilo.admin
  */
-/**
- * Code
- */
 
 // name of the language file that needs to be included
 $language_file ='admin';
-$cidReset=true;
+$cidReset = true;
 require_once '../inc/global.inc.php';
 
 // setting the section (for the tabs)
-$this_section=SECTION_PLATFORM_ADMIN;
+$this_section = SECTION_PLATFORM_ADMIN;
 api_protect_admin_script(true);
-$id=intval($_GET['id']);
-$formSent=0;
-$errorMsg='';
+$id = intval($_GET['id']);
+$formSent = 0;
+$errorMsg = '';
 
 // Database Table Definitions
 $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
 $tool_name = get_lang('EditSessionCategory');
-$interbreadcrumb[]=array('url' => 'index.php',"name" => get_lang('PlatformAdmin'));
-$interbreadcrumb[]=array('url' => "session_category_list.php","name" => get_lang('ListSessionCategory'));
+$interbreadcrumb[] = array(
+    'url' => 'index.php',
+    "name" => get_lang('PlatformAdmin')
+);
+$interbreadcrumb[] = array(
+    'url' => "session_category_list.php",
+    "name" => get_lang('ListSessionCategory')
+);
+
 $sql = "SELECT * FROM $tbl_session_category WHERE id='".$id."' ORDER BY name";
 $result=Database::query($sql);
 if (!$infos=Database::fetch_array($result)) {
@@ -38,24 +42,38 @@ if (!api_is_platform_admin() && $infos['session_admin_id']!=$_user['user_id'] &&
 	api_not_allowed(true);
 }
 
-if ($_POST['formSent']) {
-	$formSent=1;
-	$name= $_POST['name'];
-	$year_start= $_POST['year_start'];
-	$month_start=$_POST['month_start'];
-	$day_start=$_POST['day_start'];
-	$year_end=$_POST['year_end'];
-	$month_end=$_POST['month_end'];
-	$day_end=$_POST['day_end'];
-	$return = SessionManager::edit_category_session($id, $name, $year_start, $month_start, $day_start, $year_end, $month_end, $day_end);
-	if ($return == strval(intval($return))) {
-		header('Location: session_category_list.php?action=show_message&message='.urlencode(get_lang('SessionCategoryUpdate')));
-		exit();
-	}
+if (isset($_POST['formSent']) && $_POST['formSent']) {
+    $formSent = 1;
+    $name = $_POST['name'];
+    $year_start = $_POST['year_start'];
+    $month_start = $_POST['month_start'];
+    $day_start = $_POST['day_start'];
+    $year_end = $_POST['year_end'];
+    $month_end = $_POST['month_end'];
+    $day_end = $_POST['day_end'];
+    $return = SessionManager::edit_category_session(
+        $id,
+        $name,
+        $year_start,
+        $month_start,
+        $day_start,
+        $year_end,
+        $month_end,
+        $day_end
+    );
+    if ($return == strval(intval($return))) {
+        header(
+            'Location: session_category_list.php?action=show_message&message=' . urlencode(
+                get_lang('SessionCategoryUpdate')
+            )
+        );
+        exit();
+    }
 }
-$thisYear=date('Y');
-$thisMonth=date('m');
-$thisDay=date('d');
+
+$thisYear = date('Y');
+$thisMonth = date('m');
+$thisDay = date('d');
 
 // display the header
 Display::display_header($tool_name);
@@ -63,7 +81,7 @@ if (!empty($return)) {
 	Display::display_error_message($return,false);
 }
 ?>
-<form method="post" name="form" action="<?php echo api_get_self(); ?>?page=<?php echo Security::remove_XSS($_GET['page']) ?>&id=<?php echo $id; ?>" style="margin:0px;">
+<form method="post" name="form" action="<?php echo api_get_self(); ?>?id=<?php echo $id; ?>">
 <input type="hidden" name="formSent" value="1">
 <legend><?php echo $tool_name;?> </legend>
 <table border="0" cellpadding="5" cellspacing="0" width="550">
@@ -216,15 +234,14 @@ for($i=$thisYear-5;$i <= ($thisYear+5);$i++)
 <tr>
   <td>&nbsp;</td>
   <td>
-<button class="save" type="submit" value="<?php echo get_lang('ModifyThisSession') ?>"><?php echo get_lang('ModifyThisSession') ?></button>
+<button class="save" type="submit" value="<?php echo get_lang('ModifyThisSession') ?>">
+    <?php echo get_lang('ModifyThisSession') ?></button>
 
   </td>
 </tr>
-
 </table>
-
 </form>
-<script type="text/javascript">
+<script>
 <?php if($year_start=="0000") echo "setDisable(document.form.nolimit);\r\n"; ?>
 function setDisable(select){
 	document.form.day_start.disabled = (select.checked) ? true : false;
@@ -237,4 +254,3 @@ function setDisable(select){
 </script>
 <?php
 Display::display_footer();
-?>

+ 8 - 17
main/admin/session_category_list.php

@@ -17,16 +17,14 @@ api_protect_admin_script(true);
 
 // setting the section (for the tabs)
 $this_section = SECTION_PLATFORM_ADMIN;
-$htmlHeadXtra[] =
-'<script>
-    function selectAll(idCheck,numRows,action) {
-        for(i=0;i<numRows;i++) {
-            idcheck = document.getElementById(idCheck+"_"+i);
-            if (action == "true"){
-                idcheck.checked = true;
-            } else {
-                idcheck.checked = false;
-            }
+$htmlHeadXtra[] = '<script>
+function selectAll(idCheck,numRows,action) {
+    for(i=0;i<numRows;i++) {
+        idcheck = document.getElementById(idCheck+"_"+i);
+        if (action == "true"){
+            idcheck.checked = true;
+        } else {
+            idcheck.checked = false;
         }
     }
 </script>';
@@ -75,9 +73,6 @@ if (isset($_GET['search']) && $_GET['search'] == 'advanced') {
     } else {
         $where .= (empty($_REQUEST['keyword']) ? "" : " WHERE name LIKE '%".Database::escape_string(trim($_REQUEST['keyword']))."%'");
     }
-
-
-
     if (empty($where)) {
         $where = " WHERE access_url_id = ".api_get_current_access_url_id()." ";
     } else {
@@ -206,9 +201,7 @@ if (isset($_GET['search']) && $_GET['search'] == 'advanced') {
             ?>
         </table>
         <br />
-
         <div align="left">
-
             <?php
             if ($num > $limit) {
                 if ($page) {
@@ -221,9 +214,7 @@ if (isset($_GET['search']) && $_GET['search'] == 'advanced') {
                 echo get_lang('Previous');
             }
             ?>
-
                 |
-
                 <?php
                 if ($nbr_results > $limit) {
                     ?>

+ 13 - 11
main/admin/session_course_edit.php

@@ -5,8 +5,8 @@
  * @package chamilo.admin
  */
 // name of the language file that needs to be included
-$language_file='admin';
-$cidReset=true;
+$language_file = 'admin';
+$cidReset = true;
 
 require_once '../inc/global.inc.php';
 
@@ -24,23 +24,25 @@ $tbl_session		= Database::get_main_table(TABLE_MAIN_SESSION);
 $tbl_session_course	= Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
 $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
 
-$course_info=api_get_course_info($_REQUEST['course_code']);
-$tool_name=$course_info['name'];
+$course_info = api_get_course_info($_REQUEST['course_code']);
+$tool_name = $course_info['name'];
 
-$interbreadcrumb[]=array('url' => 'index.php',"name" => get_lang('PlatformAdmin'));
-$interbreadcrumb[]=array('url' => "session_list.php","name" => get_lang("SessionList"));
-$interbreadcrumb[]=array('url' => "resume_session.php?id_session=".$id_session,"name" => get_lang('SessionOverview'));
-$interbreadcrumb[]=array('url' => "session_course_list.php?id_session=$id_session","name" =>api_htmlentities($session_name,ENT_QUOTES,$charset));
-
-$result = Database::query("SELECT s.name, c.title FROM $tbl_session_course sc,$tbl_session s,$tbl_course c WHERE sc.id_session=s.id AND sc.course_code=c.code AND sc.id_session='$id_session' AND sc.course_code='".addslashes($course_code)."'");
+$result = Database::query("SELECT s.name, c.title FROM $tbl_session_course sc,$tbl_session s,$tbl_course c
+WHERE sc.id_session=s.id AND sc.course_code=c.code AND sc
+.id_session='$id_session' AND sc.course_code='".Database::escape_string($course_code)."'");
 
 if (!list($session_name,$course_title)=Database::fetch_row($result)) {
 	header('Location: session_course_list.php?id_session='.$id_session);
 	exit();
 }
 
+$interbreadcrumb[]=array('url' => 'index.php',"name" => get_lang('PlatformAdmin'));
+$interbreadcrumb[]=array('url' => "session_list.php","name" => get_lang("SessionList"));
+$interbreadcrumb[]=array('url' => "resume_session.php?id_session=".$id_session,"name" => get_lang('SessionOverview'));
+$interbreadcrumb[]=array('url' => "session_course_list.php?id_session=$id_session","name" =>api_htmlentities($session_name,ENT_QUOTES,$charset));
+
 $arr_infos = array();
-if ($_POST['formSent']) {
+if (isset($_POST['formSent']) && $_POST['formSent']) {
 	$formSent=1;
 
 	// get all tutor by course_code in the session

+ 10 - 21
main/admin/session_course_user_list.php

@@ -1,11 +1,9 @@
 <?php
 /* For licensing terms, see /license.txt */
+
 /**
 *	@package chamilo.admin
 */
-/**
- * Code
- */
 $language_file = array('admin', 'registration');
 $cidReset = true;
 
@@ -26,22 +24,24 @@ if (empty($id_session )) {
 }
 
 $course_code    = Database::escape_string(trim($_GET['course_code']));
-$page           = intval($_GET['page']);
-$action         = $_REQUEST['action'];
+$page           = isset($_GET['page']) ? intval($_GET['page']) : null;
+$action         = isset($_REQUEST['action']) ? $_REQUEST['action'] : null;
 $default_sort   = api_sort_by_first_name() ? 'firstname':'lastname';
-$sort           = in_array($_GET['sort'], array('lastname','firstname','username')) ? $_GET['sort'] : $default_sort;
-$idChecked      = (is_array($_GET['idChecked']) ? $_GET['idChecked'] : (is_array($_POST['idChecked']) ? $_POST['idChecked'] : null));
+$sort           = isset($_GET['sort']) && in_array($_GET['sort'], array('lastname','firstname','username')) ? $_GET['sort'] : $default_sort;
+$idChecked      = isset($_GET['idChecked']) && is_array($_GET['idChecked']) ? $_GET['idChecked'] : (isset($_POST['idChecked']) && is_array($_POST['idChecked']) ? $_POST['idChecked'] : null);
 $direction      = isset($_GET['direction']) && in_array($_GET['direction'], array('desc','asc')) ? $_GET['direction'] : 'desc';
 
 if (is_array($idChecked)) {
     $my_temp = array();
     foreach ($idChecked as $id) {
-        $my_temp[]= intval($id);// forcing the intval
+        // forcing the intval
+        $my_temp[]= intval($id);
     }
     $idChecked = $my_temp;
 }
 
-$sql = "SELECT s.name, c.title  FROM $tbl_session_rel_course src
+$sql = "SELECT s.name, c.title
+        FROM $tbl_session_rel_course src
 		INNER JOIN $tbl_session s ON s.id = src.id_session
 		INNER JOIN $tbl_course c ON c.code = src.course_code
 		WHERE src.id_session='$id_session' AND src.course_code='".Database::escape_string($course_code)."' ";
@@ -52,7 +52,7 @@ if (!list($session_name,$course_title) = Database::fetch_row($result)) {
 	exit();
 }
 
-switch($action) {
+switch ($action) {
     case 'delete':
         if (is_array($idChecked) && count($idChecked)>0) {
             array_map('intval', $idChecked);
@@ -77,17 +77,6 @@ switch($action) {
 $limit  = 20;
 $from   = $page * $limit;
 $is_western_name_order = api_is_western_name_order();
-
-//scru.status<>2  scru.course_code='".$course_code."'
-/*$sql = "SELECT DISTINCT
-         u.user_id,".($is_western_name_order ? 'u.firstname, u.lastname' : 'u.lastname, u.firstname').", u.username, scru.id_user as is_subscribed
-         FROM $tbl_session_rel_user s
-         INNER JOIN $tbl_user u ON (u.user_id=s.id_user)
-         LEFT JOIN $tbl_session_rel_course_rel_user scru ON (u.user_id=scru.id_user AND  scru.course_code = '".$course_code."' )
-         WHERE s.id_session='$id_session'
-         ORDER BY $sort $direction
-         LIMIT $from,".($limit+1);*/
-
 $sql = "SELECT DISTINCT
          u.user_id,".($is_western_name_order ? 'u.firstname, u.lastname' : 'u.lastname, u.firstname').", u.username, scru.id_user as is_subscribed
          FROM $tbl_session_rel_user s

+ 16 - 6
main/admin/session_edit.php

@@ -34,12 +34,18 @@ $interbreadcrumb[] = array('url' => 'index.php',"name" => get_lang('PlatformAdmi
 $interbreadcrumb[] = array('url' => "session_list.php","name" => get_lang('SessionList'));
 $interbreadcrumb[] = array('url' => "resume_session.php?id_session=".$id,"name" => get_lang('SessionOverview'));
 
-list($year_start,$month_start,$day_start)   = explode('-', $infos['date_start']);
-list($year_end,$month_end,$day_end)         = explode('-', $infos['date_end']);
+list($year_start, $month_start, $day_start) = explode('-', $infos['date_start']);
+list($year_end, $month_end, $day_end) = explode('-', $infos['date_end']);
 
-$showDescriptionChecked = null;
-if (isset($infos['show_description']) && !empty($infos['show_description'])) {
-    $showDescriptionChecked = 'checked';
+// Default value
+$showDescriptionChecked = 'checked';
+
+if (isset($infos['show_description'])) {
+    if (!empty($infos['show_description'])) {
+        $showDescriptionChecked = 'checked';
+    } else {
+        $showDescriptionChecked = null;
+    }
 }
 
 $end_year_disabled = $end_month_disabled = $end_day_disabled = '';
@@ -348,7 +354,11 @@ if (!empty($return)) {
             <?php echo get_lang('SessionVisibility') ?> <br />
             <select name="session_visibility" style="width:250px;">
                 <?php
-                $visibility_list = array(SESSION_VISIBLE_READ_ONLY=>get_lang('SessionReadOnly'), SESSION_VISIBLE=>get_lang('SessionAccessible'), SESSION_INVISIBLE=>api_ucfirst(get_lang('SessionNotAccessible')));
+                $visibility_list = array(
+                    SESSION_VISIBLE_READ_ONLY => get_lang('SessionReadOnly'),
+                    SESSION_VISIBLE => get_lang('SessionAccessible'),
+                    SESSION_INVISIBLE => api_ucfirst(get_lang('SessionNotAccessible'))
+                );
                 foreach($visibility_list as $key=>$item): ?>
                 <option value="<?php echo $key; ?>" <?php if($key == $infos['visibility']) echo 'selected="selected"'; ?>><?php echo $item; ?></option>
                 <?php endforeach; ?>

+ 50 - 47
main/admin/session_import.php

@@ -39,20 +39,20 @@ set_time_limit(0);
 
 // Set this option to true to enforce strict purification for usenames.
 $purification_option_for_usernames = false;
-
 $inserted_in_course = array();
 
 global $_configuration;
-
+$warn = null;
 if (isset($_POST['formSent']) && $_POST['formSent']) {
-    if (isset($_FILES['import_file']['tmp_name']) && !empty($_FILES['import_file']['tmp_name'])) {
+    if (isset($_FILES['import_file']['tmp_name']) &&
+        !empty($_FILES['import_file']['tmp_name'])
+    ) {
         $form_sent = $_POST['formSent'];
-        $file_type = $_POST['file_type'];
-        $send_mail = $_POST['sendMail'] ? 1 : 0;
-        $isOverwrite = $_POST['overwrite'] ? true: false;
+        $file_type = isset($_POST['file_type']) ? $_POST['file_type'] : null;
+        $send_mail = isset($_POST['sendMail']) && $_POST['sendMail'] ? 1 : 0;
+        $isOverwrite = isset($_POST['overwrite']) && $_POST['overwrite'] ? true: false;
         $deleteUsersNotInList = isset($_POST['delete_users_not_in_list']) ? true : false;
         $sessions = array();
-
         $session_counter = 0;
 
         if ($file_type == 'xml') {
@@ -74,7 +74,6 @@ if (isset($_POST['formSent']) && $_POST['formSent']) {
 
             if (is_object($root)) {
                 if (count($root->Users->User) > 0) {
-
                     // Creating/updating users from <Sessions> <Users> base node.
                     foreach ($root->Users->User as $node_user) {
                         $username = $username_old = trim(api_utf8_decode($node_user->Username));
@@ -96,24 +95,24 @@ if (isset($_POST['formSent']) && $_POST['formSent']) {
                             }
 
                             $result = UserManager::create_user(
-                                    api_utf8_decode($node_user->Firstname),
-                                    api_utf8_decode($node_user->Lastname),
-                                    $status,
-                                    api_utf8_decode($node_user->Email),
-                                    $username,
-                                    $password,
-                                    api_utf8_decode($node_user->OfficialCode),
-                                    null,
-                                    api_utf8_decode($node_user->Phone),
-                                    null,
-                                    PLATFORM_AUTH_SOURCE,
-                                    null,
-                                    1,
-                                    0,
-                                    null,
-                                    null,
-                                    $send_mail
-                                    );
+                                api_utf8_decode($node_user->Firstname),
+                                api_utf8_decode($node_user->Lastname),
+                                $status,
+                                api_utf8_decode($node_user->Email),
+                                $username,
+                                $password,
+                                api_utf8_decode($node_user->OfficialCode),
+                                null,
+                                api_utf8_decode($node_user->Phone),
+                                null,
+                                PLATFORM_AUTH_SOURCE,
+                                null,
+                                1,
+                                0,
+                                null,
+                                null,
+                                $send_mail
+                            );
                         } else {
                             $lastname = trim(api_utf8_decode($node_user->Lastname));
                             $firstname = trim(api_utf8_decode($node_user->Firstname));
@@ -144,10 +143,8 @@ if (isset($_POST['formSent']) && $_POST['formSent']) {
                 }
 
                 // Creating  courses from <Sessions> <Courses> base node.
-
                 if (count($root->Courses->Course) > 0) {
                     foreach ($root->Courses->Course as $courseNode) {
-
                         $params = array();
                         if (empty($courseNode->CourseTitle)) {
                             $params['title']            = api_utf8_decode($courseNode->CourseCode);
@@ -161,12 +158,12 @@ if (isset($_POST['formSent']) && $_POST['formSent']) {
                         $params['user_id']          = api_get_user_id();
 
                         // Looking up for the teacher.
-                        $username       = trim(api_utf8_decode($courseNode->CourseTeacher));
+                        $username = trim(api_utf8_decode($courseNode->CourseTeacher));
                         $sql = "SELECT user_id, lastname, firstname FROM $tbl_user WHERE username='$username'";
                         $rs = Database::query($sql);
                         list($user_id, $lastname, $firstname) = Database::fetch_array($rs);
 
-                        $params['teachers']  = $user_id;
+                        $params['teachers'] = $user_id;
                         CourseManager::create_course($params);
                     }
                 }
@@ -178,7 +175,10 @@ if (isset($_POST['formSent']) && $_POST['formSent']) {
                         $user_counter = 0;
 
                         $session_name = trim(api_utf8_decode($node_session->SessionName));
-                        $coach = UserManager::purify_username(api_utf8_decode($node_session->Coach), $purification_option_for_usernames);
+                        $coach = UserManager::purify_username(
+                            api_utf8_decode($node_session->Coach),
+                            $purification_option_for_usernames
+                        );
 
                         if (!empty($coach)) {
                             $coach_id = UserManager::get_user_id_from_username($coach);
@@ -192,11 +192,12 @@ if (isset($_POST['formSent']) && $_POST['formSent']) {
                             $coach_id = api_get_user_id();
                         }
 
-                        $date_start = trim(api_utf8_decode($node_session->DateStart)); // Just in case - encoding conversion.
+                        // Just in case - encoding conversion.
+                        $date_start = trim(api_utf8_decode($node_session->DateStart));
 
                         if (!empty($date_start)) {
                             list($year_start, $month_start, $day_start) = explode('/', $date_start);
-                            if(empty($year_start) || empty($month_start) || empty($day_start)) {
+                            if (empty($year_start) || empty($month_start) || empty($day_start)) {
                                 $error_message .= get_lang('WrongDate').' : '.$date_start.'<br />';
                                 break;
                             } else {
@@ -230,7 +231,8 @@ if (isset($_POST['formSent']) && $_POST['formSent']) {
                                 if ($i > 1) {
                                     $suffix = ' - '.$i;
                                 }
-                                $sql = 'SELECT 1 FROM '.$tbl_session.' WHERE name="'.Database::escape_string($session_name.$suffix).'"';
+                                $sql = 'SELECT 1 FROM '.$tbl_session.'
+                                        WHERE name="'.Database::escape_string($session_name.$suffix).'"';
                                 $rs = Database::query($sql);
                                 if (Database::result($rs, 0, 0)) {
                                     $i++;
@@ -460,6 +462,8 @@ if (isset($_POST['formSent']) && $_POST['formSent']) {
         } else {
             // CSV
             $updateCourseCoaches = isset($_POST['update_course_coaches']) ? true : false;
+            $addOriginalCourseTeachersAsCourseSessionCoaches = isset($_POST['add_me_as_coach']) ? true : false;
+
             $result = SessionManager::importCSV(
                 $_FILES['import_file']['tmp_name'],
                 $isOverwrite,
@@ -472,11 +476,13 @@ if (isset($_POST['formSent']) && $_POST['formSent']) {
                 1,
                 array(),
                 $deleteUsersNotInList,
-                $updateCourseCoaches
+                $updateCourseCoaches,
+                false,
+                $addOriginalCourseTeachersAsCourseSessionCoaches,
+                false
             );
             $sessionList = $result['session_list'];
             $error_message = $result['error_message'];
-
             $session_counter = $result['session_counter'];
         }
 
@@ -535,6 +541,7 @@ $form->addElement('radio', 'file_type', array(null, '<a href="example_session.xm
 $form->addElement('checkbox', 'overwrite', null, get_lang('IfSessionExistsUpdate'));
 $form->addElement('checkbox', 'delete_users_not_in_list', null, get_lang('DeleteUsersNotInList'));
 $form->addElement('checkbox', 'update_course_coaches', null, get_lang('CleanAndUpdateCourseCoaches'));
+$form->addElement('checkbox', 'add_me_as_coach', null, get_lang('AddMeAsCoach'));
 $form->addElement('checkbox', 'sendMail', null, get_lang('SendMailToUsers'));
 $form->addElement('button', 'submit', get_lang('ImportSession'));
 
@@ -545,19 +552,16 @@ Display::display_normal_message(get_lang('TheXMLImportLetYouAddMoreInfoAndCreate
 $form->display();
 
 ?>
-<font color="gray">
 <p><?php echo get_lang('CSVMustLookLike').' ('.get_lang('MandatoryFields').')'; ?> :</p>
-
 <blockquote>
 <pre>
-<strong>SessionName</strong>;Coach;<strong>DateStart</strong>;<strong>DateEnd</strong>;Users;Courses
-<strong>xxx1</strong>;xxx;<strong>xxx;xxx</strong>;username1|username2;course1[coach1][username1,username2,...]|course2[coach1][username1,username2,...]
-<strong>xxx2</strong>;xxx;<strong>xxx;xxx</strong>;username1|username2;course1[coach1][username1,username2,...]|course2[coach1][username1,username2,...]
+<strong>SessionName</strong>;Coach;<strong>DateStart</strong>;<strong>DateEnd</strong>;Users;Courses;VisibilityAfterExpiration
+<strong>Example 1</strong>;username;<strong>yyyy/mm/dd;yyyy/mm/dd</strong>;username1|username2;course1[coach1][username1,username2,...]|course2[coach1][username1,username2,...];read_only
+<strong>Example 2</strong>;username;<strong>yyyy/mm/dd;yyyy/mm/dd</strong>;username1|username2;course1[coach1][username1,username2,...]|course2[coach1][username1,username2,...];accessible
+<strong>Example 3</strong>;username;<strong>yyyy/mm/dd;yyyy/mm/dd</strong>;username1|username2;course1[coach1][username1,username2,...]|course2[coach1][username1,username2,...];not_accessible
 </pre>
 </blockquote>
-
 <p><?php echo get_lang('XMLMustLookLike').' ('.get_lang('MandatoryFields').')'; ?> :</p>
-
 <blockquote>
 <pre>
 &lt;?xml version=&quot;1.0&quot; encoding=&quot;<?php echo api_refine_encoding_id(api_get_system_encoding()); ?>&quot;?&gt;
@@ -586,8 +590,8 @@ $form->display();
     &lt;Session&gt;
         <strong>&lt;SessionName&gt;xxx&lt;/SessionName&gt;</strong>
         &lt;Coach&gt;xxx&lt;/Coach&gt;
-        <strong>&lt;DateStart&gt;xxx&lt;/DateStart&gt;</strong>
-        <strong>&lt;DateEnd&gt;xxx&lt;/DateEnd&gt;</strong>
+        <strong>&lt;DateStart&gt;yyyy/mm/dd&lt;/DateStart&gt;</strong>
+        <strong>&lt;DateEnd&gt;yyyy/mm/dd&lt;/DateEnd&gt;</strong>
         &lt;User&gt;xxx&lt;/User&gt;
         &lt;User&gt;xxx&lt;/User&gt;
         &lt;Course&gt;
@@ -615,8 +619,7 @@ $form->display();
 &lt;/Sessions&gt;
 </pre>
 </blockquote>
-</font>
+
 <?php
 
-/* FOOTER */
 Display::display_footer();

+ 8 - 7
main/admin/session_list.php

@@ -4,9 +4,6 @@
  * List sessions in an efficient and usable way
  * @package chamilo.admin
  */
-/**
- * Code
- */
 $language_file = array('admin', 'courses');
 $cidReset = true;
 
@@ -36,7 +33,8 @@ $interbreadcrumb[]=array("url" => "index.php","name" => get_lang('PlatformAdmin'
 $tool_name = get_lang('SessionList');
 Display::display_header($tool_name);
 
-$error_message = ''; // Avoid conflict with the global variable $error_msg (array type) in add_course.conf.php.
+$error_message = '';
+// Avoid conflict with the global variable $error_msg (array type) in add_course.conf.php.
 if (isset($_GET['action']) && $_GET['action'] == 'show_message') {
     $error_message = Security::remove_XSS($_GET['message']);
 }
@@ -111,7 +109,8 @@ $column_model   = array(
     array('name'=>'date_start',     'index'=>'s.date_start',    'width'=>'40',   'align'=>'left', 'search' => 'true'),
     array('name'=>'date_end',       'index'=>'s.date_end',      'width'=>'40',   'align'=>'left', 'search' => 'true'),
     array('name'=>'coach_name',     'index'=>'coach_name',    'width'=>'80',   'align'=>'left', 'search' => 'false'),
-    array('name'=>'status',         'index'=>'session_active','width'=>'50',   'align'=>'left', 'search' => 'true', 'stype'=>'select',
+    array('name'=>'status',         'index'=>'session_active','width'=>'45',
+        'align'=>'left', 'search' => 'true', 'stype'=>'select',
         //for the bottom bar
         'searchoptions' => array(
             'defaultValue'  => ':',
@@ -122,9 +121,11 @@ $column_model   = array(
             'value' => ':'.get_lang('All').';1:'.get_lang('Active').';0:'.get_lang('Inactive')
         )
     ),
-    array('name'=>'visibility',     'index'=>'visibility',      'width'=>'40',   'align'=>'left', 'search' => 'false'),
-    array('name'=>'actions',        'index'=>'actions',         'width'=>'100',  'align'=>'left','formatter'=>'action_formatter','sortable'=>'false', 'search' => 'false')
+    array('name'=>'visibility',     'index'=>'visibility', 'width'=>'45', 'align'=>'left', 'search' => 'false'),
+    array('name'=>'actions',        'index'=>'actions', 'width'=>'90',
+        'align'=>'left','formatter'=>'action_formatter','sortable'=>'false', 'search' => 'false')
 );
+
 //Autowidth
 $extra_params['autowidth'] = 'true';
 

+ 97 - 0
main/admin/session_user_edit.php

@@ -0,0 +1,97 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+$language_file = 'admin';
+$cidReset = true;
+
+// including the global Chamilo file
+require_once '../inc/global.inc.php';
+
+api_protect_admin_script(true);
+
+$sessionId = isset($_GET['session_id']) ? $_GET['session_id'] : null;
+$userId = isset($_GET['user_id']) ? $_GET['user_id'] : null;
+
+SessionManager::protect_session_edit($sessionId);
+
+$sessionInfo = api_get_session_info($sessionId);
+if (empty($sessionInfo)) {
+    api_not_allowed(true);
+}
+
+if (!isset($sessionInfo['duration']) ||
+    isset($sessionInfo['duration']) && empty($sessionInfo['duration'])) {
+    api_not_allowed(true);
+}
+
+if (!SessionManager::durationPerUserIsEnabled()) {
+    api_not_allowed(true);
+}
+if (empty($sessionId) || empty($userId)) {
+    api_not_allowed(true);
+}
+
+$interbreadcrumb[] = array('url' => 'index.php', 'name' => get_lang('PlatformAdmin'));
+$interbreadcrumb[] = array('url' => 'session_list.php','name' => get_lang('SessionList'));
+$interbreadcrumb[] = array('url' => "resume_session.php?id_session=".$sessionId, "name" => get_lang('SessionOverview'));
+
+$form = new FormValidator('edit', 'post', api_get_self().'?session_id='.$sessionId.'&user_id='.$userId);
+$form->add_header(get_lang('EditUserSessionDuration'));
+$data = SessionManager::getUserSession($userId, $sessionId);
+$userInfo = api_get_user_info($userId);
+
+// Show current end date for the session for this user, if any
+$userAccess = CourseManager::getFirstCourseAccessPerSessionAndUser(
+    $sessionId,
+    $userId
+);
+if (count($userAccess) == 0) {
+    // User never accessed the session. End date is still open
+    $msg = sprintf(get_lang('UserNeverAccessedSessionDefaultDurationIsX'), $sessionInfo['duration']);
+} else {
+    // The user already accessed the session. Show a clear detail of the days count.
+    $duration = $sessionInfo['duration'];
+    if (!empty($data['duration'])) {
+        $duration = $duration + $data['duration'];
+    }
+    $days = SessionManager::getDayLeftInSession($sessionId, $userId, $duration);
+    $firstAccess = api_strtotime($userAccess['login_course_date'], 'UTC');
+    $firstAccessString = api_convert_and_format_date($userAccess['login_course_date'], DATE_FORMAT_SHORT, 'UTC');
+    if ($days > 0) {
+        $msg = sprintf(get_lang('FirstAccessWasXSessionDurationYEndDateInZDays'), $firstAccessString, $duration, $days);
+    } else {
+        $endDateInSeconds = $firstAccess + $duration*24*60*60;
+        $last = api_convert_and_format_date($endDateInSeconds, DATE_FORMAT_SHORT);
+        $msg = sprintf(get_lang('FirstAccessWasXSessionDurationYEndDateWasZ'), $firstAccessString, $duration, $last);
+    }
+}
+$form->addElement('html', sprintf(get_lang('UserXSessionY'), $userInfo['complete_name'], $sessionInfo['name']));
+$form->addElement('html', '<br>');
+$form->addElement('html', $msg);
+
+$form->addElement('text', 'duration', array(get_lang('ExtraDurationForUser'), null, get_lang('Days')));
+$form->addElement('button', 'submit', get_lang('Send'));
+
+if (empty($data['duration'])) {
+    $data['duration'] = 0;
+}
+$form->setDefaults($data);
+$message = null;
+if ($form->validate()) {
+    $duration = $form->getSubmitValue('duration');
+    // Only update if the duration is different from the default duration
+    if ($duration != 0) {
+        SessionManager::editUserSessionDuration($duration, $userId, $sessionId);
+        $message = Display::return_message(get_lang('ItemUpdated'), 'confirmation');
+    } else {
+        $message = Display::return_message(get_lang('DurationIsSameAsDefault'), 'warning');
+    }
+}
+
+// display the header
+Display::display_header(get_lang('Edit'));
+
+echo $message;
+$form->display();
+
+Display :: display_footer();

+ 2 - 2
main/admin/session_user_import.php

@@ -28,7 +28,7 @@ $tool_name = get_lang('ImportUsers');
 $session_id = isset($_GET['id_session']) ? intval($_GET['id_session']) : null;
 
 if (empty($session_id)) {
-    api_not_allowed(true);
+    api_not_allowed(true);    
 }
 
 $interbreadcrumb[] = array('url' => 'index.php', 'name' => get_lang('PlatformAdmin'));
@@ -43,7 +43,7 @@ if (isset($_POST['formSent']) && $_POST['formSent']) {
         $send_mail = $_POST['sendMail'] ? 1 : 0;
 
         // CSV
-        $users     = Import::csv_to_array($_FILES['import_file']['tmp_name']);
+        $users = Import::csv_to_array($_FILES['import_file']['tmp_name']);
         $user_list = array();
         foreach ($users as $user_data) {
             $username = $user_data['username'];

+ 15 - 8
main/admin/settings.lib.php

@@ -17,7 +17,6 @@
  */
 function handle_regions()
 {
-
     if (isset($_POST['submit_plugins'])) {
         store_regions();
         // Add event to the system log.
@@ -117,7 +116,13 @@ function handle_plugins()
         // Add event to the system log.
         $user_id = api_get_user_id();
         $category = $_GET['category'];
-        event_system(LOG_CONFIGURATION_SETTINGS_CHANGE, LOG_CONFIGURATION_SETTINGS_CATEGORY, $category, api_get_utc_datetime(), $user_id);
+         event_system(
+             LOG_CONFIGURATION_SETTINGS_CHANGE,
+             LOG_CONFIGURATION_SETTINGS_CATEGORY,
+             $category,
+             api_get_utc_datetime(),
+             $user_id
+         );
         Display :: display_confirmation_message(get_lang('SettingsStored'));
     }
 
@@ -148,6 +153,7 @@ function handle_plugins()
         if (file_exists($plugin_info_file)) {
             $plugin_info = array();
             require $plugin_info_file;
+
             if (in_array($plugin, $installed_plugins)) {
                 echo '<tr class="row_selected">';
             } else {
@@ -238,6 +244,8 @@ function handle_stylesheets()
         }
     }
 
+    // Stylesheet upload.
+
     if (isset($_POST['stylesheet_upload'])) {
         if ($form->validate()) {
             $values = $form->exportValues();
@@ -717,6 +725,7 @@ function handle_search()
  * Wrapper for the templates
  *
  * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University, Belgium
+ * @author Julio Montoya.
  * @version August 2008
  * @since Dokeos 1.8.6
  */
@@ -747,7 +756,6 @@ function handle_templates() {
             $category = $_GET['category'];
             event_system(LOG_CONFIGURATION_SETTINGS_CHANGE, LOG_CONFIGURATION_SETTINGS_CATEGORY, $category, api_get_utc_datetime(), $user_id);
         }
-
         display_templates();
     }
 }
@@ -969,7 +977,7 @@ function add_edit_template() {
            if ($_GET['action'] == 'add') {
                $content_template = '<head>{CSS}<style type="text/css">.text{font-weight: normal;}</style></head><body>'.Database::escape_string($values['template_text']).'</body>';
                $sql = "INSERT INTO $table_system_template (title, content, image) VALUES ('".Database::escape_string($values['title'])."','".$content_template."','".Database::escape_string($new_file_name)."')";
-               $result = Database::query($sql);
+               Database::query($sql);
 
                // Display a feedback message.
                Display::display_confirmation_message(get_lang('TemplateAdded'));
@@ -981,7 +989,7 @@ function add_edit_template() {
                    $sql .= ", image = '".Database::escape_string($new_file_name)."'";
                }
                $sql .= " WHERE id='".Database::escape_string($_GET['id'])."'";
-               $result = Database::query($sql);
+               Database::query($sql);
 
                // Display a feedback message.
                Display::display_confirmation_message(get_lang('TemplateEdited'));
@@ -1030,7 +1038,7 @@ function delete_template($id) {
 
 /**
  * Returns the list of timezone identifiers used to populate the select
- *
+ * This function is called through a call_user_func() in the generate_settings_form function.
  * @return array List of timezone identifiers
  *
  * @author Guillaume Viguier <guillaume.viguier@beeznest.com>
@@ -1042,7 +1050,7 @@ function select_timezone_value() {
 
 /**
  * Returns an array containing the list of options used to populate the gradebook_number_decimals variable
- *
+ * This function is called through a call_user_func() in the generate_settings_form function.
  * @return array List of gradebook_number_decimals options
  *
  * @author Guillaume Viguier <guillaume.viguier@beeznest.com>
@@ -1106,7 +1114,6 @@ function generate_settings_form($settings, $settings_by_access_list) {
     }
 
     $default_values = array();
-
     $url_info = api_get_access_url($url_id);
 
     $i = 0;

+ 3 - 3
main/admin/settings.php

@@ -159,12 +159,12 @@ if (!empty($_GET['category']) && !in_array($_GET['category'], array('Plugins', '
                             $changeable = 1;
                         }
 
-                        $params = array('variable = ?' =>  array($key));
+                        $params = array('variable = ?' => array($key));
                         $data = api_get_settings_params($params);
 
                         if (!empty($data)) {
                             foreach ($data as $item) {
-                                $params = array('id' =>$item['id'], 'access_url_changeable' => $changeable);
+                                $params = array('id' => $item['id'], 'access_url_changeable' => $changeable);
                                 api_set_setting_simple($params);
                             }
                         }
@@ -443,7 +443,7 @@ if (!empty($_GET['category'])) {
         case 'Plugins':
             // Displaying the extensions: Plugins.
             // This will be available to all the sites (access_urls).
-            $securityToken = Security::remove_XSS($_GET['sec_token']);
+            $securityToken = isset($_GET['sec_token']) ? Security::remove_XSS($_GET['sec_token']) : null;
             if (isset($_POST['submit_dashboard_plugins']) && Security::check_token($securityToken)) {
                 Security::clear_token();
                 $affected_rows = DashboardManager::store_dashboard_plugins($_POST);

+ 1 - 2
main/admin/statistics/index.php

@@ -81,7 +81,6 @@ switch ($_REQUEST['report']) {
     case 'courselastvisit':
         Statistics::print_course_last_visit();
         break;
-    //---
     case 'users':
         // total amount of users
         Statistics::print_stats(
@@ -135,4 +134,4 @@ switch ($_REQUEST['report']) {
         break;
 }
 
-Display::display_footer();
+Display::display_footer();

+ 1 - 1
main/admin/sub_language.class.php

@@ -4,7 +4,7 @@
 
 /**
  * SubLanguageManager class definition file
- * @package chamilo.admin.sublanguage 
+ * @package chamilo.admin.sublanguage
  * @todo clean this lib and move to main/inc/lib
  */
 class SubLanguageManager {

+ 78 - 39
main/admin/subscribe_user2course.php

@@ -48,15 +48,10 @@ Display :: display_header($tool_name);
 $link_add_group = '<a href="usergroups.php">'.Display::return_icon('multiple.gif',get_lang('RegistrationByUsersGroups')).get_lang('RegistrationByUsersGroups').'</a>';
 echo '<div class="actions">'.$link_add_group.'</div>';
 
-// displaying the tool title
-// api_display_tool_title($tool_name);
-
 $form = new FormValidator('subscribe_user2course');
 $form->addElement('header', '', $tool_name);
 $form->display();
 
-/* MAIN CODE */
-
 //checking for extra field with filter on
 $extra_field_list= UserManager::get_extra_fields();
 $new_field_list = array();
@@ -70,7 +65,7 @@ if (is_array($extra_field_list)) {
 }
 
 /* React on POSTed request */
-if ($_POST['form_sent']) {
+if (isset($_POST['form_sent']) && $_POST['form_sent']) {
     $form_sent = $_POST['form_sent'];
     $users = is_array($_POST['UserList']) ? $_POST['UserList'] : array() ;
     $courses = is_array($_POST['CourseList']) ? $_POST['CourseList'] : array() ;
@@ -82,7 +77,7 @@ if ($_POST['form_sent']) {
     }
 
     if ($form_sent == 1) {
-        if ( count($users) == 0 || count($courses) == 0) {
+        if (count($users) == 0 || count($courses) == 0) {
             Display :: display_error_message(get_lang('AtLeastOneUserAndOneCourse'));
         } else {
             $errorDrh = 0;
@@ -90,12 +85,13 @@ if ($_POST['form_sent']) {
                 foreach ($users as $user_id) {
                     $user = api_get_user_info($user_id);
                     if ($user['status'] <> DRH) {
-                        CourseManager::subscribe_user($user_id,$course_code);
+                        CourseManager::subscribe_user($user_id, $course_code);
                     } else {
                         $errorDrh = 1;
                     }
                 }
             }
+
             if ($errorDrh == 0) {
                 Display :: display_confirmation_message(get_lang('UsersAreSubscibedToCourse'));
             } else {
@@ -106,18 +102,21 @@ if ($_POST['form_sent']) {
 }
 
 /* Display GUI */
-if(empty($first_letter_user)) {
+if (empty($first_letter_user)) {
     $sql = "SELECT count(*) as nb_users FROM $tbl_user";
     $result = Database::query($sql);
     $num_row = Database::fetch_array($result);
-    if($num_row['nb_users']>1000)
-    {//if there are too much users to gracefully handle with the HTML select list,
-     // assign a default filter on users names
+    if  ($num_row['nb_users']>1000) {
+        //if there are too much users to gracefully handle with the HTML select list,
+        // assign a default filter on users names
         $first_letter_user = 'A';
     }
     unset($result);
 }
 
+
+$where_filter = null;
+
 //Filter by Extra Fields
 $use_extra_fields = false;
 if (is_array($extra_field_list)) {
@@ -128,7 +127,10 @@ if (is_array($extra_field_list)) {
             if (UserManager::is_extra_field_available($new_field['variable'])) {
                 if (isset($_POST[$varname]) && $_POST[$varname]!='0') {
                     $use_extra_fields = true;
-                    $extra_field_result[]= UserManager::get_extra_user_data_by_value($new_field['variable'], $_POST[$varname]);
+                    $extra_field_result[]= UserManager::get_extra_user_data_by_value(
+                        $new_field['variable'],
+                        $_POST[$varname]
+                    );
                 }
             }
         }
@@ -147,8 +149,7 @@ if ($use_extra_fields) {
         $final_result = $extra_field_result[0];
     }
 
-    $where_filter ='';
-    if ($_configuration['multiple_access_urls']) {
+    if (api_is_multiple_url_enabled()) {
         if (is_array($final_result) && count($final_result)>0) {
             $where_filter = " AND u.user_id IN  ('".implode("','",$final_result)."') ";
         } else {
@@ -166,21 +167,35 @@ if ($use_extra_fields) {
 }
 
 $target_name = api_sort_by_first_name() ? 'firstname' : 'lastname';
-$sql = "SELECT user_id,lastname,firstname,username
+$orderBy = $target_name;
+$showOfficialCode = false;
+global $_configuration;
+if (isset($_configuration['order_user_list_by_official_code']) &&
+     $_configuration['order_user_list_by_official_code']
+) {
+    $showOfficialCode = true;
+    $orderBy = " official_code, firstname, lastname";
+}
+
+$sql = "SELECT user_id, lastname, firstname, username, official_code
         FROM $tbl_user
         WHERE user_id<>2 AND ".$target_name." LIKE '".$first_letter_user."%' $where_filter
-        ORDER BY ". (count($users) > 0 ? "(user_id IN(".implode(',', $users).")) DESC," : "")." ".$target_name;
+        ORDER BY ". (count($users) > 0 ? "(user_id IN(".implode(',', $users).")) DESC," : "")." ".$orderBy;
 
-global $_configuration;
-if ($_configuration['multiple_access_urls']) {
+if (api_is_multiple_url_enabled()) {
     $tbl_user_rel_access_url= Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
     $access_url_id = api_get_current_access_url_id();
     if ($access_url_id != -1){
-        $sql = "SELECT u.user_id,lastname,firstname,username  FROM ".$tbl_user ." u
-        INNER JOIN $tbl_user_rel_access_url user_rel_url
-        ON (user_rel_url.user_id = u.user_id)
-        WHERE u.user_id<>2 AND access_url_id =  $access_url_id AND (".$target_name." LIKE '".$first_letter_user."%' ) $where_filter
-        ORDER BY ". (count($users) > 0 ? "(u.user_id IN(".implode(',', $users).")) DESC," : "")." ".$target_name;
+        $sql = "SELECT u.user_id,lastname,firstname,username, official_code
+                FROM ".$tbl_user ." u
+                INNER JOIN $tbl_user_rel_access_url user_rel_url
+                ON (user_rel_url.user_id = u.user_id)
+                WHERE
+                    u.user_id<>2 AND
+                    access_url_id =  $access_url_id AND
+                    (".$target_name." LIKE '".$first_letter_user."%' )
+                    $where_filter
+                ORDER BY ". (count($users) > 0 ? "(u.user_id IN(".implode(',', $users).")) DESC," : "")." ".$orderBy;
     }
 }
 
@@ -188,17 +203,23 @@ $result = Database::query($sql);
 $db_users = Database::store_result($result);
 unset($result);
 
-$sql = "SELECT code,visual_code,title FROM $tbl_course WHERE visual_code LIKE '".$first_letter_course."%' ORDER BY ". (count($courses) > 0 ? "(code IN('".implode("','", $courses)."')) DESC," : "")." visual_code";
+$sql = "SELECT code,visual_code,title
+        FROM $tbl_course
+        WHERE visual_code LIKE '".$first_letter_course."%'
+        ORDER BY ". (count($courses) > 0 ? "(code IN('".implode("','", $courses)."')) DESC," : "")." visual_code";
 
-if ($_configuration['multiple_access_urls']) {
+if (api_is_multiple_url_enabled()) {
     $tbl_course_rel_access_url= Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
     $access_url_id = api_get_current_access_url_id();
     if ($access_url_id != -1){
         $sql = "SELECT code, visual_code, title
                 FROM $tbl_course as course
-                  INNER JOIN $tbl_course_rel_access_url course_rel_url
+                INNER JOIN $tbl_course_rel_access_url course_rel_url
                 ON (course_rel_url.course_code= course.code)
-                  WHERE access_url_id =  $access_url_id  AND (visual_code LIKE '".$first_letter_course."%' ) ORDER BY ". (count($courses) > 0 ? "(code IN('".implode("','", $courses)."')) DESC," : "")." visual_code";
+                WHERE
+                    access_url_id =  $access_url_id  AND
+                    (visual_code LIKE '".$first_letter_course."%' )
+                ORDER BY ". (count($courses) > 0 ? "(code IN('".implode("','", $courses)."')) DESC," : "")." visual_code";
     }
 }
 
@@ -206,22 +227,25 @@ $result = Database::query($sql);
 $db_courses = Database::store_result($result);
 unset($result);
 
-if ($_configuration['multiple_access_urls']) {
+if (api_is_multiple_url_enabled()) {
     $tbl_course_rel_access_url= Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
+    $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
     $access_url_id = api_get_current_access_url_id();
     if ($access_url_id != -1){
         $sqlNbCours = "	SELECT course_rel_user.course_code, course.title
             FROM $tbl_course_user as course_rel_user
             INNER JOIN $tbl_course as course
             ON course.code = course_rel_user.course_code
-              INNER JOIN $tbl_course_rel_access_url course_rel_url
+            INNER JOIN $tbl_course_rel_access_url course_rel_url
             ON (course_rel_url.course_code= course.code)
-              WHERE access_url_id =  $access_url_id  AND course_rel_user.user_id='".$_user['user_id']."' AND course_rel_user.status='1'
-              ORDER BY course.title";
+            WHERE
+                access_url_id =  $access_url_id  AND
+                course_rel_user.user_id='".$_user['user_id']."' AND
+                course_rel_user.status='1'
+            ORDER BY course.title";
     }
 }
 ?>
-
 <form name="formulaire" method="post" action="<?php echo api_get_self(); ?>" style="margin:0px;">
 <?php
 if (is_array($extra_field_list)) {
@@ -280,23 +304,38 @@ if (is_array($extra_field_list)) {
     <td width="40%" align="center">
      <select name="UserList[]" multiple="multiple" size="20" style="width:300px;">
 <?php
-        foreach ($db_users as $user) {
+    foreach ($db_users as $user) {
 ?>
-      <option value="<?php echo $user['user_id']; ?>" <?php if(in_array($user['user_id'],$users)) echo 'selected="selected"'; ?>><?php echo api_get_person_name($user['firstname'], $user['lastname']).' ('.$user['username'].')'; ?></option>
+      <option value="<?php echo $user['user_id']; ?>" <?php if(in_array($user['user_id'],$users)) echo 'selected="selected"'; ?>>
+      <?php
+        $userName = api_get_person_name($user['firstname'], $user['lastname']).' ('.$user['username'].')';
+        if ($showOfficialCode) {
+
+            $officialCode = !empty($user['official_code']) ? $user['official_code'].' - ' : '? - ';
+            $userName = $officialCode.$userName;
+        }
+
+        echo $userName;
+      ?>
+      </option>
 <?php
 }
 ?>
     </select>
    </td>
    <td width="20%" valign="middle" align="center">
-    <button type="submit" class="add" value="<?php echo get_lang('AddToThatCourse'); ?> &gt;&gt;"><?php echo get_lang('AddToThatCourse'); ?></button>
+    <button type="submit" class="add" value="<?php echo get_lang('AddToThatCourse'); ?> &gt;&gt;">
+        <?php echo get_lang('AddToThatCourse'); ?>
+    </button>
    </td>
    <td width="40%" align="center">
     <select name="CourseList[]" multiple="multiple" size="20" style="width:300px;">
 <?php
-        foreach ($db_courses as $course) {
+    foreach ($db_courses as $course) {
 ?>
-     <option value="<?php echo $course['code']; ?>" <?php if(in_array($course['code'],$courses)) echo 'selected="selected"'; ?>><?php echo '('.$course['visual_code'].') '.$course['title']; ?></option>
+     <option value="<?php echo $course['code']; ?>" <?php if(in_array($course['code'],$courses)) echo 'selected="selected"'; ?>>
+         <?php echo '('.$course['visual_code'].') '.$course['title']; ?>
+     </option>
 <?php
 }
 ?>
@@ -306,5 +345,5 @@ if (is_array($extra_field_list)) {
  </table>
 </form>
 <?php
-/* FOOTER */
+
 Display :: display_footer();

+ 1 - 1
main/admin/system_announcements.php

@@ -65,7 +65,7 @@ $show_announcement_list = true;
 $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : null;
 
 // Form was posted?
-if (isset ($_POST['action'])) {
+if (isset($_POST['action'])) {
     $action_todo = true;
 }
 

+ 4 - 4
main/admin/user_add.php

@@ -163,9 +163,9 @@ if (api_get_setting('login_is_email') != 'true') {
 $group = array();
 $auth_sources = 0; //make available wider as we need it in case of form reset (see below)
 $nb_ext_auth_source_added = 0;
-if (count($extAuthSource) > 0) {
+if (isset($extAuthSource) && count($extAuthSource) > 0) {
 	$auth_sources = array();
-	foreach($extAuthSource as $key => $info) {
+	foreach ($extAuthSource as $key => $info) {
 	    // @todo : make uniform external authentification configuration (ex : cas and external_login ldap)
 	    // Special case for CAS. CAS is activated from Chamilo > Administration > Configuration > CAS
 	    // extAuthSource always on for CAS even if not activated
@@ -291,9 +291,9 @@ if( $form->validate()) {
 		$picture        = $_FILES['picture'];
 		$platform_admin = intval($user['admin']['platform_admin']);
 		$send_mail      = intval($user['mail']['send_mail']);
-		$hr_dept_id     = intval($user['hr_dept_id']);
+		$hr_dept_id     = isset($user['hr_dept_id']) ? intval($user['hr_dept_id']) : 0;
 
-		if (count($extAuthSource) > 0 && $user['password']['password_auto'] == '2') {
+		if (isset($extAuthSource) && count($extAuthSource) > 0 && $user['password']['password_auto'] == '2') {
 			$auth_source = $user['password']['auth_source'];
 			$password = 'PLACEHOLDER';
 		} else {

+ 23 - 24
main/admin/user_edit.php

@@ -23,7 +23,6 @@ $htmlHeadXtra[] = '<script src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/tag
 $htmlHeadXtra[] = '<link  href="'.api_get_path(WEB_LIBRARY_PATH).'javascript/tag/style.css" rel="stylesheet" type="text/css" />';
 $htmlHeadXtra[] = '
 <script>
-
 var is_platform_id = "'.$is_platform_admin.'";
 
 <!--
@@ -89,8 +88,8 @@ $table_admin = Database::get_main_table(TABLE_MAIN_ADMIN);
 $sql = "SELECT u.*, a.user_id AS is_admin FROM $table_user u LEFT JOIN $table_admin a ON a.user_id = u.user_id WHERE u.user_id = '".$user_id."'";
 $res = Database::query($sql);
 if (Database::num_rows($res) != 1) {
-	header('Location: user_list.php');
-	exit;
+    header('Location: user_list.php');
+    exit;
 }
 
 $user_data = Database::fetch_array($res, 'ASSOC');
@@ -180,25 +179,25 @@ if (api_get_setting('login_is_email') != 'true') {
 // Password
 $form->addElement('radio', 'reset_password', get_lang('Password'), get_lang('DontResetPassword'), 0);
 $nb_ext_auth_source_added = 0;
-if (isset($extAuthSource) && count($extAuthSource) > 0) {
-	$auth_sources = array();
-	foreach ($extAuthSource as $key => $info) {
-	    // @todo : make uniform external authentification configuration (ex : cas and external_login ldap)
-	    // Special case for CAS. CAS is activated from Chamilo > Administration > Configuration > CAS
-	    // extAuthSource always on for CAS even if not activated
-	    // same action for file user_add.php
-	    if (($key == CAS_AUTH_SOURCE && api_get_setting('cas_activate') === 'true') || ($key != CAS_AUTH_SOURCE)) {
-    		$auth_sources[$key] = $key;
-    		$nb_ext_auth_source_added++;
-	    }
-	}
-	if ($nb_ext_auth_source_added > 0) {
-	    // @todo check the radio button for external authentification and select the external authentification in the menu
-	    $group[] =$form->createElement('radio', 'reset_password', null, get_lang('ExternalAuthentication').' ', 3);
-	    $group[] =$form->createElement('select', 'auth_source', null, $auth_sources);
-	    $group[] =$form->createElement('static', '', '', '<br />');
-	    $form->addGroup($group, 'password', null, '', false);
-	}
+if (isset($extAuthSource) && !empty($extAuthSource) && count($extAuthSource) > 0) {
+    $auth_sources = array();
+    foreach ($extAuthSource as $key => $info) {
+        // @todo : make uniform external authentification configuration (ex : cas and external_login ldap)
+        // Special case for CAS. CAS is activated from Chamilo > Administration > Configuration > CAS
+        // extAuthSource always on for CAS even if not activated
+        // same action for file user_add.php
+        if (($key == CAS_AUTH_SOURCE && api_get_setting('cas_activate') === 'true') || ($key != CAS_AUTH_SOURCE)) {
+            $auth_sources[$key] = $key;
+            $nb_ext_auth_source_added++;
+        }
+    }
+    if ($nb_ext_auth_source_added > 0) {
+        // @todo check the radio button for external authentification and select the external authentification in the menu
+        $group[] = $form->createElement('radio', 'reset_password', null, get_lang('ExternalAuthentication').' ', 3);
+        $group[] = $form->createElement('select', 'auth_source', null, $auth_sources);
+        $group[] = $form->createElement('static', '', '', '<br />');
+        $form->addGroup($group, 'password', null, '', false);
+    }
 }
 $form->addElement('radio', 'reset_password', null, get_lang('AutoGeneratePassword'), 1);
 $group = array();
@@ -252,8 +251,8 @@ $form->addElement('select_language', 'language', get_lang('Language'));
 
 // Send email
 $group = array();
-$group[] =$form->createElement('radio', 'send_mail', null, get_lang('Yes'), 1);
-$group[] =$form->createElement('radio', 'send_mail', null, get_lang('No'), 0);
+$group[] = $form->createElement('radio', 'send_mail', null, get_lang('Yes'), 1);
+$group[] = $form->createElement('radio', 'send_mail', null, get_lang('No'), 0);
 $form->addGroup($group, 'mail', get_lang('SendMailToNewUser'), '&nbsp;', false);
 
 // Registration User and Date

+ 1 - 1
main/admin/user_export.php

@@ -94,7 +94,7 @@ if ($form->validate()) {
 			$sql .= " FROM $user_table u ORDER BY lastname,firstname";
 		}
 		$filename = 'export_users_'.date('Y-m-d_H-i-s');
-	}	
+	}
 	$data = array();
 	$extra_fields = UserManager::get_extra_fields(0, 0, 5, 'ASC',false);
 	if ($export['addcsvheader']=='1' AND $export['file_type']=='csv') {

+ 103 - 42
main/admin/user_import.php

@@ -9,7 +9,7 @@
  * Validate the imported data.
  */
 
-$language_file = array ('admin', 'registration');
+$language_file = array('admin', 'registration');
 
 $cidReset = true;
 require '../inc/global.inc.php';
@@ -22,7 +22,12 @@ require_once api_get_path(LIBRARY_PATH).'import.lib.php';
 // Set this option to true to enforce strict purification for usenames.
 $purification_option_for_usernames = false;
 
-function validate_data($users)
+/**
+ * @param array $users
+ * @param bool  $checkUniqueEmail
+ * @return array
+ */
+function validate_data($users, $checkUniqueEmail = false)
 {
     global $defined_auth_sources;
     $errors = array();
@@ -31,9 +36,10 @@ function validate_data($users)
     // 1. Check if mandatory fields are set.
     $mandatory_fields = array('LastName', 'FirstName');
 
-    if (api_get_setting('registration', 'email') == 'true') {
+    if (api_get_setting('registration', 'email') == 'true' || $checkUniqueEmail) {
         $mandatory_fields[] = 'Email';
     }
+
     $classExistList = array();
     $usergroup = new UserGroup();
 
@@ -44,26 +50,43 @@ function validate_data($users)
                 $errors[] = $user;
             }
         }
-
+        $username = $user['UserName'];
         // 2. Check username, first, check whether it is empty.
-        if (!UserManager::is_username_empty($user['UserName'])) {
+        if (!UserManager::is_username_empty($username)) {
             // 2.1. Check whether username is too long.
-            if (UserManager::is_username_too_long($user['UserName'])) {
+            if (UserManager::is_username_too_long($username)) {
                 $user['error'] = get_lang('UserNameTooLong');
                 $errors[] = $user;
             }
+            // 2.1.1
+            $hasDash = strpos($username, '-');
+            if ($hasDash !== false) {
+                $user['error'] = get_lang('UserNameHasDash');
+                $errors[] = $user;
+            }
             // 2.2. Check whether the username was used twice in import file.
             if (isset($usernames[$user['UserName']])) {
                 $user['error'] = get_lang('UserNameUsedTwice');
                 $errors[] = $user;
             }
             $usernames[$user['UserName']] = 1;
-            // 2.3. Check whether username is allready occupied.
+            // 2.3. Check whether username is already occupied.
             if (!UserManager::is_username_available($user['UserName'])) {
                 $user['error'] = get_lang('UserNameNotAvailable');
                 $errors[] = $user;
             }
         }
+
+        if ($checkUniqueEmail) {
+            if (isset($user['Email'])) {
+                $userFromEmail = api_get_user_info_from_email($user['Email']);
+                if (!empty($userFromEmail)) {
+                    $user['error'] = get_lang('EmailUsedTwice');
+                    $errors[] = $user;
+                }
+            }
+        }
+
         // 3. Check status.
         if (isset($user['Status']) && !api_status_exists($user['Status'])) {
             $user['error'] = get_lang('WrongStatus');
@@ -105,12 +128,20 @@ function validate_data($users)
 function complete_missing_data($user)
 {
     global $purification_option_for_usernames;
+
     // 1. Create a username if necessary.
     if (UserManager::is_username_empty($user['UserName'])) {
-        $user['UserName'] = UserManager::create_unique_username($user['FirstName'], $user['LastName']);
+        $user['UserName'] = UserManager::create_unique_username(
+            $user['FirstName'],
+            $user['LastName']
+        );
     } else {
-        $user['UserName'] = UserManager::purify_username($user['UserName'], $purification_option_for_usernames);
+        $user['UserName'] = UserManager::purify_username(
+            $user['UserName'],
+            $purification_option_for_usernames
+        );
     }
+
     // 2. Generate a password if necessary.
     if (empty($user['Password'])) {
         $user['Password'] = api_generate_password();
@@ -123,6 +154,11 @@ function complete_missing_data($user)
     if (empty($user['AuthSource'])) {
         $user['AuthSource'] = PLATFORM_AUTH_SOURCE;
     }
+
+    if (empty($user['ExpiryDate'])) {
+        $user['ExpiryDate'] = '0000-00-00 00:00:00';
+    }
+
     return $user;
 }
 
@@ -139,9 +175,9 @@ function save_data($users)
     if (!isset($inserted_in_course)) {
         $inserted_in_course = array();
     }
-    require_once api_get_path(LIBRARY_PATH).'mail.lib.inc.php';
     $usergroup = new UserGroup();
     $send_mail = $_POST['sendMail'] ? true : false;
+
     if (is_array($users)) {
         foreach ($users as $user) {
             $user = complete_missing_data($user);
@@ -158,7 +194,7 @@ function save_data($users)
                 $user['PhoneNumber'],
                 '',
                 $user['AuthSource'],
-                null,
+                $user['ExpiryDate'],
                 1,
                 0,
                 null,
@@ -301,13 +337,13 @@ function parse_xml_data($file)
     xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false);
     xml_parse($parser, api_utf8_encode_xml(file_get_contents($file)));
     xml_parser_free($parser);
+
     return $users;
 }
 
 $this_section = SECTION_PLATFORM_ADMIN;
 api_protect_admin_script(true, null, 'login');
 
-
 $defined_auth_sources[] = PLATFORM_AUTH_SOURCE;
 
 if (is_array($extAuthSource)) {
@@ -322,24 +358,30 @@ $extra_fields = UserManager::get_extra_fields(0, 0, 5, 'ASC', true);
 $user_id_error = array();
 $error_message = '';
 
-if (isset($_POST['formSent']) && $_POST['formSent'] AND $_FILES['import_file']['size'] !== 0) {
+if (isset($_POST['formSent']) && $_POST['formSent'] AND
+    $_FILES['import_file']['size'] !== 0
+) {
     $file_type = $_POST['file_type'];
     Security::clear_token();
     $tok = Security::get_token();
     $allowed_file_mimetype = array('csv', 'xml');
     $error_kind_file = false;
 
+    $checkUniqueEmail = isset($_POST['check_unique_email']) ? $_POST['check_unique_email'] :null;
+
     $uploadInfo = pathinfo($_FILES['import_file']['name']);
     $ext_import_file = $uploadInfo['extension'];
-
+    $users = array();
     if (in_array($ext_import_file, $allowed_file_mimetype)) {
-        if (strcmp($file_type, 'csv') === 0 && $ext_import_file == $allowed_file_mimetype[0]) {
+        if (strcmp($file_type, 'csv') === 0 &&
+            $ext_import_file == $allowed_file_mimetype[0]
+        ) {
             $users	= parse_csv_data($_FILES['import_file']['tmp_name']);
-            $errors = validate_data($users);
+            $errors = validate_data($users, $checkUniqueEmail);
             $error_kind_file = false;
         } elseif (strcmp($file_type, 'xml') === 0 && $ext_import_file == $allowed_file_mimetype[1]) {
             $users = parse_xml_data($_FILES['import_file']['tmp_name']);
-            $errors = validate_data($users);
+            $errors = validate_data($users, $checkUniqueEmail);
             $error_kind_file = false;
         } else {
             $error_kind_file = true;
@@ -349,17 +391,22 @@ if (isset($_POST['formSent']) && $_POST['formSent'] AND $_FILES['import_file']['
     }
 
     // List user id with error.
-    $users_to_insert = $user_id_error = array();
+    $users_to_insert = array();
+
+    $keyToCheck = 'Username';
+    if ($checkUniqueEmail || api_get_setting('registration', 'email') == 'true') {
+        $keyToCheck = 'Email';
+    }
 
     if (is_array($errors)) {
         foreach ($errors as $my_errors) {
-            $user_id_error[] = $my_errors['UserName'];
+            $user_id_error[] = $my_errors[$keyToCheck];
         }
     }
 
     if (is_array($users)) {
         foreach ($users as $my_user) {
-            if (!in_array($my_user['UserName'], $user_id_error)) {
+            if (!in_array($my_user[$keyToCheck], $user_id_error)) {
                 $users_to_insert[] = $my_user;
             }
         }
@@ -383,10 +430,14 @@ if (isset($_POST['formSent']) && $_POST['formSent'] AND $_FILES['import_file']['
     if (count($errors) != 0) {
         $warning_message = '<ul>';
         foreach ($errors as $index => $error_user) {
+            $email = isset($error_user['Email']) ? ' - '.$error_user['Email'] : null;
             $warning_message .= '<li><b>'.$error_user['error'].'</b>: ';
             $warning_message .=
-                '<strong>'.$error_user['UserName'].'</strong>&nbsp;('.
-                api_get_person_name($error_user['FirstName'], $error_user['LastName']).')';
+                '<strong>'.$error_user['UserName'].'</strong> - '.
+                api_get_person_name(
+                    $error_user['FirstName'],
+                    $error_user['LastName']).'
+                '.$email;
             $warning_message .= '</li>';
         }
         $warning_message .= '</ul>';
@@ -403,8 +454,8 @@ if (isset($_POST['formSent']) && $_POST['formSent'] AND $_FILES['import_file']['
         header('Location: '.api_get_path(WEB_CODE_PATH).'admin/user_list.php?action=show_message&warn='.urlencode($warning_message).'&message='.urlencode($see_message_import).'&sec_token='.$tok);
         exit;
     }
-
 }
+
 Display :: display_header($tool_name);
 
 if (!empty($error_message)) {
@@ -415,28 +466,38 @@ $form = new FormValidator('user_import','post','user_import.php');
 $form->addElement('header', '', $tool_name);
 $form->addElement('hidden', 'formSent');
 $form->addElement('file', 'import_file', get_lang('ImportFileLocation'));
-$group = array();
-$group[] = $form->createElement(
-    'radio',
-    'file_type',
-    '',
-    'CSV (<a href="example.csv" target="_blank">'.get_lang('ExampleCSVFile').'</a>)',
-    'csv'
-);
-$group[] = $form->createElement(
-    'radio',
-    'file_type',
-    null,
-    'XML (<a href="example.xml" target="_blank">'.get_lang('ExampleXMLFile').'</a>)',
-    'xml'
+$group = array(
+    $form->createElement(
+        'radio',
+        'file_type',
+        '',
+        'CSV (<a href="example.csv" target="_blank">'.get_lang('ExampleCSVFile').'</a>)',
+        'csv'
+    ),
+    $form->createElement(
+        'radio',
+        'file_type',
+        null,
+        'XML (<a href="example.xml" target="_blank">'.get_lang('ExampleXMLFile').'</a>)',
+        'xml'
+    )
 );
+
 $form->addGroup($group, '', get_lang('FileType'), '<br/>');
 
-$group = array();
-$group[] = $form->createElement('radio', 'sendMail', '', get_lang('Yes'), 1);
-$group[] = $form->createElement('radio', 'sendMail', null, get_lang('No'), 0);
+$group = array(
+    $form->createElement('radio', 'sendMail', '', get_lang('Yes'), 1),
+    $form->createElement('radio', 'sendMail', null, get_lang('No'), 0)
+);
 $form->addGroup($group, '', get_lang('SendMailToUsers'), '<br/>');
 
+$form->addElement(
+    'checkbox',
+    'check_unique_email',
+    '',
+    get_lang('CheckUniqueEmail')
+);
+
 $form->addElement('style_submit_button', 'submit', get_lang('Import'), 'class="save"');
 $defaults['formSent'] = 1;
 $defaults['sendMail'] = 0;
@@ -466,8 +527,8 @@ if ($count_fields > 0) {
     <p><?php echo get_lang('CSVMustLookLike').' ('.get_lang('MandatoryFields').')'; ?> :</p>
     <blockquote>
 <pre>
-<b>LastName</b>;<b>FirstName</b>;<b>Email</b>;UserName;Password;AuthSource;OfficialCode;PhoneNumber;Status;<span style="color:red;"><?php if (count($list) > 0) echo implode(';', $list).';'; ?></span>Courses;ClassId;
-<b>xxx</b>;<b>xxx</b>;<b>xxx</b>;xxx;xxx;<?php echo implode('/', $defined_auth_sources); ?>;xxx;xxx;user/teacher/drh;<span style="color:red;"><?php if (count($list_reponse) > 0) echo implode(';', $list_reponse).';'; ?></span>xxx1|xxx2|xxx3;1;<br />
+<b>LastName</b>;<b>FirstName</b>;<b>Email</b>;UserName;Password;AuthSource;OfficialCode;PhoneNumber;Status;ExpiryDate;<span style="color:red;"><?php if (count($list) > 0) echo implode(';', $list).';'; ?></span>Courses;ClassId;
+<b>xxx</b>;<b>xxx</b>;<b>xxx</b>;xxx;xxx;<?php echo implode('/', $defined_auth_sources); ?>;xxx;xxx;user/teacher/drh;0000-00-00 00:00:00;<span style="color:red;"><?php if (count($list_reponse) > 0) echo implode(';', $list_reponse).';'; ?></span>xxx1|xxx2|xxx3;1;<br />
 </pre>
 </blockquote>
 <p><?php echo get_lang('XMLMustLookLike').' ('.get_lang('MandatoryFields').')'; ?> :</p>

+ 292 - 113
main/admin/user_information.php

@@ -5,44 +5,28 @@
  * @author Bart Mollet
  * @package chamilo.admin
  */
-/**
- * INIT SECTION
- */
+
 // name of the language file that needs to be included
-$language_file = 'admin';
+$language_file = array('registration', 'index', 'tracking', 'exercice', 'admin', 'gradebook');
 $cidReset = true;
 require_once '../inc/global.inc.php';
-$this_section=SECTION_PLATFORM_ADMIN;
+$this_section = SECTION_PLATFORM_ADMIN;
+require_once api_get_path(LIBRARY_PATH).'export.lib.inc.php';
+require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
+require_once api_get_path(SYS_CODE_PATH).'work/work.lib.php';
 
 api_protect_admin_script();
 
-$interbreadcrumb[] = array ("url" => 'index.php', "name" => get_lang('PlatformAdmin'));
-$interbreadcrumb[] = array ("url" => 'user_list.php', "name" => get_lang('UserList'));
+$interbreadcrumb[] = array("url" => 'index.php', "name" => get_lang('PlatformAdmin'));
+$interbreadcrumb[] = array("url" => 'user_list.php', "name" => get_lang('UserList'));
 if (!isset($_GET['user_id'])) {
     api_not_allowed();
 }
-$user = api_get_user_info($_GET['user_id']);
+$user = api_get_user_info($_GET['user_id'], true);
 $tool_name = $user['complete_name'].(empty($user['official_code'])?'':' ('.$user['official_code'].')');
-
-/**
- * Display
- */
-Display::display_header($tool_name);
-
 $table_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
 $table_course = Database :: get_main_table(TABLE_MAIN_COURSE);
-if (isset($_GET['action'])) {
-    switch ($_GET['action']) {
-        case 'unsubscribe':
-            if (CourseManager::get_user_in_course_status($_GET['user_id'], $_GET['course_code']) == STUDENT) {
-                CourseManager::unsubscribe_user($_GET['user_id'], $_GET['course_code']);
-                Display::display_normal_message(get_lang('UserUnsubscribed'));
-            } else {
-                Display::display_error_message(get_lang('CannotUnsubscribeUserFromCourse'));
-            }
-            break;
-    }
-}
+
 // only allow platform admins to login_as, or session admins only for students (not teachers nor other admins)
 $login_as_icon = null;
 $editUser = null;
@@ -51,24 +35,24 @@ if (api_is_platform_admin()) {
         '<a href="'.api_get_path(WEB_CODE_PATH).'admin/user_list.php'
         .'?action=login_as&amp;user_id='.$user['user_id'].'&amp;'
         .'sec_token='.$_SESSION['sec_token'].'">'
-        .Display::return_icon('login_as.gif', get_lang('LoginAs')).'</a>';
+        .Display::return_icon('login_as.png', get_lang('LoginAs'),
+            array(), ICON_SIZE_MEDIUM).'</a>';
     $editUser = Display::url(
         Display::return_icon(
             'edit.png',
             get_lang('Edit'),
-            array()
+            array(),
+            ICON_SIZE_MEDIUM
         ),
         api_get_path(WEB_CODE_PATH).'admin/user_edit.php?user_id='.$user['user_id']
     );
-}
-echo '<div class="actions">
-        <a href="'.api_get_path(WEB_CODE_PATH).'mySpace/myStudents.php?student='.intval($_GET['user_id']).'" title="'.get_lang('Reporting').'">'.Display::return_icon('statistics.png', get_lang('Reporting'), '', ICON_SIZE_MEDIUM).'
-        </a>
-        '.$login_as_icon.'
-        '.$editUser.'
-    </div>';
 
-echo Display::page_header($tool_name);
+    $exportLink = Display::url(
+        Display::return_icon(
+            'export_csv.png', get_lang('ExportAsCSV'),'', ICON_SIZE_MEDIUM),
+        api_get_self().'?user_id='.$user['user_id'].'&action=export'
+    );
+}
 
 // Getting the user image
 $sysdir_array = UserManager::get_user_picture_path_by_id($user['user_id'], 'system', false, true);
@@ -87,56 +71,104 @@ $onclick = $window_name."=window.open('".$fullurl."','".$window_name
     ."location=no,directories=no,status=no,menubar=no,scrollbars=no,"
     ."resizable=no,width=".$width.",height=".$height.",left=200,top=20');"
     ." return false;";
-echo '<a href="javascript: void(0);" onclick="'.$onclick.'" >'
-    .'<img src="'.$fullurl.'" '.$resizing.' alt="'.$alt.'"/></a><br />';
-echo '<p>'.($user['status'] == 1 ? get_lang('Teacher') : get_lang('Student'))
-    .'</p>';
-echo '<p>'.Display :: encrypted_mailto_link($user['mail'], $user['mail']).'</p>';
+
 // Show info about who created this user and when
 $creatorId = $user['creator_id'];
 $creatorInfo = api_get_user_info($creatorId);
 $registrationDate = $user['registration_date'];
-echo '<p>'.sprintf(get_lang('CreatedByXYOnZ'), 'user_information.php?user_id='.$creatorId, $creatorInfo['username'], api_get_utc_datetime($registrationDate)).'</p>';
 
-/**
- * Show the sessions and the courses in which this user is subscribed
- */
+$csvContent = array();
 
-echo Display::page_subheader(get_lang('SessionList'));
+$table = new HTML_Table(array('class' => 'data_table'));
+$table->setHeaderContents(0, 0, get_lang('Information'));
+$csvContent[] = get_lang('Information');
+$data = array(
+    get_lang('Name') => $user['complete_name'],
+    get_lang('Email') => $user['email'],
+    get_lang('Phone') => $user['phone'],
+    get_lang('OfficialCode') => $user['official_code'],
+    get_lang('Online') => $user['user_is_online'] ?
+        Display::return_icon('online.png') : Display::return_icon('offline.png'),
+    get_lang('Status') => $user['status'] == 1 ? get_lang('Teacher') : get_lang('Student'),
+    null => sprintf(get_lang('CreatedByXYOnZ'), 'user_information.php?user_id='
+        .$creatorId, $creatorInfo['username'], api_get_utc_datetime($registrationDate))
+);
 
-$tbl_session_course         = Database :: get_main_table(TABLE_MAIN_SESSION_COURSE);
-$tbl_session_course_user    = Database :: get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
-$tbl_session                = Database :: get_main_table(TABLE_MAIN_SESSION);
-$tbl_course                 = Database :: get_main_table(TABLE_MAIN_COURSE);
-$tbl_user                   = Database :: get_main_table(TABLE_MAIN_USER);
+$row = 1;
+foreach ($data as $label => $item) {
+    if (!empty($label)) {
+        $label = $label.': ';
+    }
+    $table->setCellContents($row, 0, $label.$item);
+    $csvContent[] = array($label, strip_tags($item));
+    $row++;
+}
+$userInformation = $table->toHtml();
 
-$user_id = $user['user_id'];
+$table = new HTML_Table(array('class' => 'data_table'));
+$table->setHeaderContents(0, 0, get_lang('Tracking'));
+$csvContent[] = get_lang('Tracking');
+$data = array(
+    get_lang('FirstLogin') => Tracking :: get_first_connection_date($user['user_id']),
+    get_lang('LatestLogin') => Tracking :: get_last_connection_date($user['user_id'], true)
+);
+$row = 1;
+foreach ($data as $label => $item) {
+    if (!empty($label)) {
+        $label = $label.': ';
+    }
+    $table->setCellContents($row, 0, $label.$item);
+    $csvContent[] = array($label, strip_tags($item));
+    $row++;
+}
+$trackingInformation = $table->toHtml();
 
+$tbl_session_course = Database:: get_main_table(TABLE_MAIN_SESSION_COURSE);
+$tbl_session_course_user = Database:: get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
+$tbl_session = Database:: get_main_table(TABLE_MAIN_SESSION);
+$tbl_course = Database:: get_main_table(TABLE_MAIN_COURSE);
+$tbl_user = Database:: get_main_table(TABLE_MAIN_USER);
+$user_id = $user['user_id'];
 $sessions = SessionManager::get_sessions_by_user($user_id, true);
-
 $personal_course_list = array();
+$courseToolInformationTotal = null;
 if (count($sessions) > 0) {
-    $header[] = array (get_lang('Code'), true);
-    $header[] = array (get_lang('Title'), true);
-    $header[] = array (get_lang('Status'), true);
-    $header[] = array ('', false);
+    $sessionInformation = null;
+    $header = array(
+        array(get_lang('Code'), true),
+        array(get_lang('Title'), true),
+        array(get_lang('Status'), true),
+        array(get_lang('TimeSpentInTheCourse'), true),
+        array(get_lang('TotalPostsInAllForums'), true),
+        array('', false)
+    );
+
+    $headerList = array();
+    foreach ($header as $item) {
+        $headerList[] = $item[0];
+    }
 
+    $csvContent[] = array();
+    $csvContent[] = array(get_lang('Sessions'));
 
     foreach ($sessions as $session_item) {
-
-        $data = array ();
+        $data = array();
         $personal_course_list = array();
         $id_session = $session_item['session_id'];
 
+        $csvContent[] = array($session_item['session_name']);
+        $csvContent[] = $headerList;
+
         foreach ($session_item['courses'] as $my_course) {
-            $course_info = api_get_course_info($my_course['code']);
-            $row = array();
-            $row[] = $my_course['code'];
-            $row[] = $course_info['title'];
-            $sessionStatus = SessionManager::get_user_status_in_session($user['user_id'], $my_course['code'], $id_session);
+            $courseInfo = api_get_course_info($my_course['code']);
+            $sessionStatus = SessionManager::get_user_status_in_session(
+                $user['user_id'],
+                $my_course['code'],
+                $id_session
+            );
             $status = null;
-
-            switch($sessionStatus) {
+            switch ($sessionStatus) {
+                case 0:
                 case STUDENT:
                     $status = get_lang('Student');
                     break;
@@ -144,21 +176,57 @@ if (count($sessions) > 0) {
                     $status = get_lang('CourseCoach');
                     break;
             }
-
-            $row[] = $status;
-
-            $tools = '<a href="course_information.php?code='.$course_info['code'].'&id_session='.$id_session.'">'.
-                      Display::return_icon('synthese_view.gif', get_lang('Overview')).'</a>'.
-                    '<a href="'.api_get_path(WEB_COURSE_PATH).$course_info['path'].'?id_session='.$id_session.'">'.
-                      Display::return_icon('course_home.gif', get_lang('CourseHomepage')).'</a>';
+            $tools = '<a href="course_information.php?code='.$courseInfo['code'].'&id_session='.$id_session.'">'.
+                Display::return_icon('synthese_view.gif', get_lang('Overview')).'</a>'.
+                '<a href="'.api_get_path(WEB_COURSE_PATH).$courseInfo['path'].'?id_session='.$id_session.'">'.
+                Display::return_icon('course_home.gif', get_lang('CourseHomepage')).'</a>';
 
             if ($my_course['status'] == STUDENT) {
-                $tools .= '<a href="user_information.php?action=unsubscribe&course_code='.$course_info['code'].'&user_id='.$user['user_id'].'">'.
-                      Display::return_icon('delete.png', get_lang('Delete')).'</a>';
+                $tools .= '<a href="user_information.php?action=unsubscribe&course_code='.$courseInfo['code'].'&user_id='.$user['user_id'].'">'.
+                    Display::return_icon('delete.png', get_lang('Delete')).'</a>';
             }
-            $row[] = $tools;
+
+            $timeSpent = api_time_to_hms(
+                Tracking :: get_time_spent_on_the_course(
+                    $user['user_id'],
+                    $courseInfo['code'],
+                    $id_session
+                )
+            );
+
+            $totalForumMessages = CourseManager::getCountPostInForumPerUser(
+                $user['user_id'],
+                $courseInfo['real_id'],
+                $id_session
+            );
+
+            $row = array(
+                Display::url(
+                    $my_course['code'],
+                    $courseInfo['course_public_url'].'?id_session='.$id_session
+                ),
+                $courseInfo['title'],
+                $status,
+                $timeSpent,
+                $totalForumMessages,
+                $tools
+            );
+
+            $csvContent[] = array_map('strip_tags', $row);
             $data[] = $row;
+
+            $result = TrackingUserLogCSV::getToolInformation(
+                $user['user_id'],
+                $courseInfo,
+                $id_session
+            );
+
+            if (!empty($result['html'])) {
+                $courseToolInformationTotal .= $result['html'];
+                $csvContent = array_merge($csvContent, $result['array']);
+            }
         }
+
         if ($session_item['date_start'] == '0000-00-00') {
             $session_item['date_start'] = null;
         }
@@ -170,23 +238,26 @@ if (count($sessions) > 0) {
         $dates = array_filter(
             array($session_item['date_start'], $session_item['date_end'])
         );
-        echo Display::page_subheader(
-            '<a href="'.api_get_path(WEB_CODE_PATH).'admin/resume_session.php?id_session='.$id_session.'">'.$session_item['session_name'].'</a>',
+
+        $sessionInformation .= Display::page_subheader(
+            '<a href="'.api_get_path(WEB_CODE_PATH).'admin/resume_session.php?id_session='.$id_session.'">'.
+            $session_item['session_name'].'</a>',
             ' '.implode(' - ', $dates)
         );
 
-        Display :: display_sortable_table(
+        $sessionInformation .= Display::return_sortable_table(
             $header,
             $data,
-            array (),
             array(),
-            array ('user_id' => intval($_GET['user_id']))
+            array(),
+            array('user_id' => intval($_GET['user_id']))
         );
+        $sessionInformation .= $courseToolInformationTotal;
     }
 } else {
-    echo '<p>'.get_lang('NoSessionsForThisUser').'</p>';
+    $sessionInformation = '<p>'.get_lang('NoSessionsForThisUser').'</p>';
 }
-
+$courseToolInformationTotal = null;
 
 /**
  * Show the courses in which this user is subscribed
@@ -196,62 +267,170 @@ $sql = 'SELECT * FROM '.$table_course_user.' cu, '.$table_course.' c'.
     ' AND cu.relation_type <> '.COURSE_RELATION_TYPE_RRHH.' ';
 $res = Database::query($sql);
 if (Database::num_rows($res) > 0) {
-    $header=array();
-    $header[] = array (get_lang('Code'), true);
-    $header[] = array (get_lang('Title'), true);
-    $header[] = array (get_lang('Status'), true);
-    $header[] = array ('', false);
-    $data = array ();
+    $header = array(
+        array(get_lang('Code'), true),
+        array(get_lang('Title'), true),
+        array(get_lang('Status'), true),
+        array(get_lang('TimeSpentInTheCourse'), true),
+        array(get_lang('TotalPostsInAllForums'), true),
+        array('', false)
+    );
+
+    $headerList = array();
+    foreach ($header as $item) {
+        $headerList[] = $item[0];
+    }
+    $csvContent[] = array();
+    $csvContent[] = array(get_lang('Courses'));
+    $csvContent[] = $headerList;
+
+    $data = array();
+    $courseToolInformationTotal = null;
     while ($course = Database::fetch_object($res)) {
-        $row = array ();
-        $row[] = $course->code;
-        $row[] = $course->title;
-        $row[] = $course->status == STUDENT ? get_lang('Student') : get_lang('Teacher');
+        $courseToolInformation = null;
+
         $tools = '<a href="course_information.php?code='.$course->code.'">'.Display::return_icon('synthese_view.gif', get_lang('Overview')).'</a>'.
-                '<a href="'.api_get_path(WEB_COURSE_PATH).$course->directory.'">'.Display::return_icon('course_home.gif', get_lang('CourseHomepage')).'</a>' .
-                '<a href="course_edit.php?course_code='.$course->code.'">'.Display::return_icon('edit.gif', get_lang('Edit')).'</a>';
+            '<a href="'.api_get_path(WEB_COURSE_PATH).$course->directory.'">'.Display::return_icon('course_home.gif', get_lang('CourseHomepage')).'</a>' .
+            '<a href="course_edit.php?course_code='.$course->code.'">'.Display::return_icon('edit.gif', get_lang('Edit')).'</a>';
         if ($course->status == STUDENT) {
             $tools .= '<a href="user_information.php?action=unsubscribe&course_code='.$course->code.'&user_id='.$user['user_id'].'">'.Display::return_icon('delete.png', get_lang('Delete')).'</a>';
         }
-        $row[] = $tools;
+
+        $timeSpent = api_time_to_hms(
+            Tracking :: get_time_spent_on_the_course(
+                $user['user_id'],
+                $course->code,
+                0
+            )
+        );
+
+        $totalForumMessages = CourseManager::getCountPostInForumPerUser(
+            $user['user_id'],
+            $course->id,
+            0
+        );
+        $courseInfo = api_get_course_info($course->code);
+        $row = array(
+            Display::url($course->code, $courseInfo['course_public_url']),
+            $course->title,
+            $course->status == STUDENT ? get_lang('Student') : get_lang('Teacher'),
+            $timeSpent,
+            $totalForumMessages,
+            $tools,
+        );
+
+        $csvContent[] = array_map('strip_tags', $row);
         $data[] = $row;
+
+        $result = TrackingUserLogCSV::getToolInformation(
+            $user['user_id'],
+            $courseInfo,
+            0
+        );
+        $courseToolInformationTotal .= $result['html'];
+        $csvContent = array_merge($csvContent, $result['array']);
     }
-    echo Display::page_subheader(get_lang('Courses'));
-    Display :: display_sortable_table(
+
+    $courseInformation = Display::page_subheader(get_lang('Courses'));
+    $courseInformation .= Display::return_sortable_table(
         $header,
         $data,
-        array (),
-        array (),
-        array ('user_id' => intval($_GET['user_id']))
+        array(),
+        array(),
+        array('user_id' => intval($_GET['user_id']))
     );
+    $courseInformation .=  $courseToolInformationTotal;
+
 } else {
-    echo '<p>'.get_lang('NoCoursesForThisUser').'</p>';
+    $courseInformation = '<p>'.get_lang('NoCoursesForThisUser').'</p>';
 }
+
 /**
  * Show the URL in which this user is subscribed
  */
+$urlInformation = null;
 if (api_is_multiple_url_enabled()) {
-    $url_list= UrlManager::get_access_url_from_user($user['user_id']);
-    if (count($url_list) > 0) {
+    $urlList= UrlManager::get_access_url_from_user($user['user_id']);
+    if (count($urlList) > 0) {
         $header = array();
-        $header[] = array ('URL', true);
-        $data = array ();
-        foreach ($url_list as $url) {
+        $header[] = array('URL', true);
+        $data = array();
+
+        $csvContent[] = array();
+        $csvContent[] = array('Url');
+        foreach ($urlList as $url) {
             $row = array();
             $row[] = Display::url($url['url'], $url['url']);
+            $csvContent[] = array_map('strip_tags', $row);
             $data[] = $row;
         }
-        echo '<p><b>'.get_lang('URLList').'</b></p>';
-        Display :: display_sortable_table(
+
+        $urlInformation = Display::page_subheader(get_lang('URLList'));
+        $urlInformation .= Display::return_sortable_table(
             $header,
             $data,
-            array (),
-            array (),
-            array ('user_id' => intval($_GET['user_id']))
+            array(),
+            array(),
+            array('user_id' => intval($_GET['user_id']))
         );
     } else {
-        echo '<p>'.get_lang('NoUrlForThisUser').'</p>';
+        $urlInformation = '<p>'.get_lang('NoUrlForThisUser').'</p>';
+    }
+}
+$message = null;
+
+if (isset($_GET['action'])) {
+    switch ($_GET['action']) {
+        case 'unsubscribe':
+            if (CourseManager::get_user_in_course_status($_GET['user_id'], $_GET['course_code']) == STUDENT) {
+                CourseManager::unsubscribe_user($_GET['user_id'], $_GET['course_code']);
+                $message = Display::return_message(get_lang('UserUnsubscribed'));
+            } else {
+                $message = Display::return_message(
+                    get_lang('CannotUnsubscribeUserFromCourse'),
+                    'error'
+                );
+            }
+            break;
+        case 'export':
+            Export :: export_table_csv_utf8($csvContent, 'user_information_'.$user);
+            exit;
+            break;
     }
 }
 
+Display::display_header($tool_name);
+
+echo '<div class="actions">
+        <a href="'.api_get_path(WEB_CODE_PATH).'mySpace/myStudents.php?student='.intval($_GET['user_id']).'" title="'.get_lang('Reporting').'">'.Display::return_icon('statistics.png', get_lang('Reporting'), '', ICON_SIZE_MEDIUM).'
+        </a>
+        '.$login_as_icon.'
+        '.$editUser.'
+        '.$exportLink.'
+    </div>';
+
+echo Display::page_header($tool_name);
+
+echo '<div class="row">';
+echo '<div class="span2">';
+echo '<a href="javascript: void(0);" onclick="'.$onclick.'" >'
+    .'<img src="'.$fullurl.'" '.$resizing.' /></a><br />';
+echo '</div>';
+
+echo $message;
+
+echo '<div class="span5">';
+echo $userInformation;
+echo '</div>';
+
+echo '<div class="span5">';
+echo $trackingInformation;
+echo '</div>';
+echo '</div>';
+
+echo Display::page_subheader(get_lang('SessionList'));
+echo $sessionInformation;
+echo $courseInformation;
+echo $urlInformation;
+
 Display::display_footer();

+ 8 - 2
main/admin/user_list.php

@@ -655,10 +655,16 @@ if (!empty($action)) {
 			case 'show_message' :
                 if (!empty($_GET['warn'])) {
                     // to prevent too long messages
-                    if ($_GET['warn'] == 'session_message'){
+                    if ($_GET['warn'] == 'session_message') {
                         $_GET['warn'] = $_SESSION['session_message_import_users'];
                     }
-                    $message .= Display::return_message(Security::remove_XSS($_GET['warn']), 'warning', false);
+                    if (isset($_GET['warn']) && !empty($_GET['warn'])) {
+                        $message .= Display::return_message(
+                            Security::remove_XSS($_GET['warn']),
+                            'warning',
+                            false
+                        );
+                    }
                 }
                 if (!empty($_GET['message'])) {
                     $message .= Display::return_message(stripslashes($_GET['message']), 'confirmation');

+ 2 - 4
main/admin/user_move_stats.php

@@ -188,8 +188,7 @@ if (isset($_REQUEST['load_ajax'])) {
                             }
                         }                                       
                     }                
-                }
-                
+                }                
                 
                 //2.track_e_attempt, track_e_attempt_recording, track_e_downloads
                 //Nothing to do because there are not relationship with a session
@@ -235,8 +234,7 @@ if (isset($_REQUEST['load_ajax'])) {
                     }  
                 }                
                 
-                //5. lp_item_view           
-                 
+                //5. lp_item_view
                //CHECK ORIGIN
                
                 $sql = "SELECT * FROM $TBL_LP_VIEW WHERE user_id = $user_id AND session_id = $origin_session_id AND c_id = $course_id ";

+ 492 - 0
main/admin/user_update_import.php

@@ -0,0 +1,492 @@
+<?php
+/* For licensing terms, see /license.txt */
+/**
+ * This tool allows platform admins to add users by uploading a CSV or XML file
+ * @package chamilo.admin
+ */
+
+/**
+ * Validate the imported data.
+ */
+
+$language_file = array ('admin', 'registration');
+
+$cidReset = true;
+require '../inc/global.inc.php';
+require_once api_get_path(LIBRARY_PATH).'mail.lib.inc.php';
+require_once api_get_path(LIBRARY_PATH).'fileManage.lib.php';
+require_once api_get_path(LIBRARY_PATH).'classmanager.lib.php';
+require_once api_get_path(LIBRARY_PATH).'usergroup.lib.php';
+require_once api_get_path(LIBRARY_PATH).'import.lib.php';
+
+// Set this option to true to enforce strict purification for usenames.
+$purification_option_for_usernames = false;
+
+function validate_data($users)
+{
+    global $defined_auth_sources;
+    $errors = array();
+    $usernames = array();
+
+    // 1. Check if mandatory fields are set.
+    $mandatory_fields = array('LastName', 'FirstName');
+
+    if (api_get_setting('registration', 'email') == 'true') {
+        $mandatory_fields[] = 'Email';
+    }
+    $classExistList = array();
+    $usergroup = new UserGroup();
+
+    foreach ($users as $user) {
+        foreach ($mandatory_fields as $field) {
+            if (isset($user[$field])) {
+                if (empty($user[$field])) {
+                    $user['error'] = get_lang($field.'Mandatory');
+                    $errors[] = $user;
+                }
+            }
+        }
+
+        // 2. Check username, first, check whether it is empty.
+        
+        if (isset($user['NewUserName'])) {
+            if (!UserManager::is_username_empty($user['NewUserName'])) {
+                // 2.1. Check whether username is too long.
+                if (UserManager::is_username_too_long($user['NewUserName'])) {
+                    $user['error'] = get_lang('UserNameTooLong');
+                    $errors[] = $user;
+                }
+                // 2.2. Check whether the username was used twice in import file.
+                if (isset($usernames[$user['NewUserName']])) {
+                    $user['error'] = get_lang('UserNameUsedTwice');
+                    $errors[] = $user;
+                }
+                $usernames[$user['UserName']] = 1;
+                // 2.3. Check whether username is allready occupied.
+                if (!UserManager::is_username_available($user['NewUserName']) && $user['NewUserName'] != $user['UserName']) {
+                    $user['error'] = get_lang('UserNameNotAvailable');
+                    $errors[] = $user;
+                }
+             }
+          }
+          
+        // 3. Check status.
+        if (isset($user['Status']) && !api_status_exists($user['Status'])) {
+            $user['error'] = get_lang('WrongStatus');
+            $errors[] = $user;
+        }
+
+        // 4. Check ClassId
+        if (!empty($user['ClassId'])) {
+            $classId = explode('|', trim($user['ClassId']));
+            foreach ($classId as $id) {
+                if (in_array($id, $classExistList)) {
+                    continue;
+                }
+                $info = $usergroup->get($id);
+                if (empty($info)) {
+                    $user['error'] = sprintf(get_lang('ClassIdDoesntExists'), $id);
+                    $errors[] = $user;
+                } else {
+                    $classExistList[] = $info['id'];
+                }
+            }
+        }
+
+        // 5. Check authentication source
+        if (!empty($user['AuthSource'])) {
+            if (!in_array($user['AuthSource'], $defined_auth_sources)) {
+                $user['error'] = get_lang('AuthSourceNotAvailable');
+                $errors[] = $user;
+            }
+        }
+    }
+
+    return $errors;
+}
+
+/**
+ * Add missing user-information (which isn't required, like password, username etc).
+ */
+function complete_missing_data($user)
+{
+    global $purification_option_for_usernames;
+    // 1. Create a username if necessary.
+    if (UserManager::is_username_empty($user['UserName'])) {
+        $user['UserName'] = UserManager::create_unique_username($user['FirstName'], $user['LastName']);
+    } else {
+        $user['UserName'] = UserManager::purify_username($user['UserName'], $purification_option_for_usernames);
+    }
+    // 2. Generate a password if necessary.
+    if (empty($user['Password'])) {
+        $user['Password'] = api_generate_password();
+    }
+    // 3. Set status if not allready set.
+    if (empty($user['Status'])) {
+        $user['Status'] = 'user';
+    }
+    // 4. Set authsource if not allready set.
+    if (empty($user['AuthSource'])) {
+        $user['AuthSource'] = PLATFORM_AUTH_SOURCE;
+    }
+    return $user;
+}
+
+/**
+ * Update users from the imported data
+ * @param   array   $users List of users
+ * @return  void
+ * @uses global variable $inserted_in_course, which returns the list of courses the user was inserted in
+ */
+ 
+function updateUsers($users)
+{
+    global $insertedIn_course;
+    // Not all scripts declare the $inserted_in_course array (although they should).
+    if (!isset($inserted_in_course)) {
+        $inserted_in_course = array();
+    }
+    require_once api_get_path(LIBRARY_PATH).'mail.lib.inc.php';
+    $usergroup = new UserGroup();
+    $send_mail = $_POST['sendMail'] ? true : false;
+    if (is_array($users)) {
+        foreach ($users as $user) {
+            $user = complete_missing_data($user);
+            $user['Status'] = api_status_key($user['Status']);
+            $userName = $user['UserName'];
+            $userInfo = api_get_user_info_from_username($userName);
+            $user_id = $userInfo['user_id'];
+            if ($user_id == 0) {
+                return false;
+            } 
+            $firstName = isset($user['FirstName']) ? $user['FirstName'] : $userInfo['firstname'];
+            $lastName = isset($user['LastName']) ? $user['LastName'] : $userInfo['lastname'];
+            $userName = isset($user['NewUserName']) ? $user['NewUserName'] : $userInfo['username'];
+            $password = isset($user['Password']) ? $user['Password'] : $userInfo['password'];
+            $authSource = isset($user['AuthSource']) ? $user['AuthSource'] : $userInfo['auth_source'];
+            $email = isset($user['Email']) ? $user['Email'] : $userInfo['email'];
+            $status = isset($user['Status']) ? $user['Status'] : $userInfo['status'];
+            $officialCode = isset($user['OfficialCode']) ? $user['OfficialCode'] : $userInfo['official_code'];
+            $phone = isset($user['PhoneNumber']) ? $user['PhoneNumber'] : $userInfo['phone'];
+            $pictureUrl = isset($user['PictureUri']) ? $user['PictureUri'] : $userInfo['picture_url'];
+            $expirationDate = isset($user['ExpiryDate']) ? $user['ExpiryDate'] : $userInfo['expiration_date'];
+            $active = isset($user['Active']) ? $user['Active'] : $userInfo['active'];
+            $creatorId = $userInfo['creator_id'];
+            $hrDeptId = $userInfo['hr_dept_id'];
+            $language = isset($user['Language']) ? $user['Language'] : $userInfo['language'];
+            $sendEmail = isset($user['SendEmail']) ? $user['SendEmail'] : $userInfo['language'];
+            $userUpdated = UserManager :: update_user(
+                $user_id,
+                $firstName,
+                $lastName,
+                $userName,
+                $password,
+                $authSource,
+                $email,
+                $status,
+                $officialCode,
+                $phone,
+                $pictureUrl,
+                $expirationDate,
+                $active,
+                $creatorId,
+                $hrDeptId,
+                null,
+                $language,
+                '',   
+                '',
+                ''
+                
+            );
+            if (!is_array($user['Courses']) && !empty($user['Courses'])) {
+                $user['Courses'] = array($user['Courses']);
+            }
+            if (is_array($user['Courses'])) {
+                foreach ($user['Courses'] as $course) {
+                    if (CourseManager::course_exists($course)) {
+                        CourseManager::subscribe_user($user_id, $course, $user['Status']);
+                        $course_info = CourseManager::get_course_information($course);
+                        $inserted_in_course[$course] = $course_info['title'];
+                    }
+                    if (CourseManager :: course_exists($course, true)) {
+                        // Also subscribe to virtual courses through check on visual code.
+                        $list = CourseManager :: get_courses_info_from_visual_code($course);
+                        foreach ($list as $vcourse) {
+                            if ($vcourse['code'] == $course) {
+                                // Ignore, this has already been inserted.
+                            } else {
+                                CourseManager :: subscribe_user($user_id, $vcourse['code'], $user['Status']);
+                                $inserted_in_course[$vcourse['code']] = $vcourse['title'];
+                            }
+                        }
+                    }
+                }
+            }
+            if (!empty($user['ClassId'])) {
+                $classId = explode('|', trim($user['ClassId']));
+                foreach ($classId as $id) {
+                    $usergroup->subscribe_users_to_usergroup($id, array($user_id), false);
+                }
+            }
+
+            // Saving extra fields.
+            global $extra_fields;
+
+            // We are sure that the extra field exists.
+            foreach ($extra_fields as $extras) {
+                if (isset($user[$extras[1]])) {
+                    $key 	= $extras[1];
+                    $value 	= $user[$extras[1]];
+                    UserManager::update_extra_field_value($user_id, $key, $value);
+                }
+            }
+        }
+    }
+}
+
+
+/**
+ * Read the CSV-file
+ * @param string $file Path to the CSV-file
+ * @return array All userinformation read from the file
+ */
+function parse_csv_data($file)
+{
+    $users = Import :: csv_to_array($file);
+    foreach ($users as $index => $user) {
+        if (isset ($user['Courses'])) {
+            $user['Courses'] = explode('|', trim($user['Courses']));
+        }
+        $users[$index] = $user;
+    }
+    return $users;
+}
+/**
+ * XML-parser: handle start of element
+ * @param   string  $parser Deprecated?
+ * @param   string  $data The data to be parsed
+ */
+function element_start($parser, $data)
+{
+    $data = api_utf8_decode($data);
+    global $user;
+    global $current_tag;
+    switch ($data) {
+        case 'Contact':
+            $user = array ();
+            break;
+        default:
+            $current_tag = $data;
+    }
+}
+
+/**
+ * XML-parser: handle end of element
+ * @param   string  $parser Deprecated?
+ * @param   string  $data   The data to be parsed
+ */
+function element_end($parser, $data)
+{
+    $data = api_utf8_decode($data);
+    global $user;
+    global $users;
+    global $current_value;
+    switch ($data) {
+        case 'Contact':
+            if ($user['Status'] == '5') {
+                $user['Status'] = STUDENT;
+            }
+            if ($user['Status'] == '1') {
+                $user['Status'] = COURSEMANAGER;
+            }
+            $users[] = $user;
+            break;
+        default:
+            $user[$data] = $current_value;
+            break;
+    }
+}
+
+/**
+ * XML-parser: handle character data
+ * @param   string  $parser Parser (deprecated?)
+ * @param   string  $data The data to be parsed
+ * @return  void
+ */
+function character_data($parser, $data)
+{
+    $data = trim(api_utf8_decode($data));
+    global $current_value;
+    $current_value = $data;
+}
+
+/**
+ * Read the XML-file
+ * @param string $file Path to the XML-file
+ * @return array All user information read from the file
+ */
+function parse_xml_data($file)
+{
+    global $users;
+    $users = array();
+    $parser = xml_parser_create('UTF-8');
+    xml_set_element_handler($parser, 'element_start', 'element_end');
+    xml_set_character_data_handler($parser, 'character_data');
+    xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false);
+    xml_parse($parser, api_utf8_encode_xml(file_get_contents($file)));
+    xml_parser_free($parser);
+    return $users;
+}
+
+$this_section = SECTION_PLATFORM_ADMIN;
+api_protect_admin_script(true, null, 'login');
+
+
+$defined_auth_sources[] = PLATFORM_AUTH_SOURCE;
+
+if (is_array($extAuthSource)) {
+    $defined_auth_sources = array_merge($defined_auth_sources, array_keys($extAuthSource));
+}
+
+$tool_name = get_lang('ImportUserListXMLCSV');
+$interbreadcrumb[] = array("url" => 'index.php', "name" => get_lang('PlatformAdmin'));
+
+set_time_limit(0);
+$extra_fields = UserManager::get_extra_fields(0, 0, 5, 'ASC', true);
+$user_id_error = array();
+$error_message = '';
+
+if (isset($_POST['formSent']) && $_POST['formSent'] AND $_FILES['import_file']['size'] !== 0) {
+    
+    $file_type = 'csv';    
+   
+    Security::clear_token();
+    $tok = Security::get_token();
+    $allowed_file_mimetype = array('csv', 'xml');
+    $error_kind_file = false;
+
+    $uploadInfo = pathinfo($_FILES['import_file']['name']);
+    $ext_import_file = $uploadInfo['extension'];
+
+    if (in_array($ext_import_file, $allowed_file_mimetype)) {
+        if (strcmp($file_type, 'csv') === 0 && $ext_import_file == $allowed_file_mimetype[0]) {
+            $users	= parse_csv_data($_FILES['import_file']['tmp_name']);
+            $errors = validate_data($users);
+            $error_kind_file = false;
+        } elseif (strcmp($file_type, 'xml') === 0 && $ext_import_file == $allowed_file_mimetype[1]) {
+            $users = parse_xml_data($_FILES['import_file']['tmp_name']);
+            $errors = validate_data($users);
+            $error_kind_file = false;
+        } else {
+        
+            $error_kind_file = true;
+        }
+    } else {
+        $error_kind_file = true;
+    }
+
+    // List user id with error.
+    $users_to_insert = $user_id_error = array();
+
+    if (is_array($errors)) {
+        foreach ($errors as $my_errors) {
+            $user_id_error[] = $my_errors['UserName'];
+        }
+    }
+
+    if (is_array($users)) {
+        foreach ($users as $my_user) {
+            if (!in_array($my_user['UserName'], $user_id_error)) {
+                $users_to_insert[] = $my_user;
+            }
+        }
+    }
+
+    $inserted_in_course = array();
+    if (strcmp($file_type, 'csv') === 0) {
+        updateUsers($users_to_insert);
+    } else {
+        $error_message = get_lang('YouMustImportAFileAccordingToSelectedOption1');
+    }
+
+    if (count($errors) > 0) {
+        $see_message_import = get_lang('FileImportedJustUsersThatAreNotRegistered');
+    } else {
+        $see_message_import = get_lang('FileImported');
+    }
+
+    if (count($errors) != 0) {
+        $warning_message = '<ul>';
+        foreach ($errors as $index => $error_user) {
+            $warning_message .= '<li><b>'.$error_user['error'].'</b>: ';
+            $warning_message .=
+                '<strong>'.$error_user['UserName'].'</strong>&nbsp;('.
+                api_get_person_name($error_user['FirstName'], $error_user['LastName']).')';
+            $warning_message .= '</li>';
+        }
+        $warning_message .= '</ul>';
+    }
+
+    // if the warning message is too long then we display the warning message trough a session
+
+    $_SESSION['session_message_import_users'] = $warning_message;
+    $warning_message = 'session_message';
+
+    if ($error_kind_file) {
+        $error_message = get_lang('YouMustImportAFileAccordingToSelectedOption');
+    } else {
+        header('Location: '.api_get_path(WEB_CODE_PATH).'admin/user_list.php?action=show_message&warn='.urlencode($warning_message).'&message='.urlencode($see_message_import).'&sec_token='.$tok);
+        exit;
+    }
+
+}
+Display :: display_header($tool_name);
+
+if (!empty($error_message)) {
+    Display::display_error_message($error_message);
+}
+
+$form = new FormValidator('user_update_import','post','user_update_import.php');
+$form->addElement('header', '', $tool_name);
+$form->addElement('hidden', 'formSent');
+$form->addElement('file', 'import_file', get_lang('ImportFileLocation'));
+
+$group = array();
+
+$form->addElement('style_submit_button', 'submit', get_lang('Import'), 'class="save"');
+$defaults['formSent'] = 1;
+$defaults['sendMail'] = 0;
+$defaults['file_type'] = 'csv';
+$form->setDefaults($defaults);
+$form->display();
+
+$list = array();
+$list_reponse = array();
+$result_xml = '';
+$i = 0;
+$count_fields = count($extra_fields);
+if ($count_fields > 0) {
+    foreach ($extra_fields as $extra) {
+        $list[] = $extra[1];
+        $list_reponse[] = 'xxx';
+        $spaces = '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
+        $result_xml .= $spaces.'&lt;'.$extra[1].'&gt;xxx&lt;/'.$extra[1].'&gt;';
+        if ($i != $count_fields - 1) {
+            $result_xml .= '<br/>';
+        }
+        $i++;
+    }
+}
+
+?>
+    <p><?php echo get_lang('CSVMustLookLike').' ('.get_lang('MandatoryFields').')'; ?> :</p>
+     
+        <blockquote>
+            <pre>
+                <b>UserName</b>;LastName;FirstName;Email;NewUserName;Password;AuthSource;OfficialCode;PhoneNumber;Status;ExpiryDate;Active;Language;Courses;ClassId;
+                xxx;xxx;xxx;xxx;xxx;xxx;xxx;xxx;xxx;user/teacher/drh;0000-00-00 00:00:00;0/1;xxx;<span style="color:red;"><?php if (count($list_reponse) > 0) echo implode(';', $list_reponse).';'; ?></span>xxx1|xxx2|xxx3;1;<br />
+            </pre>
+        </blockquote>
+    <p><?php
+
+Display :: display_footer();

+ 14 - 11
main/admin/usergroup_import.php

@@ -1,13 +1,10 @@
 <?php
 /* For licensing terms, see /license.txt */
 /**
+ *  This tool allows platform admins to add classes by uploading a CSV file
+ *  @todo Add some langvars to DLTT
  * 	@package chamilo.admin
  */
-/**
- * Code
- *   This     tool allows platform admins to add classes by uploading a CSV file
- * @todo Add some langvars to DLTT
- */
 
 /**
  * Validates imported data.
@@ -21,23 +18,29 @@ function validate_data($classes) {
             $class['line'] = $index + 2;
             $class['error'] = get_lang('MissingClassName');
             $errors[] = $class;
-        }
-        // 2. Check whether class doesn't exist yet.
-        else {
+        } else {
+            // 2. Check whether class doesn't exist yet.
             if ($usergroup->usergroup_exists($class['name'])) {
                 $class['line'] = $index + 2;
-                $class['error'] = get_lang('ClassNameExists') . ' <strong>' . $class['ClassName'] . '</strong>';
+                $class['error'] = get_lang('ClassNameExists') .
+                    ': <strong>' .$class['name'] . '</strong>';
                 $errors[] = $class;
             }
         }
     }
+
     return $errors;
 }
 
 /**
  * Save imported class data to database
+ *
+ * @param $classes
+ *
+ * @return int
  */
-function save_data($classes) {
+function save_data($classes)
+{
     $number_of_added_classes = 0;
     $usergroup = new UserGroup();
     foreach ($classes as $index => $class) {
@@ -115,4 +118,4 @@ $form->display();
 </pre>
 <?php
 // Displaying the footer.
-Display :: display_footer();
+Display :: display_footer();

+ 12 - 6
main/admin/usergroups.php

@@ -121,6 +121,11 @@ if (isset($_GET['action']) && $_GET['action'] == 'add') {
             $res = $usergroup->save($values);
             if ($res) {
                 Display::display_confirmation_message(get_lang('ItemAdded'));
+            } else {
+                Display::display_warning_message(
+                    Security::remove_XSS($values['name']).': '.
+                    get_lang('AlreadyExists')
+                );
             }
         }
         Security::clear_token();
@@ -140,7 +145,7 @@ if (isset($_GET['action']) && $_GET['action'] == 'add') {
     $form = new FormValidator('career', 'post', api_get_self().'?action='.Security::remove_XSS($_GET['action']).'&id='.Security::remove_XSS($_GET['id']));
     // Setting the form elements
     $form->addElement('header', '', get_lang('Modify'));
-    $form->addElement('hidden', 'id',intval($_GET['id']));
+    $form->addElement('hidden', 'id', intval($_GET['id']));
     $form->addElement('text', 'name', get_lang('Name'), array('size' => '70'));
     $form->add_html_editor('description', get_lang('Description'), false, false, array('Width' => '95%', 'Height' => '250'));
     $form->addElement('style_submit_button', 'submit', get_lang('Modify'), 'class="save"');
@@ -160,6 +165,11 @@ if (isset($_GET['action']) && $_GET['action'] == 'add') {
             $res = $usergroup->update($values);
             if ($res) {
                 Display::display_confirmation_message(get_lang('Updated'));
+            } else {
+                Display::display_warning_message(
+                    Security::remove_XSS($values['name']).': '.
+                    get_lang('AlreadyExists')
+                );
             }
         }
         Security::clear_token();
@@ -173,10 +183,7 @@ if (isset($_GET['action']) && $_GET['action'] == 'add') {
         $form->setConstants(array('sec_token' => $token));
         $form->display();
     }
-}
-
-// Action handling: deleting a note
-elseif (isset($_GET['action']) && $_GET['action'] == 'delete' && is_numeric($_GET['id'])) {
+} elseif (isset($_GET['action']) && $_GET['action'] == 'delete' && is_numeric($_GET['id'])) {
     $res = $usergroup->delete(Security::remove_XSS($_GET['id']));
     if ($res) {
         Display::display_confirmation_message(get_lang('Deleted'));
@@ -185,5 +192,4 @@ elseif (isset($_GET['action']) && $_GET['action'] == 'delete' && is_numeric($_GE
 } else {
     $usergroup->display();
 }
-
 Display :: display_footer();

+ 10 - 1
main/announcements/announcement_email.class.php

@@ -183,6 +183,7 @@ class AnnouncementEmail
                 $new_list_users[$user['user_id']] = array('user_id' => $user['user_id']);
             }
         }
+
         return $new_list_users;
     }
 
@@ -196,6 +197,7 @@ class AnnouncementEmail
     public function sender($key = '')
     {
         global $_user;
+
         return $key ? $_user[$key] : $_user;
     }
 
@@ -287,6 +289,7 @@ class AnnouncementEmail
 
     /**
      * Send emails to users.
+     * @param bool $sendToUsersInSession
      */
     public function send($sendToUsersInSession = false)
     {
@@ -315,12 +318,18 @@ class AnnouncementEmail
                     $userList = CourseManager::get_user_list_from_course_code($this->course['code'], $sessionId);
                     if (!empty($userList)) {
                         foreach ($userList as $user) {
-                            MessageManager::send_message_simple($user['user_id'], $subject, $message, $sender['user_id']);
+                            MessageManager::send_message_simple(
+                                $user['user_id'],
+                                $subject,
+                                $message,
+                                $sender['user_id']
+                            );
                         }
                     }
                 }
             }
         }
+
         $this->log_mail_sent();
     }
 

+ 8 - 4
main/announcements/announcements.inc.php

@@ -710,7 +710,7 @@ class AnnouncementManager
      */
     public static function construct_not_selected_select_form($group_list = null, $user_list = null, $to_already_selected)
     {
-        echo '<select name="not_selected_form[]" size="7" class="span4" multiple>';
+        echo '<select id="not_selected_form" name="not_selected_form[]" size="7" class="span4" multiple>';
         // adding the groups to the select form
         if ($group_list) {
             foreach ($group_list as $this_group) {
@@ -1197,7 +1197,7 @@ class AnnouncementManager
 
     /**
      * This function delete a attachment file by id
-     * @param integer attachment file Id
+     * @param integer $id attachment file Id
      *
      */
     public static function delete_announcement_attachment_file($id)
@@ -1209,9 +1209,13 @@ class AnnouncementManager
         Database::query($sql);
     }
 
-    public static function send_email($annoucement_id, $sendToUsersInSession = false)
+    /**
+     * @param int $id
+     * @param bool $sendToUsersInSession
+     */
+    public static function send_email($id, $sendToUsersInSession = false)
     {
-        $email = AnnouncementEmail::create(null, $annoucement_id);
+        $email = AnnouncementEmail::create(null, $id);
         $email->send($sendToUsersInSession);
     }
 }

+ 80 - 50
main/announcements/announcements.php

@@ -67,6 +67,7 @@ require_once $lib.'fileUpload.lib.php';
 require_once 'announcements.inc.php';
 
 $course_id = api_get_course_int_id();
+$_course = api_get_course_info();
 
 /*	Tracking	*/
 event_access_tool(TOOL_ANNOUNCEMENT);
@@ -78,12 +79,19 @@ $safe_newContent = isset($_POST['newContent']) ? $_POST['newContent'] : null;
 $content_to_modify = $title_to_modify 	= '';
 
 if (!empty($_POST['To'])) {
-	if (api_get_session_id()!=0 && api_is_allowed_to_session_edit(false,true)==false) {
+	if (api_get_session_id()!=0 &&
+        api_is_allowed_to_session_edit(false, true) == false
+    ) {
 		api_not_allowed(true);
 	}
 	$display_form = true;
 
-	$form_elements = array ('emailTitle'=>$safe_emailTitle, 'newContent'=>$safe_newContent, 'id'=>$_POST['id'], 'emailoption'=>$_POST['email_ann']);
+    $form_elements = array(
+        'emailTitle' => $safe_emailTitle,
+        'newContent' => $safe_newContent,
+        'id' => $_POST['id'],
+        'emailoption' => $_POST['email_ann']
+    );
     $_SESSION['formelements'] = $form_elements;
 
     $form_elements            	= $_SESSION['formelements'];
@@ -113,8 +121,10 @@ $origin = isset($_GET['origin']) ? Security::remove_XSS($_GET['origin']) : null;
 /* 	Action handling */
 
 // display the form
-if (((!empty($_GET['action']) && $_GET['action'] == 'add') && $_GET['origin'] == "") || (!empty($_GET['action']) && $_GET['action'] == 'edit') || !empty($_POST['To'])) {
-	if (api_get_session_id()!=0 && api_is_allowed_to_session_edit(false,true)==false) {
+if (((!empty($_GET['action']) && $_GET['action'] == 'add') && $_GET['origin'] == "") ||
+    (!empty($_GET['action']) && $_GET['action'] == 'edit') || !empty($_POST['To'])
+) {
+	if (api_get_session_id()!=0 && api_is_allowed_to_session_edit(false,true) == false) {
 		api_not_allowed(true);
 	}
 	$display_form = true;
@@ -130,7 +140,8 @@ $htmlHeadXtra[] = AnnouncementManager::to_javascript();
 /*	Filter user/group */
 
 if(!empty($_GET['toolgroup'])){
-	if($_GET['toolgroup'] == strval(intval($_GET['toolgroup']))){ //check is integer
+	if($_GET['toolgroup'] == strval(intval($_GET['toolgroup']))){
+	    //check is integer
 		$toolgroup = intval($_GET['toolgroup']);
 		$_SESSION['select_groupusers'] = 'hide';
 	} else {
@@ -146,16 +157,19 @@ $stok = Security::get_token();
 $to = null;
 $email_ann = null;
 
-if (!empty($_SESSION['formelements']) and !empty($_GET['originalresource']) and $_GET['originalresource'] == 'no') {
+if (!empty($_SESSION['formelements']) and
+    !empty($_GET['originalresource']) and
+    $_GET['originalresource'] == 'no'
+) {
 	$form_elements			= $_SESSION['formelements'];
 	$title_to_modify		= $form_elements['emailTitle'];
 	$content_to_modify		= $form_elements['newContent'];
 	$announcement_to_modify	= $form_elements['id'];
 	$to						= $form_elements['to'];
-	//load_edit_users('announcement',$announcement_to_modify);
 	$email_ann				= $form_elements['emailoption'];
 }
-if(!empty($_GET['remind_inactive'])) {
+
+if (!empty($_GET['remind_inactive'])) {
 	$to[] = 'USER:'.intval($_GET['remind_inactive']);
 }
 
@@ -163,8 +177,8 @@ $group_id = api_get_group_id();
 
 if (!empty($group_id)) {
 	$group_properties  = GroupManager :: get_group_properties($group_id);
-	$interbreadcrumb[] = array ("url" => "../group/group.php", "name" => get_lang('Groups'));
-	$interbreadcrumb[] = array ("url"=>"../group/group_space.php?gidReq=".$group_id, "name"=> get_lang('GroupSpace').' '.$group_properties['name']);
+	$interbreadcrumb[] = array("url" => "../group/group.php", "name" => get_lang('Groups'));
+	$interbreadcrumb[] = array("url"=>"../group/group_space.php?gidReq=".$group_id, "name"=> get_lang('GroupSpace').' '.$group_properties['name']);
 }
 
 $announcement_id = isset($_GET['id']) ? intval($_GET['id']) : null;
@@ -175,7 +189,9 @@ if (empty($_GET['origin']) or $_GET['origin'] !== 'learnpath') {
 	Display::display_header($nameTools,get_lang('Announcements'));
 }
 
-if (api_is_allowed_to_edit(false,true) OR (api_get_course_setting('allow_user_edit_announcement') && !api_is_anonymous())) {
+if (api_is_allowed_to_edit(false,true) OR
+    (api_get_course_setting('allow_user_edit_announcement') && !api_is_anonymous())
+) {
     /*
         Change visibility of announcement
     */
@@ -189,7 +205,6 @@ if (api_is_allowed_to_edit(false,true) OR (api_get_course_setting('allow_user_ed
 			}
 			if (!api_is_course_coach() || api_is_element_in_the_session(TOOL_ANNOUNCEMENT, $_GET['id'])) {
 				if ($ctok == $_GET['sec_token']) {
-
 					AnnouncementManager::change_visibility_announcement($_course, $_GET['id']);
 					$message = get_lang('VisibilityChanged');
 				}
@@ -197,12 +212,10 @@ if (api_is_allowed_to_edit(false,true) OR (api_get_course_setting('allow_user_ed
 		}
 	}
 
-	/*
-		Delete announcement
-	*/
+	/* Delete announcement */
 	if (!empty($_GET['action']) && $_GET['action']=='delete' && isset($_GET['id'])) {
-		$id=intval($_GET['id']);
-		if (api_get_session_id()!=0 && api_is_allowed_to_session_edit(false,true)==false) {
+		$id = intval($_GET['id']);
+		if (api_get_session_id()!=0 && api_is_allowed_to_session_edit(false, true) == false) {
 			api_not_allowed();
 		}
 
@@ -230,9 +243,7 @@ if (api_is_allowed_to_edit(false,true) OR (api_get_course_setting('allow_user_ed
         }
     }
 
-	/*
-		Delete all announcements
-	*/
+	/* Delete all announcements */
 	if (!empty($_GET['action']) and $_GET['action']=='delete_all') {
 		if (api_is_allowed_to_edit()) {
 			AnnouncementManager::delete_all_announcements($_course);
@@ -243,10 +254,7 @@ if (api_is_allowed_to_edit(false,true) OR (api_get_course_setting('allow_user_ed
 		}
 	}
 
-	/*
-		Modify announcement
-	*/
-
+	/* Modify announcement */
 	if (!empty($_GET['action']) and $_GET['action']=='modify' AND isset($_GET['id'])) {
 		if (api_get_session_id()!=0 && api_is_allowed_to_session_edit(false,true)==false) {
 			api_not_allowed();
@@ -262,7 +270,11 @@ if (api_is_allowed_to_edit(false,true) OR (api_get_course_setting('allow_user_ed
 			$rs 	= Database::query($sql);
 			$myrow  = Database::fetch_array($rs);
 			$last_id = $id;
-			$edit_attachment = AnnouncementManager::edit_announcement_attachment_file($last_id, $_FILES['user_upload'], $file_comment);
+			$edit_attachment = AnnouncementManager::edit_announcement_attachment_file(
+                $last_id,
+                $_FILES['user_upload'],
+                $file_comment
+            );
 
 			if ($myrow) {
 				$announcement_to_modify 	= $myrow['id'];
@@ -283,10 +295,7 @@ if (api_is_allowed_to_edit(false,true) OR (api_get_course_setting('allow_user_ed
 		}
 	}
 
-	/*
-		Move announcement up/down
-	*/
-
+	/* Move announcement up/down */
 	if (isset($_GET['sec_token']) && $ctok == $_GET['sec_token']) {
 		if (!empty($_GET['down'])) {
 			$thisAnnouncementId = intval($_GET['down']);
@@ -303,17 +312,18 @@ if (api_is_allowed_to_edit(false,true) OR (api_get_course_setting('allow_user_ed
 		if (!in_array(trim(strtoupper($sortDirection)), array('ASC', 'DESC'))) {
 			$sortDirection='ASC';
 		}
-		$my_sql = "SELECT announcement.id, announcement.display_order " .
-				"FROM $tbl_announcement announcement, " .
-				"$tbl_item_property itemproperty " .
-				"WHERE
-				announcement.c_id =  $course_id AND
-				itemproperty.c_id =  $course_id AND
-					itemproperty.ref=announcement.id " .
-				"AND itemproperty.tool='".TOOL_ANNOUNCEMENT."' " .
-				"AND itemproperty.visibility<>2 " .
-				"ORDER BY display_order $sortDirection";
-		$result = Database::query($my_sql);
+
+		$sql = "SELECT announcement.id, announcement.display_order
+                FROM $tbl_announcement announcement,
+				$tbl_item_property itemproperty
+				WHERE
+				    announcement.c_id =  $course_id AND
+				    itemproperty.c_id =  $course_id AND
+					itemproperty.ref=announcement.id AND
+                    itemproperty.tool='".TOOL_ANNOUNCEMENT."'  AND
+                    itemproperty.visibility<>2
+                ORDER BY display_order $sortDirection";
+		$result = Database::query($sql);
 
 		while (list ($announcementId, $announcementOrder) = Database::fetch_row($result)) {
 			// STEP 2 : FOUND THE NEXT ANNOUNCEMENT ID AND ORDER.
@@ -336,13 +346,10 @@ if (api_is_allowed_to_edit(false,true) OR (api_get_course_setting('allow_user_ed
 		$message = get_lang('AnnouncementMoved');
 	}
 
-	/*
-		Submit announcement
-	*/
-
-	$emailTitle=(!empty($_POST['emailTitle'])?$safe_emailTitle:'');
-	$newContent=(!empty($_POST['newContent'])?$safe_newContent:'');
+	/* Submit announcement */
 
+	$emailTitle = (!empty($_POST['emailTitle'])?$safe_emailTitle:'');
+	$newContent = (!empty($_POST['newContent'])?$safe_newContent:'');
 	$submitAnnouncement = isset($_POST['submitAnnouncement'])?$_POST['submitAnnouncement']:0;
 
 	$id = 0;
@@ -361,7 +368,15 @@ if (api_is_allowed_to_edit(false,true) OR (api_get_course_setting('allow_user_ed
 			if ($ctok == $_POST['sec_token']) {
 				$file_comment = $_POST['file_comment'];
 				$file = $_FILES['user_upload'];
-				AnnouncementManager::edit_announcement($id,	$emailTitle, $newContent, $_POST['selectedform'], $file, $file_comment, $sendToUsersInSession);
+                AnnouncementManager::edit_announcement(
+                    $id,
+                    $emailTitle,
+                    $newContent,
+                    $_POST['selectedform'],
+                    $file,
+                    $file_comment,
+                    $sendToUsersInSession
+                );
 
                 /*		MAIL FUNCTION	*/
                 if ($_POST['email_ann'] && empty($_POST['onlyThoseMails'])) {
@@ -375,15 +390,30 @@ if (api_is_allowed_to_edit(false,true) OR (api_get_course_setting('allow_user_ed
                 $file = $_FILES['user_upload'];
                 $file_comment = $_POST['file_comment'];
                 if (!empty($group_id)) {
-                    $insert_id = AnnouncementManager::add_group_announcement($safe_emailTitle, $safe_newContent, array('GROUP:'.$group_id), $_POST['selectedform'], $file, $file_comment, $sendToUsersInSession);
+                    $insert_id = AnnouncementManager::add_group_announcement(
+                        $safe_emailTitle,
+                        $safe_newContent,
+                        array('GROUP:' . $group_id),
+                        $_POST['selectedform'],
+                        $file,
+                        $file_comment,
+                        $sendToUsersInSession
+                    );
                 } else {
-                    $insert_id = AnnouncementManager::add_announcement($safe_emailTitle, $safe_newContent, $_POST['selectedform'], $file, $file_comment, $sendToUsersInSession);
+                    $insert_id = AnnouncementManager::add_announcement(
+                        $safe_emailTitle,
+                        $safe_newContent,
+                        $_POST['selectedform'],
+                        $file,
+                        $file_comment,
+                        $sendToUsersInSession
+                    );
                 }
                 //store_resources($_SESSION['source_type'],$insert_id);
                 $_SESSION['select_groupusers']="hide";
                 $message = get_lang('AnnouncementAdded');
 
-                /*		MAIL FUNCTION	*/
+                /* MAIL FUNCTION */
                 if ($_POST['email_ann'] && empty($_POST['onlyThoseMails'])) {
                     AnnouncementManager::send_email($insert_id, $sendToUsersInSession);
                 }

+ 6 - 13
main/attendance/attendance_controller.php

@@ -389,11 +389,11 @@
 
     /**
      * It's used to print attendance sheet
-     * @param string action
-     * @param int    attendance id
+     * @param string $action
+     * @param int    $attendance_id
      */
-    public function attendance_sheet_export_to_pdf($action, $attendance_id, $student_id = 0, $course_id = '') {
-
+    public function attendance_sheet_export_to_pdf($action, $attendance_id, $student_id = 0, $course_id = '')
+    {
         $attendance = new Attendance();
         $courseInfo = CourseManager::get_course_information($course_id);
 
@@ -429,12 +429,9 @@
             $data_array['user_id'] = $user_id;
         }
 
-
-
         $data_array['next_attendance_calendar_id'] = $attendance->get_next_attendance_calendar_id($attendance_id);
 
-        //Set headers pdf
-
+        // Set headers pdf.
         $courseCategory = CourseManager::get_course_category($courseInfo['category_code']);
         $teacherInfo    = CourseManager::get_teacher_list_from_course_code($courseInfo['code']);
         $teacherName = null;
@@ -444,21 +441,17 @@
                 $teacherName.= $dados['firstname']." ".$dados['lastname'];
         }
 
-        // Get data table - Marco - ordenacao fixa - just fullname
+        // Get data table
 
         $data_table = array();
 
         $head_table = array('#', get_lang('Name'));
         foreach ($data_array['attendant_calendar'] as $class_day) {
-            //$head_table[] = api_format_date($class_day['date_time'], DATE_FORMAT_SHORT).' <br />'.api_format_date($class_day['date_time'], TIME_NO_SEC_FORMAT);
             $head_table[] = api_format_date($class_day['date_time'], DATE_FORMAT_NUMBER_NO_YEAR);
         }
         $data_table[] = $head_table;
-
         $dataClass = array();
-
         $max_dates_per_page = 10;
-
         $data_attendant_calendar = $data_array['attendant_calendar'];
         $data_users_presence = $data_array['users_presence'];
         $count = 1;

+ 0 - 1
main/attendance/index.php

@@ -1,5 +1,4 @@
 <?php
-
 /* For licensing terms, see /license.txt */
 
 /**

+ 76 - 78
main/auth/courses.php

@@ -27,33 +27,34 @@ require_once api_get_path(LIBRARY_PATH).'mail.lib.inc.php';
 if (api_get_setting('show_courses_descriptions_in_catalog') == 'true') {
     $htmlHeadXtra[] = '
     <script>
-    	$(document).ready(function() {
-	        $(\'.ajax\').live(\'click\', function() {
-	            var url     = this.href;
-	            var dialog  = $("#dialog");
-	            if ($("#dialog").length == 0) {
-	                dialog  = $(\'<div id="dialog" style="display:hidden"></div>\').appendTo(\'body\');
-	            }
-
-	            // load remote content
-	            dialog.load(
-	                    url,
-	                    {},
-	                    function(responseText, textStatus, XMLHttpRequest) {
-	                        dialog.dialog({
-	                            modal	: true,
-	            				width	: 540,
-	            				height	: 400,
-	                        });
-				});
-	            //prevent the browser to follow the link
-	            return false;
-	        });
+    $(document).ready(function() {
+        $(\'.ajax\').live(\'click\', function() {
+            var url     = this.href;
+            var dialog  = $("#dialog");
+            if ($("#dialog").length == 0) {
+                dialog  = $(\'<div id="dialog" style="display:hidden"></div>\').appendTo(\'body\');
+            }
+
+            // load remote content
+            dialog.load(
+                url,
+                {},
+                function(responseText, textStatus, XMLHttpRequest) {
+                    dialog.dialog({
+                    modal : true,
+                    width : 540,
+                    height : 400
+                });
+            });
+            //prevent the browser to follow the link
+            return false;
         });
-
+    });
     </script>';
 }
 
+// Get Limit data
+$limit = getLimitArray();
 
 // Section for the tabs.
 $this_section = SECTION_COURSES;
@@ -76,42 +77,34 @@ if (api_is_platform_admin() || api_is_course_admin() || api_is_allowed_to_create
 }
 
 // filter actions
-$actions = array('sortmycourses', 'createcoursecategory', 'subscribe', 'deletecoursecategory', 'display_courses', 'display_random_courses', 'subscribe_user_with_password');
-$action = 'display_random_courses';
-$nameTools = get_lang('SortMyCourses');
-
-if (isset($_GET['action']) && in_array($_GET['action'],$actions)) {
-	$action = $_GET['action'];
-}
-
-if ($action == 'createcoursecategory') {
-	$nameTools = get_lang('CreateCourseCategory');
-}
-if ($action == 'subscribe') {
-	$nameTools = get_lang('CourseManagement');
-}
-
-if ($action == 'subscribe_user_with_password') {
-	$nameTools = get_lang('CourseManagement');
-}
-
-if ($action == 'display_random_courses' || $action == 'display_courses' ) {
-	$nameTools = get_lang('CourseManagement');
+$actions = array(
+    'sortmycourses',
+    'createcoursecategory',
+    'subscribe',
+    'deletecoursecategory',
+    'display_courses',
+    'display_random_courses',
+    'subscribe_user_with_password',
+    'display_sessions'
+);
+
+$action = CoursesAndSessionsCatalog::is(CATALOG_SESSIONS) ? 'display_sessions' : 'display_random_courses';
+if (isset($_GET['action']) && in_array($_GET['action'], $actions)) {
+    $action = Security::remove_XSS($_GET['action']);
+} else {
+    // Nothing to do
 }
 
-// Breadcrumbs.
-$interbreadcrumb[] = array('url' => api_get_path(WEB_PATH).'user_portal.php', 'name' => get_lang('MyCourses'));
-
+$nameTools = getCourseCatalogNameTools($action);
 if (empty($nameTools)) {
-	$nameTools = get_lang('CourseManagement');
+    $nameTools = get_lang('CourseManagement');
 } else {
-
-	if (!in_array($action, array('sortmycourses', 'createcoursecategory', 'display_random_courses', 'display_courses', 'subscribe'))) {
-		$interbreadcrumb[] = array('url' => api_get_path(WEB_CODE_PATH).'auth/courses.php', 'name' => get_lang('CourseManagement'));
-	}
-	if ($action == 'createcoursecategory') {
-		$interbreadcrumb[] = array('url' => api_get_path(WEB_CODE_PATH).'auth/courses.php?action=sortmycourses', 'name' => get_lang('SortMyCourses'));
-	}
+    if (!in_array($action, array('sortmycourses', 'createcoursecategory', 'display_random_courses', 'display_courses', 'subscribe'))) {
+        $interbreadcrumb[] = array('url' => api_get_path(WEB_CODE_PATH).'auth/courses.php', 'name' => get_lang('CourseManagement'));
+    }
+    if ($action == 'createcoursecategory') {
+        $interbreadcrumb[] = array('url' => api_get_path(WEB_CODE_PATH).'auth/courses.php?action=sortmycourses', 'name' => get_lang('SortMyCourses'));
+    }
     $interbreadcrumb[] = array('url' => '#', 'name' => $nameTools);
 }
 
@@ -120,16 +113,16 @@ $courses_controller = new CoursesController();
 
 // We are moving a course or category of the user up/down the list (=Sort My Courses).
 if (isset($_GET['move'])) {
-	if (isset($_GET['course'])) {
-		if ($ctok == $_GET['sec_token']) {
+    if (isset($_GET['course'])) {
+        if ($ctok == $_GET['sec_token']) {
             $courses_controller->move_course($_GET['move'], $_GET['course'], $_GET['category']);
-		}
-	}
-	if (isset($_GET['category']) && !$_GET['course']) {
-		if ($ctok == $_GET['sec_token']) {
+        }
+    }
+    if (isset($_GET['category']) && !$_GET['course']) {
+        if ($ctok == $_GET['sec_token']) {
             $courses_controller->move_category($_GET['move'], $_GET['category']);
-		}
-	}
+        }
+    }
 }
 
 // We are moving the course of the user to a different user defined course category (=Sort My Courses).
@@ -141,31 +134,31 @@ if (isset($_POST['submit_change_course_category'])) {
 
 // We edit course category
 if (isset($_POST['submit_edit_course_category']) && isset($_POST['title_course_category']) && strlen(trim($_POST['title_course_category'])) > 0) {
-	if ($ctok == $_POST['sec_token']) {
-		$courses_controller->edit_course_category($_POST['title_course_category'], $_POST['edit_course_category']);
-	}
+    if ($ctok == $_POST['sec_token']) {
+        $courses_controller->edit_course_category($_POST['title_course_category'], $_POST['edit_course_category']);
+    }
 }
 
 // we are deleting a course category
 if ($action == 'deletecoursecategory' && isset($_GET['id'])) {
-	if ($ctok == $_GET['sec_token']) {
-		$get_id_cat = intval($_GET['id']);
-		$courses_controller->delete_course_category($get_id_cat);
-	}
+    if ($ctok == $_GET['sec_token']) {
+        $get_id_cat = intval($_GET['id']);
+        $courses_controller->delete_course_category($get_id_cat);
+    }
 }
 
 // We are creating a new user defined course category (= Create Course Category).
 if (isset($_POST['create_course_category']) && isset($_POST['title_course_category']) && strlen(trim($_POST['title_course_category'])) > 0) {
-	if ($ctok == $_POST['sec_token']) {
+    if ($ctok == $_POST['sec_token']) {
         $courses_controller->add_course_category($_POST['title_course_category']);
-	}
+    }
 }
 
 // search courses
 if (isset($_REQUEST['search_course'])) {
     //echo "<p><strong>".get_lang('SearchResultsFor')." ".api_htmlentities($_POST['search_term'], ENT_QUOTES, api_get_system_encoding())."</strong><br />";
     if ($ctok == $_REQUEST['sec_token']) {
-        $courses_controller->search_courses($_REQUEST['search_term']);
+        $courses_controller->search_courses($_REQUEST['search_term'], null, null, null, $limit);
     }
 }
 
@@ -177,17 +170,17 @@ if (isset($_REQUEST['subscribe_course'])) {
 }
 // We are unsubscribing from a course (=Unsubscribe from course).
 if (isset($_GET['unsubscribe'])) {
-	if ($ctok == $_GET['sec_token']) {
+    if ($ctok == $_GET['sec_token']) {
         $courses_controller->unsubscribe_user_from_course($_GET['unsubscribe'], $_GET['search_term'], $_GET['category_code']);
             //$message = remove_user_from_course($_user['user_id'], $_POST['unsubscribe']);
-	}
+    }
 }
 // We are unsubscribing from a course (=Unsubscribe from course).
 if (isset($_POST['unsubscribe'])) {
-	if ($ctok == $_POST['sec_token']) {
+    if ($ctok == $_POST['sec_token']) {
         $courses_controller->unsubscribe_user_from_course($_POST['unsubscribe']);
             //$message = remove_user_from_course($_user['user_id'], $_POST['unsubscribe']);
-	}
+    }
 }
 
 switch ($action) {
@@ -205,6 +198,8 @@ switch ($action) {
         $courses_controller->courses_list($action);
         break;
     case 'subscribe':
+        $courses_controller->courses_categories($action, $_GET['category_code'], null, null, null, $limit);
+        break;
     case 'display_random_courses':
         if ($user_can_view_page) {
             $courses_controller->courses_categories($action);
@@ -213,6 +208,9 @@ switch ($action) {
         }
         break;
     case 'display_courses':
-        $courses_controller->courses_categories($action, $_GET['category_code']);
+        $courses_controller->courses_categories($action, $_GET['category_code'], null, null, null, $limit);
+        break;
+    case 'display_sessions':
+        $courses_controller->sessionsList($action, $nameTools, $limit);
         break;
 }

+ 321 - 35
main/auth/courses_controller.php

@@ -4,13 +4,11 @@
  * This file contains class used like controller, it should be included inside a dispatcher file (e.g: index.php)
  * @author Christian Fasanando <christian1827@gmail.com> - BeezNest
  * @package chamilo.auth
+ *
+ * Class CoursesController
  */
-/**
- * Code
- * @package chamilo.auth
- */
-class CoursesController { // extends Controller {
-
+class CoursesController
+{
     private $toolname;
     private $view;
     private $model;
@@ -18,7 +16,8 @@ class CoursesController { // extends Controller {
     /**
      * Constructor
      */
-    public function __construct() {
+    public function __construct()
+    {
         $this->toolname = 'auth';
         $actived_theme_path = api_get_template();
         $this->view = new View($this->toolname, $actived_theme_path);
@@ -31,7 +30,8 @@ class CoursesController { // extends Controller {
      * @param string   	action
      * @param string    confirmation message(optional)
      */
-    public function courses_list($action, $message = '') {
+    public function courses_list($action, $message = '')
+    {
         $data = array();
         $user_id = api_get_user_id();
 
@@ -39,9 +39,7 @@ class CoursesController { // extends Controller {
         $data['user_course_categories']   = $this->model->get_user_course_categories();
         $data['courses_in_category']      = $this->model->get_courses_in_category();
         $data['all_user_categories']      = $this->model->get_user_course_categories();
-
         $data['action'] = $action;
-
         $data['message'] = $message;
 
         // render to the view
@@ -59,7 +57,8 @@ class CoursesController { // extends Controller {
      * @param string    confirmation message(optional)
      * @param string    error message(optional)
      */
-    public function categories_list($action, $message='', $error='') {
+    public function categories_list($action, $message='', $error='')
+    {
         $data = array();
         $data['user_course_categories'] = $this->model->get_user_course_categories();
         $data['action'] = $action;
@@ -76,20 +75,34 @@ class CoursesController { // extends Controller {
     /**
      * It's used for listing courses with categories,
      * render to courses_categories view
-     * @param string   	action
-     * @param string    Category code (optional)
+     * @param $action
+     * @param string $category_code
+     * @param string $message
+     * @param string $error
+     * @param string $content
+     * @param array $limit will be used if $random_value is not set.
+     * This array should contains 'start' and 'length' keys
+     * @internal param \action $string
+     * @internal param \Category $string code (optional)
      */
-    public function courses_categories($action, $category_code = null, $message = '', $error = '', $content = null) {
+    public function courses_categories($action, $category_code = null, $message = '', $error = '', $content = null, $limit = array())
+    {
         $data = array();
         $browse_course_categories = $this->model->browse_course_categories();
 
+        global $_configuration;
+
+        $data['countCoursesInCategory'] = $this->model->count_courses_in_category($category_code);
         if ($action == 'display_random_courses') {
+            // Random value is used instead limit filter
             $data['browse_courses_in_category'] = $this->model->browse_courses_in_category(null, 10);
+            $data['countCoursesInCategory'] = count($data['browse_courses_in_category']);
         } else {
             if (!isset($category_code)) {
                 $category_code = $browse_course_categories[0][1]['code']; // by default first category
             }
-            $data['browse_courses_in_category'] = $this->model->browse_courses_in_category($category_code);
+            $limit = isset($limit) ? $limit : getLimitArray();
+            $data['browse_courses_in_category'] = $this->model->browse_courses_in_category($category_code, null, $limit);
         }
 
         $data['browse_course_categories'] = $browse_course_categories;
@@ -119,6 +132,12 @@ class CoursesController { // extends Controller {
         $data['message']          = $message;
         $data['content']          = $content;
         $data['error']            = $error;
+        
+        $data['catalogShowCoursesSessions'] = 0;
+        
+        if (isset($_configuration['catalog_show_courses_sessions'])) {
+            $data['catalogShowCoursesSessions'] = $_configuration['catalog_show_courses_sessions'];
+        }
 
         // render to the view
         $this->view->set_data($data);
@@ -128,19 +147,20 @@ class CoursesController { // extends Controller {
     }
 
     /**
-     *
      * @param string $search_term
      * @param string $message
      * @param string $error
      * @param string $content
+     * @param $limit
      */
-    public function search_courses($search_term, $message = '', $error = '', $content = null) {
-
+    public function search_courses($search_term, $message = '', $error = '', $content = null, $limit = array())
+    {
         $data = array();
+        $limit = !empty($limit) ? $limit : getLimitArray();
 
         $browse_course_categories = $this->model->browse_course_categories();
-
-        $data['browse_courses_in_category'] = $this->model->search_courses($search_term);
+        $data['countCoursesInCategory'] = $this->model->count_courses_in_category('ALL', $search_term);
+        $data['browse_courses_in_category'] = $this->model->search_courses($search_term, $limit);
         $data['browse_course_categories']   = $browse_course_categories;
 
         $data['search_term'] = Security::remove_XSS($search_term); //filter before showing in template
@@ -204,11 +224,15 @@ class CoursesController { // extends Controller {
      * render to listing view
      * @param   string  Category title
      */
-    public function add_course_category($category_title) {
+    public function add_course_category($category_title)
+    {
         $result = $this->model->store_course_category($category_title);
         $message = '';
-        if ($result) { $message = get_lang("CourseCategoryStored"); }
-        else { $error = get_lang('ACourseCategoryWithThisNameAlreadyExists');}
+        if ($result) {
+            $message = get_lang("CourseCategoryStored");
+        } else {
+            $error = get_lang('ACourseCategoryWithThisNameAlreadyExists');
+        }
         $action = 'sortmycourses';
         $this->courses_list($action, $message);
     }
@@ -219,10 +243,13 @@ class CoursesController { // extends Controller {
      * @param string    Course code
      * @param int    Category id
      */
-    public function change_course_category($course_code, $category_id) {
+    public function change_course_category($course_code, $category_id)
+    {
         $result = $this->model->store_changecoursecategory($course_code, $category_id);
         $message = '';
-        if ($result) { $message = get_lang('EditCourseCategorySucces'); }
+        if ($result) {
+            $message = get_lang('EditCourseCategorySucces');
+        }
         $action = 'sortmycourses';
         $this->courses_list($action, $message);
     }
@@ -234,10 +261,13 @@ class CoursesController { // extends Controller {
      * @param string    Course code
      * @param int    Category id
      */
-    public function move_course($move, $course_code, $category_id) {
+    public function move_course($move, $course_code, $category_id)
+    {
         $result = $this->model->move_course($move, $course_code, $category_id);
         $message = '';
-        if ($result) { $message = get_lang('CourseSortingDone'); }
+        if ($result) {
+            $message = get_lang('CourseSortingDone');
+        }
         $action = 'sortmycourses';
         $this->courses_list($action, $message);
     }
@@ -248,10 +278,13 @@ class CoursesController { // extends Controller {
      * @param string    move to up or down
      * @param int    Category id
      */
-    public function move_category($move, $category_id) {
+    public function move_category($move, $category_id)
+    {
         $result = $this->model->move_category($move, $category_id);
         $message = '';
-        if ($result) { $message = get_lang('CategorySortingDone'); }
+        if ($result) {
+            $message = get_lang('CategorySortingDone');
+        }
         $action = 'sortmycourses';
         $this->courses_list($action, $message);
     }
@@ -262,10 +295,13 @@ class CoursesController { // extends Controller {
      * @param string Category title
      * @param int    Category id
      */
-    public function edit_course_category($title, $category) {
+    public function edit_course_category($title, $category)
+    {
         $result = $this->model->store_edit_course_category($title, $category);
         $message = '';
-        if ($result) { $message = get_lang('CourseCategoryEditStored'); }
+        if ($result) {
+            $message = get_lang('CourseCategoryEditStored');
+        }
         $action = 'sortmycourses';
         $this->courses_list($action, $message);
     }
@@ -275,10 +311,13 @@ class CoursesController { // extends Controller {
      * render to listing view
      * @param int    Category id
      */
-    public function delete_course_category($category_id) {
+    public function delete_course_category($category_id)
+    {
         $result = $this->model->delete_course_category($category_id);
         $message = '';
-        if ($result) { $message = get_lang('CourseCategoryDeleted'); }
+        if ($result) {
+            $message = get_lang('CourseCategoryDeleted');
+        }
         $action = 'sortmycourses';
         $this->courses_list($action, $message);
     }
@@ -288,10 +327,13 @@ class CoursesController { // extends Controller {
      * render to listing view
      * @param string    Course code
      */
-    public function unsubscribe_user_from_course($course_code, $search_term = null, $category_code = null) {
+    public function unsubscribe_user_from_course($course_code, $search_term = null, $category_code = null)
+    {
         $result = $this->model->remove_user_from_course($course_code);
         $message = '';
-        if ($result) { $message = get_lang('YouAreNowUnsubscribed'); }
+        if ($result) {
+            $message = get_lang('YouAreNowUnsubscribed');
+        }
         $action = 'sortmycourses';
         if (!empty($search_term)) {
             $this->search_courses($search_term, $message, $error);
@@ -299,4 +341,248 @@ class CoursesController { // extends Controller {
             $this->courses_categories('subcribe', $category_code, $message, $error);
         }
     }
+
+    /**
+     * Get the html block for courses categories
+     * @param string $code Current category code
+     * @param boolean $hiddenLinks Whether hidden links
+     * @param array $limit
+     * @return string The HTML block
+     */
+    public function getCoursesCategoriesBlock($code = null, $hiddenLinks = false, $limit = null)
+    {
+        $categories = $this->model->browse_course_categories();
+
+        $html = '';
+
+        if (!empty($categories)) {
+            $action = 'display_courses';
+            foreach ($categories[0] as $category) {
+                $categoryName = $category['name'];
+                $categoryCode = $category['code'];
+                $categoryCourses = $category['count_courses'];
+
+                $html .= '<li>';
+
+                if ($code == $categoryCode) {
+                    $html .= '<strong>';
+                    $html .= "$categoryName ($categoryCourses)";
+                    $html .= '</strong>';
+                } else {
+                    if (!empty($categoryCourses)) {
+                        $html .= '<a href="' . getCourseCategoryUrl(
+                                1,
+                                $limit['length'],
+                                $categoryCode,
+                                $hiddenLinks,
+                                $action
+                            ) . '">';
+                        $html .= "$categoryName ($categoryCourses)";
+                        $html .= '</a>';
+                    } else {
+                        $html .= "$categoryName ($categoryCourses)";
+                    }
+                }
+
+                if (!empty($categories[$categoryCode])) {
+                    $html .= '<ul class="nav nav-list">';
+
+                    foreach ($categories[$categoryCode] as $subCategory1) {
+                        $subCategory1Name = $subCategory1['name'];
+                        $subCategory1Code = $subCategory1['code'];
+                        $subCategory1Courses = $subCategory1['count_courses'];
+
+                        $html .= '<li>';
+
+                        if ($code == $subCategory1Code) {
+                            $html .= "<strong>$subCategory1Name ($subCategory1Courses)</strong>";
+                        } else {
+                            $html .= '<a href="' . getCourseCategoryUrl(
+                                    1,
+                                    $limit['length'],
+                                    $categoryCode,
+                                    $hiddenLinks,
+                                    $action
+                                ) . '">';
+                            $html .= "$subCategory1Name ($subCategory1Courses)";
+                            $html .= '</a>';
+                        }
+
+                        if (!empty($categories[$subCategory1Code])) {
+                            $html .= '<ul class="nav nav-list">';
+
+                            foreach ($categories[$subCategory1Code] as $subCategory2) {
+                                $subCategory2Name = $subCategory2['name'];
+                                $subCategory2Code = $subCategory2['code'];
+                                $subCategory2Courses = $subCategory2['count_courses'];
+
+                                $html .= '<li>';
+
+                                if ($code == $subCategory2Code) {
+                                    $html .= "<strong>$subCategory2Name ($subCategory2Courses)</strong>";
+                                } else {
+                                    $html .= '<a href="' . getCourseCategoryUrl(
+                                            1,
+                                            $limit['length'],
+                                            $categoryCode,
+                                            $hiddenLinks,
+                                            $action
+                                        ) . '">';
+                                    $html .= "$subCategory2Name ($subCategory2Courses)";
+                                    $html .= '</a>';
+                                }
+
+                                if (!empty($categories[$subCategory2Code])) {
+                                    $html .= '<ul class="nav nav-list">';
+
+                                    foreach ($categories[$subCategory2Code] as $subCategory3) {
+                                        $subCategory3Name = $subCategory3['name'];
+                                        $subCategory3Code = $subCategory3['code'];
+                                        $subCategory3Courses = $subCategory3['count_courses'];
+
+                                        $html .= '<li>';
+
+                                        if ($code == $subCategory3Code) {
+                                            $html .= "<strong>$subCategory3Name ($subCategory3Courses)</strong>";
+                                        } else {
+                                            $html .= '<a href="' . getCourseCategoryUrl(
+                                                    1,
+                                                    $limit['length'],
+                                                    $categoryCode,
+                                                    $hiddenLinks,
+                                                    $action
+                                                ) . '">';
+                                            $html .= "$subCategory3Name ($subCategory3Courses)";
+                                            $html .= '</a>';
+                                        }
+
+                                        $html .= '</li>';
+                                    }
+
+                                    $html .= '</ul>';
+                                }
+
+                                $html .= '</li>';
+                            }
+
+                            $html .= '</ul>';
+                        }
+
+                        $html .= '</li>';
+                    }
+
+                    $html .= '</ul>';
+                }
+
+                $html .= '</li>';
+            }
+        }
+
+        return $html;
+    }
+
+    /**
+     * Get a HTML button for subscribe to session
+     * @param string $sessionName The session name
+     * @return string The button
+     */
+    public function getRegisterInSessionButton($sessionName)
+    {
+        $sessionName = urlencode($sessionName);
+
+        $url = api_get_path(WEB_PATH) . "main/inc/email_editor.php?action=subscribe_me_to_session&session=$sessionName";
+
+        return Display::url(get_lang('Subscribe'), $url, array(
+                    'class' => 'btn btn-large btn-primary',
+        ));
+    }
+
+    /**
+     * Generate a label if the user has been  registered in session
+     * @return string The label
+     */
+    public function getAlreadyRegisterInSessionLabel()
+    {
+        $icon = Display::return_icon('students.gif', get_lang('Student'));
+
+        return Display::label($icon . ' ' . get_lang("AlreadyRegisteredToSession"), "info");
+    }
+
+    /**
+     * Get a icon for a session
+     * @param string $sessionName The session name
+     * @return string The icon
+     */
+    public function getSessionIcon($sessionName)
+    {
+        return Display::return_icon('window_list.png', $sessionName, null, ICON_SIZE_BIG);
+    }
+
+    /**
+     * Return Session Catalogue rendered view
+     * @param string $action
+     * @param string $nameTools
+     * @param array $limit
+     */
+    public function sessionsList($action, $nameTools, $limit = array())
+    {
+        $date = isset($_POST['date']) ? $_POST['date'] : date('Y-m-d');
+        $hiddenLinks = isset($_GET['hidden_links']) ? intval($_GET['hidden_links']) == 1 : false;
+
+        $limit = isset($limit) ? $limit : getLimitArray();
+
+        $countSessions = $this->model->countSessions($date);
+        $sessions = $this->model->browseSessions($date, $limit);
+
+        $pageTotal = intval(ceil(intval($countSessions) / $limit['length']));
+        // Do NOT show pagination if only one page or less
+        $cataloguePagination = $pageTotal > 1 ?
+            getCataloguePagination($limit['current'], $limit['length'], $pageTotal) :
+            '';
+        $sessionsBlocks = array();
+
+        // Get session list catalogue URL
+        $sessionUrl = getCourseCategoryUrl(1, $limit['length'], null, 0, 'display_sessions');
+        // Get session search catalogue URL
+        $courseUrl = getCourseCategoryUrl(1, $limit['length'], null, 0, 'subscribe');
+
+        foreach ($sessions as $session) {
+            $sessionsBlocks[] = array(
+                'id' => $session['id'],
+                'name' => $session['name'],
+                'nbr_courses' => $session['nbr_courses'],
+                'nbr_users' => $session['nbr_users'],
+                'coach_name' => $session['coach_name'],
+                'is_subscribed' => $session['is_subscribed'],
+                'icon' => $this->getSessionIcon($session['name']),
+                'date' => SessionManager::getSessionFormattedDate($session),
+                'subscribe_button' => $this->getRegisterInSessionButton($session['name'])
+            );
+        }
+
+        $tpl = new Template();
+        $tpl->assign('action', $action);
+        $tpl->assign('showCourses', CoursesAndSessionsCatalog::showCourses());
+        $tpl->assign('showSessions', CoursesAndSessionsCatalog::showSessions());
+        $tpl->assign('api_get_self', api_get_self());
+        $tpl->assign('sessionUrl', $sessionUrl);
+        $tpl->assign('courseUrl', $courseUrl);
+        $tpl->assign('nameTools', $nameTools);
+
+        $tpl->assign('coursesCategoriesList', $this->getCoursesCategoriesBlock(null, false, $limit));
+        $tpl->assign('cataloguePagination', $cataloguePagination);
+
+        $tpl->assign('hiddenLinks', $hiddenLinks);
+        $tpl->assign('searchToken', Security::get_token());
+
+        $tpl->assign('searchDate', $date);
+        $tpl->assign('web_session_courses_ajax_url', api_get_path(WEB_AJAX_PATH) . 'course.ajax.php');
+        $tpl->assign('sessions_blocks', $sessionsBlocks);
+        $tpl->assign('already_subscribed_label', $this->getAlreadyRegisterInSessionLabel());
+
+        $contentTemplate = $tpl->get_template('auth/sessions_catalog.tpl');
+
+        $tpl->display($contentTemplate);
+    }
+
 }

+ 2 - 3
main/auth/gotocourse.php

@@ -9,10 +9,9 @@
  *
  */
 
-require('../inc/global.inc.php');
+require '../inc/global.inc.php';
 require_once(api_get_path(SYS_PATH).'main/auth/cas/authcas.php');
-
-
+$msg = null;
 if (isset($_GET['firstpage'])) {
     $firstpage = $_GET['firstpage'];
 

+ 44 - 44
main/auth/inscription.php

@@ -2,8 +2,8 @@
 /* For licensing terms, see /license.txt */
 
 /**
- *	This script displays a form for registering new users.
- *	@package	 chamilo.auth
+ *  This script displays a form for registering new users.
+ *  @package    chamilo.auth
  */
 
 use \ChamiloSession as Session;
@@ -51,11 +51,11 @@ if (!empty($course_code_redirect)) {
 if ($user_already_registered_show_terms == false) {
 
     if (api_is_western_name_order()) {
-        //	FIRST NAME and LAST NAME
+        // FIRST NAME and LAST NAME
         $form->addElement('text', 'firstname', get_lang('FirstName'), array('size' => 40));
         $form->addElement('text', 'lastname', get_lang('LastName'), array('size' => 40));
     } else {
-        //	LAST NAME and FIRST NAME
+        // LAST NAME and FIRST NAME
         $form->addElement('text', 'lastname', get_lang('LastName'), array('size' => 40));
         $form->addElement('text', 'firstname', get_lang('FirstName'), array('size' => 40));
     }
@@ -63,7 +63,7 @@ if ($user_already_registered_show_terms == false) {
     $form->addRule('lastname',  get_lang('ThisFieldIsRequired'), 'required');
     $form->addRule('firstname', get_lang('ThisFieldIsRequired'), 'required');
 
-    //	EMAIL
+    // EMAIL
     $form->addElement('text', 'email', get_lang('Email'), array('size' => 40));
     if (api_get_setting('registration', 'email') == 'true') {
         $form->addRule('email', get_lang('ThisFieldIsRequired'), 'required');
@@ -83,14 +83,14 @@ if ($user_already_registered_show_terms == false) {
         $form->addElement('text', 'openid', get_lang('OpenIDURL'), array('size' => 40));
     }
     // Enabled by Ivan Tcholakov, 06-APR-2009. CONFVAL_ASK_FOR_OFFICIAL_CODE = false by default.
-    //	OFFICIAL CODE
+    // OFFICIAL CODE
     if (CONFVAL_ASK_FOR_OFFICIAL_CODE) {
         $form->addElement('text', 'official_code', get_lang('OfficialCode'), array('size' => 40));
         if (api_get_setting('registration', 'officialcode') == 'true')
             $form->addRule('official_code', get_lang('ThisFieldIsRequired'), 'required');
     }
 
-    //	USERNAME
+    // USERNAME
     if (api_get_setting('login_is_email') != 'true') {
         $form->addElement('text', 'username', get_lang('UserName'), array('id' => 'username', 'size' => USERNAME_MAX_LENGTH));
         $form->applyFilter('username','trim');
@@ -100,7 +100,7 @@ if ($user_already_registered_show_terms == false) {
         $form->addRule('username', get_lang('UserTaken'), 'username_available');
     }
 
-    //	PASSWORD
+    // PASSWORD
     $form->addElement('password', 'pass1', get_lang('Pass'), array('id' => 'pass1', 'size' => 20, 'autocomplete' => 'off'));
 
     if (isset($_configuration['allow_strength_pass_checker']) && $_configuration['allow_strength_pass_checker']) {
@@ -115,7 +115,7 @@ if ($user_already_registered_show_terms == false) {
     if (CHECK_PASS_EASY_TO_FIND)
         $form->addRule('password1', get_lang('PassTooEasy').': '.api_generate_password(), 'callback', 'api_check_password');
 
-    //	PHONE
+    // PHONE
     $form->addElement('text', 'phone', get_lang('Phone'), array('size' => 20));
     if (api_get_setting('registration', 'phone') == 'true')
         $form->addRule('phone', get_lang('ThisFieldIsRequired'), 'required');
@@ -127,11 +127,11 @@ if ($user_already_registered_show_terms == false) {
         $form->addRule('picture', get_lang('OnlyImagesAllowed').' ('.implode(',', $allowed_picture_types).')', 'filetype', $allowed_picture_types);
     }*/
 
-    //	LANGUAGE
+    // LANGUAGE
     if (api_get_setting('registration', 'language') == 'true') {
         $form->addElement('select_language', 'language', get_lang('Language'));
     }
-    //	STUDENT/TEACHER
+    // STUDENT/TEACHER
     if (api_get_setting('allow_registration_as_teacher') != 'false') {
         $form->addElement('radio', 'status', get_lang('Profile'), get_lang('RegStudent'), STUDENT);
         $form->addElement('radio', 'status', null, get_lang('RegAdmin'), COURSEMANAGER);
@@ -165,7 +165,7 @@ if ($user_already_registered_show_terms == false) {
         $form->addRule('captcha', get_lang('TheTextYouEnteredDoesNotMatchThePicture'), 'CAPTCHA', $captcha_question);
     }
 
-    //	EXTENDED FIELDS
+    // EXTENDED FIELDS
     if (api_get_setting('extended_profile') == 'true' && api_get_setting('extendedprofile_registration', 'mycomptetences') == 'true') {
         $form->add_html_editor('competences', get_lang('MyCompetences'), false, false, array('ToolbarSet' => 'register', 'Width' => '100%', 'Height' => '130'));
     }
@@ -358,6 +358,23 @@ if ($form->validate()) {
         $is_admin = UserManager::is_admin($user_id);
         Session::write('is_platformAdmin', $is_admin);
     } else {
+        // Moved here to include extra fields when creating a user. Formerly placed after user creation
+        // Register extra fields
+        $extras = array();
+        foreach ($values as $key => $value) {
+            if (substr($key, 0, 6) == 'extra_') {
+                //an extra field
+                $extras[substr($key, 6)] = $value;
+            } elseif (strpos($key, 'remove_extra_') !== false) {
+                $extra_value = Security::filter_filename(urldecode(key($value)));
+                // To remove from user_field_value and folder
+                UserManager::update_extra_field_value(
+                    $user_id,
+                    substr($key,13),
+                    $extra_value
+                );
+            }
+        }
 
         // Creates a new user
         $user_id = UserManager::create_user(
@@ -375,28 +392,11 @@ if ($form->validate()) {
             null,
             1,
             0,
-            null,
+            $extras,
             null,
             true
         );
 
-        // Register extra fields
-        $extras = array();
-        foreach ($values as $key => $value) {
-            if (substr($key, 0, 6) == 'extra_') {
-                //an extra field
-                $extras[substr($key, 6)] = $value;
-            } elseif (strpos($key, 'remove_extra_') !== false) {
-                $extra_value = Security::filter_filename(urldecode(key($value)));
-                // To remove from user_field_value and folder
-                UserManager::update_extra_field_value(
-                    $user_id,
-                    substr($key,13),
-                    $extra_value
-                );
-            }
-        }
-
         //update the extra fields
         $count_extra_field = count($extras);
         if ($count_extra_field > 0) {
@@ -485,26 +485,26 @@ if ($form->validate()) {
                 Database::query($sql);
 
                 // 2. Send mail to all platform admin
-                $emailsubject	 = get_lang('ApprovalForNewAccount',null,$values['language']).': '.$values['username'];
-                $emailbody		 = get_lang('ApprovalForNewAccount',null,$values['language'])."\n";
-                $emailbody		.= get_lang('UserName',null,$values['language']).': '.$values['username']."\n";
+                $emailsubject  = get_lang('ApprovalForNewAccount',null,$values['language']).': '.$values['username'];
+                $emailbody = get_lang('ApprovalForNewAccount',null,$values['language'])."\n";
+                $emailbody .= get_lang('UserName',null,$values['language']).': '.$values['username']."\n";
 
                 if (api_is_western_name_order()) {
-                    $emailbody	.= get_lang('FirstName',null,$values['language']).': '.$values['firstname']."\n";
-                    $emailbody	.= get_lang('LastName',null,$values['language']).': '.$values['lastname']."\n";
+                    $emailbody .= get_lang('FirstName',null,$values['language']).': '.$values['firstname']."\n";
+                    $emailbody .= get_lang('LastName',null,$values['language']).': '.$values['lastname']."\n";
                 } else {
-                    $emailbody	.= get_lang('LastName',null,$values['language']).': '.$values['lastname']."\n";
-                    $emailbody	.= get_lang('FirstName',null,$values['language']).': '.$values['firstname']."\n";
+                    $emailbody .= get_lang('LastName',null,$values['language']).': '.$values['lastname']."\n";
+                    $emailbody .= get_lang('FirstName',null,$values['language']).': '.$values['firstname']."\n";
                 }
-                $emailbody		.= get_lang('Email',null,$values['language']).': '.$values['email']."\n";
-                $emailbody		.= get_lang('Status',null,$values['language']).': '.$values['status']."\n\n";
+                $emailbody .= get_lang('Email',null,$values['language']).': '.$values['email']."\n";
+                $emailbody .= get_lang('Status',null,$values['language']).': '.$values['status']."\n\n";
 
                 $url_edit = Display::url(
                     api_get_path(WEB_CODE_PATH).'admin/user_edit.php?user_id='.$user_id,
                     api_get_path(WEB_CODE_PATH).'admin/user_edit.php?user_id='.$user_id
                 );
 
-                $emailbody		.= get_lang('ManageUser',null,$values['language']).": $url_edit";
+                $emailbody .= get_lang('ManageUser',null,$values['language']).": $url_edit";
 
                 $admins = UserManager::get_all_administrators();
                 foreach ($admins as $admin_info) {
@@ -551,10 +551,10 @@ if ($form->validate()) {
     /* SESSION REGISTERING */
     /* @todo move this in a function */
     $_user['firstName'] = stripslashes($values['firstname']);
-    $_user['lastName'] 	= stripslashes($values['lastname']);
-    $_user['mail'] 		= $values['email'];
-    $_user['language'] 	= $values['language'];
-    $_user['user_id']	= $user_id;
+    $_user['lastName'] = stripslashes($values['lastname']);
+    $_user['mail'] = $values['email'];
+    $_user['language'] = $values['language'];
+    $_user['user_id'] = $user_id;
     $is_allowedCreateCourse = $values['status'] == 1;
     $usersCanCreateCourse = (api_get_setting('allow_users_to_create_courses') == 'true');
 

+ 23 - 42
main/auth/lostPassword.php

@@ -29,56 +29,37 @@ require_once api_get_path(LIBRARY_PATH).'mail.lib.inc.php';
 global $_configuration;
 
 if (CustomPages::enabled()) {
-    //Reset Password when user goes to the link
-    if ($_GET['reset'] && $_GET['id']) {
+    // Reset Password when user goes to the link
+    if (isset($_GET['reset']) && $_GET['reset'] &&
+        isset($_GET['id']) && $_GET['id']
+    ) {
         $mesg = Login::reset_password($_GET["reset"], $_GET["id"], true);
         CustomPages::display(CustomPages::INDEX_UNLOGGED, array('info' => $mesg));
     }
 
-    //Check email/username and do the right thing
-    if (isset($_POST['user']) && isset ($_POST['email'])) {
-        $user = $_POST['user'];
-        $email = $_POST['email'];
+    // Check email/username and do the right thing
+    if (isset($_POST['user'])) {
+        $usersRelatedToUsername = Login::get_user_accounts_by_username($_POST['user']);
 
-        $condition = '';
-        if (!empty($email)) {
-            $condition = " AND LOWER(email) = '".Database::escape_string($email)."' ";
-        }
-
-        $tbl_user = Database :: get_main_table(TABLE_MAIN_USER);
-        $query = " SELECT user_id AS uid, lastname AS lastName, firstname AS firstName,
-                    username AS loginName, password, email, status AS status,
-                    official_code, phone, picture_uri, creator_id
-                    FROM ".$tbl_user."
-                    WHERE ( username = '".Database::escape_string($user)."' $condition ) ";
-
-        $result 	= Database::query($query);
-        $num_rows 	= Database::num_rows($result);
-
-        if ($result && $num_rows > 0) {
-            if ($num_rows > 1) {
-                // more than one user
-                $by_username = false;
-                while ($data = Database::fetch_array($result)) {
-                    $user[] = $data;
+        if ($usersRelatedToUsername) {
+            $by_username = true;
+            foreach ($usersRelatedToUsername as $user) {
+                if ($_configuration['password_encryption'] != 'none') {
+                    Login::handle_encrypted_password($user, $by_username);
+                } else {
+                    Login::send_password_to_user($user, $by_username);
                 }
-            } else {
-                // single user (valid user + email)
-                $by_username = true;
-                $user = Database::fetch_array($result);
-            }
-            if ($_configuration['password_encryption'] != 'none') {
-                // Send email with secret link to user
-                Login::handle_encrypted_password($user, $by_username);
-            } else {
-                Login::send_password_to_user($user, $by_username);
             }
         } else {
-            CustomPages::display(CustomPages::LOST_PASSWORD, array('error' => get_lang('NoUserAccountWithThisEmailAddress')));
+            CustomPages::display(
+                CustomPages::LOST_PASSWORD,
+                array('error' => get_lang('NoUserAccountWithThisEmailAddress'))
+            );
         }
     } else {
         CustomPages::display(CustomPages::LOST_PASSWORD);
     }
+
     CustomPages::display(
         CustomPages::INDEX_UNLOGGED,
         array('info' => get_lang('YourPasswordHasBeenEmailed'))
@@ -104,16 +85,16 @@ if (isset($_GET['reset']) && isset($_GET['id'])) {
 	$form = new FormValidator('lost_password');
     $form->addElement('header', $tool_name);
 	$form->addElement('text', 'user', array(get_lang('LoginOrEmailAddress'), get_lang('EnterEmailUserAndWellSendYouPassword')), array('size'=>'40'));
-
 	$form->addElement('style_submit_button', 'submit', get_lang('Send'),'class="btn"');
 
-	// setting the rules
+	// Setting the rules
 	$form->addRule('user', get_lang('ThisFieldIsRequired'), 'required');
 
 	if ($form->validate()) {
 		$values = $form->exportValues();
-
-        $users_related_to_username = Login::get_user_accounts_by_username($values['user']);
+        $users_related_to_username = Login::get_user_accounts_by_username(
+            $values['user']
+        );
 
 		if ($users_related_to_username) {
             $by_username = true;

+ 7 - 7
main/auth/my_progress.php

@@ -22,7 +22,6 @@ $nameTools = get_lang('MyProgress');
 api_block_anonymous_users();
 
 $htmlHeadXtra[] = api_get_js('jquery.timelinr-0.9.5.js');
-
 $htmlHeadXtra[] = '
 <script language="javascript">
 $(function() {
@@ -48,7 +47,6 @@ $(function() {
 require_once api_get_path(SYS_CODE_PATH).'mySpace/myspace.lib.php';
 
 $user_id = api_get_user_id();
-
 $course_user_list = CourseManager::get_courses_list_by_user_id($user_id);
 $dates = $issues = '';
 
@@ -74,13 +72,17 @@ if (!empty($course_user_list)) {
                         <div class="row">
                             <div class="span2"><div class="thumbnail">'.$course_image.'</div>
                         </div>
-                        <div class="span3">'.sprintf(get_lang('YouHaveEnteredTheCourseXInY'), $result['course_code'], api_convert_and_format_date($login, DATE_FORMAT_LONG)).'</div>
+                        <div class="span3">'.sprintf(
+                            get_lang('YouHaveEnteredTheCourseXInY'),
+                            $result['course_code'],
+                            api_convert_and_format_date($login, DATE_FORMAT_LONG)
+                        ).'</div>
                     </li>';
         $count++;
     }
 }
 
-$content .= Tracking::show_user_progress(api_get_user_id());
+$content .= Tracking::show_user_progress(api_get_user_id(), $_GET['session_id']);
 $content .= Tracking::show_course_detail(api_get_user_id(), $_GET['course'], $_GET['session_id']);
 
 if (!empty($dates)) {
@@ -88,13 +90,11 @@ if (!empty($dates)) {
         $content .= '<br /><br />';
     }
     $content .= '<div class="row"><div class="span12">'.Display::page_subheader(get_lang('Timeline')).'</div>';
-
     $content .= '<div id="my_timeline">
         <div class="actions">
             <a href="#" id="prev"></a> <!-- optional -->
             <a href="#" id="next"></a> <!-- optional -->
         </div>
-
     <ul id="dates">
         '.$dates.'
     </ul>
@@ -112,4 +112,4 @@ $tpl = new Template($tool_name);
 
 $tpl->assign('message', $message);
 $tpl->assign('content', $content);
-$tpl->display_one_col_template();
+$tpl->display_one_col_template();

+ 9 - 12
main/auth/profile.php

@@ -8,9 +8,6 @@
 *
 * @package chamilo.auth
 */
-/**
- * Code
- */
 
 // Language files that should be included.
 $language_file = array('registration', 'messages', 'userInfo');
@@ -25,7 +22,6 @@ if (api_get_setting('allow_social_tool') == 'true') {
     $this_section = SECTION_MYPROFILE;
 }
 
-
 $htmlHeadXtra[] = api_get_password_checker_js('#username', '#password1');
 
 $_SESSION['this_section'] = $this_section;
@@ -119,6 +115,9 @@ $value_array = $array_list_key[$id_temp_key];
 $user_data['api_key_generate'] = $value_array;
 
 if ($user_data !== false) {
+    if (api_get_setting('login_is_email') == 'true') {
+        $user_data['username'] = $user_data['email'];
+    }
     if (is_null($user_data['language'])) {
         $user_data['language'] = api_get_setting('platformLanguage');
     }
@@ -149,7 +148,7 @@ $form->addRule('firstname', get_lang('ThisFieldIsRequired'), 'required');
 
 //    USERNAME
 $form->addElement('text', 'username', get_lang('UserName'), array('id' => 'username', 'maxlength' => USERNAME_MAX_LENGTH, 'size' => USERNAME_MAX_LENGTH));
-if (api_get_setting('profile', 'login') !== 'true') {
+if (api_get_setting('profile', 'login') !== 'true' || api_get_setting('login_is_email') == 'true') {
     $form->freeze('username');
 }
 $form->applyFilter('username', 'stripslashes');
@@ -301,7 +300,6 @@ if (is_profile_editable()) {
 } else {
     $form->freeze();
 }
-
 $user_data = array_merge($user_data, $extra_data);
 $form->setDefaults($user_data);
 
@@ -478,8 +476,10 @@ if ($form->validate()) {
         $user_data['picture_uri'] = '';
     }
 
-    //Remove production
-    if (is_array($user_data['remove_production'])) {
+    // Remove production.
+    if (isset($user_data['remove_production']) &&
+        is_array($user_data['remove_production'])
+    ) {
         foreach (array_keys($user_data['remove_production']) as $production) {
             UserManager::remove_user_production(api_get_user_id(), urldecode($production));
         }
@@ -659,8 +659,6 @@ if ($form->validate()) {
     exit;
 }
 
-
-/*          MAIN DISPLAY SECTION  */
 // the header
 Display::display_header(get_lang('ModifyProfile'));
 
@@ -701,7 +699,6 @@ if (!empty($file_deleted)) {
     Display :: display_confirmation_message($message, false);
 }
 
-
 if (!empty($msg_fail_changue_email)){
     $errormail=get_lang('ToChangeYourEmailMustTypeYourPassword');
     Display :: display_error_message($errormail, false);
@@ -712,7 +709,7 @@ if (!empty($msg_is_not_password)){
     Display :: display_warning_message($warning_msg, false);
 }
 
-//User picture size is calculated from SYSTEM path
+// User picture size is calculated from SYSTEM path
 $image_syspath = UserManager::get_user_picture_path_by_id(api_get_user_id(), 'system', false, true);
 $image_syspath['dir'].$image_syspath['file'];
 

+ 109 - 53
main/calendar/agenda.lib.php

@@ -14,6 +14,7 @@ class Agenda
     public $type = 'personal';
     public $types = array('personal', 'admin', 'course');
     public $sessionId = 0;
+    public $senderId;
     /** @var array */
     public $course;
 
@@ -34,10 +35,11 @@ class Agenda
         if (!empty($courseInfo)) {
             $this->course = $courseInfo;
         }
-        $this->sessionId = api_get_session_id();
+        $this->setSessionId(api_get_session_id());
+        $this->setSenderId(api_get_user_id());
         $this->events = array();
 
-        //Event colors
+        // Event colors
         $this->event_platform_color = 'red'; //red
         $this->event_course_color = '#458B00'; //green
         $this->event_group_color = '#A0522D'; //siena
@@ -45,6 +47,46 @@ class Agenda
         $this->event_personal_color = 'steel blue'; //steel blue
     }
 
+    /**
+     * @param int $senderId
+     */
+    public function setSenderId($senderId)
+    {
+        $this->senderId = intval($senderId);
+    }
+
+    /**
+     * @return int
+     */
+    public function getSenderId()
+    {
+        return $this->senderId;
+    }
+
+    /**
+     * @param string $type can be 'personal', 'admin'  or  'course'
+     */
+    public function setType($type)
+    {
+        $this->type = $type;
+    }
+
+    /**
+     * @param int $id
+     */
+    public function setSessionId($id)
+    {
+        $this->sessionId = intval($id);
+    }
+
+    /**
+     * @return int $id
+     */
+    public function getSessionId()
+    {
+        return $this->sessionId;
+    }
+
     /**
      * @param array $courseInfo
      */
@@ -103,7 +145,10 @@ class Agenda
                     'enddate' => $end,
                     'all_day' => $allDay
                 );
-                $id = Database::insert($this->tbl_personal_agenda, $attributes);
+                $id = Database::insert(
+                    $this->tbl_personal_agenda,
+                    $attributes
+                );
                 break;
             case 'course':
                 $attributes = array(
@@ -112,7 +157,7 @@ class Agenda
                     'start_date' => $start,
                     'end_date' => $end,
                     'all_day' => $allDay,
-                    'session_id' => api_get_session_id(),
+                    'session_id' => $this->getSessionId(),
                     'c_id' => $this->course['real_id']
                 );
 
@@ -120,6 +165,9 @@ class Agenda
                     $attributes['parent_event_id'] = $parentEventId;
                 }
 
+                $senderId = $this->getSenderId();
+                $sessionId = $this->getSessionId();
+
                 // Simple course event.
                 $id = Database::insert($this->tbl_course_agenda, $attributes);
 
@@ -135,22 +183,24 @@ class Agenda
                                 TOOL_CALENDAR_EVENT,
                                 $id,
                                 "AgendaAdded",
-                                api_get_user_id(),
+                                $senderId,
                                 $groupId,
                                 '',
                                 $start,
-                                $end
+                                $end,
+                                $sessionId
                             );
                             api_item_property_update(
                                 $this->course,
                                 TOOL_CALENDAR_EVENT,
                                 $id,
                                 "visible",
-                                api_get_user_id(),
+                                $senderId,
                                 $groupId,
                                 '',
                                 $start,
-                                $end
+                                $end,
+                                $sessionId
                             );
                         } else {
                             // Storing the selected groups
@@ -161,11 +211,12 @@ class Agenda
                                         TOOL_CALENDAR_EVENT,
                                         $id,
                                         "AgendaAdded",
-                                        api_get_user_id(),
+                                        $senderId,
                                         $group,
                                         0,
                                         $start,
-                                        $end
+                                        $end,
+                                        $sessionId
                                     );
 
                                     api_item_property_update(
@@ -173,11 +224,12 @@ class Agenda
                                         TOOL_CALENDAR_EVENT,
                                         $id,
                                         "visible",
-                                        api_get_user_id(),
+                                        $senderId,
                                         $group,
                                         0,
                                         $start,
-                                        $end
+                                        $end,
+                                        $sessionId
                                     );
                                 }
                             }
@@ -190,11 +242,12 @@ class Agenda
                                         TOOL_CALENDAR_EVENT,
                                         $id,
                                         "AgendaAdded",
-                                        api_get_user_id(),
+                                        $senderId,
                                         $groupId,
                                         $userId,
                                         $start,
-                                        $end
+                                        $end,
+                                        $sessionId
                                     );
 
                                     api_item_property_update(
@@ -202,11 +255,12 @@ class Agenda
                                         TOOL_CALENDAR_EVENT,
                                         $id,
                                         "visible",
-                                        api_get_user_id(),
+                                        $senderId,
                                         $groupId,
                                         $userId,
                                         $start,
-                                        $end
+                                        $end,
+                                        $sessionId
                                     );
                                 }
                             }
@@ -543,7 +597,11 @@ class Agenda
                         $this->tbl_course_agenda,
                         $attributes,
                         array(
-                            'id = ? AND c_id = ? AND session_id = ? ' => array($id, $course_id, api_get_session_id())
+                            'id = ? AND c_id = ? AND session_id = ? ' => array(
+                                $id,
+                                $course_id,
+                                $this->sessionId
+                            )
                         )
                     );
 
@@ -557,41 +615,34 @@ class Agenda
                         $groupToAdd = array_diff($sendTo['groups'], $eventInfo['send_to']['groups']);
 
                         if ($sendTo['everyone']) {
-                            // Delete all:
-                            if (!empty($eventInfo['send_to']['groups']) &&
-                                isset($eventInfo['send_to']['groups'])
+
+                            // Delete all from group
+                            if (isset($eventInfo['send_to']['groups']) &&
+                                !empty($eventInfo['send_to']['groups'])
                             ) {
                                 foreach ($eventInfo['send_to']['groups'] as $group) {
-                                    api_item_property_update(
+                                    api_item_property_delete(
                                         $this->course,
                                         TOOL_CALENDAR_EVENT,
                                         $id,
-                                        "delete",
-                                        api_get_user_id(),
-                                        $group,
                                         0,
-                                        $start,
-                                        $end,
+                                        $group,
                                         $this->sessionId
                                     );
                                 }
                             }
 
-                            // storing the selected users
-                            if (!empty($eventInfo['send_to']['users']) &&
-                                isset($eventInfo['send_to']['users'])
+                            // Storing the selected users.
+                            if (isset($eventInfo['send_to']['users']) &&
+                                !empty($eventInfo['send_to']['users'])
                             ) {
                                 foreach ($eventInfo['send_to']['users'] as $userId) {
-                                    api_item_property_update(
+                                    api_item_property_delete(
                                         $this->course,
                                         TOOL_CALENDAR_EVENT,
                                         $id,
-                                        "delete",
-                                        api_get_user_id(),
-                                        $groupId,
                                         $userId,
-                                        $start,
-                                        $end,
+                                        $groupId,
                                         $this->sessionId
                                     );
                                 }
@@ -605,13 +656,24 @@ class Agenda
                                 "visible",
                                 api_get_user_id(),
                                 $groupId,
-                                '',
+                                null,
                                 $start,
                                 $end,
                                 $this->sessionId
                             );
                         } else {
-                            // Groups
+
+                            // Delete "everyone".
+                            api_item_property_delete(
+                                $this->course,
+                                TOOL_CALENDAR_EVENT,
+                                $id,
+                                0,
+                                0,
+                                $this->sessionId
+                            );
+
+                            // Add groups
                             if (!empty($groupToAdd)) {
                                 foreach ($groupToAdd as $group) {
                                     api_item_property_update(
@@ -629,24 +691,21 @@ class Agenda
                                 }
                             }
 
+                            // Delete groups.
                             if (!empty($groupsToDelete)) {
                                 foreach ($groupsToDelete as $group) {
-                                    api_item_property_update(
+                                    api_item_property_delete(
                                         $this->course,
                                         TOOL_CALENDAR_EVENT,
                                         $id,
-                                        "delete",
-                                        api_get_user_id(),
-                                        $group,
                                         0,
-                                        $start,
-                                        $end,
+                                        $group,
                                         $this->sessionId
                                     );
                                 }
                             }
 
-                            // Users.
+                            // Add users.
                             if (!empty($usersToAdd)) {
                                 foreach ($usersToAdd as $userId) {
                                     api_item_property_update(
@@ -664,18 +723,15 @@ class Agenda
                                 }
                             }
 
+                            // Delete users.
                             if (!empty($usersToDelete)) {
                                 foreach ($usersToDelete as $userId) {
-                                    api_item_property_update(
+                                    api_item_property_delete(
                                         $this->course,
                                         TOOL_CALENDAR_EVENT,
                                         $id,
-                                        "delete",
-                                        api_get_user_id(),
-                                        $groupId,
                                         $userId,
-                                        $start,
-                                        $end,
+                                        $groupId,
                                         $this->sessionId
                                     );
                                 }
@@ -814,7 +870,7 @@ class Agenda
                 $this->get_platform_events($start, $end);
                 break;
             case 'course':
-                $session_id = api_get_session_id();
+                $session_id = $this->sessionId;
                 $courseInfo = api_get_course_info_by_id($course_id);
                 $this->get_course_events(
                     $start,
@@ -1807,13 +1863,13 @@ class Agenda
 
         $userList = CourseManager::get_user_list_from_course_code(
             api_get_course_id(),
-            api_get_session_id(),
+            $this->sessionId,
             null,
             $order
         );
         $groupList = CourseManager::get_group_list_of_course(
             api_get_course_id(),
-            api_get_session_id()
+            $this->sessionId
         );
 
         $this->setSendToSelect(

+ 1 - 4
main/calendar/agenda.php

@@ -1,12 +1,10 @@
 <?php
 /* For licensing terms, see /license.txt */
+
 /**
  * @package chamilo.calendar
  */
 
-/**
- * INIT SECTION
- */
 use \ChamiloSession as Session;
 
 // name of the language file that needs to be included
@@ -202,7 +200,6 @@ if (api_is_allowed_to_edit(false, true) OR
                 }
 
                 // Editing normal event.
-
                 $agenda->edit_event(
                     $eventId,
                     $startDate,

+ 10 - 9
main/chat/chat.php

@@ -4,9 +4,6 @@
  * Chat tool
  * @package chamilo.chat
  */
-/**
- * Code
- */
 
 $language_file = array('chat');
 require_once '../inc/global.inc.php';
@@ -59,9 +56,12 @@ $groupId = api_get_group_id();
 // If it is a group chat then the breadcrumbs.
 if (!empty($groupId)) {
 	$group_properties  = GroupManager :: get_group_properties($groupId);
-	$interbreadcrumb[] = array('url' => '../group/group.php', 'name' => get_lang('Groups'));
+    $interbreadcrumb[] = array(
+        'url' => api_get_path(WEB_CODE_PATH).'group/group.php?'.api_get_cidreq(),
+        'name' => get_lang('Groups')
+    );
 	$interbreadcrumb[] = array(
-        'url' => '../group/group_space.php?gidReq='.api_get_group_id(),
+        'url' => api_get_path(WEB_CODE_PATH).'group/group_space.php?'.api_get_cidreq(),
         'name' => get_lang('GroupSpace').' '.$group_properties['name']
     );
 	$noPHP_SELF = true;
@@ -76,12 +76,13 @@ if (empty($open_chat_window)) {
     Display::display_header($tool_name, 'Chat');
 }
 
+$url = api_get_path(WEB_CODE_PATH).'chat/';
 
 echo '<div class="page-chat">';
-echo '<iframe src="chat_whoisonline.php?cidReq='.$cidreq.'" name="chat_whoisonline" scrolling="no" style="height:500px; width:35%; border: 0px none; float:left"></iframe>';
-echo '<iframe src="chat_chat.php?origin='.$origin.'&target='.$target.'&amp;cidReq='.$cidreq.'" name="chat_chat" id="chat_chat" scrolling="auto" height="380" style="width:65%; border: 0px none; float:right"></iframe>';
-echo '<iframe src="chat_message.php?cidReq='.$cidreq.'" name="chat_message" scrolling="no" height="180" style="width:65%; border: 0px none; float:right"></iframe>';
-echo '<iframe src="chat_hidden.php?cidReq='.$cidreq.'" name="chat_hidden" height="0" style="border: 0px none"></iframe>';
+echo '<iframe src="'.$url.'chat_whoisonline.php?cidReq='.$cidreq.'" name="chat_whoisonline" scrolling="no" style="height:500px; width:35%; border: 0px none; float:left"></iframe>';
+echo '<iframe src="'.$url.'chat_chat.php?origin='.$origin.'&target='.$target.'&amp;cidReq='.$cidreq.'" name="chat_chat" id="chat_chat" scrolling="auto" height="380" style="width:65%; border: 0px none; float:right"></iframe>';
+echo '<iframe src="'.$url.'chat_message.php?cidReq='.$cidreq.'" name="chat_message" scrolling="no" height="180" style="width:65%; border: 0px none; float:right"></iframe>';
+echo '<iframe src="'.$url.'chat_hidden.php?cidReq='.$cidreq.'" name="chat_hidden" height="0" style="border: 0px none"></iframe>';
 echo '</div>';
 
 if (empty($open_chat_window)) {

+ 28 - 25
main/chat/chat_chat.php

@@ -7,9 +7,6 @@
  *	@author Olivier Brouckaert
  *	@package chamilo.chat
  */
-/**
- * Code
- */
 
 define('FRAME', 'chat');
 
@@ -22,12 +19,15 @@ require_once api_get_path(LIBRARY_PATH).'groupmanager.lib.php';
 $course = $_GET['cidReq'];
 $session_id = api_get_session_id();
 $group_id 	= api_get_group_id();
+$userId = api_get_user_id();
+$_course = api_get_course_info();
+$time = api_get_utc_datetime();
 
 // if we have the session set up
 if (!empty($course)) {
     $reset = isset($_GET['reset']) ? (bool)$_GET['reset'] : null;
     $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
-    $query = "SELECT username FROM $tbl_user WHERE user_id='".intval($_user['user_id'])."'";
+    $query = "SELECT username FROM $tbl_user WHERE user_id='".$userId."'";
     $result = Database::query($query);
 
     list($pseudo_user) = Database::fetch_row($result);
@@ -67,22 +67,22 @@ if (!empty($course)) {
         }
     }
 
-	$filename_chat = '';
-	if (!empty($group_id)) {
-		$filename_chat = 'messages-'.$date_now.'_gid-'.$group_id.'.log.html';
-	} else if (!empty($session_id)) {
-		$filename_chat = 'messages-'.$date_now.'_sid-'.$session_id.'.log.html';
-	} else {
-		$filename_chat = 'messages-'.$date_now.'.log.html';
-	}
+    $filename_chat = '';
+    if (!empty($group_id)) {
+        $filename_chat = 'messages-'.$date_now.'_gid-'.$group_id.'.log.html';
+    } else if (!empty($session_id)) {
+        $filename_chat = 'messages-'.$date_now.'_sid-'.$session_id.'.log.html';
+    } else {
+        $filename_chat = 'messages-'.$date_now.'.log.html';
+    }
 
 	if (!file_exists($chat_path.$filename_chat)) {
 		@fclose(fopen($chat_path.$filename_chat, 'w'));
 		if (!api_is_anonymous()) {
 			$doc_id = add_document($_course, $basepath_chat.'/'.$filename_chat, 'file', 0, $filename_chat);
-			api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'DocumentAdded', $_user['user_id'], $group_id, null, null, null, $session_id);
-			api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'invisible', $_user['user_id'], $group_id, null, null, null, $session_id);
-			item_property_update_on_folder($_course, $basepath_chat, $_user['user_id']);
+			api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'DocumentAdded', $userId, $group_id, null, null, null, $session_id);
+			api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'invisible', $userId, $group_id, null, null, null, $session_id);
+			item_property_update_on_folder($_course, $basepath_chat, $userId);
 		}
 	}
 
@@ -103,14 +103,12 @@ if (!empty($course)) {
 		}
 
 		@rename($chat_path.$basename_chat.'.log.html', $chat_path.$basename_chat.'-'.$i.'.log.html');
-
 		@fclose(fopen($chat_path.$basename_chat.'.log.html', 'w'));
-
 		$doc_id = add_document($_course, $basepath_chat.'/'.$basename_chat.'-'.$i.'.log.html', 'file', filesize($chat_path.$basename_chat.'-'.$i.'.log.html'), $basename_chat.'-'.$i.'.log.html');
 
-		api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'DocumentAdded', $_user['user_id'], $group_id, null, null, null, $session_id);
-		api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'invisible', $_user['user_id'], $group_id, null, null, null, $session_id);
-		item_property_update_on_folder($_course,$basepath_chat, $_user['user_id']);
+		api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'DocumentAdded', $userId, $group_id, null, null, null, $session_id);
+		api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'invisible', $userId, $group_id, null, null, null, $session_id);
+		item_property_update_on_folder($_course, $basepath_chat, $userId);
 
 		$doc_id = DocumentManager::get_document_id($_course, $basepath_chat.'/'.$basename_chat.'.log.html');
 
@@ -132,12 +130,15 @@ if (!empty($course)) {
 	array_splice($content, 0, $remove);
 	require 'header_frame.inc.php';
 
-	if (isset($_GET['origin']) && $_GET['origin'] == 'whoisonline') {  //the caller
+	if (isset($_GET['origin']) && $_GET['origin'] == 'whoisonline') {
+	    //the caller
 		$content[0] = get_lang('CallSent').'<br />'.$content[0];
 	}
-	if (isset($_GET['origin']) && $_GET['origin'] == 'whoisonlinejoin') {   //the joiner (we have to delete the chat request to him when he joins the chat)
+	if (isset($_GET['origin']) && $_GET['origin'] == 'whoisonlinejoin') {
+	    //the joiner (we have to delete the chat request to him when he joins the chat)
 		$track_user_table = Database::get_main_table(TABLE_MAIN_USER);
-		$sql = "UPDATE $track_user_table set chatcall_user_id = '', chatcall_date = '', chatcall_text='' WHERE (user_id = ".$_user['user_id'].")";
+		$sql = "UPDATE $track_user_table set chatcall_user_id = '', chatcall_date = '', chatcall_text=''
+		        WHERE (user_id = ".$userId.")";
 		$result = Database::query($sql);
 	}
 
@@ -150,7 +151,9 @@ if (!empty($course)) {
 	if ($isMaster || $is_courseCoach) {
 		$rand = mt_rand(1, 1000);
 		echo '<div id="clear-chat">';
-		echo '<a href="'.api_get_self().'?rand='.$rand.'&reset=1&'.api_get_cidreq().'#bottom" onclick="javascript: if(!confirm(\''.addslashes(api_htmlentities(get_lang('ConfirmReset'), ENT_QUOTES)).'\')) return false;">'.Display::return_icon('delete.png', get_lang('ClearList')).' '.get_lang('ClearList').'</a>';
+		echo '<a href="'.api_get_self().'?rand='.$rand.'&reset=1&'.api_get_cidreq().'#bottom" onclick="javascript: if(!confirm(\''.addslashes(api_htmlentities(get_lang('ConfirmReset'), ENT_QUOTES)).'\')) return false;">'.
+            Display::return_icon('delete.png', get_lang('ClearList')).' '.get_lang('ClearList').
+            '</a>';
 		echo '</div>';
 	}
 } else {
@@ -159,4 +162,4 @@ if (!empty($course)) {
 	$message = get_lang('CloseOtherSession');
 	Display :: display_error_message($message);
 }
-require 'footer_frame.inc.php';
+require 'footer_frame.inc.php';

+ 7 - 21
main/chat/chat_functions.lib.php

@@ -4,22 +4,21 @@
  *	@package chamilo.chat
  */
 
-
 /**
  * @author isaac flores paz
- * @param integer the user id
+ * @param integer $user_id
+ *
  * @return boolean
  * @todo this function need more parameters seems not to be use anymore
  * @deprecated fix this function or create another
  */
-function user_connected_in_chat ($user_id)
+function user_connected_in_chat($user_id)
 {
  	$tbl_chat_connected = Database::get_course_table(TABLE_CHAT_CONNECTED);
     $user_id 	= intval($user_id);
  	$session_id = api_get_session_id();
     $group_id   = api_get_group_id();
     $course_id  = api_get_course_int_id();
-	$extra_condition = '';
 
 	if (!empty($group_id)) {
 		$extra_condition = " AND to_group_id = '$group_id'";
@@ -27,7 +26,8 @@ function user_connected_in_chat ($user_id)
 		$extra_condition = api_get_session_condition($session_id);
 	}
 
- 	$sql = 'SELECT COUNT(*) AS count FROM '.$tbl_chat_connected .' c WHERE c_id = '.$course_id.' AND user_id='.$user_id.$extra_condition;
+ 	$sql = 'SELECT COUNT(*) AS count FROM '.$tbl_chat_connected .' c
+ 	        WHERE c_id = '.$course_id.' AND user_id='.$user_id.$extra_condition;
  	$result = Database::query($sql);
  	$count  = Database::fetch_array($result,'ASSOC');
  	return $count['count'] == 1;
@@ -41,24 +41,13 @@ function exit_of_chat($user_id)
 {
     $user_id = intval($user_id);
     $list_course = CourseManager::get_courses_list_by_user_id($user_id);
-
-    /*$session_id = api_get_session_id();
-    $group_id   = api_get_group_id();
-
-	$extra_condition = '';
-	if (!empty($group_id)) {
-		$extra_condition = " AND to_group_id = '$group_id'";
-	} else {
-		$extra_condition = api_get_session_condition($session_id);
-	}
-    $extra_condition.= " AND course_id = $course_id";*/
-
     $tbl_chat_connected = Database::get_course_table(TABLE_CHAT_CONNECTED);
 
     foreach ($list_course as $course) {
         $response = user_connected_in_chat($user_id);
         //if ($response === true) {
-            $sql = 'DELETE FROM '.$tbl_chat_connected.' WHERE c_id = '.$course['real_id'].' AND user_id = '.$user_id;
+            $sql = 'DELETE FROM '.$tbl_chat_connected.'
+                    WHERE c_id = '.$course['real_id'].' AND user_id = '.$user_id;
             Database::query($sql);
         //}
     }
@@ -69,8 +58,6 @@ function exit_of_chat($user_id)
  */
 function disconnect_user_of_chat()
 {
-	$list_info_user_in_chat = array();
-    $course_id = api_get_course_int_id();
     $list_info_user_in_chat = users_list_in_chat();
     $course_id = api_get_course_int_id();
 
@@ -111,7 +98,6 @@ function users_list_in_chat()
  	$session_id = api_get_session_id();
     $group_id   = api_get_group_id();
 
-	$extra_condition = '';
 	if (!empty($group_id)) {
 		$extra_condition = " WHERE to_group_id = '$group_id'";
 	} else{

+ 13 - 12
main/chat/chat_hidden.php

@@ -7,9 +7,6 @@
  *	@author Olivier Brouckaert
  *	@package chamilo.chat
  */
-/**
- * Code
- */
 
 define('FRAME', 'hidden');
 
@@ -19,12 +16,12 @@ require_once '../inc/global.inc.php';
 require_once api_get_path(LIBRARY_PATH).'groupmanager.lib.php';
 require_once 'chat_functions.lib.php';
 
-$tbl_user 				= Database::get_main_table(TABLE_MAIN_USER);
-$tbl_chat_connected 	= Database::get_course_table(TABLE_CHAT_CONNECTED);
-
+$tbl_user = Database::get_main_table(TABLE_MAIN_USER);
+$tbl_chat_connected = Database::get_course_table(TABLE_CHAT_CONNECTED);
+$userId = api_get_user_id();
 $course_id = api_get_course_int_id();
 
-$query = "SELECT username FROM $tbl_user WHERE user_id='".$_user['user_id']."'";
+$query = "SELECT username FROM $tbl_user WHERE user_id='".$userId."'";
 $result = Database::query($query);
 
 list($pseudo_user) = Database::fetch_row($result);
@@ -76,26 +73,30 @@ if (file_exists($file)) {
     $chat_size_new = filesize($file);
 }
 
-$sql = "SELECT user_id FROM $tbl_chat_connected WHERE user_id='".$_user['user_id']."' $extra_condition";
+$sql = "SELECT user_id FROM $tbl_chat_connected WHERE user_id='".$userId."' $extra_condition";
 $result = Database::query($sql);
 
 // The user_id exists so we must do an UPDATE and not a INSERT
 $current_time = date('Y-m-d H:i:s');
 if (Database::num_rows($result) == 0) {
-	$query = "INSERT INTO $tbl_chat_connected(c_id, user_id,last_connection,session_id,to_group_id) VALUES($course_id, '".$_user['user_id']."','$current_time','$session_id','$group_id')";
+	$query = "INSERT INTO $tbl_chat_connected(c_id, user_id,last_connection,session_id,to_group_id)
+	          VALUES($course_id, '".$userId."','$current_time','$session_id','$group_id')";
 } else {
-	$query = "UPDATE $tbl_chat_connected set last_connection='".$current_time."' WHERE c_id = $course_id AND user_id='".$_user['user_id']."' AND session_id='$session_id' AND to_group_id='$group_id'";
+	$query = "UPDATE $tbl_chat_connected set last_connection='".$current_time."'
+	          WHERE c_id = $course_id AND user_id='".$userId."' AND session_id='$session_id' AND to_group_id='$group_id'";
 }
 
 Database::query($query);
 
-$query = "SELECT COUNT(user_id) FROM $tbl_chat_connected WHERE last_connection>'".date('Y-m-d H:i:s',time()-60*5)."' $extra_condition";
+$query = "SELECT COUNT(user_id) FROM $tbl_chat_connected
+          WHERE last_connection>'".date('Y-m-d H:i:s',time()-60*5)."' $extra_condition";
 $result = Database::query($query);
 
 $connected_old = isset($_POST['connected_old']) ? intval($_POST['connected_old']) : null;
 list($connected_new) = Database::fetch_row($result);
+
 /*disconnected user of chat*/
-disconnect_user_of_chat ();
+disconnect_user_of_chat();
 require 'header_frame.inc.php';
 ?>
 <form name="formHidden" method="post" action="<?php echo api_get_self().'?'.api_get_cidreq(); ?>">

+ 22 - 25
main/chat/chat_message.php

@@ -8,18 +8,12 @@
  * 	Modified by Alex Aragón (BeezNest)
  *	@package chamilo.chat
  */
-/**
- * Code
- */
-
-/*		INIT SECTION */
 
 define('FRAME', 'message');
-
 $language_file = array('chat');
-
 require_once '../inc/global.inc.php';
-
+$userId = api_get_user_id();
+$userInfo = api_get_user_info();
 $course = api_get_course_id();
 $session_id = api_get_session_id();
 $group_id 	= api_get_group_id();
@@ -55,14 +49,14 @@ function close_chat_window() {
 
 // Mode open in a new window: close the window when there isn't an user login
 
-if (empty($_user['user_id'])) {
+if (empty($userId)) {
 	echo '<script languaje="javascript" type="text/javascript"> close_chat_window(); </script>';
 } else {
 	api_protect_course_script();
 }
 
 // if we have the session set up
-if (!empty($course) && !empty($_user['user_id'])) {
+if (!empty($course) && !empty($userId)) {
 	require_once api_get_path(LIBRARY_PATH).'document.lib.php';
 	require_once api_get_path(LIBRARY_PATH).'fileUpload.lib.php';
 
@@ -73,7 +67,8 @@ if (!empty($course) && !empty($_user['user_id'])) {
 
     /*	MAIN CODE */
 
-    $query = "SELECT user_id, lastname, firstname, username, picture_uri FROM $tbl_user WHERE user_id='".intval($_user['user_id'])."'";
+    $query = "SELECT user_id, lastname, firstname, username, picture_uri
+              FROM $tbl_user WHERE user_id='".$userId."'";
     $result = Database::query($query);
 
     list($pseudo_user) = Database::fetch_row($result);
@@ -85,6 +80,7 @@ if (!empty($course) && !empty($_user['user_id'])) {
     $firstname = Database::result($result, 0, 'firstname');
     $lastname  = Database::result($result, 0, 'lastname');
     $picture  = Database::result($result, 0, 'picture_uri');
+    $fullName = api_get_person_name($firstname, $lastname);
 
     $date_now = date('Y-m-d');
 
@@ -206,34 +202,35 @@ if (!empty($course) && !empty($_user['user_id'])) {
                 if (!file_exists($chat_path.$basename_chat.'.log.html')) {
 					$doc_id = add_document($_course, $basepath_chat.'/'.$basename_chat.'.log.html', 'file', 0, $basename_chat.'.log.html');
 
-					api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'DocumentAdded', $_user['user_id'], $group_id, null, null, null, $session_id);
-					api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'invisible', $_user['user_id'], $group_id, null, null, null, $session_id);
-					item_property_update_on_folder($_course, $basepath_chat, $_user['user_id']);
+					api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'DocumentAdded', $userId, $group_id, null, null, null, $session_id);
+					api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'invisible', $userId, $group_id, null, null, null, $session_id);
+					item_property_update_on_folder($_course, $basepath_chat, $userId);
 				} else {
 					$doc_id = DocumentManager::get_document_id($_course, $basepath_chat.'/'.$basename_chat.'.log.html');
 				}
 
 				$fp = fopen($chat_path.$basename_chat.'.log.html', 'a');
-					// view user picture
-					$userImage = UserManager::get_user_picture_path_by_id($user_id, 'web', false, true);
-                                        if (substr($userImage['file'],0,7) != 'unknown') {
-    					$userPhoto = $userImage['dir'].'medium_'.$userImage['file'];
-                                        } else {
-    					$userPhoto = $userImage['dir'].$userImage['file'];
-                                        }
-					$filePhoto = '<img class="chat-image" src="'.$userPhoto.'"/>';
+                // view user picture
+                $userImage = UserManager::get_user_picture_path_by_id($userId, 'web', false, true);
+
+                if (substr($userImage['file'],0,7) != 'unknown') {
+                    $userPhoto = $userImage['dir'].'medium_'.$userImage['file'];
+                } else {
+                    $userPhoto = $userImage['dir'].$userImage['file'];
+                }
 
+                $filePhoto = '<img class="chat-image" src="'.$userPhoto.'"/>';
 				if ($isMaster) {
-					fputs($fp, '<div class="message-teacher"><div class="content-message"><div>'.$message.'</div><div class="message-date">'.$timeNow.'</div></div><div class="icon-message"></div>'.$filePhoto.'</div>'."\n");
+					fputs($fp, '<div class="message-teacher"><div class="content-message"><div class="chat-message-block-name">'.$fullName.'</div><div>'.$message.'</div><div class="message-date">'.$timeNow.'</div></div><div class="icon-message"></div>'.$filePhoto.'</div>'."\n");
 				} else {
-					fputs($fp, '<div class="message-student">'.$filePhoto.'<div class="icon-message"></div><div class="content-message"><div>'.$message.'</div><div class="message-date">'.$timeNow.'</div></div></div>'."\n");
+					fputs($fp, '<div class="message-student">'.$filePhoto.'<div class="icon-message"></div><div class="content-message"><div class="chat-message-block-name">'.$fullName.'</div><div>'.$message.'</div><div class="message-date">'.$timeNow.'</div></div></div>'."\n");
 				}
 				fclose($fp);
 
 				$chat_size = filesize($chat_path.$basename_chat.'.log.html');
 
 				update_existing_document($_course, $doc_id, $chat_size);
-				item_property_update_on_folder($_course, $basepath_chat, $_user['user_id']);
+				item_property_update_on_folder($_course, $basepath_chat, $userId);
 			}
 		}
 	}

Some files were not shown because too many files changed in this diff