Browse Source

Adds schema changes following mainline

Conflicts:
  main/inc/Entity/BranchSync.php
    Union merge including both new data members.
  main/install/1.10.0/db_main.sql
  main/install/1.10.0/migrate-db-1.9.0-1.10.0-pre.sql
    Main change, move schema modifications to
    main/install/1.10.0/update.php
Marco Villegas 11 years ago
parent
commit
d0d0e84491
100 changed files with 6337 additions and 6630 deletions
  1. 13 1
      .gitignore
  2. 2 2
      README.md
  3. 16 12
      composer.json
  4. 0 3642
      composer.lock
  5. 4 1
      config/configuration.dist.php
  6. 1 0
      config/configuration.dist.yml.php
  7. 1 0
      config/profile.conf.dist.php
  8. 12 0
      config/routing.yml
  9. 4 6
      console.php
  10. 146 14
      documentation/changelog.html
  11. 28 16
      documentation/credits.html
  12. 1 1
      documentation/dependencies.html
  13. 61 58
      documentation/installation_guide.html
  14. 14 14
      documentation/installation_guide_es_ES.html
  15. 57 3
      documentation/optimization.html
  16. 1 1
      main/admin/access_url_edit_users_to_url.php
  17. 42 41
      main/admin/careers.php
  18. 1 0
      main/admin/configure_homepage.php
  19. 1 0
      main/admin/course_add.php
  20. 44 26
      main/admin/course_category.php
  21. 7 2
      main/admin/course_edit.php
  22. 55 44
      main/admin/course_import.php
  23. 5 5
      main/admin/course_information.php
  24. 4 0
      main/admin/course_list.php
  25. 281 0
      main/admin/exercise_report.php
  26. 1 1
      main/admin/extra_fields.php
  27. 3 460
      main/admin/index.php
  28. 28 28
      main/admin/promotions.php
  29. 5 3
      main/admin/settings.lib.php
  30. 4 3
      main/admin/settings.php
  31. 153 160
      main/admin/user_add.php
  32. 25 16
      main/admin/user_import.php
  33. 11 9
      main/admin/user_information.php
  34. 66 15
      main/admin/user_list.php
  35. 18 18
      main/auth/courses.php
  36. 26 18
      main/auth/courses_controller.php
  37. 12 8
      main/auth/inscription.php
  38. 12 21
      main/auth/profile.php
  39. 192 354
      main/calendar/agenda.inc.php
  40. 945 0
      main/calendar/agenda.lib.php
  41. 2 1
      main/course_home/activity.php
  42. 78 59
      main/course_home/vertical_activity.php
  43. 7 1
      main/course_info/infocours.php
  44. 50 50
      main/coursecopy/classes/Announcement.class.php
  45. 18 17
      main/coursecopy/classes/Attendance.class.php
  46. 299 297
      main/coursecopy/classes/Course.class.php
  47. 16 6
      main/coursecopy/classes/CourseArchiver.class.php
  48. 622 662
      main/coursecopy/classes/CourseBuilder.class.php
  49. 37 22
      main/coursecopy/classes/CourseRecycler.class.php
  50. 337 453
      main/coursecopy/classes/CourseRestorer.class.php
  51. 4 3
      main/coursecopy/classes/CourseSelectForm.class.php
  52. 4 1
      main/coursecopy/classes/Resource.class.php
  53. 36 0
      main/coursecopy/classes/Work.class.php
  54. 5 29
      main/create_course/add_course.php
  55. 680 0
      main/cron/import_csv.php
  56. 118 26
      main/css/base.css
  57. BIN
      main/css/chamilo_electric_blue/images/header-logo.png
  58. BIN
      main/css/chamilo_green/images/header-logo.png
  59. BIN
      main/css/chamilo_orange/images/header-logo.png
  60. BIN
      main/css/chamilo_red/images/header-logo.png
  61. 538 0
      main/css/digedd/dataTable.css
  62. 201 0
      main/css/digedd/default.css
  63. 983 0
      main/css/digedd/frames.css
  64. BIN
      main/css/digedd/images/2leftarrow.gif
  65. BIN
      main/css/digedd/images/2rightarrow.gif
  66. BIN
      main/css/digedd/images/background_message.png
  67. BIN
      main/css/digedd/images/bar_1.gif
  68. BIN
      main/css/digedd/images/bar_1m.gif
  69. BIN
      main/css/digedd/images/bar_1r.gif
  70. BIN
      main/css/digedd/images/bar_1u.gif
  71. BIN
      main/css/digedd/images/bg-button.gif
  72. BIN
      main/css/digedd/images/bg-footer.gif
  73. BIN
      main/css/digedd/images/bg-header1.gif
  74. BIN
      main/css/digedd/images/bg-header4.png
  75. BIN
      main/css/digedd/images/bg-main.png
  76. BIN
      main/css/digedd/images/bg-menu.png
  77. BIN
      main/css/digedd/images/bgmenusup.png
  78. BIN
      main/css/digedd/images/bullet.gif
  79. BIN
      main/css/digedd/images/button_accept.gif
  80. BIN
      main/css/digedd/images/button_add.gif
  81. BIN
      main/css/digedd/images/button_back.gif
  82. BIN
      main/css/digedd/images/button_back.jpg
  83. BIN
      main/css/digedd/images/button_delete.gif
  84. BIN
      main/css/digedd/images/button_login.gif
  85. BIN
      main/css/digedd/images/button_minus.gif
  86. BIN
      main/css/digedd/images/button_next.gif
  87. BIN
      main/css/digedd/images/button_plus.gif
  88. BIN
      main/css/digedd/images/button_refresh.gif
  89. BIN
      main/css/digedd/images/button_search.gif
  90. BIN
      main/css/digedd/images/button_upload.gif
  91. BIN
      main/css/digedd/images/dataTable/Sorting icons.psd
  92. BIN
      main/css/digedd/images/dataTable/back_disabled.jpg
  93. BIN
      main/css/digedd/images/dataTable/back_enabled.jpg
  94. BIN
      main/css/digedd/images/dataTable/favicon.ico
  95. BIN
      main/css/digedd/images/dataTable/forward_disabled.jpg
  96. BIN
      main/css/digedd/images/dataTable/forward_enabled.jpg
  97. BIN
      main/css/digedd/images/dataTable/sort_asc.png
  98. BIN
      main/css/digedd/images/dataTable/sort_asc_disabled.png
  99. BIN
      main/css/digedd/images/dataTable/sort_both.png
  100. BIN
      main/css/digedd/images/dataTable/sort_desc.png

+ 13 - 1
.gitignore

@@ -1,12 +1,14 @@
 # Chamilo
 
 main/inc/conf
+main/lang/*
 config/auth.conf.php
 config/configuration.php
 config/events.conf.php
 config/mail.conf.php
 config/portfolio.conf.php
 config/profile.conf.php
+tests/unittests/db.conf.php
 
 temp/*
 !temp/twig/PLACEHOLDER
@@ -29,9 +31,19 @@ logs/*
 *.orig
 nbproject/*
 vendor/.git
+.*.swp
 
-#Doctrine entities generation tests
+vendor/ezyang/htmlpurifier/docs/*
+vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Filter/ExtractStyleBlocks.txt
+vendor/ezyang/htmlpurifier/smoketests/*
+vendor/realityking/pchart/Sample/*
+vendor/realityking/pchart/Example*
+
+# Doctrine entities generation tests
 
 tests/doctrine_console/generated
 tests/doctrine_console/mapping
 tests/doctrine_console/Proxies
+
+# OS stuff
+.DS_Store

+ 2 - 2
README.md

@@ -1,7 +1,7 @@
 Chamilo LMS
 =============
 
-It's a next generation learning content management system focusing on ease of use, re-usibality, collaboration and sharing.
+A next generation Learning Content Management system focused on ease of use, collaboration and sharing.
 See documentation/index.html for a complete overview of Chamilo.
 
 Installation
@@ -32,4 +32,4 @@ Visit the official Chamilo Forum: http://www.chamilo.org/forum
 License
 ----------
 
-Chamilo is licensed under the GPLv3 license.
+Chamilo is licensed under the GPLv3 license.

+ 16 - 12
composer.json

@@ -38,8 +38,8 @@
         }
     ],
     "require": {
-        "php": ">=5.3.2",
-        "silex/silex": "~1.0",
+        "php": ">=5.3.3",
+        "silex/silex": "1.*",
         "symfony/console"  : "~2.3",
         "symfony/twig-bridge": "~2.3",
         "symfony/doctrine-bridge": "2.3.*@dev",
@@ -49,6 +49,8 @@
         "symfony/validator": "~2.3",
         "symfony/translation": "~2.3",
         "symfony/dependency-injection": "~2.3",
+        "symfony/filesystem": "~2.3",
+        "symfony/finder": "2.3.*@dev",
         "monolog/monolog" : ">=1.0.0",
         "symfony/config": "~2.3",
         "symfony/yaml": "~2.3",
@@ -58,38 +60,40 @@
         "dflydev/doctrine-orm-service-provider": "1.0.*@dev",
         "doctrine/migrations": "dev-master",
         "gedmo/doctrine-extensions": "2.3.*@dev",
-        "chamilo/chash": "dev-master",
         "swiftmailer/swiftmailer": ">=4.1.2,<4.2-dev",
         "pagerfanta/pagerfanta": "dev-master",
-        "franmomu/silex-pagerfanta-provider": "2.3.*@dev",
+        "franmomu/silex-pagerfanta-provider": "1.0.*@dev",
         "igorw/config-service-provider": "1.2.*@dev",
         "mpdf/mpdf": "v5.6.1",
         "ezyang/htmlpurifier": "v4.5.0",
         "realityking/pchart": "dev-master",
-        "imagine/imagine": "dev-develop",
+        "imagine/imagine": "v0.5.0",
         "grom/silex-service-provider": "dev-master",
         "knplabs/knp-menu": "2.0.*@dev",
         "knplabs/knp-snappy": "dev-master",
         "knplabs/console-service-provider": "dev-master",
-        "knplabs/gaufrette": "0.2.*@dev",
         "jmontoyaa/phpqrcode": "dev-master",
-        "bt51/gaufrette-serviceprovider": "dev-master",
         "neutron/silex-filesystem-provider": "dev-master",
-        "jbroadway/urlify": "dev-master",
-        "sensio/framework-extra-bundle": "2.3.*@dev"
+        "jbroadway/urlify": "1.0.0-stable",
+        "sensio/framework-extra-bundle": "2.3.*@dev",
+        "chamilo/chash": "dev-master",
+        "composer/composer": "1.0.0-alpha7",
+        "flint/flint" : "dev-master"
     },
     "require-dev": {
-        "symfony/browser-kit": "2.3.*@dev",
+        "knplabs/gaufrette": "0.2.*@dev",
+        "bt51/gaufrette-serviceprovider": "dev-master",
+        "symfony/browser-kit": "~2.3",
         "symfony/web-profiler-bundle": "~2.3",
         "silex/web-profiler": "1.0.x-dev",
         "natxet/CssMin": "dev-master",
         "leafo/lessphp": "dev-master",
         "mheap/silex-assetic": "1.0.*@dev",
         "filp/whoops": "dev-master"
+
     },
     "scripts": {
         "post-install-cmd": "ChamiloLMS\\Composer\\Tasks::postInstall",
         "post-update-cmd": "ChamiloLMS\\Composer\\Tasks::postUpdate"
-    },
-    "minimum-stability": "stable"
+    }
 }

+ 0 - 3642
composer.lock

@@ -1,3642 +0,0 @@
-{
-    "_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"
-    ],
-    "hash": "94cb7c5f7d4efa532d6bd2b1a4ba0cd6",
-    "packages": [
-        {
-            "name": "bt51/gaufrette-serviceprovider",
-            "version": "dev-master",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/bt51/GaufretteServiceProvider.git",
-                "reference": "6bba885170beb6719e7256e407b172f90af3159a"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/bt51/GaufretteServiceProvider/zipball/6bba885170beb6719e7256e407b172f90af3159a",
-                "reference": "6bba885170beb6719e7256e407b172f90af3159a",
-                "shasum": ""
-            },
-            "require": {
-                "knplabs/gaufrette": "dev-master@dev",
-                "php": ">=5.3.2"
-            },
-            "require-dev": {
-                "silex/silex": "1.0.x-dev"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-0": {
-                    "Bt51\\Silex\\Provider\\GaufretteServiceProvider": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Ben Tollakson",
-                    "email": "ben.tollakson@gmail.com"
-                }
-            ],
-            "description": "Gaufrette service provider for silex",
-            "homepage": "https://github.com/bt51/GaufretteServiceProvider",
-            "keywords": [
-                "extension",
-                "gaufrette",
-                "silex",
-                "silex-extension"
-            ],
-            "time": "2012-12-07 00:50:44"
-        },
-        {
-            "name": "chamilo/chash",
-            "version": "dev-master",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/chamilo/chash.git",
-                "reference": "0720bc4ab428494465ac6bab6532cb167704183f"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/chamilo/chash/zipball/0720bc4ab428494465ac6bab6532cb167704183f",
-                "reference": "0720bc4ab428494465ac6bab6532cb167704183f",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.2",
-                "symfony/console": ">=2.3,<3.0",
-                "symfony/yaml": ">=2.3,<3.0"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-0": {
-                    "Chash": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "homepage": "http://www.chamilo.org",
-            "time": "2013-06-14 09:54:38"
-        },
-        {
-            "name": "dflydev/doctrine-orm-service-provider",
-            "version": "dev-master",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/dflydev/dflydev-doctrine-orm-service-provider.git",
-                "reference": "a8c4f4cc15750c00746cf4cfb55220ebc707727c"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/dflydev/dflydev-doctrine-orm-service-provider/zipball/a8c4f4cc15750c00746cf4cfb55220ebc707727c",
-                "reference": "a8c4f4cc15750c00746cf4cfb55220ebc707727c",
-                "shasum": ""
-            },
-            "require": {
-                "doctrine/orm": ">=2.3,<3.0",
-                "php": ">=5.3.3",
-                "pimple/pimple": "1.*@dev"
-            },
-            "require-dev": {
-                "cilex/cilex": "1.*@dev",
-                "cilex/console-service-provider": "@dev",
-                "silex/silex": "1.*@dev"
-            },
-            "suggest": {
-                "dflydev/psr0-resource-locator-service-provider": "1.0.*@dev"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Dflydev\\Cilex\\Provider\\DoctrineOrm": "src",
-                    "Dflydev\\Pimple\\Provider\\DoctrineOrm": "src",
-                    "Dflydev\\Silex\\Provider\\DoctrineOrm": "src"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Dragonfly Development Inc.",
-                    "email": "info@dflydev.com",
-                    "homepage": "http://dflydev.com"
-                },
-                {
-                    "name": "Beau Simensen",
-                    "email": "beau@dflydev.com",
-                    "homepage": "http://beausimensen.com"
-                }
-            ],
-            "description": "Doctrine ORM Service Provider",
-            "keywords": [
-                "cilex",
-                "doctrine",
-                "orm",
-                "pimple",
-                "silex"
-            ],
-            "time": "2013-06-05 14:23:06"
-        },
-        {
-            "name": "doctrine/common",
-            "version": "2.3.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/doctrine/common",
-                "reference": "2.3.0"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://github.com/doctrine/common/zipball/2.3.0",
-                "reference": "2.3.0",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.2"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Doctrine\\Common": "lib/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Jonathan Wage",
-                    "email": "jonwage@gmail.com",
-                    "homepage": "http://www.jwage.com/"
-                },
-                {
-                    "name": "Guilherme Blanco",
-                    "email": "guilhermeblanco@gmail.com",
-                    "homepage": "http://www.instaclick.com"
-                },
-                {
-                    "name": "Roman Borschel",
-                    "email": "roman@code-factory.org"
-                },
-                {
-                    "name": "Benjamin Eberlei",
-                    "email": "kontakt@beberlei.de"
-                },
-                {
-                    "name": "Johannes M. Schmitt",
-                    "email": "schmittjoh@gmail.com",
-                    "homepage": "http://jmsyst.com",
-                    "role": "Developer of wrapped JMSSerializerBundle"
-                }
-            ],
-            "description": "Common Library for Doctrine projects",
-            "homepage": "http://www.doctrine-project.org",
-            "keywords": [
-                "annotations",
-                "collections",
-                "eventmanager",
-                "persistence",
-                "spl"
-            ],
-            "time": "2012-09-19 22:55:18"
-        },
-        {
-            "name": "doctrine/dbal",
-            "version": "2.3.4",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/doctrine/dbal.git",
-                "reference": "2.3.4"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/doctrine/dbal/zipball/2.3.4",
-                "reference": "2.3.4",
-                "shasum": ""
-            },
-            "require": {
-                "doctrine/common": ">=2.3.0,<2.5-dev",
-                "php": ">=5.3.2"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Doctrine\\DBAL": "lib/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Jonathan Wage",
-                    "email": "jonwage@gmail.com",
-                    "homepage": "http://www.jwage.com/"
-                },
-                {
-                    "name": "Guilherme Blanco",
-                    "email": "guilhermeblanco@gmail.com",
-                    "homepage": "http://www.instaclick.com"
-                },
-                {
-                    "name": "Roman Borschel",
-                    "email": "roman@code-factory.org"
-                },
-                {
-                    "name": "Benjamin Eberlei",
-                    "email": "kontakt@beberlei.de"
-                }
-            ],
-            "description": "Database Abstraction Layer",
-            "homepage": "http://www.doctrine-project.org",
-            "keywords": [
-                "database",
-                "dbal",
-                "persistence",
-                "queryobject"
-            ],
-            "time": "2013-05-11 07:45:37"
-        },
-        {
-            "name": "doctrine/migrations",
-            "version": "dev-master",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/doctrine/migrations.git",
-                "reference": "ced3b419252af47f29d6680f9ec74df00ee0c58e"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/doctrine/migrations/zipball/ced3b419252af47f29d6680f9ec74df00ee0c58e",
-                "reference": "ced3b419252af47f29d6680f9ec74df00ee0c58e",
-                "shasum": ""
-            },
-            "require": {
-                "doctrine/dbal": ">=2.0,<2.5.x-dev",
-                "php": ">=5.3.2"
-            },
-            "require-dev": {
-                "symfony/console": "2.*",
-                "symfony/yaml": "2.*"
-            },
-            "suggest": {
-                "symfony/console": "to run the migration from the console"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-0": {
-                    "Doctrine\\DBAL\\Migrations": "lib"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "LGPL"
-            ],
-            "authors": [
-                {
-                    "name": "Jonathan Wage",
-                    "email": "jonwage@gmail.com",
-                    "homepage": "http://www.jwage.com/"
-                },
-                {
-                    "name": "Benjamin Eberlei",
-                    "email": "kontakt@beberlei.de"
-                }
-            ],
-            "description": "Database Schema migrations using Doctrine DBAL",
-            "homepage": "http://www.doctrine-project.org",
-            "keywords": [
-                "database",
-                "migrations"
-            ],
-            "time": "2013-06-27 19:46:00"
-        },
-        {
-            "name": "doctrine/orm",
-            "version": "2.3.4",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/doctrine/doctrine2.git",
-                "reference": "2.3.4"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/doctrine/doctrine2/zipball/2.3.4",
-                "reference": "2.3.4",
-                "shasum": ""
-            },
-            "require": {
-                "doctrine/dbal": "2.3.*",
-                "ext-pdo": "*",
-                "php": ">=5.3.2",
-                "symfony/console": "2.*"
-            },
-            "suggest": {
-                "symfony/yaml": "If you want to use YAML Metadata Mapping Driver"
-            },
-            "bin": [
-                "bin/doctrine",
-                "bin/doctrine.php"
-            ],
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Doctrine\\ORM": "lib/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Jonathan Wage",
-                    "email": "jonwage@gmail.com",
-                    "homepage": "http://www.jwage.com/"
-                },
-                {
-                    "name": "Guilherme Blanco",
-                    "email": "guilhermeblanco@gmail.com",
-                    "homepage": "http://www.instaclick.com"
-                },
-                {
-                    "name": "Roman Borschel",
-                    "email": "roman@code-factory.org"
-                },
-                {
-                    "name": "Benjamin Eberlei",
-                    "email": "kontakt@beberlei.de"
-                }
-            ],
-            "description": "Object-Relational-Mapper for PHP",
-            "homepage": "http://www.doctrine-project.org",
-            "keywords": [
-                "database",
-                "orm"
-            ],
-            "time": "2013-05-11 07:51:12"
-        },
-        {
-            "name": "ezyang/htmlpurifier",
-            "version": "v4.5.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/ezyang/htmlpurifier.git",
-                "reference": "v4.5.0"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/v4.5.0",
-                "reference": "v4.5.0",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.2"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-0": {
-                    "HTMLPurifier": "library/"
-                },
-                "files": [
-                    "library/HTMLPurifier.composer.php"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "LGPL"
-            ],
-            "authors": [
-                {
-                    "name": "Edward Z. Yang",
-                    "email": "admin@htmlpurifier.org",
-                    "homepage": "http://ezyang.com"
-                }
-            ],
-            "description": "Standards compliant HTML filter written in PHP",
-            "homepage": "http://htmlpurifier.org/",
-            "keywords": [
-                "html"
-            ],
-            "time": "2013-02-18 00:04:08"
-        },
-        {
-            "name": "franmomu/silex-pagerfanta-provider",
-            "version": "2.3.x-dev",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/jmontoyaa/silex-pagerfanta-provider.git",
-                "reference": "9e88fe51bb42cd5dec754bba9e8a5186f905778b"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/jmontoyaa/silex-pagerfanta-provider/zipball/9e88fe51bb42cd5dec754bba9e8a5186f905778b",
-                "reference": "9e88fe51bb42cd5dec754bba9e8a5186f905778b",
-                "shasum": ""
-            },
-            "require": {
-                "pagerfanta/pagerfanta": "dev-master",
-                "silex/silex": "1.0.*@dev",
-                "symfony/property-access": "2.3.*@dev"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "FranMoreno": "src/"
-                }
-            },
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fran Moreno",
-                    "email": "franmomu@gmail.com",
-                    "homepage": "http://showmethecode.es"
-                }
-            ],
-            "description": "Silex ServiceProvider for Pagerfanta Library",
-            "homepage": "https://github.com/franmomu/silex-pagerfanta-provider",
-            "keywords": [
-                "pagerfanta",
-                "service provider",
-                "silex"
-            ],
-            "support": {
-                "source": "https://github.com/jmontoyaa/silex-pagerfanta-provider/tree/2.3"
-            },
-            "time": "2013-04-22 11:39:08"
-        },
-        {
-            "name": "gedmo/doctrine-extensions",
-            "version": "dev-master",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/l3pp4rd/DoctrineExtensions.git",
-                "reference": "f9322867ee9ded7531c3f2f5d8c6c146c4ed2e9e"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/l3pp4rd/DoctrineExtensions/zipball/f9322867ee9ded7531c3f2f5d8c6c146c4ed2e9e",
-                "reference": "f9322867ee9ded7531c3f2f5d8c6c146c4ed2e9e",
-                "shasum": ""
-            },
-            "require": {
-                "doctrine/common": ">=2.2,<2.5-dev",
-                "php": ">=5.3.2"
-            },
-            "require-dev": {
-                "doctrine/common": ">=2.4.0-RC3",
-                "doctrine/dbal": ">=2.4.0-RC1",
-                "doctrine/mongodb": ">=1.0.3",
-                "doctrine/mongodb-odm": ">=1.0.0-BETA9",
-                "doctrine/orm": ">=2.4.0-RC1",
-                "symfony/yaml": "2.3.1"
-            },
-            "suggest": {
-                "doctrine/dbal": ">=2.3.2",
-                "doctrine/mongodb": ">=1.0.1",
-                "doctrine/mongodb-odm": ">=1.0.0-BETA7",
-                "doctrine/orm": ">=2.3.2"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Gedmo\\": "lib/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "David Buchmann",
-                    "email": "david@liip.ch"
-                },
-                {
-                    "name": "Gediminas Morkevicius",
-                    "email": "gediminas.morkevicius@gmail.com"
-                },
-                {
-                    "name": "Gustavo Falco",
-                    "email": "comfortablynumb84@gmail.com"
-                }
-            ],
-            "description": "Doctrine2 behavioral extensions",
-            "homepage": "http://gediminasm.org/",
-            "keywords": [
-                "Blameable",
-                "behaviors",
-                "doctrine2",
-                "extensions",
-                "gedmo",
-                "loggable",
-                "nestedset",
-                "sluggable",
-                "sortable",
-                "timestampable",
-                "translatable",
-                "tree",
-                "uploadable"
-            ],
-            "time": "2013-06-26 14:50:24"
-        },
-        {
-            "name": "grom/silex-service-provider",
-            "version": "dev-master",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/GromNaN/SilexServiceProvider.git",
-                "reference": "v1.0.0"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/GromNaN/SilexServiceProvider/zipball/v1.0.0",
-                "reference": "v1.0.0",
-                "shasum": ""
-            },
-            "require": {
-                "imagine/imagine": "*",
-                "knplabs/knp-snappy": "dev-master",
-                "silex/silex": ">=1.0.0-dev"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-0": {
-                    "Grom\\Silex": "src"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Jérôme Tamarelle",
-                    "email": "jerome@tamarelle.net"
-                }
-            ],
-            "description": "Imagine & KnpSnappy integration for Silex.",
-            "homepage": "http://github.com/GromNaN/SilexServiceProvider",
-            "keywords": [
-                "image",
-                "imagine",
-                "pdf",
-                "silex",
-                "snappy"
-            ],
-            "time": "2012-06-03 01:27:23"
-        },
-        {
-            "name": "igorw/config-service-provider",
-            "version": "dev-master",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/igorw/ConfigServiceProvider.git",
-                "reference": "v1.2.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/igorw/ConfigServiceProvider/zipball/v1.2.1",
-                "reference": "v1.2.1",
-                "shasum": ""
-            },
-            "require": {
-                "silex/silex": ">=1.0,<2.0"
-            },
-            "require-dev": {
-                "jamesmoss/toml": ">=0.1,<1.0",
-                "symfony/yaml": ">=2.1,<3.0"
-            },
-            "suggest": {
-                "jamesmoss/toml": "~0.1",
-                "symfony/yaml": "~2.1"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.2-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Igorw\\Silex": "src"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Igor Wiedler",
-                    "email": "igor@wiedler.ch",
-                    "homepage": "http://wiedler.ch/igor/"
-                },
-                {
-                    "name": "Contributors",
-                    "homepage": "https://github.com/igorw/ConfigServiceProvider/contributors"
-                }
-            ],
-            "description": "A config ServiceProvider for Silex with support for php, json and yaml.",
-            "keywords": [
-                "silex"
-            ],
-            "time": "2013-05-31 14:23:34"
-        },
-        {
-            "name": "imagine/imagine",
-            "version": "dev-develop",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/avalanche123/Imagine.git",
-                "reference": "9c70f0d12b44e16f31fc7a4701082aa46d523761"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/avalanche123/Imagine/zipball/9c70f0d12b44e16f31fc7a4701082aa46d523761",
-                "reference": "9c70f0d12b44e16f31fc7a4701082aa46d523761",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.2"
-            },
-            "require-dev": {
-                "sami/sami": "dev-master"
-            },
-            "suggest": {
-                "ext-gd": "to use the GD implementation",
-                "ext-gmagick": "to use the Gmagick implementation",
-                "ext-imagick": "to use the Imagick implementation"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-0": {
-                    "Imagine": "lib/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Bulat Shakirzyanov",
-                    "email": "mallluhuct@gmail.com",
-                    "homepage": "http://avalanche123.com"
-                }
-            ],
-            "description": "Image processing for PHP 5.3",
-            "homepage": "http://imagine.readthedocs.org/",
-            "keywords": [
-                "drawing",
-                "graphics",
-                "image manipulation",
-                "image processing"
-            ],
-            "time": "2013-04-29 19:10:37"
-        },
-        {
-            "name": "jbroadway/urlify",
-            "version": "dev-master",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/jbroadway/urlify.git",
-                "reference": "064241f45d198239b589c657ea22966f95c80d96"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/jbroadway/urlify/zipball/064241f45d198239b589c657ea22966f95c80d96",
-                "reference": "064241f45d198239b589c657ea22966f95c80d96",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.0"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-0": {
-                    "URLify": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Johnny Broadway",
-                    "email": "johnny@johnnybroadway.com",
-                    "homepage": "http://www.johnnybroadway.com/",
-                    "role": "Main Developer"
-                }
-            ],
-            "description": "PHP port of URLify.js from the Django project. Transliterates non-ascii characters for use in URLs.",
-            "homepage": "https://github.com/jbroadway/urlify",
-            "keywords": [
-                "encode",
-                "iconv",
-                "link",
-                "slug",
-                "translit",
-                "transliterate",
-                "transliteration",
-                "url",
-                "urlify"
-            ],
-            "time": "2013-04-08 13:21:42"
-        },
-        {
-            "name": "jmontoyaa/phpqrcode",
-            "version": "dev-master",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/jmontoyaa/phpqrcode.git",
-                "reference": "f7b600722469b0d98de509206afc4e0738cb44cb"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/jmontoyaa/phpqrcode/zipball/f7b600722469b0d98de509206afc4e0738cb44cb",
-                "reference": "f7b600722469b0d98de509206afc4e0738cb44cb",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=4.3.10"
-            },
-            "type": "library",
-            "autoload": {
-                "classmap": [
-                    "."
-                ]
-            },
-            "license": [
-                "LGPL"
-            ],
-            "authors": [
-                {
-                    "name": "Julio Montoya"
-                }
-            ],
-            "description": "A PHP class to generate QR Code",
-            "homepage": "http://github.com/jmontoyaa/phpqrcode/",
-            "keywords": [
-                "php",
-                "qrcode"
-            ],
-            "support": {
-                "source": "https://github.com/jmontoyaa/phpqrcode/tree/master"
-            },
-            "time": "2013-05-10 14:08:33"
-        },
-        {
-            "name": "knplabs/console-service-provider",
-            "version": "dev-master",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/KnpLabs/ConsoleServiceProvider.git",
-                "reference": "1f1a3315409814d01702a47a8823549c6996de41"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/KnpLabs/ConsoleServiceProvider/zipball/1f1a3315409814d01702a47a8823549c6996de41",
-                "reference": "1f1a3315409814d01702a47a8823549c6996de41",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.2",
-                "symfony/console": ">=2.1,<3.0"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-0": {
-                    "Knp\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "KnpLabs",
-                    "homepage": "http://knplabs.com"
-                }
-            ],
-            "description": "console service provider for Silex",
-            "homepage": "http://knplabs.com",
-            "keywords": [
-                "console",
-                "silex"
-            ],
-            "time": "2013-06-13 12:43:39"
-        },
-        {
-            "name": "knplabs/gaufrette",
-            "version": "dev-master",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/KnpLabs/Gaufrette.git",
-                "reference": "067c6f4e56c9debcda0bc90029cd4c24aac2de9b"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/KnpLabs/Gaufrette/zipball/067c6f4e56c9debcda0bc90029cd4c24aac2de9b",
-                "reference": "067c6f4e56c9debcda0bc90029cd4c24aac2de9b",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.2"
-            },
-            "require-dev": {
-                "amazonwebservices/aws-sdk-for-php": "1.5.*",
-                "doctrine/dbal": ">=2.3",
-                "dropbox-php/dropbox-php": "*",
-                "herzult/php-ssh": "*",
-                "phpseclib/phpseclib": "dev-master",
-                "phpspec/phpspec": "2.0.*",
-                "phpunit/phpunit": "3.7.*",
-                "rackspace/php-cloudfiles": "*",
-                "rackspace/php-opencloud": "dev-master"
-            },
-            "suggest": {
-                "amazonwebservices/aws-sdk-for-php": "to use the Amazon S3 adapter",
-                "doctrine/dbal": "to use the Doctrine DBAL adapter",
-                "dropbox-php/dropbox-php": "to use the Dropbox adapter",
-                "ext-apc": "to use the APC adapter",
-                "ext-curl": "*",
-                "ext-fileinfo": "*",
-                "ext-mbstring": "*",
-                "ext-mongo": "*",
-                "ext-zip": "to use the Zip adapter",
-                "knplabs/knp-gaufrette-bundle": "to use with Symfony2",
-                "phpseclib/phpseclib": "to use the SFTP",
-                "rackspace/php-opencloud": "to use Opencloud adapter"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "0.2.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Gaufrette": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "The contributors",
-                    "homepage": "http://github.com/knplabs/Gaufrette/contributors"
-                },
-                {
-                    "name": "KnpLabs Team",
-                    "homepage": "http://knplabs.com"
-                }
-            ],
-            "description": "PHP5 library that provides a filesystem abstraction layer",
-            "homepage": "http://knplabs.com",
-            "keywords": [
-                "abstraction",
-                "file",
-                "filesystem",
-                "media"
-            ],
-            "time": "2013-06-28 08:38:50"
-        },
-        {
-            "name": "knplabs/knp-menu",
-            "version": "dev-master",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/KnpLabs/KnpMenu.git",
-                "reference": "7baf621fb77867e49daca7dd72b443ea232cb5e1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/KnpLabs/KnpMenu/zipball/7baf621fb77867e49daca7dd72b443ea232cb5e1",
-                "reference": "7baf621fb77867e49daca7dd72b443ea232cb5e1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.0"
-            },
-            "require-dev": {
-                "pimple/pimple": "1.0.*",
-                "silex/silex": "1.0.*",
-                "twig/twig": ">=1.2,<2.0-dev"
-            },
-            "suggest": {
-                "pimple/pimple": "for the built-in implementations of the menu provider and renderer provider",
-                "silex/silex": "for the integration with your silex application",
-                "twig/twig": "for the TwigRenderer and the integration with your templates"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.0.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Knp\\Menu\\": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Christophe Coevoet",
-                    "email": "stof@notk.org"
-                },
-                {
-                    "name": "Knplabs",
-                    "homepage": "http://knplabs.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "https://github.com/KnpLabs/KnpMenu/contributors"
-                }
-            ],
-            "description": "An object oriented menu library",
-            "homepage": "http://knplabs.com",
-            "keywords": [
-                "menu",
-                "tree"
-            ],
-            "time": "2013-06-24 00:02:29"
-        },
-        {
-            "name": "knplabs/knp-snappy",
-            "version": "dev-master",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/KnpLabs/snappy.git",
-                "reference": "524bbd3b1883204ea3a7f11f31fc38b81f6426fe"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/KnpLabs/snappy/zipball/524bbd3b1883204ea3a7f11f31fc38b81f6426fe",
-                "reference": "524bbd3b1883204ea3a7f11f31fc38b81f6426fe",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.0"
-            },
-            "suggest": {
-                "google/wkhtmltopdf-amd64": "Provide wkhtmltopdf-amd64 binary, use version `0.11.0-RC1` as dependency",
-                "google/wkhtmltopdf-i386": "Provide wkhtmltopdf-i386 binary, use version `0.11.0-RC1` as dependency",
-                "symfony/process": "Process Component of Symfony2."
-            },
-            "type": "library",
-            "autoload": {
-                "psr-0": {
-                    "Knp\\Snappy": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "KnpLabs Team",
-                    "homepage": "http://knplabs.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://github.com/KnpLabs/snappy/contributors"
-                }
-            ],
-            "description": "PHP5 library allowing thumbnail, snapshot or PDF generation from a url or a html page. Wrapper for wkhtmltopdf/wkhtmltoimage.",
-            "homepage": "http://github.com/KnpLabs/snappy",
-            "keywords": [
-                "knp",
-                "knplabs",
-                "pdf",
-                "snapshot",
-                "thumbnail",
-                "wkhtmltopdf"
-            ],
-            "time": "2013-04-10 07:21:56"
-        },
-        {
-            "name": "monolog/monolog",
-            "version": "1.5.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/Seldaek/monolog.git",
-                "reference": "1.5.0"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/Seldaek/monolog/zipball/1.5.0",
-                "reference": "1.5.0",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.0",
-                "psr/log": ">=1.0,<2.0"
-            },
-            "require-dev": {
-                "doctrine/couchdb": "dev-master",
-                "mlehner/gelf-php": "1.0.*",
-                "raven/raven": "0.3.*"
-            },
-            "suggest": {
-                "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",
-                "mlehner/gelf-php": "Allow sending log messages to a GrayLog2 server",
-                "raven/raven": "Allow sending log messages to a Sentry server"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.4.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Monolog": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Jordi Boggiano",
-                    "email": "j.boggiano@seld.be",
-                    "homepage": "http://seld.be",
-                    "role": "Developer"
-                }
-            ],
-            "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": "2013-04-23 10:09:48"
-        },
-        {
-            "name": "mpdf/mpdf",
-            "version": "v5.6.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/finwe/mpdf.git",
-                "reference": "v5.6.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/finwe/mpdf/zipball/v5.6.1",
-                "reference": "v5.6.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=4.3.10"
-            },
-            "type": "library",
-            "autoload": {
-                "classmap": [
-                    "mpdf.php",
-                    "classes"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "GPL-1.0+"
-            ],
-            "authors": [
-                {
-                    "name": "Ian Back"
-                }
-            ],
-            "description": "A PHP class to generate PDF files from HTML with Unicode/UTF-8 and CJK support",
-            "homepage": "http://www.mpdf1.com/mpdf/index.php",
-            "keywords": [
-                "pdf",
-                "php",
-                "utf-8"
-            ],
-            "time": "2013-01-26 08:22:27"
-        },
-        {
-            "name": "neutron/silex-filesystem-provider",
-            "version": "dev-master",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/romainneutron/Silex-Filesystem-Service-Provider.git",
-                "reference": "98771524bba1ffa58373c4c06d438f5fb5442ff4"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/romainneutron/Silex-Filesystem-Service-Provider/zipball/98771524bba1ffa58373c4c06d438f5fb5442ff4",
-                "reference": "98771524bba1ffa58373c4c06d438f5fb5442ff4",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3",
-                "silex/silex": ">=1.0",
-                "symfony/filesystem": ">=2.0"
-            },
-            "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": "A Silex Provider for Symfony Filesystem component",
-            "keywords": [
-                "filesystem",
-                "silex",
-                "temporary-filesystem"
-            ],
-            "time": "2012-11-08 21:07:08"
-        },
-        {
-            "name": "pagerfanta/pagerfanta",
-            "version": "dev-master",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/whiteoctober/Pagerfanta.git",
-                "reference": "1a3cb8addb92df6396e59a2c44c3b7f216b4218a"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/whiteoctober/Pagerfanta/zipball/1a3cb8addb92df6396e59a2c44c3b7f216b4218a",
-                "reference": "1a3cb8addb92df6396e59a2c44c3b7f216b4218a",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.0"
-            },
-            "require-dev": {
-                "doctrine/mongodb-odm": "*",
-                "doctrine/orm": "2.*",
-                "mandango/mandango": "*",
-                "propel/propel1": ">=1.6,<2.0",
-                "solarium/solarium": "dev-develop"
-            },
-            "suggest": {
-                "doctrine/mongodb-odm": "To use the DoctrineODMMongoDBAdapter.",
-                "doctrine/orm": "To use the DoctrineORMAdapter.",
-                "mandango/mandango": "To use the MandangoAdapter.",
-                "propel/propel1": "To use the PropelAdapter",
-                "solarium/solarium": "To use the SolariumAdapter."
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Pagerfanta\\": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Pablo Díez",
-                    "email": "pablodip@gmail.com",
-                    "homepage": "http://github.com/pablodip"
-                }
-            ],
-            "description": "Pagination for PHP 5.3",
-            "keywords": [
-                "page",
-                "pagination",
-                "paginator",
-                "paging"
-            ],
-            "time": "2013-06-13 22:25:28"
-        },
-        {
-            "name": "pimple/pimple",
-            "version": "v1.0.2",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/fabpot/Pimple.git",
-                "reference": "v1.0.2"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/fabpot/Pimple/zipball/v1.0.2",
-                "reference": "v1.0.2",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.0"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Pimple": "lib/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                }
-            ],
-            "description": "Pimple is a simple Dependency Injection Container for PHP 5.3",
-            "homepage": "http://pimple.sensiolabs.org",
-            "keywords": [
-                "container",
-                "dependency injection"
-            ],
-            "time": "2013-03-08 08:21:40"
-        },
-        {
-            "name": "psr/log",
-            "version": "1.0.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/php-fig/log",
-                "reference": "1.0.0"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://github.com/php-fig/log/archive/1.0.0.zip",
-                "reference": "1.0.0",
-                "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": "realityking/pchart",
-            "version": "dev-master",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/realityking/pChart.git",
-                "reference": "46fd01cad5a4d761b599df1ab09361fad55c83b6"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/realityking/pChart/zipball/46fd01cad5a4d761b599df1ab09361fad55c83b6",
-                "reference": "46fd01cad5a4d761b599df1ab09361fad55c83b6",
-                "shasum": ""
-            },
-            "type": "library",
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "GPL-1.0+"
-            ],
-            "authors": [
-                {
-                    "name": "Rouven Weßling",
-                    "email": "me@rouvenwessling.de",
-                    "homepage": "http://www.rouvenwessling.de"
-                }
-            ],
-            "description": "A fork of the popular pChart library.",
-            "time": "2013-03-18 08:23:38"
-        },
-        {
-            "name": "silex/silex",
-            "version": "v1.0.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/fabpot/Silex.git",
-                "reference": "v1.0.0"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/fabpot/Silex/zipball/v1.0.0",
-                "reference": "v1.0.0",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3",
-                "pimple/pimple": "1.*",
-                "symfony/event-dispatcher": ">=2.1,<2.4-dev",
-                "symfony/http-foundation": ">=2.1,<2.4-dev",
-                "symfony/http-kernel": ">=2.1,<2.4-dev",
-                "symfony/routing": ">=2.1,<2.4-dev"
-            },
-            "require-dev": {
-                "doctrine/dbal": ">=2.2.0,<2.4.0-dev",
-                "monolog/monolog": ">=1.4,<2.0,>=1.4.1",
-                "swiftmailer/swiftmailer": "5.*",
-                "symfony/browser-kit": ">=2.1,<2.4-dev",
-                "symfony/config": ">=2.1,<2.4-dev",
-                "symfony/css-selector": ">=2.1,<2.4-dev",
-                "symfony/dom-crawler": ">=2.1,<2.4-dev",
-                "symfony/finder": ">=2.1,<2.4-dev",
-                "symfony/form": ">=2.1.4,<2.4-dev",
-                "symfony/locale": ">=2.1,<2.4-dev",
-                "symfony/monolog-bridge": ">=2.1,<2.4-dev",
-                "symfony/options-resolver": ">=2.1,<2.4-dev",
-                "symfony/process": ">=2.1,<2.4-dev",
-                "symfony/security": ">=2.1,<2.4-dev",
-                "symfony/serializer": ">=2.1,<2.4-dev",
-                "symfony/translation": ">=2.1,<2.4-dev",
-                "symfony/twig-bridge": ">=2.1,<2.4-dev",
-                "symfony/validator": ">=2.1,<2.4-dev",
-                "twig/twig": ">=1.8.0,<2.0-dev"
-            },
-            "suggest": {
-                "symfony/browser-kit": ">=2.1,<2.4-dev",
-                "symfony/css-selector": ">=2.1,<2.4-dev",
-                "symfony/dom-crawler": ">=2.1,<2.4-dev",
-                "symfony/form": ">= 2.1.4,<2.4-dev"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Silex": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Igor Wiedler",
-                    "email": "igor@wiedler.ch",
-                    "homepage": "http://wiedler.ch/igor/"
-                }
-            ],
-            "description": "The PHP micro-framework based on the Symfony2 Components",
-            "homepage": "http://silex.sensiolabs.org",
-            "keywords": [
-                "microframework"
-            ],
-            "time": "2013-05-03 16:49:57"
-        },
-        {
-            "name": "swiftmailer/swiftmailer",
-            "version": "v4.1.8",
-            "source": {
-                "type": "git",
-                "url": "git://github.com/swiftmailer/swiftmailer.git",
-                "reference": "v4.1.8"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://github.com/swiftmailer/swiftmailer/zipball/v4.1.8",
-                "reference": "v4.1.8",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.2.4"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "4.1-dev"
-                }
-            },
-            "autoload": {
-                "files": [
-                    "lib/swift_required.php"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "LGPL"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Chris Corbyn"
-                }
-            ],
-            "description": "Swiftmailer, free feature-rich PHP mailer",
-            "homepage": "http://swiftmailer.org",
-            "keywords": [
-                "mail",
-                "mailer"
-            ],
-            "time": "2012-06-17 13:55:34"
-        },
-        {
-            "name": "symfony/config",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Component/Config",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/Config.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Config/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3",
-                "symfony/filesystem": ">=2.3,<3.0"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\Config\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony Config Component",
-            "homepage": "http://symfony.com",
-            "time": "2013-06-03 00:18:25"
-        },
-        {
-            "name": "symfony/console",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Component/Console",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/Console.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Console/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "symfony/event-dispatcher": ">=2.1,<3.0"
-            },
-            "suggest": {
-                "symfony/event-dispatcher": ""
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\Console\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony Console Component",
-            "homepage": "http://symfony.com",
-            "time": "2013-06-11 07:15:14"
-        },
-        {
-            "name": "symfony/debug",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Component/Debug",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/Debug.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Debug/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "symfony/http-foundation": ">=2.1,<3.0",
-                "symfony/http-kernel": ">=2.1,<3.0"
-            },
-            "suggest": {
-                "symfony/class-loader": "",
-                "symfony/http-foundation": "",
-                "symfony/http-kernel": ""
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\Debug\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony Debug Component",
-            "homepage": "http://symfony.com",
-            "time": "2013-06-02 11:58:44"
-        },
-        {
-            "name": "symfony/dependency-injection",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Component/DependencyInjection",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/DependencyInjection.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "symfony/config": ">=2.2,<3.0",
-                "symfony/yaml": ">=2.0,<3.0"
-            },
-            "suggest": {
-                "symfony/config": "",
-                "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them",
-                "symfony/yaml": ""
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\DependencyInjection\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony DependencyInjection Component",
-            "homepage": "http://symfony.com",
-            "time": "2013-06-05 09:51:05"
-        },
-        {
-            "name": "symfony/doctrine-bridge",
-            "version": "2.3.x-dev",
-            "target-dir": "Symfony/Bridge/Doctrine",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/DoctrineBridge.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/DoctrineBridge/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "doctrine/common": ">=2.2,<3.0",
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "doctrine/data-fixtures": "1.0.*",
-                "doctrine/dbal": ">=2.2,<3.0",
-                "doctrine/orm": ">=2.2,<3.0,>=2.2.3",
-                "symfony/dependency-injection": ">=2.0,<3.0",
-                "symfony/form": ">=2.2,<3.0",
-                "symfony/http-kernel": ">=2.2,<3.0",
-                "symfony/security": ">=2.2,<3.0",
-                "symfony/stopwatch": ">=2.2,<3.0",
-                "symfony/validator": ">=2.2,<3.0"
-            },
-            "suggest": {
-                "doctrine/data-fixtures": "",
-                "doctrine/dbal": "",
-                "doctrine/orm": "",
-                "symfony/form": "",
-                "symfony/validator": ""
-            },
-            "type": "symfony-bridge",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Bridge\\Doctrine\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony Doctrine Bridge",
-            "homepage": "http://symfony.com",
-            "time": "2013-05-16 08:06:37"
-        },
-        {
-            "name": "symfony/event-dispatcher",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Component/EventDispatcher",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/EventDispatcher.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "symfony/dependency-injection": ">=2.0,<3.0"
-            },
-            "suggest": {
-                "symfony/dependency-injection": "",
-                "symfony/http-kernel": ""
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\EventDispatcher\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony EventDispatcher Component",
-            "homepage": "http://symfony.com",
-            "time": "2013-05-13 14:36:40"
-        },
-        {
-            "name": "symfony/filesystem",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Component/Filesystem",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/Filesystem.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Filesystem/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\Filesystem\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony Filesystem Component",
-            "homepage": "http://symfony.com",
-            "time": "2013-06-04 15:02:05"
-        },
-        {
-            "name": "symfony/form",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Component/Form",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/Form.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Form/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3",
-                "symfony/event-dispatcher": ">=2.1,<3.0",
-                "symfony/intl": ">=2.3,<3.0",
-                "symfony/options-resolver": ">=2.1,<3.0",
-                "symfony/property-access": ">=2.2,<3.0"
-            },
-            "require-dev": {
-                "symfony/http-foundation": ">=2.2,<3.0",
-                "symfony/validator": ">=2.2,<3.0"
-            },
-            "suggest": {
-                "symfony/http-foundation": "",
-                "symfony/validator": ""
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\Form\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony Form Component",
-            "homepage": "http://symfony.com",
-            "time": "2013-06-02 12:05:51"
-        },
-        {
-            "name": "symfony/http-foundation",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Component/HttpFoundation",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/HttpFoundation.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\HttpFoundation\\": ""
-                },
-                "classmap": [
-                    "Symfony/Component/HttpFoundation/Resources/stubs"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony HttpFoundation Component",
-            "homepage": "http://symfony.com",
-            "time": "2013-05-10 06:00:03"
-        },
-        {
-            "name": "symfony/http-kernel",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Component/HttpKernel",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/HttpKernel.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/HttpKernel/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3",
-                "psr/log": ">=1.0,<2.0",
-                "symfony/debug": ">=2.3,<3.0",
-                "symfony/event-dispatcher": ">=2.1,<3.0",
-                "symfony/http-foundation": ">=2.2,<3.0"
-            },
-            "require-dev": {
-                "symfony/browser-kit": "2.2.*",
-                "symfony/class-loader": ">=2.1,<3.0",
-                "symfony/config": ">=2.0,<3.0",
-                "symfony/console": "2.2.*",
-                "symfony/dependency-injection": ">=2.0,<3.0",
-                "symfony/finder": ">=2.0,<3.0",
-                "symfony/process": ">=2.0,<3.0",
-                "symfony/routing": ">=2.2,<3.0",
-                "symfony/stopwatch": ">=2.2,<3.0"
-            },
-            "suggest": {
-                "symfony/browser-kit": "",
-                "symfony/class-loader": "",
-                "symfony/config": "",
-                "symfony/console": "",
-                "symfony/dependency-injection": "",
-                "symfony/finder": ""
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\HttpKernel\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony HttpKernel Component",
-            "homepage": "http://symfony.com",
-            "time": "2013-06-11 11:46:38"
-        },
-        {
-            "name": "symfony/icu",
-            "version": "v1.2.0",
-            "target-dir": "Symfony/Component/Icu",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/Icu.git",
-                "reference": "v1.2.0"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Icu/zipball/v1.2.0",
-                "reference": "v1.2.0",
-                "shasum": ""
-            },
-            "require": {
-                "lib-icu": ">=4.4",
-                "php": ">=5.3.3",
-                "symfony/intl": ">=2.3,<3.0"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\Icu\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                },
-                {
-                    "name": "Bernhard Schussek",
-                    "email": "bschussek@gmail.com"
-                }
-            ],
-            "description": "Contains an excerpt of the ICU data and classes to load it.",
-            "homepage": "http://symfony.com",
-            "keywords": [
-                "icu",
-                "intl"
-            ],
-            "time": "2013-06-03 18:32:58"
-        },
-        {
-            "name": "symfony/intl",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Component/Intl",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/Intl.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Intl/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3",
-                "symfony/icu": ">=1.0-RC,<2.0"
-            },
-            "require-dev": {
-                "symfony/filesystem": ">=2.1"
-            },
-            "suggest": {
-                "ext-intl": "to use the component with locales other than \"en\""
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\Intl\\": ""
-                },
-                "classmap": [
-                    "Symfony/Component/Intl/Resources/stubs"
-                ],
-                "files": [
-                    "Symfony/Component/Intl/Resources/stubs/functions.php"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                },
-                {
-                    "name": "Igor Wiedler",
-                    "email": "igor@wiedler.ch",
-                    "homepage": "http://wiedler.ch/igor/"
-                },
-                {
-                    "name": "Bernhard Schussek",
-                    "email": "bschussek@gmail.com"
-                },
-                {
-                    "name": "Eriksen Costa",
-                    "email": "eriksen.costa@infranology.com.br"
-                }
-            ],
-            "description": "A PHP replacement layer for the C intl extension that includes additional data from the ICU library.",
-            "homepage": "http://symfony.com",
-            "keywords": [
-                "i18n",
-                "icu",
-                "internationalization",
-                "intl",
-                "l10n",
-                "localization"
-            ],
-            "time": "2013-05-18 11:21:22"
-        },
-        {
-            "name": "symfony/locale",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Component/Locale",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/Locale.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Locale/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3",
-                "symfony/intl": ">=2.3"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\Locale\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony Locale Component",
-            "homepage": "http://symfony.com",
-            "time": "2013-04-11 09:29:25"
-        },
-        {
-            "name": "symfony/monolog-bridge",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Bridge/Monolog",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/MonologBridge.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/MonologBridge/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "monolog/monolog": ">=1.3,<2.0",
-                "php": ">=5.3.3",
-                "symfony/http-kernel": ">=2.2,<3.0"
-            },
-            "type": "symfony-bridge",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Bridge\\Monolog\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony Monolog Bridge",
-            "homepage": "http://symfony.com",
-            "time": "2013-05-24 13:05:33"
-        },
-        {
-            "name": "symfony/options-resolver",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Component/OptionsResolver",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/OptionsResolver.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/OptionsResolver/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\OptionsResolver\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony OptionsResolver Component",
-            "homepage": "http://symfony.com",
-            "keywords": [
-                "config",
-                "configuration",
-                "options"
-            ],
-            "time": "2013-04-11 06:50:46"
-        },
-        {
-            "name": "symfony/property-access",
-            "version": "2.3.x-dev",
-            "target-dir": "Symfony/Component/PropertyAccess",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/PropertyAccess.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/PropertyAccess/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\PropertyAccess\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony PropertyAccess Component",
-            "homepage": "http://symfony.com",
-            "keywords": [
-                "access",
-                "array",
-                "extraction",
-                "index",
-                "injection",
-                "object",
-                "property",
-                "property path",
-                "reflection"
-            ],
-            "time": "2013-04-30 16:43:32"
-        },
-        {
-            "name": "symfony/routing",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Component/Routing",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/Routing.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Routing/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "doctrine/common": ">=2.2,<3.0",
-                "psr/log": ">=1.0,<2.0",
-                "symfony/config": ">=2.2,<3.0",
-                "symfony/yaml": ">=2.0,<3.0"
-            },
-            "suggest": {
-                "doctrine/common": "",
-                "symfony/config": "",
-                "symfony/yaml": ""
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\Routing\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony Routing Component",
-            "homepage": "http://symfony.com",
-            "time": "2013-05-20 08:57:26"
-        },
-        {
-            "name": "symfony/security",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Component/Security",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/Security.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Security/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3",
-                "symfony/event-dispatcher": ">=2.1,<3.0",
-                "symfony/http-foundation": ">=2.1,<3.0",
-                "symfony/http-kernel": ">=2.1,<3.0"
-            },
-            "require-dev": {
-                "doctrine/common": ">=2.2,<3.0",
-                "doctrine/dbal": ">=2.2,<3.0",
-                "ircmaxell/password-compat": "1.0.*",
-                "psr/log": ">=1.0,<2.0",
-                "symfony/form": ">=2.0,<3.0",
-                "symfony/routing": ">=2.2,<3.0",
-                "symfony/validator": ">=2.2,<3.0"
-            },
-            "suggest": {
-                "doctrine/dbal": "to use the built-in ACL implementation",
-                "ircmaxell/password-compat": "",
-                "symfony/class-loader": "",
-                "symfony/finder": "",
-                "symfony/form": "",
-                "symfony/routing": "",
-                "symfony/validator": ""
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\Security\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony Security Component",
-            "homepage": "http://symfony.com",
-            "time": "2013-06-02 22:50:02"
-        },
-        {
-            "name": "symfony/translation",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Component/Translation",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/Translation.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Translation/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "symfony/config": ">=2.0,<3.0",
-                "symfony/yaml": ">=2.2,<3.0"
-            },
-            "suggest": {
-                "symfony/config": "",
-                "symfony/yaml": ""
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\Translation\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony Translation Component",
-            "homepage": "http://symfony.com",
-            "time": "2013-05-13 14:36:40"
-        },
-        {
-            "name": "symfony/twig-bridge",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Bridge/Twig",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/TwigBridge.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/TwigBridge/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3",
-                "twig/twig": ">=1.11.0,<2.0"
-            },
-            "require-dev": {
-                "symfony/form": "2.2.*",
-                "symfony/http-kernel": ">=2.2,<3.0",
-                "symfony/routing": ">=2.2,<3.0",
-                "symfony/security": ">=2.0,<3.0",
-                "symfony/templating": ">=2.1,<3.0",
-                "symfony/translation": ">=2.2,<3.0",
-                "symfony/yaml": ">=2.0,<3.0"
-            },
-            "suggest": {
-                "symfony/form": "",
-                "symfony/http-kernel": "",
-                "symfony/routing": "",
-                "symfony/security": "",
-                "symfony/templating": "",
-                "symfony/translation": "",
-                "symfony/yaml": ""
-            },
-            "type": "symfony-bridge",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Bridge\\Twig\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony Twig Bridge",
-            "homepage": "http://symfony.com",
-            "time": "2013-05-16 10:19:58"
-        },
-        {
-            "name": "symfony/validator",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Component/Validator",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/Validator.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Validator/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3",
-                "symfony/translation": ">=2.0,<3.0"
-            },
-            "require-dev": {
-                "symfony/config": ">=2.2,<3.0",
-                "symfony/http-foundation": ">=2.1,<3.0",
-                "symfony/intl": ">=2.3,<3.0",
-                "symfony/yaml": ">=2.0,<3.0"
-            },
-            "suggest": {
-                "doctrine/common": "",
-                "symfony/config": "",
-                "symfony/http-foundation": "",
-                "symfony/intl": "",
-                "symfony/yaml": ""
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\Validator\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony Validator Component",
-            "homepage": "http://symfony.com",
-            "time": "2013-06-10 16:23:25"
-        },
-        {
-            "name": "symfony/yaml",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Component/Yaml",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/Yaml.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Yaml/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\Yaml\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony Yaml Component",
-            "homepage": "http://symfony.com",
-            "time": "2013-05-10 18:12:13"
-        },
-        {
-            "name": "twig/twig",
-            "version": "v1.13.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/fabpot/Twig.git",
-                "reference": "v1.13.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/fabpot/Twig/zipball/v1.13.1",
-                "reference": "v1.13.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.2.4"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.13-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Twig_": "lib/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Armin Ronacher",
-                    "email": "armin.ronacher@active-4.com"
-                }
-            ],
-            "description": "Twig, the flexible, fast, and secure template language for PHP",
-            "homepage": "http://twig.sensiolabs.org",
-            "keywords": [
-                "templating"
-            ],
-            "time": "2013-06-06 06:06:01"
-        }
-    ],
-    "packages-dev": [
-        {
-            "name": "filp/whoops",
-            "version": "dev-master",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/filp/whoops.git",
-                "reference": "cb2fa6ce8b34290345557ff5079328b97a6b61b6"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/filp/whoops/zipball/cb2fa6ce8b34290345557ff5079328b97a6b61b6",
-                "reference": "cb2fa6ce8b34290345557ff5079328b97a6b61b6",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.0"
-            },
-            "require-dev": {
-                "mockery/mockery": "dev-master",
-                "silex/silex": "1.0.*@dev"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-0": {
-                    "Whoops": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Filipe Dobreira",
-                    "homepage": "https://github.com/filp",
-                    "role": "Developer"
-                }
-            ],
-            "description": "php error handling for cool kids",
-            "homepage": "https://github.com/filp/whoops",
-            "keywords": [
-                "error",
-                "exception",
-                "handling",
-                "library",
-                "silex-provider",
-                "whoops",
-                "zf2"
-            ],
-            "time": "2013-06-19 20:39:43"
-        },
-        {
-            "name": "kriswallsmith/assetic",
-            "version": "v1.1.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/kriswallsmith/assetic.git",
-                "reference": "v1.1.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/kriswallsmith/assetic/zipball/v1.1.1",
-                "reference": "v1.1.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.1",
-                "symfony/process": ">=2.1,<3.0"
-            },
-            "require-dev": {
-                "cssmin/cssmin": "*",
-                "joliclic/javascript-packer": "*",
-                "kamicane/packager": "*",
-                "leafo/lessphp": "*",
-                "leafo/scssphp": "*",
-                "leafo/scssphp-compass": "*",
-                "mrclay/minify": "*",
-                "phpunit/phpunit": ">=3.7,<4.0",
-                "ptachoire/cssembed": "*",
-                "twig/twig": ">=1.6,<2.0"
-            },
-            "suggest": {
-                "leafo/lessphp": "Assetic provides the integration with the lessphp LESS compiler",
-                "leafo/scssphp": "Assetic provides the integration with the scssphp SCSS compiler",
-                "leafo/scssphp-compass": "Assetic provides the integration with the SCSS compass plugin",
-                "ptachoire/cssembed": "Assetic provides the integration with phpcssembed to embed data uris",
-                "twig/twig": "Assetic provides the integration with the Twig templating engine"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.1-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Assetic": "src/"
-                },
-                "files": [
-                    "src/functions.php"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Kris Wallsmith",
-                    "email": "kris.wallsmith@gmail.com",
-                    "homepage": "http://kriswallsmith.net/"
-                }
-            ],
-            "description": "Asset Management for PHP",
-            "homepage": "https://github.com/kriswallsmith/assetic",
-            "keywords": [
-                "assets",
-                "compression",
-                "minification"
-            ],
-            "time": "2013-06-01 22:13:43"
-        },
-        {
-            "name": "leafo/lessphp",
-            "version": "dev-master",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/leafo/lessphp.git",
-                "reference": "ff86f2941c3f3d67d56acad2f8902ca57c73b359"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/leafo/lessphp/zipball/ff86f2941c3f3d67d56acad2f8902ca57c73b359",
-                "reference": "ff86f2941c3f3d67d56acad2f8902ca57c73b359",
-                "shasum": ""
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "0.3-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "lessc.inc.php"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT",
-                "GPL-3.0"
-            ],
-            "authors": [
-                {
-                    "name": "Leaf Corcoran",
-                    "email": "leafot@gmail.com",
-                    "homepage": "http://leafo.net"
-                }
-            ],
-            "description": "lessphp is a compiler for LESS written in PHP.",
-            "homepage": "http://leafo.net/lessphp/",
-            "time": "2013-05-22 17:52:29"
-        },
-        {
-            "name": "mheap/silex-assetic",
-            "version": "dev-master",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/mheap/Silex-Assetic.git",
-                "reference": "8e6243f84100987a313ebb903e378b1de6cc8fb8"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/mheap/Silex-Assetic/zipball/8e6243f84100987a313ebb903e378b1de6cc8fb8",
-                "reference": "8e6243f84100987a313ebb903e378b1de6cc8fb8",
-                "shasum": ""
-            },
-            "require": {
-                "kriswallsmith/assetic": ">=1.0,<2.0",
-                "php": ">=5.3.0",
-                "symfony/finder": ">=2.1,<2.3-dev"
-            },
-            "require-dev": {
-                "phpunit/phpunit": ">=3.7.10.0,<3.8",
-                "silex/silex": ">=1.0,<2.0",
-                "twig/twig": ">=1.2,<2.0"
-            },
-            "suggest": {
-                "twig/twig": "~1.2"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "SilexAssetic": "src"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Sven Eisenschmidt",
-                    "email": "sven.eisenschmidt@gmail.com",
-                    "homepage": "http://unsicherheitsagent.de/"
-                },
-                {
-                    "name": "Michael Heap",
-                    "email": "m@michaelheap.com",
-                    "homepage": "http://michaelheap.com/"
-                }
-            ],
-            "description": "Assetic extension for Silex",
-            "homepage": "https://github.com/mheap/Silex-Assetic",
-            "keywords": [
-                "assetic",
-                "silex"
-            ],
-            "time": "2013-05-28 13:04:36"
-        },
-        {
-            "name": "natxet/CssMin",
-            "version": "dev-master",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/natxet/CssMin.git",
-                "reference": "9801e2a0de7ae252ca4f2b85542d75a82047a8b4"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/natxet/CssMin/zipball/9801e2a0de7ae252ca4f2b85542d75a82047a8b4",
-                "reference": "9801e2a0de7ae252ca4f2b85542d75a82047a8b4",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.0"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-0": {
-                    "CssMin": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Joe Scylla",
-                    "email": "joe.scylla@gmail.com",
-                    "homepage": "https://profiles.google.com/joe.scylla"
-                }
-            ],
-            "description": "Minifying CSS",
-            "homepage": "http://code.google.com/p/cssmin/",
-            "keywords": [
-                "css",
-                "minify"
-            ],
-            "time": "2013-03-15 18:47:32"
-        },
-        {
-            "name": "sensio/framework-extra-bundle",
-            "version": "dev-master",
-            "target-dir": "Sensio/Bundle/FrameworkExtraBundle",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sensiolabs/SensioFrameworkExtraBundle.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sensiolabs/SensioFrameworkExtraBundle/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "doctrine/common": ">=2.2,<3.0",
-                "symfony/framework-bundle": ">=2.2,<3.0"
-            },
-            "type": "symfony-bundle",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Sensio\\Bundle\\FrameworkExtraBundle": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                }
-            ],
-            "description": "This bundle provides a way to configure your controllers with annotations",
-            "keywords": [
-                "annotations",
-                "controllers"
-            ],
-            "time": "2013-06-02 16:13:20"
-        },
-        {
-            "name": "silex/web-profiler",
-            "version": "dev-master",
-            "target-dir": "Silex/Provider",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/silexphp/Silex-WebProfiler.git",
-                "reference": "3d875ac4f583e893a076ec51478e38eeaf0cb562"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/silexphp/Silex-WebProfiler/zipball/3d875ac4f583e893a076ec51478e38eeaf0cb562",
-                "reference": "3d875ac4f583e893a076ec51478e38eeaf0cb562",
-                "shasum": ""
-            },
-            "require": {
-                "silex/silex": ">=1.0,<2.0",
-                "symfony/stopwatch": ">=2.2,<3.0",
-                "symfony/web-profiler-bundle": ">=2.2,<3.0"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Silex\\Provider\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                }
-            ],
-            "description": "A WebProfiler for Silex",
-            "homepage": "http://silex.sensiolabs.org/",
-            "time": "2013-05-03 17:04:41"
-        },
-        {
-            "name": "symfony/browser-kit",
-            "version": "2.3.x-dev",
-            "target-dir": "Symfony/Component/BrowserKit",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/BrowserKit.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/BrowserKit/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3",
-                "symfony/dom-crawler": ">=2.0,<3.0"
-            },
-            "require-dev": {
-                "symfony/css-selector": ">=2.0,<3.0",
-                "symfony/process": ">=2.0,<3.0"
-            },
-            "suggest": {
-                "symfony/process": ""
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\BrowserKit\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony BrowserKit Component",
-            "homepage": "http://symfony.com",
-            "time": "2013-05-15 15:16:47"
-        },
-        {
-            "name": "symfony/dom-crawler",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Component/DomCrawler",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/DomCrawler.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/DomCrawler/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "symfony/css-selector": ">=2.0,<3.0"
-            },
-            "suggest": {
-                "symfony/css-selector": ""
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\DomCrawler\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony DomCrawler Component",
-            "homepage": "http://symfony.com",
-            "time": "2013-06-11 07:15:14"
-        },
-        {
-            "name": "symfony/finder",
-            "version": "v2.2.3",
-            "target-dir": "Symfony/Component/Finder",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/Finder.git",
-                "reference": "v2.2.3"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Finder/zipball/v2.2.3",
-                "reference": "v2.2.3",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.2-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\Finder\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony Finder Component",
-            "homepage": "http://symfony.com",
-            "time": "2013-06-10 18:35:46"
-        },
-        {
-            "name": "symfony/framework-bundle",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Bundle/FrameworkBundle",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/FrameworkBundle.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/FrameworkBundle/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "doctrine/common": ">=2.2,<3.0",
-                "php": ">=5.3.3",
-                "symfony/config": ">=2.2,<3.0",
-                "symfony/dependency-injection": ">=2.2,<3.0",
-                "symfony/event-dispatcher": ">=2.1,<3.0",
-                "symfony/filesystem": ">=2.3,<3.0",
-                "symfony/http-kernel": ">=2.3,<3.0",
-                "symfony/routing": ">=2.2,<3.0",
-                "symfony/stopwatch": ">=2.3,<3.0",
-                "symfony/templating": ">=2.1,<3.0",
-                "symfony/translation": ">=2.3,<3.0"
-            },
-            "require-dev": {
-                "symfony/class-loader": ">=2.1,<3.0",
-                "symfony/finder": ">=2.0,<3.0",
-                "symfony/form": ">=2.3,<3.0",
-                "symfony/security": ">=2.3,<3.0",
-                "symfony/validator": ">=2.1,<3.0"
-            },
-            "suggest": {
-                "symfony/console": "",
-                "symfony/finder": "",
-                "symfony/form": "",
-                "symfony/validator": ""
-            },
-            "type": "symfony-bundle",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Bundle\\FrameworkBundle\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony FrameworkBundle",
-            "homepage": "http://symfony.com",
-            "time": "2013-06-07 22:05:01"
-        },
-        {
-            "name": "symfony/process",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Component/Process",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/Process.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Process/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\Process\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony Process Component",
-            "homepage": "http://symfony.com",
-            "time": "2013-05-06 20:03:44"
-        },
-        {
-            "name": "symfony/stopwatch",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Component/Stopwatch",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/Stopwatch.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\Stopwatch\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony Stopwatch Component",
-            "homepage": "http://symfony.com",
-            "time": "2013-04-17 07:17:10"
-        },
-        {
-            "name": "symfony/templating",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Component/Templating",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/Templating.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Templating/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\Templating\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony Templating Component",
-            "homepage": "http://symfony.com",
-            "time": "2013-04-17 05:31:37"
-        },
-        {
-            "name": "symfony/web-profiler-bundle",
-            "version": "v2.3.1",
-            "target-dir": "Symfony/Bundle/WebProfilerBundle",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/WebProfilerBundle.git",
-                "reference": "v2.3.1"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/WebProfilerBundle/zipball/v2.3.1",
-                "reference": "v2.3.1",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3",
-                "symfony/http-kernel": ">=2.2,<3.0",
-                "symfony/routing": ">=2.2,<3.0",
-                "symfony/twig-bridge": ">=2.2,<3.0"
-            },
-            "require-dev": {
-                "symfony/config": ">=2.2,<3.0",
-                "symfony/dependency-injection": ">=2.0,<3.0",
-                "symfony/stopwatch": ">=2.2,<3.0"
-            },
-            "type": "symfony-bundle",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Symfony\\Bundle\\WebProfilerBundle\\": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "http://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony WebProfilerBundle",
-            "homepage": "http://symfony.com",
-            "time": "2013-05-24 14:20:41"
-        }
-    ],
-    "aliases": [
-
-    ],
-    "minimum-stability": "stable",
-    "stability-flags": {
-        "symfony/doctrine-bridge": 20,
-        "symfony/property-access": 20,
-        "dflydev/doctrine-orm-service-provider": 20,
-        "doctrine/migrations": 20,
-        "gedmo/doctrine-extensions": 20,
-        "chamilo/chash": 20,
-        "pagerfanta/pagerfanta": 20,
-        "franmomu/silex-pagerfanta-provider": 20,
-        "igorw/config-service-provider": 20,
-        "realityking/pchart": 20,
-        "imagine/imagine": 20,
-        "grom/silex-service-provider": 20,
-        "knplabs/knp-menu": 20,
-        "knplabs/knp-snappy": 20,
-        "knplabs/console-service-provider": 20,
-        "knplabs/gaufrette": 20,
-        "jmontoyaa/phpqrcode": 20,
-        "bt51/gaufrette-serviceprovider": 20,
-        "neutron/silex-filesystem-provider": 20,
-        "jbroadway/urlify": 20,
-        "symfony/browser-kit": 20,
-        "silex/web-profiler": 20,
-        "natxet/cssmin": 20,
-        "leafo/lessphp": 20,
-        "mheap/silex-assetic": 20,
-        "filp/whoops": 20,
-        "sensio/framework-extra-bundle": 20
-    },
-    "platform": {
-        "php": ">=5.3.2"
-    },
-    "platform-dev": [
-
-    ]
-}

+ 4 - 1
config/configuration.dist.php

@@ -27,6 +27,8 @@
  */
 // Host.
 $_configuration['db_host']     = '{DATABASE_HOST}';
+// Port.
+$_configuration['db_port']     = '{DATABASE_PORT}';
 // Username.
 $_configuration['db_user']     = '{DATABASE_USER}';
 // Password.
@@ -38,9 +40,10 @@ $_configuration['main_database'] = '{DATABASE_MAIN}';
 
 /** Directory settings */
 // URL to the root of your Chamilo installation, e.g.: http://www.mychamilo.com/
+// Comment this line if you want to enable multiple URLs
 $_configuration['root_web']    = '{ROOT_WEB}';
 
-/** Chamilo will automatically manage all this paths */
+/** Chamilo will automatically manage the following paths */
 
 // Path to the webroot of system, example: /var/www/chamilo
 //$_configuration['root_sys'] = '{ROOT_SYS}';

+ 1 - 0
config/configuration.dist.yml.php

@@ -21,6 +21,7 @@ $_configuration['main_database']         = 'chamilo';
  * Directory settings
  */
 // URL to the root of your Chamilo installation, e.g.: http://www.mychamilo.com/
+// Comment this line if you want to enable multiple URLs
 $_configuration['root_web']       = 'http://localhost/chamilo';
 $_configuration['root_sys']       = '/var/www/chamilo';
 

+ 1 - 0
config/profile.conf.dist.php

@@ -11,6 +11,7 @@
 define('CHECK_PASS_EASY_TO_FIND', false);
 
 $profileIsEditable = true;
+$profileIsReadable = true;
 
 // User photos
 define('PREFIX_IMAGE_FILENAME_WITH_UID', true); // If true, filename of images on server begin with uid of the user.

+ 12 - 0
config/routing.yml

@@ -0,0 +1,12 @@
+admin_login_check:
+    pattern:   /admin/login_check
+admin_logout:
+    pattern:   /admin/logout
+
+home:
+    path:      /home
+    defaults:  { _controller: index.controller:indexAction, culture: en }
+
+example:
+    resource: "src/ChamiloLMS/Resources/config/route_example.yml"
+    prefix:   /example-route

+ 4 - 6
console.php

@@ -71,11 +71,7 @@ $cli->addCommands(
         new \Doctrine\DBAL\Migrations\Tools\Console\Command\VersionCommand(),
 
         // Chamilo commands.
-        new ChamiloLMS\Command\Database\UpgradeCommand(),
-        new ChamiloLMS\Command\Database\InstallCommand(),
-        //new ChamiloLMS\Command\Database\InstallExtendCommand(),
-        new ChamiloLMS\Command\Database\StatusCommand(),
-        new ChamiloLMS\Command\Database\SetupCommand(),
+
         new ChamiloLMS\Command\Template\AsseticDumpCommand(),
         new ChamiloLMS\Command\Translation\ExportLanguagesCommand(),
 
@@ -86,8 +82,10 @@ $cli->addCommands(
         new Chash\Command\Database\SQLCountCommand(),
         new Chash\Command\Database\FullBackupCommand(),
         new Chash\Command\Database\DropDatabaseCommand(),
+
         new Chash\Command\Files\CleanTempFolderCommand(),
-        new Chash\Command\Files\CleanConfigFiles(),
+        new Chash\Command\Files\CleanConfigFilesCommand(),
+
         new Chash\Command\Translation\ExportLanguageCommand(),
         new Chash\Command\Translation\ImportLanguageCommand()
     )

+ 146 - 14
documentation/changelog.html

@@ -44,7 +44,6 @@
 <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.10.0 - ???, 31st of ???, 2012</h1>
 <h3>Release notes - summary</h3>
 <p>Chamilo 1.10.0 is a major stable version with loads of added features.</p>
@@ -68,39 +67,170 @@
   <li></li>
 </ul>
 
-<h1>Chamilo 1.9.6 - Mystery, 18th of April, 2013</h1>
+<h1>Chamilo 1.9.8 - Mystery name, Mystery date, 2013</h1>
 <h3>Release notes - summary</h3>
-<p>Chamilo 1.9.6 is a minor stable version with a series of improvements on top of 1.9.4.</p>
+<p>Chamilo 1.9.8 is a minor stable version with a series of improvements on top of 1.9.6.</p>
 <h3>Release name</h3>
-<p><a href="http://en.wikipedia.org/wiki/Mystery">Mystery</a> is a name we give new versions before we know their name. </p>
+<p><a href="http://fr.wikipedia.org/wiki/">City name</a> is a city ... </p>
+<h3>Security</h3>
+<ul>
+  <li></li>
+</ul>
 <h3>New Features</h3>
 <ul>
-  <li>Documents gallery now creates thumbnails to speed rendering up (#4536)</li>
-  <li>New "Impress" visualization for learning paths (#4595)</li>
-  <li>Show weight of current teacher's documents in session (#5298)</li>
-  <li>Show user data in admin tracking (#5723)</li>
-  <li>User import through CSV now accepts language (#5746)</li>
-  <li>Written assignments can be downloaded by teacher (#5805)</li>
+  <li></li>
 </ul>
 <h3>Improvements</h3>
 <ul>
+  <li>Increased maximum lifetime of videoconference sessions - now 5h (#6261)</li>
   <li></li>
 </ul>
 <h3>Debugging</h3>
 <ul>
   <li></li>
 </ul>
-<h3>Third-Party Libraries additions/updates</h3>
+<h3>Stylesheets and theming</h3>
 <ul>
   <li></li>
 </ul>
-<h3>Removals</h3>
+<h3>Web services</h3>
 <ul>
   <li></li>
 </ul>
+
+
+<h1>Chamilo 1.9.6 - Rochefort, 4th of June, 2013</h1>
+<h3>Release notes - summary</h3>
+<p>Chamilo 1.9.6 is a minor stable version with security patches and a series of improvements on top of 1.9.4.</p>
+<h3>Release name</h3>
+<p><a href="http://fr.wikipedia.org/wiki/Rochefort_%28Belgique%29">Rochefort</a> is a small city in the South of Belgium, that has existed at least since year 1041 and has shown impressive resilience and stability, which we think 1.9.6 has reached as well. Rochefort's Brewery produces a very nice trappist beer exported even to Peru! As we are getting ready for a larger battle, getting Chamilo LMS every day to a larger community, we thought we'd make a last quiet stop and salute the little town where several contributors of Chamilo have set foot in the past.</p>
+<h3>Security</h3>
+<ul>
+  <li>Fixed XSS vulnerabilities in announcement, blog and chat tools - see <a href="https://support.chamilo.org/projects/chamilo-18/wiki/Security_issues">our security page for details</a></li>
+  <li>Fixed unreported design flaw in e-mail password resetter</li>
+</ul>
+<h3>New Features</h3>
+<ul>
+  <li>Documents gallery now creates thumbnails to speed rendering up (#4536)</li>
+  <li>New "Impress" visualization for learning paths (#4595)</li>
+  <li>Show weight of current teacher's documents in session (#5298)</li>
+  <li>Added system tracking for homepage edition (#5597)</li>
+  <li>Show user data in admin tracking (#5723)</li>
+  <li>User import through CSV now accepts language (#5746)</li>
+  <li>Online-text assignments can be downloaded by teacher (#5805)</li>
+  <li>Added improved permissions checker to installer to avoid HTTP 500 Server error page when entering the course on a Security Enhanced server (#5863)</li>
+  <li>Added feature to "Mark all as read" in social messaging (#6019)</li>
+</ul>
+<h3>Improvements</h3>
+<ul>
+  <li>Fixed wrong uploader user reference in e-mail sent to teacher when assignment is uploaded (#5970)</li>
+  <li>Added return link on top of courses tree on homepage (#5986)</li>
+  <li>Set minimum certification score to 75 by default in gradebook (#6001)</li>
+  <li>Changed "Edit settings" label in groups edition (#6003)</li>
+  <li>Improved (visually) the procedure to add new friends in the social network (#6015)</li>
+  <li>Added "Re:[subject]" as title to answers in social messaging (#6018)</li>
+  <li>Authorize .psd files uploads in custom stylesheet uploads to avoid frustration (#6038)</li>
+  <li>Updated logo of all Chamilo styles with the new logo</li>
+  <li>Improved visualization of very long assignments titles (cut at 27 chars)(#6163)</li>
+  <li>Reverted the order of columns in gradebook flat view graphics (linked to #5883 but not exactly the topic)</li>
+</ul>
+<h3>Debugging</h3>
+<ul>
+  <li>Fixed filter function in agenda tool (#2238)</li>
+  <li>Fixed bug preventing HotPotatoes exercises from opening for students (#3993)</li>
+  <li>Fixed missing conclusion text for exercises when seen from LP (#4227)</li>
+  <li>Fixed bug changing forum post as main thread when edited by admin (#4271)</li>
+  <li>Fixed bug preventing the creation of links in assignments description (#4374)</li>
+  <li>Fixed confusing message for expired session (#4797)</li>
+  <li>Fixed bug preventing import of large course backup files (#5334)</li>
+  <li>Fixed confusing Nanogong text in admin settings (#5400)</li>
+  <li>Fixed fonts size in Windows 7 (#5410)</li>
+  <li>Fixed messaging isolation bug in multi-URL installations (#5441)</li>
+  <li>Fixed bug importing backup copy (#5460)</li>
+  <li>Fixed bug in survey not showing questions when invitation sent by mail (#5529)</li>
+  <li>Fixed header in backup progress page (#5540)</li>
+  <li>Fixed teacher viewing more folders in drop-down list (#5555)</li>
+  <li>Fixed side panel not hiding in learning path when using through mobile device (#5563)</li>
+  <li>Fixed 1.9.4 installation bug (#5565)</li>
+  <li>Fixed wrong number of questions in survey list (#5567)</li>
+  <li>Fixed reverse numbering of courses and users in sessions reporting block (#5594)</li>
+  <li>Fixed users import from CSV in groups (#5603)</li>
+  <li>Fixed groups too visible (#5608)</li>
+  <li>Fixed score bug in exercise showing different scores to student and teacher (#5623)</li>
+  <li>Fixed bug preventing edition of groups (#5625)</li>
+  <li>Fixed visual bug in admin section, caused by mobile tweaks (#5660)</li>
+  <li>Fixed bug in course code handling when importing users through CSV in course (#5670)</li>
+  <li>Fixed crypto bug when upgrading from 1.8.8.4 to 1.9.2 (#5685)</li>
+  <li>Fixed users edition bug after upgrading from 1.8.8.4 to 1.9.2 (#5687)</li>
+  <li>Fixed wrong link in mail sent to user when a test has been reviewed by the teacher (#5697)</li>
+  <li>Fixed bug in teacher report chart in admin dashboard (#5713)</li>
+  <li>Fixed bug in end of HotPotatoes tests (#5719)</li>
+  <li>Fixed quick toolbar icons not showing nicely in IE (#5733)</li>
+  <li>Fixed e-mail sender for teacher announcements (#5738)</li>
+  <li>Fixed missing images after backup restoration (#5765)</li>
+  <li>Fixed bug preventing user from changing his stylesheet (#5767)</li>
+  <li>Fixed notice message in local.inc.php (#5769)</li>
+  <li>Fixed display bugs in IE (#5775)</li>
+  <li>Fixed "FillGroup" confusing translation (#5778)</li>
+  <li>Fixed students limit in a class (#5804)</li>
+  <li>Removed mail sending to students when exercise is "exam" type (#5807)</li>
+  <li>Fixed group chat history not being logged in documents (#5837)</li>
+  <li>Fixed missing removal of survey invitations and answers on delete_user() call (#5847)</li>
+  <li>Fixed course subcategories not showing after adding new course on same category (#5850)</li>
+  <li>Fixed learning path view in student mode (#5855)</li>
+  <li>Removed double course code info in admin courses list (#5865)</li>
+  <li>Fixed bug preventing the printing of the gradebook flat view page (#5883)</li>
+  <li>Fixed bug in BigBlueButton videoconference plugin to enable audio (#5884)</li>
+  <li>Fixed several issues in recording of videoconference sessions (#5885)</li>
+  <li>Fixed bug preventing the update of users picture (#5903)</li>
+  <li>Fixed minor notice message about is_courseCoach (#5909)</li>
+  <li>Fixed message when max_upload_filesize reached (#5938)</li>
+  <li>Fixed downloadability of assignment when "invisible" (#5947)</li>
+  <li>Fixed PDF export to include images (#5948)</li>
+  <li>Fixed translation quirks for Spanish (#5949)</li>
+  <li>Fixed bug removing students answers when modifying question (#5950)</li>
+  <li>Fixed issue giving wrong time info in backup filename (#5951)</li>
+  <li>Fixed horizontal/vertical view in survey questions (#5956)</li>
+  <li>Fixed big issue in IE7&amp;8 preventing to move to the next question in exercises (#5957)</li>
+  <li>Fixed bug not showing phone number in student details (#5958)</li>
+  <li>Fixed list of sessions not showing sessions (#5960)</li>
+  <li>Fixed issue blocking the switch between tabs in session view (#5961)</li>
+  <li>Fixed list of assignments not showing course assignments in session (#5963)</li>
+  <li>Fixed issue uploading custom stylesheets (#5967)</li>
+  <li>Fixed display issue in scoring system (gradebook) (#5969)</li>
+  <li>Re-applied chart appearing in session view (#5971)</li>
+  <li>Fixed missing title attribute in links on course homepage (#5976)</li>
+  <li>Fixed missing images in glossary export (#5979)</li>
+  <li>Fixed locking of user subscription to session when name contains special character (#5981)</li>
+  <li>Aligned pager icons in images gallery (#5982)</li>
+  <li>Minor orthographic fixes (#5985,#5987,#6002,#6063 and many others not referenced)</li>
+  <li>Fixed CSS for categories list on homepage (#5989)</li>
+  <li>Fixed missing results after exercise taken in learning path (#5990)</li>
+  <li>Fixed style between course title and teacher name in courses tree on homepage (#5991)</li>
+  <li>Fixed alignment in questions list for small screen resolutions (#5995)</li>
+  <li>Fixed SQL error in update-db-1.8.7-1.8.8.inc.php (#5998)</li>
+  <li>Fixed bug preventing change of password in profile (#5999, #6127)</li>
+  <li>Fixed bug preventing display of documents templates when adding an element to the learning path (#6000)</li>
+  <li>Fixed security issue allowing a student to take hiddn tests through the progress page (#6014)</li>
+  <li>Fixed SQL error when uploading file to dropbox without destination (#6034)</li>
+  <li>Fixed regression for score in forum threads (#6035)</li>
+  <li>Fixed issue deleting one document at a time through course recycling feature (#6045)</li>
+  <li>Fixed visibility of files in group documents for sender when just uploaded (#6046)</li>
+  <li>Fixed bug preventing the re-enabling of the table of contents in learning paths (#6047)</li>
+  <li>Fixed minor issue loading glyphicons from bootstrap.css (#6049)</li>
+  <li>Fixed issue in Portuguese date format (#6054)</li>
+  <li>Fixed security issue with reset password e-mail (#6113)</li>
+  <li>Fixed warning in gradebook (#6122)</li>
+  <li>Fixed bug preventing session coach to import users in his session even when authorized by admin (#6141)</li>
+  <li>Fixed display issue in long HotPotatoes tests (#6150)</li>
+  <li>Fixed learning path student view issue created from improvements to user experience (#6154)</li>
+  <li>Fixed bug with jqgrid column titles character set not showing properly (#6159)</li>
+  <li>Fixed missing variable definition in check_abs_path() function (#5705)</li>
+  <li>Fixed bug whereby non-admin coaches can't see the details of an exam in a session (#6160)</li>
+</ul>
 <h3>Stylesheets and theming</h3>
 <ul>
-  <li></li>
+  <li>Updated Chamilo logo in default styles</li>
 </ul>
 <h3>Web services</h3>
 <ul>
@@ -379,6 +509,7 @@
   <li>Added session-box-text and session-item elements to improve styling</li>
   <li>Modified #main_content to #top_main_content to avoid double #main_content id on the same page</li>
 </ul>
+  
 
 
 <h1>Chamilo 1.9.2 - Hanga Roa, 27th of September, 2012</h1>
@@ -476,6 +607,7 @@
   <li>Social network: An user could not modify its own official code, even if configured to be possible (#5538)</li>
 </ul>
 
+
 <h1>Chamilo 1.9.0 - Vogüé, 31st of July, 2012</h1>
 
 <h3>Release notes - summary</h3>
@@ -536,7 +668,7 @@ This version of Chamilo includes a few new features.
   <li>Assignments: The teacher can now download all files from a specific assignment in one Zip (#4687)</li>
   <li>Documents: Added Flash(TM) webcam photoboot, whereby teachers (or students through groups) can take pictures from their webcam, wich get uploaded to the documents tool directly (#4856) (enable through admin settings)</li>
   <li>Plugins: Added plugin for School Server of OLPC Perú project (Squid proxy filtering from course) (#4925)</li>
-  <li>Exerciss: Added new type of questions that automate the repartition of score between available answers (#5012)</li>
+  <li>Exercises: Added new type of questions that automate the repartition of score between available answers (#5012)</li>
   <li>Exercises: Time counter now changes color at 3, then 1 minute to increase awareness of student, and appears nicely in all-questions-on-one-page exercises (#5043, #5267)</li>
   <li>System: The stats collection of Chamilo.org is now automatic. If you want to disable this feature, edit admin/index.php and look for fsockopen() (#5104)</li>
   <li>Global: Improvements for iPad(TM) and iPhone(TM) by disabling auto-capitalization (#5116)</li>

+ 28 - 16
documentation/credits.html

@@ -62,6 +62,7 @@ In the following credits, when possible, we tried to put the latest contributors
 <ul>
   <li>Julio Allen Montoya Armas (gugli100@gmail.com) - Lead developer - BeezNest, France</li>
   <li>Yannick Warnier (yannick.warnier@beeznest.com) - Technical coordinator, Project Leader - BeezNest, Peru</li>
+  <li>Yoselyn Castillo (yoselyn.castillo@beeznest.com) - Maintainer developer - BeezNest, Cuba</li>
   <li>Coursenligne45 - Anonymous reporter and contributor to many bugfixes - France</li>
   <li>Hubert Borderiou - Developer responsible for exercises categories and many other practical fixes - Université de Grenoble, France</li>
   <li>Juan Carlos Raña Trabado - Independent developer and mastermind for documents, wiki and other pedagogical tools - Spain</li>
@@ -73,17 +74,24 @@ In the following credits, when possible, we tried to put the latest contributors
 
 <h2>Previous versions</h2>
 <ul>
-  <li>BeezNest Latino (ex Dokeos Latinoamérica) (2008-2012)
+  <li>BeezNest Latino (2007-2013) (aka Dokeos Latinoamérica from 2007-2009)
   <ul>
       <li>Yannick Warnier (ywarnier@beeznest.org) - Lead developer</li>
       <li>Julio Allen Montoya Armas (gugli100@gmail.com) - Lead Latino developer</li>
       <li>Christian Fasanando (christian534@hotmail.com) - 2009-2010</li>
+      <li>Yoselyn Castillo (yoselyn.castillo@beeznest.com) - Maintainer developer</li>
     </ul>
     </li>
-    <li>Independent (2008-2012)
+    <li>Independent (2008-2013)
     <ul>
-      <li> Juan Carlos Raña Trabado - considerable work on the wiki integration and improvements, and the FCKEditor/Mimetex extension as well as *many* FCKEditor's file manager and other modules improvements, as well as a continuous stream of recommendations that helped shape 1.8.5 and 1.8.6.*</li>
-      <li> Ivan Tcholakov - various bugfixes in 1.8.6.*, very accurate bug reporting contributions and a considerable work in the integration of a new version of FCKEditor, along with a bunch of useful plugins and an exceptional work on internationalization</li>
+      <li>Juan Carlos Raña Trabado - considerable work on the wiki integration and improvements, and the FCKEditor/Mimetex extension as well as *many* FCKEditor's file manager and other modules improvements, as well as a continuous stream of recommendations that helped shape 1.8.5 and 1.8.6.*</li>
+      <li>Ivan Tcholakov - various bugfixes in 1.8.6.*, very accurate bug reporting contributions and a considerable work in the integration of a new version of FCKEditor, along with a bunch of useful plugins and an exceptional work on internationalization</li>
+      <li>Coursenligne45 - Anonymous reporter and contributor to many bugfixes - France</li>
+    </ul>
+    </li>
+    <li>Université de Grenoble, France (2011-2013)
+    <ul>
+      <li>Hubert Borderiou - Reporter and occasional developer</li>
     </ul>
     </li>
     <li>Dokeos (2004-2009)
@@ -123,15 +131,15 @@ In the following credits, when possible, we tried to put the latest contributors
 <a name="quality-assurance"></a>
 <h1>Quality Assurance</h1>
 <ul>
-  <li>Yannick Warnier as QA coordinator</li>
-  <li>Yoselyn Castillo</li>
-  <li>Jeremy Saavedra</li>
-  <li>Coursenligne on the forum</li>
-  <li>Noa Orizales, through numerous implementations in Spain</li>
-  <li>Hector Lacherre and colleagues from USIL, Lima</li>
-  <li>Carlos Vargas</li>
-  <li>Arthur Portugal</li>
-  <li>Ricardo Rodriguez</li>
+  <li>Yannick Warnier as QA coordinator (2008-2013)</li>
+  <li>Noa Orizales, through numerous implementations in Spain (2008-2013)</li>
+  <li>Coursenligne on the forum (2012-2013)</li>
+  <li>Yoselyn Castillo (2012-2013)</li>
+  <li>Jeremy Saavedra (2012)</li>
+  <li>Hector Lacherre and colleagues from USIL, Lima (2008-2011)</li>
+  <li>Carlos Vargas (2009)</li>
+  <li>Arthur Portugal (2009)</li>
+  <li>Ricardo Rodriguez (2009)</li>
 </ul>
 
 <a name="performance"></a>
@@ -549,8 +557,13 @@ There are too much translators to list them all. Please check http://translate.c
 <a name="documentation"></a>
 <h1>Documentation</h1>
 <ul>
-  <li>Arnaud Ligot</li>
+  <li>Yannick Warnier</li>
+  <li>Steve Miller</li>
+  <li>Anaël Boulier</li>
+  <li>Laura Guirao</li>
+  <li>José Garcia</li>
   <li>Jerome Warnier</li>
+  <li>Arnaud Ligot</li>
   <li>Andrew Lynn (alynn@strathclyde.ac.be)</li>
   <li>Emmanuel Pecquet (emmanuel.pecquet@wanadoo.fr) </li>
   <li>Nikolai Stiehl (nikolai.stiehl@web.de)</li>
@@ -562,10 +575,8 @@ There are too much translators to list them all. Please check http://translate.c
   <li>Roan Embrechts (roan.embrechts@vub.ac.be)</li>
   <li>Hugues Peeters</li>
   <li>René Haentjens</li>
-  <li>Yannick Warnier</li>
   <li>Arthur Portugal</li>
   <li>Sergio Infante Montero, for (humble) technical documentation translation to Spanish</li>
-  <li>Steve Miller</li>
 </ul>
 
 <a name="special-thanks"></a>
@@ -665,6 +676,7 @@ Note that we are infinitely grateful to our translators, having made the spread
   <li>Jeremy Saavedra, for bug reports in LMS 1.9.2</li>
   <li>Ricel Leite, for bug reports and fixes in LMS 1.9.4</li>
   <li>Fausto Puppo, for bug reports and testing on exercises and learning paths in LMS 1.9.4</li>
+  <li>Carlos del Solar, for bug reports and testing on exercises and learning paths in LMS 1.9.4</li>
   <li>Alexander Hu, for bug reports in LMS 1.9.4</li>
   <li>Fernando Muñoz (occasionally via Secunia SVCRP) for multiple security vulnerability reports in Chamilo 1.8-1.9</li>
   <li>All the supporting parents, partners, children, friends, colleagues and sometimes students, of the very special geeks that we are, for their continous support and inspiration</li> 

+ 1 - 1
documentation/dependencies.html

@@ -57,7 +57,7 @@ required information to install it.</p>
 <a name="dependencies"></a>
 <h2>Dependencies - client-side</h2>
 <ul>
-  <li>Any modern browser (IE6 *excluded*). Safari is known to have minor issues with the WYSIWYG editor.</li>
+  <li>Any modern browser (IE6 is obviously *excluded*). Safari is known to have small issues with the WYSIWYG editor.</li>
   <li>Optional: Flash plugin (only required for a few features)</li>
 </ul>
 <h2>Dependencies - server-side</h2>

+ 61 - 58
documentation/installation_guide.html

@@ -23,17 +23,17 @@
             <ul class="nav">
                 <li><a href="index.html">Home</a></li>
                 <li ><a href="readme.html">About</a></li>
-                <li ><a href="license.html">License</a></li>            
-                <li><a href="credits.html">Credits</a></li>            
-                <li><a href="dependencies.html">Dependencies</a></li>            
+                <li ><a href="license.html">License</a></li>
+                <li><a href="credits.html">Credits</a></li>
+                <li><a href="dependencies.html">Dependencies</a></li>
                 <li><a href="changelog.html">Changelog</a></li>
-            </ul>        
+            </ul>
             </div><!--/.nav-collapse -->
         </div>
     </div>
-</div>    
+</div>
 
-<div class="container">    
+<div class="container">
 <h1>Chamilo - Installation Guide</h1>
 
 <p>Thank you for downloading Chamilo</p>
@@ -73,7 +73,7 @@ optimal flexibility, remote control and scalability. <br />
 
 <br />
 
-Chamilo is mainly a LMS running from <span style="font-weight: bold;">Apache (1.3, 2.0 or 2.2)</span>, with a <span style="font-weight: bold;">MySQL 5.1 (or MariaDB)</span> database backend and <span style="font-weight: bold;">PHP 5.3 (or 5.4)</span> (the so called <span style="font-weight: bold;">AMP</span> trilogy). <br />
+Chamilo is mainly a LMS running from <span style="font-weight: bold;">Apache (1.3, 2.0 or 2.2)</span>, with a <span style="font-weight: bold;">MySQL 5.1 (or MariaDB)</span> database backend and <span style="font-weight: bold;">PHP 5.3.3 (or 5.4)</span> (the so called <span style="font-weight: bold;">AMP</span> trilogy). <br />
 
 
 <br />
@@ -102,13 +102,14 @@ For instance, on an Ubuntu server,&nbsp;use apt-get from the Shell or Synaptic f
 
 <h3><span style="font-weight: bold;">MySQL or MariaDB database server</span></h3>
 
-You will need a login and password allowing to manage and create 
+You will need a login and password allowing to manage and create
 a database. Usually, the default configuration on local computers is to allow you to connect as root with an empty password. It is highly recommended to change the password and define a user with access to only a specific database. Please refer to the MySQL or MariaDB documentation in order to do this.<br />
-<span class="muted">Note that this has been greatly simplified since version 1.9, as it 
+<span class="muted">Note that this has been greatly simplified since version 1.9, as it
 previously required to choose between multiple databases and a deprecated single-database mode.</span><br />
 
 <hr style="width: 100%; height: 2px;" />
 <h2><a name="2._Installation_of_Chamilo_LMS"></a><span style="font-weight: bold;">2. Installation of Chamilo LMS</span></h2>
+
 <h3>Configuring your web server to allow .htaccess overrides</h3>
 Starting from 1.10, Chamilo LMS allows friendly URLs if using Apache. As it is based on .htaccess and rewrites, you will be required to <b>AllowOverride All</b> (and possibly enable the ModRewrite extension for Apache). This means that, inside your Apache configuration (or your VirtualHost configuration), you will need to have a block similar to this (the directory given is the same as in the <i>DocumentRoot</i> directive):
 <pre>
@@ -140,7 +141,7 @@ On the RewriteBase line, where it normally says "/", change it to whatever subdi
   <li>Process through the web installation process. You can safely accept all default values. Consider changing the admin password to remember it.</li>
 </ol>
 <br />
-Only the following directories need to be readable, writeable and executable by your web server. 
+Only the following directories need to be readable, writeable and executable by your web server.
 <span class="muted">This usually requires no specific action on Windows servers, but will require a "chmod" under Linux/UNIX and Mac. See instructions below.</span>
 <br />Replace [chamilo] with the directory where your Chamilo installation is located:
 <ul>
@@ -155,15 +156,15 @@ Optionally, you can do the same to the following directories if you want to enab
   <li>[chamilo]/main/css/</li>
   <li>[chamilo]/main/lang/</li>
 </ul>
-Since Chamilo 1.8.8, you can also enable full-text indexing features which 
-require the php5-xapian PHP's extension module to be installed. If you do use 
+Since Chamilo 1.8.8, you can also enable full-text indexing features which
+require the php5-xapian PHP's extension module to be installed. If you do use
 it, you will need to allow your system to write into the searchdb directory:
 <ul>
   <li>[chamilo]/data/searchdb</li>
-</ul> 
-If you find a tests/ directory at the root of your package, please delete it. 
-This is a development directory (automated tests) that has not been checked for security issues, 
-an it should *never* be accessible to final users on a production server. 
+</ul>
+If you find a tests/ directory at the root of your package, please delete it.
+This is a development directory (automated tests) that has not been checked for security issues,
+an it should *never* be accessible to final users on a production server.
 
 <p>On Linux, Mac OS X and BSD operating systems you can use the <em>chmod
 0775</em> command to this end (although we recommend you seek advice from an
@@ -188,7 +189,7 @@ folders (right-clicking on them).</p>
 Do not edit the home_*.html files directly. Instead,
 choose "Configure the homepage" in the Chamilo administration section.</p>
 
-<p><span style="font-weight: bold;">Windows</span> : with all-in-one packages 
+<p><span style="font-weight: bold;">Windows</span> : with all-in-one packages
 like XAMPP, you can easily install Chamilo. In this case (and unless you use it
 in production), the login and password for MySQL will probably remain empty.</p>
 
@@ -200,28 +201,28 @@ in production), the login and password for MySQL will probably remain empty.</p>
 <ul>
 
   <li><strong>Protect your configuration directory: </strong>
-make sure no one (but you) can overwrite it. You can find the config directory in 
+make sure no one (but you) can overwrite it. You can find the config directory in
 <em>[chamilo]</em>/config
 Make it read-only (Windows: right-click the file to edit its
 permissions. Linux/UNIX/MacOsX: use the ""chmod 0555" command). The config
-file is created by your web server (Apache + PHP, usually) so you may 
+file is created by your web server (Apache + PHP, usually) so you may
 need to be a privileged user to change its permissions afterwards.</li>
 
   <li><strong>Protect your installation folder: </strong>
 if the <em>[chamilo]</em>/main/install
 folder is still accessible, someone could install over your existing
 version (you could lose your data that way). Move the folder somewhere
-out of the web directories so it is no longer accessible, rename it, 
-delete it completely or edit its permissions so no one can read or 
+out of the web directories so it is no longer accessible, rename it,
+delete it completely or edit its permissions so no one can read or
 execute it.</li>
 
   <li><strong>For better security: </strong>
 making the files world-writeable will help you install, and it solves many
 issues for people without much sysadmin experience. Be aware though that it is more
-secure to create a distinct user owning all the Chamilo files and folders, 
-and only give read access to the web server to all files, and write access 
-only to the directories previously mentioned. This way, these files need 
-only be readable and writeable by the Apache process owner, not by the 
+secure to create a distinct user owning all the Chamilo files and folders,
+and only give read access to the web server to all files, and write access
+only to the directories previously mentioned. This way, these files need
+only be readable and writeable by the Apache process owner, not by the
 entire world. It would also be adviseable to make all writeable directories
 refuse the interpretation of PHP files (except for the root of the courses
 directories). Don't hesitate to hire an experienced administrator to do that, you'd be happy not to lose
@@ -264,10 +265,12 @@ And optionally (for more features) the following PHP modules:
 </ul>
 
 To get the best out of Chamilo, you need to finetune your PHP settings. Consider : <br />
+
 <ul>
-  <li>Editing php.ini file (on Windows can be located at 
-  <span style="font-weight: bold;">C:\xampp\php\php.ini</span>, 
-  on Ubuntu : 
+
+  <li>Editing php.ini file (on Windows can be located at
+  <span style="font-weight: bold;">C:\xampp\php\php.ini</span>,
+  on Ubuntu :
   <span style="font-weight: bold;">/etc/php5/apache2/php.ini</span></li>
   <li>search the word "_max" and increase the two values (post_max_size and upload_max_filesize) to optimise the server</li>
   <li>we recommend the following values : </li>
@@ -294,12 +297,12 @@ On any recent Debian/Ubuntu, just copying those lines into a new .ini file insta
 
 <p>
 Past Chamilo releases required register_globals to be set to On. This is
-no longer necessary, and should preferably be set to Off. 
+no longer necessary, and should preferably be set to Off.
 <span class="muted">It is considered a bad choice in terms of security to set register_globals to On.</a></p>
 
-<p><strong>Note:</strong> if using PHP 5.3 or higher, you also need to set 
+<p><strong>Note:</strong> if using PHP 5.3.3 or higher, you also need to set
 your <em>date.timezone</em> setting to whatever your server's timezone is.
-For example, if your server is in the 'America/New_York' timezone, set this 
+For example, if your server is in the 'America/New_York' timezone, set this
 in your PHP .ini file:</p>
 
 <div class="code">
@@ -337,7 +340,7 @@ date.timezone = 'America/New_York'
 
 
 <hr />
-<h2><a name="3._Upgrade_from_a_previous_version_of"></a>3. Upgrade from a 
+<h2><a name="3._Upgrade_from_a_previous_version_of"></a>3. Upgrade from a
 previous version of Chamilo LMS (1.*) or Dok€os (&lt;2.0)</h2>
 Before upgrading, we <b>heavily</b> recommend you do a full backup of the previous
 Chamilo or Dok€os directories and databases. If you are unsure how to achieve this
@@ -350,9 +353,9 @@ GNU/GPLv3 and we cannot be held responsible for what would happen to your data
 without professional supervision). This is why we *really* recommend you take
 a full backup of your system before you upgrade.</em>
 <br />
-<div class="muted"> NOTE: This version of Chamilo can only be used to upgrade from 
-smaller versions of Chamilo or Dok€os. For example, you cannot use the normal 
-upgrade scripts from Chamilo 1.9 to upgrade from Dok€os 2.0. If you need this, 
+<div class="muted"> NOTE: This version of Chamilo can only be used to upgrade from
+smaller versions of Chamilo or Dok€os. For example, you cannot use the normal
+upgrade scripts from Chamilo 1.9 to upgrade from Dok€os 2.0. If you need this,
 please contact one of the Chamilo Association's official providers <providers@chamilo.org>)</div>
 
 <p></p>
@@ -391,12 +394,12 @@ As this is only a minor version change from previous 1.9.* versions of Chamilo,
   <li> point your browser on your portal URL + main/install/</li>
   <li> choose your language and click&nbsp;<span style="font-style: italic;">Upgrade from 1.8.x</span></li>
 </ul>
-A bunch of Chamilo administrators have reported minor issues with the migration between versions considerably apart (like from Dok€os to Chamilo). 
+A bunch of Chamilo administrators have reported minor issues with the migration between versions considerably apart (like from Dok€os to Chamilo).
 This might include loosing some assignments or forum posts. To avoid any ugly effect on your users, we recommend you first establish a checklist
-of all the content that is critical to you, and that you keep a working copy of your previous site on the side. This way, it will be easier to 
+of all the content that is critical to you, and that you keep a working copy of your previous site on the side. This way, it will be easier to
 manage the transition by letting your users get access to their contents from the previous site and making it easier for you to compare the two.
 If you are experiencing difficulties, consider asking for help from a PHP developer or hiring an <a href="http://www.chamilo.org/en/providers" target="_blank">official Chamilo provider</a>. They will make sure
-you get the best our of your Chamilo migration. 
+you get the best our of your Chamilo migration.
 <br />
 
 <span class="muted">* Styles and images are located in the main/css or main/img
@@ -566,7 +569,7 @@ Newer distributions also allow downloading rpms for additional packages.</p>
 
 <h3><b>Activating LDAP in Chamilo</b></h3>
 
-<p class="muted">Note: The LDAP mechanism has been changed in 1.9. As a result, some of the following information might not be correct. Please check 
+<p class="muted">Note: The LDAP mechanism has been changed in 1.9. As a result, some of the following information might not be correct. Please check
 the configuration settings inside Chamilo to learn the details.</p>
 
 <p>
@@ -696,8 +699,8 @@ Here is an example:
 		&nbsp;&nbsp;Allow from all<br />
 		&lt;/Directory&gt;<br />
 		</div>
-		
-		
+
+
 		<p>Adding a symbolic link can be done, under Windows, by creating a
 		  shortcut to the mimetex.exe file from the cgi-bin directory, or under
 		  Linux by issuing the following command:</p>
@@ -709,22 +712,22 @@ Here is an example:
 
     </li>
 
-	
+
 	<li>5. Make sure that the file mimetex.cgi (or mimetex.exe) has right to be executed by the web-server process. For example, on a Ubuntu Linux system you may write a command like the following:
 	    <div class="code">
 	        sudo chmod a+x mimetex.cgi
 	    </div>
 	</li>
 	<li>6. Make sure that the file mimetex.cgi (or mimetex.exe) has been uploaded in <b>BINARY</b> format.
-	
-	       This is another common problem; the fix is just to re-upload the file in ASCII format. 
+
+	       This is another common problem; the fix is just to re-upload the file in ASCII format.
 	       You'll need to consult your FTP program's documentation to figure out how to switch modes.
-           BINARY mode is used for non-text items, such as executables (*.exe), zip files (*.zip), image files (*.jpg, *.gif) and the like. 
+           BINARY mode is used for non-text items, such as executables (*.exe), zip files (*.zip), image files (*.jpg, *.gif) and the like.
            ASCII mode needs to be used for text only documents, which includes *.txt, *.cgi, *.pl *.css, *.html, etc.
            <br />
-           You can also try to re upload the mimetex file using the "Upload file" in the "Filemanager" tool in CPanel/Plesk 
+           You can also try to re upload the mimetex file using the "Upload file" in the "Filemanager" tool in CPanel/Plesk
     </li>
-    
+
 </ul>
 
 <p>As a result of this procedure, a new button becomes available in your Chamilo online editor, that gives you possibility
@@ -795,11 +798,11 @@ sudo apt-get install php5-xapian
 sudo /etc/init.d/apache2 restart
 </pre>
 
-Then go to your administration page -&gt; Configuration settings -&gt; Search 
-and enable the search tool. Follow the recommendations on the page to get the 
-complete indexing suite installed. Once you're done, all documents you import 
+Then go to your administration page -&gt; Configuration settings -&gt; Search
+and enable the search tool. Follow the recommendations on the page to get the
+complete indexing suite installed. Once you're done, all documents you import
 into your Chamilo portal in a recognized format will be indexed and searchable.
-Chamilo Administrators training (which you can ask any <a href="http://www.chamilo.org/en/providers">Chamilo's Official 
+Chamilo Administrators training (which you can ask any <a href="http://www.chamilo.org/en/providers">Chamilo's Official
 Provider</a> for) include a full review of the full-text search feature.
 </p>
 
@@ -819,23 +822,23 @@ Then go to your administration page -&gt; <i>Chamilo Rapid</i> and set the host
 <hr style="width: 100%; height: 2px;" />
 <h2><a name="12._Setting_cron_up"></a>Setting chronological tasks</h2>
 <p>
-Since Chamilo 1.8.8, a few tasks need to be executed regularly in order to get 
-the best out of your server resources. One of such tasks (and the only one 
-around at the time of Chamilo 1.8.8) is the sending of internal messaging 
+Since Chamilo 1.8.8, a few tasks need to be executed regularly in order to get
+the best out of your server resources. One of such tasks (and the only one
+around at the time of Chamilo 1.8.8) is the sending of internal messaging
 notifications by e-mail, i.e. when you receive an e-mail from another person or
 from a group inside the internal messaging system of Chamilo, if all e-mails are
-sent immediately, then you might not have the chance to receive them at your 
-pace, once a day or even once a week. For cases like this you, as a Chamilo 
+sent immediately, then you might not have the chance to receive them at your
+pace, once a day or even once a week. For cases like this you, as a Chamilo
 administrator, should setup a cron process on the server to check the queue of
 e-mails and send is timely.</p>
 <p>
 Setting up a cron task is easy and there are several ways to do it. We recommend
-you have a look at the <a href="http://drupal.org/cron">Drupal documentation 
+you have a look at the <a href="http://drupal.org/cron">Drupal documentation
 for setting up cron</a> and define your own cron process as:
 <pre>
 35 * * * * wget -O - -q -t 1 http://campus.example.com/main/cron/run.php
 </pre>
-Make sure you have a look into run.php as maybe you want to change a few 
+Make sure you have a look into run.php as maybe you want to change a few
 settings there.
 </p>
 

+ 14 - 14
documentation/installation_guide_es_ES.html

@@ -73,7 +73,7 @@
 Chamilo puede ser instalado indiferentemente en servidores Windows, Linux, Mac OS X y UNIX. Sin embargo, nosotros recomendamos el uso de un servidor Linux para una óptima flexibilidad, control remoto y escalabilidad.
 </p>
 <p>
-Chamilo es fundamentalmente un LMS que se ejecuta con Apache (1.3, 2.0 o 2.2), MySQL 5.1 (o MariaDB) y PHP 5.3 (o 5.4) (trilogía también llamada AMP).
+Chamilo es fundamentalmente un LMS que se ejecuta con Apache (1.3, 2.0 o 2.2), MySQL 5.1 (o MariaDB) y PHP 5.3.3 (o 5.4) (trilogía también llamada AMP).
 </p>
 <p>
 Todo este software es software de código abierto y está disponible libremente.
@@ -228,7 +228,7 @@ En versiones de Chamilo/Dok€os anteriores se requería que register_globals es
 necesario, puede (y debería) estar configurado en Off y Chamilo funcionará bien.<span>Se considera una mala elección en términos de seguridad configurar register_globals a On.</span>
 </p>
 
-<p><strong>Nota:</strong> si se usa PHP 5.3 o superior, se necesita configurar la variable <em>date.timezone</em> a la zona horaria de su servidor.
+<p><strong>Nota:</strong> si se usa PHP 5.3.3 o superior, se necesita configurar la variable <em>date.timezone</em> a la zona horaria de su servidor.
 Por ejemplo, si su servidor está en la zona horaria 'America/Lima', modificar en el php.ini:</p>
 
 <div class="code">
@@ -261,7 +261,7 @@ date.timezone = 'America/Lima'
 </p>
 
 <hr />
-<h2><a name="3._Upgrade_from_a_previous_version_of"></a>3. Actualizar desde una versión previa de Chamilo LMS (1.*) o Dok€os (<2.0)</h2>
+<h2><a name="3._Upgrade_from_a_previous_version_of"></a>3. Actualizar desde una versión previa de Chamilo LMS (1.*) o Dok€os (&lt;2.0)</h2>
 
 <p>
 Antes de actualizar, le recomendamos <b>seriamente</b> que haga una copia de seguridad de los directorios
@@ -282,7 +282,7 @@ Dado que se trata sólo de un cambio de versión menor  previa de Chamilo 1.9.*,
 <li>Revisar que no ha dejado alguna hoja de estilo personalizada o imagen (si es que tiene, asegúrese de guardar una copia de respaldo)</li>
 <li>Descargar el paquete de instalación de Chamilo 1.9 desde la página de descarga de Chamilo</li>
 <li>Descomprimir los nuevos archivos de Chamilo 1.9 sobre los archivos de la versión anterior (o descomprimirlos en una nueva carpeta y después copiarlos sobre los archivos de la versión anterior)</li>
-<li>Editar el archivo main/inc/conf/configuration.php: hacia el final del archivo, localizar el número de la versión (p.e. ‘1.9.2’) y cambiarlo por la nueva versión (p.e.‘1.9.4’)</li>
+<li>Editar el archivo main/inc/conf/configuration.php: hacia el final del archivo, localizar el número de la versión (p.e. ‘1.9.4’) y cambiarlo por la nueva versión (p.e.‘1.9.8’)</li>
 <li>Ya está! Ningún otro procedimiento de actualización es requerido.</li>
 </ul>
 </p>
@@ -420,11 +420,11 @@ Escribir en la línea de comandos:
   <li>mkdir /var/www/chamilo/version_antigua</li>
   <li>mv /var/www/chamilo/* /var/www/chamilo/version_antigua/</li>
   <li>chmod -R 0777 /var/www/chamilo/version_antigua/</li>
-  <li>wget http://www.chamilo.org/files/chamilo-1.9.tar.gz</li>
-  <li>tar zxvf chamilo-1.9.tar.gz</li>
-  <li>sudo cp -ra chamilo-1.9/* /var/www/chamilo/</li>
-  <li>rm chamilo-1.9.tar.gz</li>
-  <li>sudo rm -r chamilo-1.9/</li>
+  <li>wget http://www.chamilo.org/files/chamilo-1.9.8.tar.gz</li>
+  <li>tar zxvf chamilo-1.9.8.tar.gz</li>
+  <li>sudo cp -ra chamilo-1.9.8/* /var/www/chamilo/</li>
+  <li>rm chamilo-1.9.8.tar.gz</li>
+  <li>sudo rm -r chamilo-1.9.8/</li>
 </ul>
 
 <br />
@@ -706,7 +706,7 @@ sudo /etc/init.d/apache2 restart
 </pre>
 </p>
 <p>
-A continuación, vaya a la página de administración -> Ajustes de configuración -> Buscar y habilitar la herramienta de búsqueda. Siga las recomendaciones de la página para obtener la suite completa de indexación instalada. Una vez que haya terminado, todos los documentos importados en su portal Chamilo en un formato reconocido serán indexados y buscados. En formación de administradores de Chamilo ( el cual puede preguntar a cualquier <a href="http://www.chamilo.org/en/providers">Proveedor Oficial de Chamilo</a>) incluyen una revisión completa de la función de búsqueda de texto completo.
+A continuación, vaya a la página de administración -&gt; Ajustes de configuración -&gt; Buscar y habilitar la herramienta de búsqueda. Siga las recomendaciones de la página para obtener la suite completa de indexación instalada. Una vez que haya terminado, todos los documentos importados en su portal Chamilo en un formato reconocido serán indexados y buscados. En formación de administradores de Chamilo ( el cual puede preguntar a cualquier <a href="http://www.chamilo.org/en/providers">Proveedor Oficial de Chamilo</a>) incluyen una revisión completa de la función de búsqueda de texto completo.
 </p>
 
 <hr style="width: 100%; height: 2px;" />
@@ -718,11 +718,11 @@ 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
+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 -> 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.
 </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).
@@ -751,11 +751,11 @@ Como Chamilo se hace más popular y atraviesa muchas fronteras ahora, es frecuen
 <p>
 Esto fácilmente se puede modificar editando el archivo main/inc/lib/internationalization_database/name_order_conventions.php, buscando nuestro idioma y cambiando los campos. Es tan simple que se explica por sí mismo y se ve así:
 <pre>
-'simpl_chinese' => array( 'format' => 'title last_name first_name', 'sort_by' => 'last_name' ), // Eastern order
+'simpl_chinese' =&gt; array( 'format' =&gt; 'title last_name first_name', 'sort_by' =&gt; 'last_name' ), // Eastern order
 </pre>
 Siéntase libre de cambiar esto a
 <pre>
-'simpl_chinese' => array( 'format' => 'title first_name lastname', 'sort_by' => 'last_name' ), // Eastern order
+'simpl_chinese' =&gt; array( 'format' =&gt; 'title first_name lastname', 'sort_by' =&gt; 'last_name' ), // Eastern order
 </pre>
 por ejemplo. El efecto debería ser inmediato.
 </p>

+ 57 - 3
documentation/optimization.html

@@ -38,8 +38,10 @@
 
 
 <h2><b>Contents</b></h2>
+
 <ol>
-  <li><a href="#1.Using-XCache">Using xCache or APC</a></li>
+
+  <li><a href="#1.Using-XCache">Using xCache, APC or Memcache</a></li>
   <li><a href="#2.Slow-queries">Slow queries</a></li>
   <li><a href="#3.Indexes-caching">Indexes caching</a></li>
   <li><a href="#4.Sessions-directories">Sessions directories</a></li>
@@ -47,6 +49,7 @@
   <li><a href="#6.Zlib-compression">Zlib compressed output</a></li>
   <li><a href="#7.High-numbers-memory">Memory considerations for high numbers of users</a></li>
   <li><a href="#8.HTTP-caching-media">HTTP caching for media</a></li>
+  <li><a href="#9.Avoid-non-fixed-values">Avoiding non-fixed values</a></li>
 </ol>
 
 <h2><a name="1.Using-XCache"></a>1. Using xCache or APC</h2>
@@ -94,6 +97,44 @@ if(!empty($_course['id'])) {
 }
 </pre>
 Note that, as xCache is a shared caching system, it is very important to prefix your variables with a domain name or some kind of identifier, otherwise it would end up in disaster if you use a shared server for several portals.<br />
+If you use php5-memcache, then this piece of code would look like this (you need to adjust depending on your settings):
+<pre>
+    global $_configuration;
+    $_course    = api_get_course_info();
+    $course_id  = api_get_course_id();
+    $user_id    = api_get_user_id();
+
+    $html = '';
+    $xc = method_exists('Memcache','add');
+    if ($xc) {
+        // Make sure the server is available
+        $xm = new Memcache;
+        $xm->addServer('localhost', 11211);
+        $xc = $xc && ($xm->getServerStatus('localhost',11211)!=0);
+        // 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'].'_';
+    }
+    $number = 0;
+    if ((api_get_setting('showonline', 'world') == 'true' AND !$user_id) OR (api_get_setting('showonline', 'users') == 'true' AND $user_id) OR (api_get_setting('showonline', 'course') == 'true' AND $user_id AND $course_id)) {
+        if ($xc && $xm->get($xs.'wio_count_simple')) {
+            $number = $xm->get($xs.'wio_count_simple');
+        } else {
+            $number = who_is_online_count(api_get_setting('time_limit_whosonline'));
+            $xm->set($xs.'wio_count_simple',$number,0,30);
+        }
+
+        $number_online_in_course = 0;
+        if(!empty($_course['id'])) {
+            if ($xc && $xm->get($xs.'wio_count_simple_'.$_course['id'])) {
+                $number_online_in_course = $xm->get($xs.'wio_count_simple_'.$_course['id']);
+            } else {
+                $number_online_in_course = who_is_online_in_this_course_count($user_id, api_get_setting('time_limit_whosonline'), $_course['id']);
+                $xm->set($xs.'wio_count_simple_'.$_course['id'],$number_online_in_course,0,30);
+            }
+        }
+</pre>
 <br />
 An optional additional caching mechanism you may use is the realpath_cache_size and realpath_cache_ttl php.ini parameters. See <a href="http://php.net/manual/en/ini.core.php">the PHP documentation</a> for more details.
 <br />
@@ -160,7 +201,6 @@ ALTER TABLE session_rel_course_rel_user ENGINE=INNODB;
 </pre>
 If used on large tables, this might take a considerable time (can take around 60s for a million rows), so try to execute at night or during lower usage periods.
 </p>
-
 <hr />
 <h2><a name="3.Indexes-caching"></a>3. Indexes caching</h2>
 One good reference: <a href="http://dev.mysql.com/doc/refman/5.1/en/multiple-key-caches.html">MySQL documentation on multiple key caches</a><br />
@@ -301,9 +341,23 @@ These settings explicitly mention the file MIME types that will be put in cache,
 If you want to change some content put in cache by the client, though, you will need to change the name of the file (and its reference in the HTML/PHP file that includes it).<br />
 This is an easy way to massively reduce your bandwidth (80% reduction?), the speed of page loading for your users and the use of resources on your web server.
 </p>
+
+<h2><a name="#9.Avoid-non-fixed-values"></a>Avoiding non-fixed values</h2>
+Many things in Chamilo are written focusing on the ease of use, even for the administrator. Sometimes, these settings are weighing a little bit more on the system. This is the case, between others, of the mail.conf.php file (being loaded unconditionally) and its CONSTANT "IS_WINDOWS_OS", which is defined by a function call (api_is_windows_os()) at the beginning of main_api.lib.php.
+
+The definition of this constant (which is executed at *every* page load) can easily be avoided, and the only place where it is used inconditionally (mail.conf.php) can be modified to set the line as you expect it (depending on whether you use sendmail/exim or smtp).
+<pre>
+$platform_email['SMTP_MAILER']       = 'smtp';
+</pre>
+or
+<pre>
+$platform_email['SMTP_MAILER']       = 'mail';
+</pre>
+In fact, the complete loading of mail.conf.php can also be avoided if loaded conditionally (with <i>require_once</i>) when sending an e-mail (which is the only case where it is useful).
+<hr />
 <h2>Authors</h2>
 <ul>
-<li>Yannick Warnier, Zend Certified PHP Engineer, BeezNest Belgium SPRL, <a href="mailto:yannick.warnier@beeznest.com">yannick.warnier@beeznest.com</a></li>
+<li>Yannick Warnier, Zend Certified PHP Engineer, BeezNest Belgium SPRL, <a href="mailto:ywarnier@beeznest.net">ywarnier@beeznest.net</a></li>
 </ul>
 </div>
 </body>

+ 1 - 1
main/admin/access_url_edit_users_to_url.php

@@ -13,7 +13,7 @@ $language_file='admin';
 $cidReset = true;
 
 require_once '../inc/global.inc.php';
-require_once '../inc/lib/xajax/xajax.inc.php';
+require_once __DIR__.'/../inc/lib/xajax/xajax.inc.php';
 $xajax = new xajax();
 
 $xajax -> registerFunction (array('search_users', 'Accessurledituserstourl', 'search_users'));

+ 42 - 41
main/admin/careers.php

@@ -2,7 +2,7 @@
 /* For licensing terms, see /license.txt */
 
 /**
- * @package chamilo.admin
+ *  @package chamilo.admin
  */
 
 // Language files that need to be included.
@@ -15,39 +15,40 @@ $this_section = SECTION_PLATFORM_ADMIN;
 
 api_protect_admin_script();
 
+
 //Add the JS needed to use the jqgrid
 $htmlHeadXtra[] = api_get_jqgrid_js();
 
 // setting breadcrumbs
-$interbreadcrumb[] = array('url' => 'index.php', 'name' => get_lang('PlatformAdmin'));
-$interbreadcrumb[] = array('url' => 'career_dashboard.php', 'name' => get_lang('CareersAndPromotions'));
+$interbreadcrumb[]=array('url' => 'index.php','name' => get_lang('PlatformAdmin'));
+$interbreadcrumb[]=array('url' => 'career_dashboard.php','name' => get_lang('CareersAndPromotions'));
 
 $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' => 'careers.php', 'name' => get_lang('Careers'));
-    $interbreadcrumb[] = array('url' => '#', 'name' => get_lang('Add'));
+    $interbreadcrumb[]=array('url' => 'careers.php','name' => get_lang('Careers'));
+    $interbreadcrumb[]=array('url' => '#','name' => get_lang('Add'));
 } elseif ($action == 'edit') {
-    $interbreadcrumb[] = array('url' => 'careers.php', 'name' => get_lang('Careers'));
-    $interbreadcrumb[] = array('url' => '#', 'name' => get_lang('Edit'));
+    $interbreadcrumb[]=array('url' => 'careers.php','name' => get_lang('Careers'));    
+    $interbreadcrumb[]=array('url' => '#','name' => get_lang('Edit'));
 } else {
-    $interbreadcrumb[] = array('url' => '#', 'name' => get_lang('Careers'));
+    $interbreadcrumb[]=array('url' => '#','name' => get_lang('Careers'));
 }
 
 Display::display_header();
 
 //jqgrid will use this URL to do the selects
-$url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_careers';
+$url            = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_careers';
 
-//The order is important you need to check the the $column variable in the model.ajax.php file
-$columns = array(get_lang('Name'), get_lang('Description'), get_lang('Actions'));
+//The order is important you need to check the the $column variable in the model.ajax.php file 
+$columns        = array(get_lang('Name'), get_lang('Description'), get_lang('Actions'));
 
 //Column config
-$column_model = array(
-    array('name' => 'name', 'index' => 'name', 'width' => '80', 'align' => 'left'),
+$column_model   = array(
+    array('name'=>'name',           'index'=>'name',        'width'=>'80',   'align'=>'left'),
     array(
         'name'     => 'description',
         'index'    => 'description',
@@ -63,11 +64,11 @@ $column_model = array(
         'formatter' => 'action_formatter',
         'sortable'  => 'false'
     )
-);
-//Autowidth
+                       );            
+//Autowidth             
 $extra_params['autowidth'] = 'true';
-//height auto
-$extra_params['height'] = 'auto';
+//height auto 
+$extra_params['height'] = 'auto'; 
 
 //With this function we can add actions to the jgrid (edit, delete, etc)
 $action_links = 'function action_formatter(cellvalue, options, rowObject) {
@@ -93,17 +94,17 @@ $action_links = 'function action_formatter(cellvalue, options, rowObject) {
     '',
     ICON_SIZE_SMALL
 ).'</a>'.
-    '\';
-}';
+                         '\'; 
+                 }';
 ?>
-    <script>
-        $(function () {
-            <?php
-                // grid definition see the $career->display() function
-                echo Display::grid_js('careers',  $url,$columns,$column_model,$extra_params, array(), $action_links,true);
-            ?>
-        });
-    </script>
+<script>
+$(function() {
+<?php 
+    // grid definition see the $career->display() function
+    echo Display::grid_js('careers',  $url,$columns,$column_model,$extra_params, array(), $action_links,true);       
+?> 
+});
+</script>
 <?php
 $career = new Career();
 
@@ -119,14 +120,14 @@ switch ($action) {
         $form = $career->return_form($url, 'add');
 
         // The validation or display
-        if ($form->validate()) {
+        if ($form->validate()) {            
             if ($check) {
-                $values = $form->exportValues();
-                $res    = $career->save($values);
+                $values = $form->exportValues();       
+                $res    = $career->save($values);            
                 if ($res) {
                     Display::display_confirmation_message(get_lang('ItemAdded'));
                 }
-            }
+            }        
             $career->display();
         } else {
             echo '<div class="actions">';
@@ -136,23 +137,23 @@ switch ($action) {
                 '',
                 ICON_SIZE_MEDIUM
             ).'</a>';
-            echo '</div>';
+            echo '</div>';            
             $form->addElement('hidden', 'sec_token');
             $form->setConstants(array('sec_token' => $token));
             $form->display();
         }
         break;
     case 'edit':
-        // Action handling: Editing
+        // Action handling: Editing 
         $url  = api_get_self().'?action='.Security::remove_XSS($_GET['action']).'&id='.intval($_GET['id']);
-        $form = $career->return_form($url, 'edit');
+        $form = $career->return_form($url, 'edit');    
 
         // The validation or display
-        if ($form->validate()) {
+        if ($form->validate()) {            
             if ($check) {
                 $values = $form->exportValues();
-                $career->update_all_promotion_status_by_career_id($values['id'], $values['status']);
-                $res = $career->update($values);
+                $career->update_all_promotion_status_by_career_id($values['id'],$values['status']);               
+                $res    = $career->update($values);
                 if ($values['status']) {
                     Display::display_confirmation_message(
                         sprintf(get_lang('CareerXUnarchived'), $values['name']),
@@ -161,7 +162,7 @@ switch ($action) {
                 } else {
                     Display::display_confirmation_message(sprintf(get_lang('CareerXArchived'), $values['name']), false);
                 }
-            }
+            }            
             $career->display();
         } else {
             echo '<div class="actions">';
@@ -187,7 +188,7 @@ switch ($action) {
         }
         $career->display();
         break;
-    case 'copy':
+    case 'copy':        
         if (api_get_session_id() != 0 && !api_is_allowed_to_session_edit(false, true)) {
             api_not_allowed();
         }
@@ -200,7 +201,7 @@ switch ($action) {
         $career->display();
         break;
     default:
-        $career->display();
+        $career->display();   
         break;
 }
 Display :: display_footer();

+ 1 - 0
main/admin/configure_homepage.php

@@ -22,6 +22,7 @@ require_once api_get_path(LIBRARY_PATH).'WCAG/WCAG_rendering.php';
 $action = isset($_GET['action']) ? Security::remove_XSS($_GET['action']) : null;
 $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
 $tool_name = get_lang('ConfigureHomePage');
+$_languages = api_get_languages();
 
 $interbreadcrumb[] = array('url' => 'index.php', 'name' => get_lang('PlatformAdmin'));
 

+ 1 - 0
main/admin/course_add.php

@@ -90,6 +90,7 @@ $group[]= $form->createElement('radio', 'visibility', get_lang('CourseAccess'),
 $group[]= $form->createElement('radio', 'visibility', null, get_lang('OpenToThePlatform'), COURSE_VISIBILITY_OPEN_PLATFORM);
 $group[]= $form->createElement('radio', 'visibility', null, get_lang('Private'), COURSE_VISIBILITY_REGISTERED);
 $group[]= $form->createElement('radio', 'visibility', null, get_lang('CourseVisibilityClosed'), COURSE_VISIBILITY_CLOSED);
+$group[]= $form->createElement('radio', 'visibility', null, get_lang('CourseVisibilityHidden'), COURSE_VISIBILITY_HIDDEN);
 
 $form->addGroup($group,'', get_lang('CourseAccess'), '<br />');
 

+ 44 - 26
main/admin/course_category.php

@@ -24,7 +24,6 @@ $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
 $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
 
 $errorMsg = '';
-
 $id = isset($_GET['id']) ? $_GET['id'] : null;
 
 $categoryCode = isset($_POST['categoryCode']) ? $_POST['categoryCode'] : null;
@@ -36,10 +35,20 @@ $canHaveCourses = 0;
 
 if (!empty($action)) {
     if ($action == 'delete') {
-        deleteNode($id);
-        header('Location: ' . api_get_self() . '?category=' . Security::remove_XSS($category));
-        exit();
-    } elseif (($action == 'add' || $action == 'edit') && $formSent) {
+        if (api_get_multiple_access_url()) {
+            if (api_get_current_access_url_id() == 1) {
+                deleteNode($id);
+                header('Location: ' . api_get_self() . '?category=' . Security::remove_XSS($category));
+                exit();
+            } else {
+                $delError = 1;
+            }
+        } else {
+            deleteNode($_GET['id']);
+            header('Location: ' . api_get_self() . '?category=' . Security::remove_XSS($category));
+            exit();
+        }
+    } elseif (($action == 'add' || $action == 'edit') && $_POST['formSent']) {
         $_POST['categoryCode'] = trim($_POST['categoryCode']);
         $_POST['categoryName'] = trim($_POST['categoryName']);
 
@@ -65,11 +74,11 @@ if (!empty($action)) {
             $sql = "SELECT name, auth_course_child FROM $tbl_category WHERE code='$id'";
             $result = Database::query($sql);
             list($categoryName, $canHaveCourses) = Database::fetch_row($result);
-
             $canHaveCourses = ($canHaveCourses == 'FALSE') ? 0 : 1;
         }
     } elseif ($action == 'moveUp') {
         moveNodeUp($id, $_GET['tree_pos'], $category);
+
         header('Location: ' . api_get_self() . '?category=' . Security::remove_XSS($category));
         exit();
     }
@@ -91,16 +100,16 @@ if (!empty($category)) {
 }
 
 if (empty($action)) {
-    $myquery = "SELECT t1.name,t1.code,t1.parent_id,t1.tree_pos,t1.children_count,COUNT(DISTINCT t3.code) AS nbr_courses
-			 	FROM $tbl_category t1 LEFT JOIN $tbl_category t2 ON t1.code=t2.parent_id LEFT JOIN $tbl_course t3 ON t3.category_code=t1.code
-				WHERE t1.parent_id " . (empty($category) ? "IS NULL" : "='$category'") . "
+    $myquery = "SELECT t1.name,t1.code,t1.parent_id,t1.tree_pos,t1.children_count,COUNT(DISTINCT t3.code) AS nbr_courses 
+			 	FROM $tbl_category t1 LEFT JOIN $tbl_category t2 ON t1.code=t2.parent_id LEFT JOIN $tbl_course t3 ON t3.category_code=t1.code 
+				WHERE t1.parent_id " . (empty($category) ? "IS NULL" : "='$category'") . " 
 				GROUP BY t1.name,t1.code,t1.parent_id,t1.tree_pos,t1.children_count ORDER BY t1.tree_pos";
     $result = Database::query($myquery);
     $Categories = Database::store_result($result);
 }
 
 if ($action == 'add' || $action == 'edit') {
-    ?>
+    if ((api_get_multiple_access_url() && api_get_current_access_url_id() == 1) || !api_get_multiple_access_url() ) { ?>
     <div class="actions">
         <a href="<?php echo api_get_self(); ?>?category=<?php echo Security::remove_XSS($category); ?>"><?php echo Display::return_icon('folder_up.png', get_lang("Back"), '', ICON_SIZE_MEDIUM);
     if (!empty($category)) echo ' (' . Security::remove_XSS($category) . ')'; ?></a>
@@ -126,16 +135,17 @@ if ($action == 'add' || $action == 'edit') {
         <?php
         Display::display_normal_message($errorMsg); //main API
         ?>
+
                     </td>
                 </tr>
 
         <?php
     }
     ?>
+
             <tr>
                 <td nowrap="nowrap"><?php echo get_lang("CategoryCode"); ?> :</td>
-                <td>
-                    <input type="text" name="categoryCode" size="20" maxlength="20" value="<?php echo api_htmlentities(stripslashes($categoryCode), ENT_QUOTES, $charset); ?>" /></td>
+                <td><input type="text" name="categoryCode" size="20" maxlength="20" value="<?php echo api_htmlentities(stripslashes($categoryCode), ENT_QUOTES, $charset); ?>" /></td>
             </tr>
             <tr>
                 <td nowrap="nowrap"><?php echo get_lang("CategoryName"); ?> :</td>
@@ -164,21 +174,23 @@ if ($action == 'add' || $action == 'edit') {
         </table>
     </form>
 
-                <?php
+<?php  } elseif (api_get_multiple_access_url() && api_get_current_access_url_id() != 1) {
+           Display :: display_error_message(get_lang('CourseCategoriesAreGlobal'));
+       }
             } else {
-                ?>
+    if ($delError == 0) {           ?>
     <div class="actions">
-    <?php
-    if (!empty($category) && empty($action)) {
-        $myquery = "SELECT parent_id FROM $tbl_category WHERE code='$category'";
-        $result = Database::query($myquery);
-        $parent_id = 0;
-        if (Database::num_rows($result) > 0) {
-            $parent_id = Database::fetch_array($result);
-        }
+                <?php
+                if (!empty($category) && empty($action)) {
+                    $myquery = "SELECT parent_id FROM $tbl_category WHERE code='$category'";
+                    $result = Database::query($myquery);
+                    $parent_id = 0;
+                    if (Database::num_rows($result) > 0) {
+                        $parent_id = Database::fetch_array($result);
+                    }
 
-        $parent_id['parent_id'] ? $link = ' (' . $parent_id['parent_id'] . ')' : $link = '';
-        ?>
+                    $parent_id['parent_id'] ? $link = ' (' . $parent_id['parent_id'] . ')' : $link = '';
+                    ?>
 
             <a href="<?php echo api_get_self(); ?>?category=<?php echo $parent_id['parent_id']; ?>"><?php echo Display::return_icon('folder_up.png', get_lang("Back"), '', ICON_SIZE_MEDIUM);
         if (!empty($parent_id)) echo $link ?></a>
@@ -216,13 +228,20 @@ if ($action == 'add' || $action == 'edit') {
     } else {
         echo get_lang("NoCategories");
     }
-    ?>
+    } else {
+        Display :: display_error_message(get_lang('CourseCategoriesAreGlobal'));
+        
+    }?>
     </ul>
+
+
+
     <?php
 }
 
 Display::display_footer();
 
+
 function deleteNode($node) {
     global $tbl_category, $tbl_course;
     $node = Database::escape_string($node);
@@ -341,4 +360,3 @@ function compterFils($pere, $cpt) {
 
     return ($cpt + 1);
 }
-

+ 7 - 2
main/admin/course_edit.php

@@ -46,9 +46,9 @@ if (api_is_multiple_url_enabled()) {
 	$access_url_rel_user_table= Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
 	$sql = "SELECT u.user_id,lastname,firstname FROM $table_user as u
 			INNER JOIN $access_url_rel_user_table url_rel_user
-			ON (u.user_id=url_rel_user.user_id) WHERE url_rel_user.access_url_id=".api_get_current_access_url_id()." AND status=1".$order_clause;
+			ON (u.user_id=url_rel_user.user_id) WHERE url_rel_user.access_url_id=".api_get_current_access_url_id()." AND status = 1 or status = 2 ".$order_clause;
 } else {
-	$sql = "SELECT user_id,lastname,firstname FROM $table_user WHERE status='1'".$order_clause;
+	$sql = "SELECT user_id,lastname,firstname FROM $table_user WHERE status = 1 or status = 2 ".$order_clause;
 }
 
 $res = Database::query($sql);
@@ -89,6 +89,10 @@ $form->applyFilter('title','trim');
 $element = $form->addElement('text', 'real_code', array(get_lang('CourseCode'), get_lang('ThisValueCantBeChanged')));
 $element->freeze();
 
+// Id
+$element = $form->addElement('text', 'real_id', 'id');
+$element->freeze();
+
 // visual code
 $form->add_textfield('visual_code', array(get_lang('VisualCode'), get_lang('OnlyLettersAndNumbers'), get_lang('ThisValueIsUsedInTheCourseURL')), true, array('class' => 'span4'));
 
@@ -149,6 +153,7 @@ $group[]= $form->createElement('radio', 'visibility', get_lang("CourseAccess"),
 $group[]= $form->createElement('radio', 'visibility', null, get_lang('OpenToThePlatform'), COURSE_VISIBILITY_OPEN_PLATFORM);
 $group[]= $form->createElement('radio', 'visibility', null, get_lang('Private'), COURSE_VISIBILITY_REGISTERED);
 $group[]= $form->createElement('radio', 'visibility', null, get_lang('CourseVisibilityClosed'), COURSE_VISIBILITY_CLOSED);
+$group[]= $form->createElement('radio', 'visibility', null, get_lang('CourseVisibilityHidden'), COURSE_VISIBILITY_HIDDEN);
 $form->addGroup($group,'', get_lang('CourseAccess'), '<br />');
 
 $group = array();

+ 55 - 44
main/admin/course_import.php

@@ -14,11 +14,10 @@
  * Validates imported data.
  */
 function validate_data($courses) {
-    global $_configuration;
     global $purification_option_for_usernames;
-    $dbnamelength = strlen($_configuration['db_prefix']);
+
     // Ensure the prefix + database name do not get over 40 characters.
-    $maxlength = 40 - $dbnamelength;
+    $maxlength = 40;
 
     $errors = array ();
     $coursecodes = array ();
@@ -56,16 +55,24 @@ function validate_data($courses) {
             }
             $coursecodes[$course['Code']] = 1;
         }
-        /*
         // 3. Check whether teacher exists.
-        if (!UserManager::is_username_empty($course['Teacher'])) {
-            $teacher = UserManager::purify_username($course['Teacher'], $purification_option_for_usernames);
-            if (UserManager::is_username_available($teacher)) {
-                $course['error'] = get_lang('UnknownTeacher').' ('.$teacher.')';
-                $errors[] = $course;
+        $teacherList = getTeacherListInArray($course['Teacher']);
+
+        if (!empty($teacherList)) {
+            foreach ($teacherList as $teacher) {
+                $teacherInfo = api_get_user_info_from_username($teacher);
+                if (empty($teacherInfo)) {
+                    $course['error'] = get_lang('UnknownTeacher').' ('.$teacher.')';
+                    $errors[] = $course;
+                } else {
+                    if ($teacherInfo['status'] != COURSEMANAGER) {
+                        $course['error'] = get_lang('UserIsNotATeacher').' ('.$teacher.')';
+                        $errors[] = $course;
+                    }
+                }
             }
         }
-        */
+
         // 4. Check whether course category exists.
         if (isset($course['CourseCategory']) && strlen($course['CourseCategory']) != 0) {
             $category_table = Database :: get_main_table(TABLE_MAIN_CATEGORY);
@@ -81,6 +88,14 @@ function validate_data($courses) {
     return $errors;
 }
 
+function getTeacherListInArray($teachers)
+{
+    if (!empty($teachers)) {
+        return explode('|', $teachers);
+    }
+    return array();
+}
+
 /**
  * Saves imported data.
  * @param array   List of courses
@@ -93,44 +108,40 @@ function save_data($courses) {
 
     foreach ($courses as $index => $course) {
         $course_language = api_get_valid_language($course['Language']);
-        $titular = $uidCreator = $username = '';
-
-        // Get username from name (firstname lastname).
-        if (!UserManager::is_username_empty($course['Teacher'])) {
-            $teacher = UserManager::purify_username($course['Teacher'], $purification_option_for_usernames);
-            if (UserManager::is_username_available($teacher)) {
-                $sql    = "SELECT username FROM $user_table WHERE ".(api_is_western_name_order(null, $course_language) ? "CONCAT(firstname,' ',lastname)" : "CONCAT(lastname,' ',firstname)")." = '{$course['Teacher']}' LIMIT 1";
-                $rs     = Database::query($sql);
-                $user   = Database::fetch_object($rs);
-                $username = $user->username;
-            } else {
-                $username = $teacher;
+        $username = '';
+
+        $teachers = getTeacherListInArray($course['Teacher']);
+        $teacherList = array();
+        $creatorId = api_get_user_id();
+
+        if (!empty($teachers)) {
+            foreach ($teachers as $teacher) {
+                $teacherInfo = api_get_user_info_from_username($teacher);
+                if (!empty($teacherInfo)) {
+                    $teacherList[] = $teacherInfo;
             }
         }
 
-        // Get name and uid creator from username.
-        if (!empty($username)) {
-            $sql = "SELECT user_id, ".(api_is_western_name_order(null, $course_language) ? "CONCAT(firstname,' ',lastname)" : "CONCAT(lastname,' ',firstname)")." AS name FROM $user_table WHERE username = '".Database::escape_string(UserManager::purify_username($username, $purification_option_for_usernames))."'";
-            $res = Database::query($sql);
-            $teacher    = Database::fetch_object($res);
-            $titular    = $teacher->name;
-            $uidCreator = $teacher->user_id;
-        } else {
-            $titular    = $course['Teacher'];
-            $uidCreator = 1;
         }
 
         $params = array();
         $params['title']            = $course['Title'];
         $params['wanted_code']      = $course['Code'];
-        $params['tutor_name']       = $titular;
+        $params['tutor_name']       = null;
         $params['course_category']  = $course['CourseCategory'];
         $params['course_language']  = $course_language;
-        $params['user_id']          = $uidCreator;
+        $params['user_id']          = $creatorId;
 
         $course_info = CourseManager::create_course($params);
         if (!empty($course_info)) {
-            $msg .= '<a href="'.api_get_path(WEB_COURSE_PATH).$course_info['directory'].'/">'.$course_info['title'].'</a> '.get_lang('Created').'<br />';
+            if (!empty($teacherList)) {
+                foreach ($teacherList as $teacher) {
+                    CourseManager::add_user_to_course($teacher['user_id'], $course_info['code'], COURSEMANAGER);
+                }
+            }
+
+            $msg .= '<a href="'.api_get_path(WEB_COURSE_PATH).$course_info['directory'].'/">
+                    '.$course_info['title'].'</a> '.get_lang('Created').'<br />';
         }
     }
 
@@ -153,14 +164,12 @@ $language_file = array('admin', 'registration','create_course', 'document');
 
 $cidReset = true;
 
-require_once '../inc/global.inc.php';
-
 $this_section = SECTION_PLATFORM_ADMIN;
 api_protect_admin_script();
 
 $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));
 }
 
@@ -171,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);
@@ -192,11 +201,11 @@ 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>: ';
-        $error_message .= $error_course['Code'].' '.$error_course['Title'];
+        $error_message .= get_lang('Course').': '.$error_course['Title'].' ('.$error_course['Code'].')';
         $error_message .= '</li>';
     }
     $error_message .= '</ul>';
@@ -223,10 +232,12 @@ if (count($errors) != 0) {
 
 <blockquote>
 <pre>
-<strong>Code</strong>;<strong>Title</strong>;<strong>CourseCategory</strong>;<strong>Teacher</strong>;Language
-BIO0015;Biology;BIO;username;english
+<strong>Code</strong>;<strong>Title</strong>;<strong>CourseCategory</strong>;Teacher;Language
+BIO0015;Biology;BIO;teacher1;english
+BIO0016;Maths;MATH;teacher2|teacher3;english
+BIO0017;Language;LANG;;english
 </pre>
 </blockquote>
 
 <?php
-Display :: display_footer();
+Display :: display_footer();

+ 5 - 5
main/admin/course_information.php

@@ -62,15 +62,16 @@ $tool_name = $course_info['title'].' ('.$course_info['visual_code'].')';
 Display::display_header($tool_name);
 
 echo '<div class="actions">';
-echo '<a href="'.api_get_path(WEB_COURSE_PATH).$course_info['directory'].'">'.Display::display_icon('home.png', get_lang('CourseHomepage'), array(), ICON_SIZE_MEDIUM).'</a>';
+echo '<a href="'.api_get_path(WEB_COURSE_PATH).$course_info['directory'].'">'.
+        Display::display_icon('home.png', get_lang('CourseHomepage'), array(), ICON_SIZE_MEDIUM).'</a>';
 echo '</div>';
 
 echo Display::page_header($tool_name);
 
 echo Display::page_subheader(get_lang('CourseUsage'));
 
-$id_session = intval($_GET['id_session']);
-$table = new SortableTableFromArray(get_course_usage($course_info['code'],$id_session),0,20,'usage_table');
+$id_session = isset($_GET['id_session']) ? $_GET['id_session'] : 0;
+$table = new SortableTableFromArray(get_course_usage($course_info['code'], $id_session), 0, 20,'usage_table');
 $table->set_additional_parameters(array ('code' => Security::remove_XSS($_GET['code'])));
 $table->set_other_tables(array('user_table','class_table'));
 $table->set_header(0,get_lang('Tool'), true);
@@ -152,7 +153,6 @@ if (!empty($extra_fields)) {
         $value = null;
         if ($result) {
             $value = $result['field_value'];
-
             if (is_bool($value)) {
                 $value = $value ? get_lang('Yes') : get_lang('No');
             }
@@ -167,4 +167,4 @@ if (!empty($extra_fields)) {
     echo "</table>";
 }
 
-Display::display_footer();
+Display::display_footer();

+ 4 - 0
main/admin/course_list.php

@@ -157,6 +157,9 @@ function get_course_visibility_icon($v) {
         case 3:
             return Display::return_icon('bullet_blue.gif', get_lang('OpenToTheWorld'), array('style' => $style));
             break;
+        case 4:
+            return Display::return_icon('bullet_grey.gif', get_lang('CourseVisibilityHidden'), array('style' => $style));
+            break;
         default:
             return '';
     }
@@ -201,6 +204,7 @@ if (isset ($_GET['search']) && $_GET['search'] == 'advanced') {
     $form->addElement('radio', 'keyword_visibility', null, get_lang('OpenToThePlatform'), COURSE_VISIBILITY_OPEN_PLATFORM);
     $form->addElement('radio', 'keyword_visibility', null, get_lang('Private'), COURSE_VISIBILITY_REGISTERED);
     $form->addElement('radio', 'keyword_visibility', null, get_lang('CourseVisibilityClosed'), COURSE_VISIBILITY_CLOSED);
+    $form->addElement('radio', 'keyword_visibility', null, get_lang('CourseVisibilityHidden'), COURSE_VISIBILITY_HIDDEN);
     $form->addElement('radio', 'keyword_visibility', null, get_lang('All'), '%');
     $form->addElement('radio', 'keyword_subscribe', get_lang('Subscription'), get_lang('Allowed'), 1);
     $form->addElement('radio', 'keyword_subscribe', null, get_lang('Denied'), 0);

+ 281 - 0
main/admin/exercise_report.php

@@ -0,0 +1,281 @@
+<?php
+/* For licensing terms, see /license.txt */
+/**
+ * Exercise list: This script shows the list of exercises for administrators and students.
+ * @package chamilo.exercise
+ * @author Julio Montoya <gugli100@gmail.com> jqgrid integration
+ *   Modified by hubert.borderiou (question category)
+ *
+ * @todo fix excel export
+ *
+ */
+/**
+ * Code
+ */
+// name of the language file that needs to be included
+$language_file = array('exercice');
+
+api_protect_global_admin_script();
+
+$urlMainExercise = api_get_path(WEB_CODE_PATH).'exercice/';
+
+// Setting the tabs
+$this_section = SECTION_COURSES;
+
+$htmlHeadXtra[] = api_get_jqgrid_js();
+
+// including additional libraries
+require_once api_get_path(SYS_CODE_PATH).'exercice/exercise.class.php';
+require_once api_get_path(SYS_CODE_PATH).'exercice/question.class.php';
+require_once api_get_path(SYS_CODE_PATH).'exercice/answer.class.php';
+
+// need functions of statsutils lib to display previous exercices scores
+require_once api_get_path(LIBRARY_PATH).'statsUtils.lib.inc.php';
+
+// document path
+$documentPath = api_get_path(SYS_COURSE_PATH).$_course['path']."/document";
+
+/*	Constants and variables */
+$is_tutor = api_is_allowed_to_edit(true);
+
+$TBL_QUESTIONS = Database :: get_course_table(TABLE_QUIZ_QUESTION);
+$TBL_TRACK_EXERCICES = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+$TBL_TRACK_ATTEMPT = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
+$TBL_TRACK_ATTEMPT_RECORDING = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING);
+$TBL_LP_ITEM_VIEW = Database :: get_course_table(TABLE_LP_ITEM_VIEW);
+$course_id = api_get_course_int_id();
+
+if (!empty($_REQUEST['export_report']) && $_REQUEST['export_report'] == '1') {
+
+    $load_extra_data = false;
+    if (isset($_REQUEST['extra_data']) && $_REQUEST['extra_data'] == 1) {
+        $load_extra_data = true;
+    }
+    require_once 'exercise_result.class.php';
+    switch ($_GET['export_format']) {
+        case 'xls':
+            $export = new ExerciseResult();
+            $export->exportCompleteReportXLS(
+                $documentPath,
+                null,
+                $load_extra_data,
+                null,
+                $_GET['exerciseId'],
+                $_GET['hotpotato_name']
+            );
+            exit;
+            break;
+        case 'csv':
+        default:
+            $export = new ExerciseResult();
+            $export->exportCompleteReportCSV(
+                $documentPath,
+                null,
+                $load_extra_data,
+                null,
+                $_GET['exerciseId'],
+                $_GET['hotpotato_name']
+            );
+            exit;
+            break;
+    }
+
+}
+
+$nameTools = get_lang('StudentScore');
+
+$interbreadcrumb[] = array ('url' => 'index.php', 'name' => get_lang('PlatformAdmin'));
+$interbreadcrumb[] = array("url" => "", "name" => get_lang('ExercicesReport'));
+
+Display :: display_header($nameTools);
+
+$extra = '<script>
+    $(document).ready(function() {
+
+        $( "#dialog:ui-dialog" ).dialog( "destroy" );
+
+        $( "#dialog-confirm" ).dialog({
+                autoOpen: false,
+                show: "blind",
+                resizable: false,
+                height:300,
+                modal: true
+         });
+
+        $("#export_opener").click(function() {
+            var targetUrl = $(this).attr("href");
+            $( "#dialog-confirm" ).dialog({
+                width:400,
+                height:300,
+                buttons: {
+                    "'.addslashes(get_lang('Download')).'": function() {
+                        var export_format = $("input[name=export_format]:checked").val();
+                        var extra_data  = $("input[name=load_extra_data]:checked").val();
+                        location.href = targetUrl+"&export_format="+export_format+"&extra_data="+extra_data;
+                        $( this ).dialog( "close" );
+                    },
+                }
+            });
+            $( "#dialog-confirm" ).dialog("open");
+            return false;
+        });
+    });
+    </script>';
+
+$extra .= '<div id="dialog-confirm" title="'.get_lang("ConfirmYourChoice").'">';
+$form = new FormValidator('report', 'post', null, null, array('class' => 'form-vertical'));
+$form->addElement(
+    'radio',
+    'export_format',
+    null,
+    get_lang('ExportAsCSV'),
+    'csv',
+    array('id' => 'export_format_csv_label')
+);
+$form->addElement(
+    'radio',
+    'export_format',
+    null,
+    get_lang('ExportAsXLS'),
+    'xls',
+    array('id' => 'export_format_xls_label')
+);
+$form->addElement(
+    'checkbox',
+    'load_extra_data',
+    null,
+    get_lang('LoadExtraData'),
+    '0',
+    array('id' => 'export_format_xls_label')
+);
+$form->setDefaults(array('export_format' => 'csv'));
+$extra .= $form->return_form();
+$extra .= '</div>';
+
+echo $extra;
+
+$url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_admin_exercise_results';
+
+$action_links = '';
+
+//The order is important you need to check the the $column variable in the model.ajax.php file
+$columns = array(
+    get_lang('LoginName'),
+    get_lang('FirstName'),
+    get_lang('LastName'),
+    get_lang('Score'),
+    get_lang('Link'),
+    get_lang('Session')
+  //  get_lang('Actions')
+);
+
+//Column config
+$column_model = array(
+    array(
+        'name' => 'login',
+        'index' => 'username',
+        'width' => '40',
+        'align' => 'left',
+        'search' => 'true'
+    ),
+    array('name' => 'firstname', 'index' => 'firstname', 'width' => '50', 'align' => 'left', 'search' => 'true'),
+    array(
+        'name' => 'lastname',
+        'index' => 'lastname',
+        'width' => '50',
+        'align' => 'left',
+        //'formatter' => 'action_formatter',
+        'search' => 'true'
+    ),
+    array('name' => 'score', 'index' => 'exe_result', 'width' => '50', 'align' => 'left', 'search' => 'true'),
+    array('name' => 'link', 'index' => 'link', 'width' => '50', 'align' => 'left', 'search' => 'false'),
+    array('name' => 'session', 'index' => 'session_id', 'width' => '50', 'align' => 'left', 'search' => 'true'),
+);
+
+//Autowidth
+$extra_params['autowidth'] = 'true';
+
+//height auto
+$extra_params['height'] = 'auto';
+
+?>
+<script>
+
+    function setSearchSelect(columnName) {
+        $("#results").jqGrid('setColProp', columnName, {
+            searchoptions:{
+                dataInit:function (el) {
+                    $("option[value='1']", el).attr("selected", "selected");
+                    setTimeout(function () {
+                        $(el).trigger('change');
+                    }, 1000);
+                }
+            }
+        });
+    }
+
+    function exportExcel() {
+        var mya = new Array();
+        mya = $("#results").getDataIDs();  // Get All IDs
+        var data = $("#results").getRowData(mya[0]);     // Get First row to get the labels
+        var colNames = new Array();
+        var ii = 0;
+        for (var i in data) {
+            colNames[ii++] = i;
+        }    // capture col names
+        var html = "";
+
+        for (i = 0; i < mya.length; i++) {
+            data = $("#results").getRowData(mya[i]); // get each row
+            for (j = 0; j < colNames.length; j++) {
+                html = html + data[colNames[j]] + ","; // output each column as tab delimited
+            }
+            html = html + "\n";  // output each row with end of line
+        }
+        html = html + "\n";  // end of line at the end
+
+        var form = $("#export_report_form");
+
+        $("#csvBuffer").attr('value', html);
+        form.target = '_blank';
+        form.submit();
+    }
+
+    $(function () {
+    <?php
+        echo Display::grid_js('results', $url, $columns, $column_model, $extra_params, array(), $action_links, true);
+    ?>
+        //setSearchSelect("status");
+        //
+        //view:true, del:false, add:false, edit:false, excel:true}
+        $("#results").jqGrid(
+            'navGrid',
+            '#results_pager',
+            { view:true, edit:false, add:false, del:false, excel:false },
+            { height:280, reloadAfterSubmit:false }, // view options
+            { height:280, reloadAfterSubmit:false }, // edit options
+            { height:280, reloadAfterSubmit:false }, // add options
+            { reloadAfterSubmit : false }, // del options
+            { width:500 } // search options
+        );
+        //Adding search options
+        var options = {
+            'stringResult': true,
+            'autosearch' : true,
+            'searchOnEnter':false
+        }
+        jQuery("#results").jqGrid('filterToolbar', options);
+        var sgrid = $("#results")[0];
+        sgrid.triggerToolbar();
+
+    });
+</script>
+<form id="export_report_form" method="post" action="exercise_report.php">
+    <input type="hidden" name="csvBuffer" id="csvBuffer" value=""/>
+    <input type="hidden" name="export_report" id="export_report" value="1"/>
+</form>
+<?php
+
+echo Display::grid_html('results');
+
+Display :: display_footer();

+ 1 - 1
main/admin/extra_fields.php

@@ -9,11 +9,11 @@
 $language_file = array('admin');
 
 $cidReset = true;
-require_once '../inc/global.inc.php';
 
 $extraFieldType =  isset($_REQUEST['type']) ? $_REQUEST['type'] : null;
 
 $this_section = SECTION_PLATFORM_ADMIN;
+
 api_protect_admin_script();
 
 //Add the JS needed to use the jqgrid

+ 3 - 460
main/admin/index.php

@@ -1,461 +1,4 @@
 <?php
-/* For licensing terms, see /license.txt */
-/**
- * Index page of the admin tools
- * @package chamilo.admin
- */
-/**
- * Code
- */
-
-// Language files that need to be included.
-$language_file = array('admin', 'tracking','coursebackup');
-
-// Setting the section (for the tabs).
-$this_section = SECTION_PLATFORM_ADMIN;
-
-// Access restrictions.
-api_protect_admin_script(true);
-
-$nameTools = get_lang('PlatformAdmin');
-
-// Displaying the header
-$message = '';
-
-if (api_is_platform_admin()) {
-    if (is_dir(api_get_path(SYS_CODE_PATH).'install/') && is_readable(api_get_path(SYS_CODE_PATH).'install/index.php')) {
-        $message = Display::return_message(get_lang('InstallDirAccessibleSecurityThreat'),'warning');
-    }
-    if (is_dir(api_get_path(SYS_ARCHIVE_PATH)) && !is_writable(api_get_path(SYS_ARCHIVE_PATH))) {
-        $message = Display::return_message(get_lang('ArchivesDirectoryNotWriteableContactAdmin'),'warning');
-    }
-
-    /* ACTION HANDLING */
-    if (!empty($_POST['Register'])) {
-        register_site();
-        $message = Display :: return_message(get_lang('VersionCheckEnabled'),'confirmation');
-    }
-    $keyword_url = Security::remove_XSS((empty($_GET['keyword']) ? '' : $_GET['keyword']));
-}
-
-if (isset($_GET['msg']) && isset($_GET['type'])) {
-	if (in_array($_GET['msg'], array('ArchiveDirCleanupSucceeded', 'ArchiveDirCleanupFailed')))
-	switch($_GET['type']) {
-		case 'error':
-			$message = Display::return_message(get_lang($_GET['msg']), 'error');
-			break;
-		case 'confirmation':
-			$message = Display::return_message(get_lang($_GET['msg']), 'confirm');
-	}
-}
-
-$blocks = array();
-
-/* Users */
-
-$blocks['users']['icon']  = Display::return_icon('members.gif', get_lang('Users'), array(), ICON_SIZE_SMALL, false);
-$blocks['users']['label'] = api_ucfirst(get_lang('Users'));
-
-if (api_is_platform_admin()) {
-	$search_form = ' <form method="get" class="form-search" action="user_list.php">
-						<input class="span3" type="text" name="keyword" value="">
-						<button class="btn" type="submit">'.get_lang('Search').'</button>
-            		</form>';
-	$blocks['users']['search_form'] = $search_form;
-	$items = array(
-		array('url'=>'user_list.php', 	'label' => get_lang('UserList')),
-		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')),
-	);
-
-	/*if (api_get_setting('allow_social_tool') == 'true') {
-		$items[] = array('url'=>'group_add.php', 	'label' => get_lang('AddGroups'));
-		$items[] = array('url'=>'group_list.php', 	'label' => get_lang('GroupList'));
-	}*/
-	if (isset($extAuthSource) && isset($extAuthSource['ldap']) && count($extAuthSource['ldap']) > 0) {
-		$items[] = array('url'=>'ldap_users_list.php', 	'label' => get_lang('ImportLDAPUsersIntoPlatform'));
-	}
-	// $items[] = array('url'=>'user_fields.php', 	'label' => get_lang('ManageUserFields'));
-    $items[] = array('url'=>'extra_fields.php?type=user', 	'label' => get_lang('ManageUserFields'));
-    $items[] = array('url'=> api_get_path(WEB_PUBLIC_PATH).'admin/administrator/roles', 	'label' => get_lang('Roles'));
-} else {
- 	$items = array(
- 		array('url'=>'user_list.php', 	'label' => get_lang('UserList')),
- 		array('url'=>'user_add.php', 	'label' => get_lang('AddUsers')),
- 		array('url'=>'user_import.php', 'label' => get_lang('ImportUserListXMLCSV')),
- 	);
-}
-$blocks['users']['items'] = $items;
-$blocks['users']['extra'] = null;
-
-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'));
-
-	$search_form = ' <form method="get" class="form-search" action="course_list.php">
-							<input class="span3" type="text" name="keyword" value="">
-							<button class="btn" type="submit">'.get_lang('Search').'</button>
-	            		</form>';
-	$blocks['courses']['search_form'] = $search_form;
-
-	$items = array();
-	$items[] = array('url'=>'course_list.php', 	'label' => get_lang('CourseList'));
-
-	if (api_get_setting('course_validation') != 'true') {
-		$items[] = array('url'=>'course_add.php', 	'label' => get_lang('AddCourse'));
-	} else {
-		$items[] = array('url'=>'course_request_review.php', 	'label' => get_lang('ReviewCourseRequests'));
-		$items[] = array('url'=>'course_request_accepted.php', 	'label' => get_lang('AcceptedCourseRequests'));
-		$items[] = array('url'=>'course_request_rejected.php', 	'label' => get_lang('RejectedCourseRequests'));
-	}
-
-	$items[] = array('url'=>'course_export.php', 			'label' => get_lang('ExportCourses'));
-	$items[] = array('url'=>'course_import.php', 			'label' => get_lang('ImportCourses'));
-	$items[] = array('url'=>'course_category.php', 			'label' => get_lang('AdminCategories'));
-	$items[] = array('url'=>'subscribe_user2course.php', 	'label' => get_lang('AddUsersToACourse'));
-	$items[] = array('url'=>'course_user_import.php', 		'label' => get_lang('ImportUsersToACourse'));
-
-    $items[] = array('url'=>'extra_fields.php?type=course', 	'label' => get_lang('ManageCourseFields'));
-
-    $items[] = array('url'=>'extra_fields.php?type=question', 	'label' => get_lang('ManageQuestionFields'));
-
-
-    if (api_get_setting('gradebook_enable_grade_model') == 'true') {
-        $items[] = array('url'=>'grade_models.php',             'label' => get_lang('GradeModel'));
-    }
-
-    if (isset($extAuthSource) && isset($extAuthSource['ldap']) && count($extAuthSource['ldap']) > 0) {
-    	$items[] = array('url'=>'ldap_import_students.php', 	'label' => get_lang('ImportLDAPUsersIntoCourse'));
-    }
-    $blocks['courses']['items'] = $items;
-    $blocks['courses']['extra'] = null;
-
-    /* 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'));
-
-    $search_form = ' <form method="get" action="settings.php" class="form-search">
-							<input class="span3" type="text" name="search_field" value="" >
-                            <input type="hidden" value="search_setting" name="category">
-							<button class="btn" type="submit">'.get_lang('Search').'</button>
-	            		</form>';
-	$blocks['platform']['search_form'] = $search_form;
-
-
-    $items = array();
-    $items[] = array('url'=>'settings.php', 				'label' => get_lang('PlatformConfigSettings'));
-    $items[] = array('url'=>'settings.php?category=Plugins','label' => get_lang('Plugins'));
-    $items[] = array('url'=>'settings.php?category=Regions','label' => get_lang('Regions'));
-    $items[] = array('url'=>'system_announcements.php', 	'label' => get_lang('SystemAnnouncements'));
-    $items[] = array('url'=>api_get_path(WEB_CODE_PATH).'calendar/agenda_js.php?type=admin', 'label' => get_lang('GlobalAgenda'));
-    $items[] = array('url'=>'configure_homepage.php', 		'label' => get_lang('ConfigureHomePage'));
-    $items[] = array('url'=>'configure_inscription.php', 	'label' => get_lang('ConfigureInscription'));
-    $items[] = array('url'=>'statistics/index.php', 		'label' => get_lang('Statistics'));
-    $items[] = array('url'=> api_get_path(WEB_CODE_PATH).'mySpace/company_reports.php',          'label' => get_lang('Reports'));
-
-    /* Event settings */
-
-    if (api_get_setting('activate_email_template') == 'true') {
-        $items[] = array('url'=>'event_controller.php?action=listing', 		'label' => get_lang('EventMessageManagement'));
-    }
-
-    if (!empty($_configuration['multiple_access_urls'])) {
-	if (api_is_global_platform_admin()) {
-            	$items[] = array('url'=>'access_urls.php', 	'label' => get_lang('ConfigureMultipleAccessURLs'));
-        }
-    }
-
-    if (api_get_setting('allow_reservation') == 'true') {
-    	$items[] = array('url'=>'../reservation/m_category.php', 	'label' => get_lang('BookingSystem'));
-	}
-	if (api_get_setting('allow_terms_conditions') == 'true') {
-    	$items[] = array('url'=>'legal_add.php', 	'label' => get_lang('TermsAndConditions'));
-	}
-	$blocks['platform']['items'] = $items;
-    $blocks['platform']['extra'] = null;
-}
-
-/* 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'));
-
-$search_form = ' <form method="GET" class="form-search" action="'.api_get_path(WEB_CODE_PATH).'session/session_list.php">
-                    <input class="span3" type="text" name="keyword" value="">
-                    <button class="btn" type="submit">'.get_lang('Search').'</button>
-                </form>';
-$blocks['sessions']['search_form'] = $search_form;
-$items = array();
-$items[] = array('url'=> api_get_path(WEB_CODE_PATH).'session/session_list.php', 'label' => get_lang('ListSession'));
-$items[] = array('url'=> api_get_path(WEB_CODE_PATH).'session/session_add.php', 	'label' => get_lang('AddSession'));
-$items[] = array('url'=> 'session_category_list.php', 	'label' => get_lang('ListSessionCategory'));
-$items[] = array('url'=> api_get_path(WEB_CODE_PATH).'session/session_import.php', 	'label' => get_lang('ImportSessionListXMLCSV'));
-if (isset($extAuthSource) && isset($extAuthSource['ldap']) && count($extAuthSource['ldap']) > 0) {
-    $items[] = array('url'=>'ldap_import_students_to_session.php', 	'label' => get_lang('ImportLDAPUsersIntoSession'));
-}
-$items[] = array('url'=>api_get_path(WEB_CODE_PATH).'session/session_export.php', 	'label' => get_lang('ExportSessionListXMLCSV'));
-$items[] = array('url'=>'../coursecopy/copy_course_session.php', 	'label' => get_lang('CopyFromCourseInSessionToAnotherSession'));
-
-if (api_is_platform_admin()) {
-    if (is_dir(api_get_path(SYS_TEST_PATH).'datafiller/')) { // option only visible in development mode. Enable through code if required
-        $items[] = array('url'=>'user_move_stats.php', 	'label' => get_lang('MoveUserStats'));
-    }
-    $items[] = array('url'=>'career_dashboard.php', 	'label' => get_lang('CareersAndPromotions'));
-}
-
-$items[] = array('url'=>'usergroups.php', 	'label' => get_lang('Classes'));
-$items[] = array('url'=>'extra_fields.php?type=session', 	'label' => get_lang('ManageSessionFields'));
-
-$blocks['sessions']['items'] = $items;
-$blocks['sessions']['extra'] = null;
-
-
-/* Settings */
-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'));
-
-	$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').') ');
-	}
-	$items[] = array('url'=>'system_status.php', 	'label' => get_lang('SystemStatus'));
-	if (is_dir(api_get_path(SYS_TEST_PATH).'datafiller/')) {
-		$items[] = array('url'=>'filler.php', 	'label' => get_lang('DataFiller'));
-	}
-    $items[] = array('url'=>'archive_cleanup.php', 	'label' => get_lang('ArchiveDirCleanup'));
-	$items[] = array('url'=>'system_management.php', 'label' => get_lang('SystemManagement'));
-
-	$blocks['settings']['items'] = $items;
-    $blocks['settings']['extra'] = null;
-
-    $blocks['settings']['search_form'] = null;
-
-	/* Extensions */
-	/*
-	$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'));
-
-	$items = array();
-	$items[] = array('url'=>'configure_extensions.php?display=visio', 	'label' => get_lang('Visioconf'));
-	$items[] = array('url'=>'configure_extensions.php?display=ppt2lp', 	'label' => get_lang('Ppt2lp'));
-	//$items[] = array('url'=>'configure_extensions.php?display=ephorus', 	'label' => get_lang('EphorusPlagiarismPrevention'));
-	$items[] = array('url'=>'configure_extensions.php?display=search', 	'label' => get_lang('SearchEngine'));
-	$items[] = array('url'=>'configure_extensions.php?display=serverstats', 	'label' => get_lang('ServerStatistics'));
-	$items[] = array('url'=>'configure_extensions.php?display=bandwidthstats', 	'label' => get_lang('BandWidthStatistics'));
-	$blocks['extensions']['items'] = $items;
-    */
-
-    //Skills
-    if (api_get_setting('allow_skills_tool') == 'true') {
-        $blocks['skills']['icon']  = Display::return_icon('logo.gif', get_lang('Skills'), array(), ICON_SIZE_SMALL, false);
-        $blocks['skills']['label'] = get_lang('Skills');
-
-        $items = array();
-        //$items[] = array('url'=>'skills.php',           'label' => get_lang('SkillsTree'));
-        $items[] = array('url'=>'skills_wheel.php',     'label' => get_lang('SkillsWheel'));
-        $items[] = array('url'=>'skills_import.php',    'label' => get_lang('SkillsImport'));
-        //$items[] = array('url'=>'skills_profile.php',   'label' => get_lang('SkillsProfile'));
-        $items[] = array('url'=>api_get_path(WEB_CODE_PATH).'social/skills_ranking.php',   'label' => get_lang('SkillsRanking'));
-        $items[] = array('url'=>'skills_gradebook.php', 'label' => get_lang('SkillsAndGradebooks'));
-        $blocks['skills']['items'] = $items;
-        $blocks['skills']['extra'] = null;
-        $blocks['skills']['search_form'] = null;
-    }
-
-	/* Chamilo.org */
-
-	$blocks['chamilo']['icon']  = Display::return_icon('logo.gif', 'Chamilo.org', array(), ICON_SIZE_SMALL, false);
-	$blocks['chamilo']['label'] = 'Chamilo.org';
-
-	$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'));
-
-	$items[] = array('url'=>'../../documentation/installation_guide.html', 	'label' => get_lang('InstallationGuide'));
-	$items[] = array('url'=>'../../documentation/changelog.html', 	'label' => get_lang('ChangesInLastVersion'));
-	$items[] = array('url'=>'../../documentation/credits.html', 	'label' => get_lang('ContributorsList'));
-	$items[] = array('url'=>'../../documentation/security.html', 	'label' => get_lang('SecurityGuide'));
-	$items[] = array('url'=>'../../documentation/optimization.html', 	'label' => get_lang('OptimizationGuide'));
-	$items[] = array('url'=>'http://www.chamilo.org/extensions', 	'label' => get_lang('ChamiloExtensions'));
-	$items[] = array('url'=>'http://www.chamilo.org/en/providers', 	'label' => get_lang('ChamiloOfficialServicesProviders'));
-
-	$blocks['chamilo']['items'] = $items;
-    $blocks['chamilo']['extra'] = null;
-    $blocks['chamilo']['search_form'] = null;
-
-	// Try to display a maximum before we check the chamilo version and all that.
-	//session_write_close(); //close session to avoid blocking concurrent access
-	//flush(); //send data to client as much as allowed by the web server
-	//ob_flush();
-
-    //Version check
-    $blocks['version_check']['icon']  = Display::return_icon('logo.gif', 'Chamilo.org', array(), ICON_SIZE_SMALL, false);
-	$blocks['version_check']['label'] = get_lang('VersionCheck');
-	$blocks['version_check']['extra'] = version_check();
-    $blocks['version_check']['search_form'] = null;
-    $blocks['version_check']['items'] = null;
-}
-
-$app['template']->assign('blocks', $blocks);
-$app['template']->display('default/admin/settings_index.tpl');
-
-/**
- * Displays either the text for the registration or the message that the installation is (not) up to date
- *
- * @return string html code
- * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
- * @version august 2006
- * @todo have a 6monthly re-registration
- */
-function version_check() {
-    $tbl_settings = Database :: get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
-    $sql = 'SELECT selected_value FROM  '.$tbl_settings.' WHERE variable="registered" ';
-    $result = Database::query($sql);
-    $row = Database::fetch_array($result, 'ASSOC');
-
-    // The site has not been registered yet.
-    $return = '';
-    if ($row['selected_value'] == 'false') {
-        $return .= get_lang('VersionCheckExplanation');
-        $return .= '<form class="well" action="'.api_get_self().'" id="VersionCheck" name="VersionCheck" method="post">';
-        $return .= '<label class="checkbox"><input type="checkbox" name="donotlistcampus" value="1" id="checkbox" />'.get_lang('HideCampusFromPublicPlatformsList');
-        $return .= '</label><button type="submit" class="btn btn-primary" name="Register" value="'.get_lang('EnableVersionCheck').'" id="register" >'.get_lang('EnableVersionCheck').'</button>';
-        $return .= '</form>';
-        check_system_version();
-    } else {
-        // Site registered. Call anyway
-        $return .= check_system_version();
-    }
-    return $return;
-}
-
-/**
- * This setting changes the registration status for the campus
- *
- * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
- * @version August 2006
- *
- * @todo the $_settings should be reloaded here. => write api function for this and use this in global.inc.php also.
- */
-function register_site() {
-    $tbl_settings = Database :: get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
-
-    $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='registered'";
-    Database::query($sql);
-
-    if ($_POST['donotlistcampus']) {
-        $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='donotlistcampus'";
-        Database::query($sql);
-    }
-    // Reload the settings.
-}
-
-
-/**
- * Check if the current installation is up to date
- * The code is borrowed from phpBB and slighlty modified
- * @author The phpBB Group <support@phpbb.com> (the code)
- * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University (the modifications)
- * @author Yannick Warnier <ywarnier@beeznest.org> for the move to HTTP request
- * @copyright (C) 2001 The phpBB Group
- * @return language string with some layout (color)
- */
-function check_system_version() {
-    global $_configuration;
-    $system_version = trim($_configuration['system_version']); // the chamilo version of your installation
-
-    if (ini_get('allow_url_fopen') == 1) {
-        // The number of courses
-        $number_of_courses = Statistics::count_courses();
-
-        // The number of users
-        $number_of_users = statistics::count_users();
-        $number_of_active_users = statistics::count_users(null,null,null,true);
-
-        $data = array(
-            'url' => api_get_path(WEB_PATH),
-            'campus' => api_get_setting('siteName'),
-            'contact' => api_get_setting('emailAdministrator'),
-            'version' => $system_version,
-            'numberofcourses' => $number_of_courses,
-            'numberofusers' => $number_of_users,
-            'numberofactiveusers' => $number_of_active_users,
-            //The donotlistcampus setting recovery should be improved to make
-            // it true by default - this does not affect numbers counting
-            'donotlistcampus' => api_get_setting('donotlistcampus'),
-            'organisation' => api_get_setting('Institution'),
-            'language' => api_get_setting('platformLanguage'),
-            'adminname' => api_get_setting('administratorName').' '.api_get_setting('administratorSurname'),
-        );
-
-        $res = _http_request('version.chamilo.org', 80, '/version.php', $data);
-
-        if ($res !== false) {
-            $version_info = $res;
-
-            if ($system_version != $version_info) {
-                $output = '<br /><span style="color:red">' . get_lang('YourVersionNotUpToDate') . '. '.get_lang('LatestVersionIs').' <b>Chamilo '.$version_info.'</b>. '.get_lang('YourVersionIs').' <b>Chamilo '.$system_version. '</b>. '.str_replace('http://www.chamilo.org', '<a href="http://www.chamilo.org">http://www.chamilo.org</a>', get_lang('PleaseVisitOurWebsite')).'</span>';
-            } else {
-                $output = '<br /><span style="color:green">'.get_lang('VersionUpToDate').': Chamilo '.$version_info.'</span>';
-            }
-        } else {
-            $output = '<span style="color:red">' . get_lang('ImpossibleToContactVersionServerPleaseTryAgain') . '</span>';
-        }
-    } else {
-        $output = '<span style="color:red">' . get_lang('AllowurlfopenIsSetToOff') . '</span>';
-    }
-    return $output;
-}
-
-/**
- * Function to make an HTTP request through fsockopen (specialised for GET)
- * Derived from Jeremy Saintot: http://www.php.net/manual/en/function.fsockopen.php#101872
- * @param string IP or hostname
- * @param int    Target port
- * @param string URI (defaults to '/')
- * @param array  GET data
- * @param float  Timeout
- * @param bool   Include HTTP Request headers?
- * @param bool   Include HTTP Response headers?
- */
-function _http_request($ip, $port = 80, $uri = '/', $getdata = array(), $timeout = 1, $req_hdr = false, $res_hdr = false) {
-    $verb = 'GET';
-    $ret = '';
-    $getdata_str = count($getdata) ? '?' : '';
-
-    foreach ($getdata as $k => $v) {
-                $getdata_str .= urlencode($k) .'='. urlencode($v) . '&';
-    }
-
-    $crlf = "\r\n";
-    $req = $verb .' '. $uri . $getdata_str .' HTTP/1.1' . $crlf;
-    $req .= 'Host: '. $ip . $crlf;
-    $req .= 'User-Agent: Mozilla/5.0 Firefox/3.6.12' . $crlf;
-    $req .= 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' . $crlf;
-    $req .= 'Accept-Language: en-us,en;q=0.5' . $crlf;
-    $req .= 'Accept-Encoding: deflate' . $crlf;
-    $req .= 'Accept-Charset: utf-8;q=0.7,*;q=0.7' . $crlf;
-
-    $req .= $crlf;
-
-    if ($req_hdr) { $ret .= $req; }
-    if (($fp = @fsockopen($ip, $port, $errno, $errstr, $timeout)) == false) {
-        return "Error $errno: $errstr\n";
-    }
-
-    stream_set_timeout($fp, $timeout);
-    $r = @fwrite($fp, $req);
-    $line = @fread($fp,512);
-    $ret .= $line;
-    fclose($fp);
-
-    if (!$res_hdr) {
-        $ret = substr($ret, strpos($ret, "\r\n\r\n") + 4);
-    }
-
-    return trim($ret);
-}
+$url = api_get_path(WEB_PUBLIC_PATH).'admin';
+header('Location: '.$url);
+exit;

+ 28 - 28
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';
@@ -58,7 +58,7 @@ $column_model   = array(
                         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
 
@@ -73,12 +73,12 @@ $action_links = 'function action_formatter (cellvalue, options, rowObject) {
 
 ?>
 <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,55 +99,55 @@ 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();
         }
         break;
     case 'edit':
-        //Editing
-        $url  = api_get_self().'?action='.Security::remove_XSS($_GET['action']).'&id='.intval($_GET['id']);
+        //Editing 
+        $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']);
+                $promotion->update_all_sessions_status_by_promotion_id($values['id'], $values['status']);    
                 if ($values['status']) {
                     Display::display_confirmation_message(sprintf(get_lang('PromotionXUnarchived'), $values['name']), false);
                 } else {
                     Display::display_confirmation_message(sprintf(get_lang('PromotionXArchived'), $values['name']), false);
                 }
-            }
+            }            
             $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']);
@@ -155,17 +155,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;
@@ -173,4 +173,4 @@ switch ($action) {
         $promotion->display();
         break;
 }
-Display::display_footer();
+Display::display_footer();

+ 5 - 3
main/admin/settings.lib.php

@@ -232,6 +232,8 @@ function handle_stylesheets()
         }
     }
 
+    // Stylesheet upload.
+
     if (isset($_POST['stylesheet_upload'])) {
         if ($form->validate()) {
             $values = $form->exportValues();
@@ -1259,13 +1261,13 @@ function generate_settings_form($settings, $settings_by_access_list, $settings_t
         switch ($row['variable']) {
             case 'pdf_export_watermark_enable':
                 $url =  PDF::get_watermark(null);
-                $form->addElement('file', 'pdf_export_watermark_path', get_lang('AddWaterMark'));
 
                 if ($url != false) {
-                    $delete_url = '<a href="?delete_watermark">'.Display::return_icon('delete.png',get_lang('DelImage')).'</a>';
-                    $form->addElement('html', '<a href="'.$url.'">'.$url.' '.$delete_url.'</a>');
+                    $delete_url = '<a href="?delete_watermark">'.get_lang('DelImage').' '.Display::return_icon('delete.png',get_lang('DelImage')).'</a>';
+                    $form->addElement('html', '<div style="max-height:100px; max-width:100px; margin-left:162px; margin-bottom:10px; clear:both;"><img src="'.$url.'" style="margin-bottom:10px;" />'.$delete_url.'</div>');
                 }
 
+                $form->addElement('file', 'pdf_export_watermark_path', get_lang('AddWaterMark'));
                 $allowed_picture_types = array ('jpg', 'jpeg', 'png', 'gif');
                 $form->addRule('pdf_export_watermark_path', get_lang('OnlyImagesAllowed').' ('.implode(',', $allowed_picture_types).')', 'filetype', $allowed_picture_types);
 

+ 4 - 3
main/admin/settings.php

@@ -212,9 +212,7 @@ if (!empty($_GET['category']) && !in_array($_GET['category'], array('Plugins', '
             if ($pdf_export_watermark_path_result) {
                 $message['confirmation'][] = get_lang('UplUploadSucceeded');
             } else {
-                $message['warning'][] = get_lang('UplUnableToSaveFile').' '.get_lang('Folder').': '.api_get_path(
-                    SYS_CODE_PATH
-                ).'default_course_document/images';
+                $message['warning'][] = get_lang('UplUnableToSaveFile').' '.get_lang('Folder').': '.api_get_path(SYS_DEFAULT_COURSE_DOCUMENT_PATH).'/images';
             }
             unset($update_values['pdf_export_watermark_path']);
         }
@@ -557,6 +555,9 @@ if (!empty($_GET['category'])) {
         case 'Stylesheets':
             // Displaying the extensions: Stylesheets.
             handle_stylesheets();
+            if (isset($_POST)) {
+                api_set_setting_last_update();
+            }
             $form->display();
             break;
         case 'Search':

+ 153 - 160
main/admin/user_add.php

@@ -1,8 +1,8 @@
 <?php
 /* For licensing terms, see /license.txt */
 /**
- * @package chamilo.admin
- */
+*	@package chamilo.admin
+*/
 
 // Language files that should be included
 $language_file = array('admin', 'registration');
@@ -20,15 +20,33 @@ $is_platform_admin = api_is_platform_admin() ? 1 : 0;
 
 $message = null;
 
-$htmlHeadXtra[] = '<script src="'.api_get_path(
-    WEB_LIBRARY_PATH
-).'javascript/tag/jquery.fcbkcomplete.js" type="text/javascript" language="javascript"></script>';
-$htmlHeadXtra[] = '<link href="'.api_get_path(
-    WEB_LIBRARY_PATH
-).'javascript/tag/style.css" rel="stylesheet" type="text/css" />';
+$htmlHeadXtra[] = api_get_password_checker_js('#username', '#password');
+$htmlHeadXtra[] = '<script src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/tag/jquery.fcbkcomplete.js" type="text/javascript" language="javascript"></script>';
+$htmlHeadXtra[] = '<link href="'.api_get_path(WEB_LIBRARY_PATH).'javascript/tag/style.css" rel="stylesheet" type="text/css" />';
+if (isset($_configuration['allow_strength_pass_checker']) && $_configuration['allow_strength_pass_checker']) {
+$htmlHeadXtra[] = '
+<script>
+    $(document).ready(function() {
+        $("input[name=\'password[password_auto]\']").each(function(index, value) {
+            $(this).click(function() {
+                var value = $(this).attr("value");
+                if (value == 0) {
+                    $("#password_progress").show();
+                    $(".password-verdict").show();
+                    $(".error-list").show();
+                } else {
+                    $("#password_progress").hide();
+                    $(".password-verdict").hide();
+                    $(".error-list").hide();
+                }
+            });
+        });
+    });
+    </script>';
+}
+
 $htmlHeadXtra[] = '
 <script>
-<!--
 function enable_expiration_date() { //v2.0
 	document.user_add.radio_expiration_date[0].checked=false;
 	document.user_add.radio_expiration_date[1].checked=true;
@@ -63,42 +81,41 @@ function display_drh_list(){
             document.getElementById("id_platform_admin").style.display="none";
 	}
 }
-//-->
 </script>';
 
 if (!empty($_GET['message'])) {
-    $message = urldecode($_GET['message']);
+	$message = urldecode($_GET['message']);
 }
 
-$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'));
 $tool_name = get_lang('AddUsers');
 
 // Create the form
 $form = new FormValidator('user_add');
 $form->addElement('header', '', $tool_name);
 if (api_is_western_name_order()) {
-    // Firstname
-    $form->addElement('text', 'firstname', get_lang('FirstName'));
-    $form->applyFilter('firstname', 'html_filter');
-    $form->applyFilter('firstname', 'trim');
-    $form->addRule('firstname', get_lang('ThisFieldIsRequired'), 'required');
-    // Lastname
-    $form->addElement('text', 'lastname', get_lang('LastName'));
-    $form->applyFilter('lastname', 'html_filter');
-    $form->applyFilter('lastname', 'trim');
-    $form->addRule('lastname', get_lang('ThisFieldIsRequired'), 'required');
+	// Firstname
+	$form->addElement('text', 'firstname', get_lang('FirstName'));
+	$form->applyFilter('firstname', 'html_filter');
+	$form->applyFilter('firstname', 'trim');
+	$form->addRule('firstname', get_lang('ThisFieldIsRequired'), 'required');
+	// Lastname
+	$form->addElement('text', 'lastname', get_lang('LastName'));
+	$form->applyFilter('lastname', 'html_filter');
+	$form->applyFilter('lastname', 'trim');
+	$form->addRule('lastname', get_lang('ThisFieldIsRequired'), 'required');
 } else {
-    // Lastname
-    $form->addElement('text', 'lastname', get_lang('LastName'));
-    $form->applyFilter('lastname', 'html_filter');
-    $form->applyFilter('lastname', 'trim');
-    $form->addRule('lastname', get_lang('ThisFieldIsRequired'), 'required');
-    // Firstname
-    $form->addElement('text', 'firstname', get_lang('FirstName'));
-    $form->applyFilter('firstname', 'html_filter');
-    $form->applyFilter('firstname', 'trim');
-    $form->addRule('firstname', get_lang('ThisFieldIsRequired'), 'required');
+	// Lastname
+	$form->addElement('text', 'lastname', get_lang('LastName'));
+	$form->applyFilter('lastname', 'html_filter');
+	$form->applyFilter('lastname', 'trim');
+	$form->addRule('lastname', get_lang('ThisFieldIsRequired'), 'required');
+	// Firstname
+	$form->addElement('text', 'firstname', get_lang('FirstName'));
+	$form->applyFilter('firstname', 'html_filter');
+	$form->applyFilter('firstname', 'trim');
+	$form->addRule('firstname', get_lang('ThisFieldIsRequired'), 'required');
 }
 // Official code
 $form->addElement('text', 'official_code', get_lang('OfficialCode'), array('size' => '40'));
@@ -125,25 +142,15 @@ if (api_get_setting('login_is_email') == 'true') {
 $form->addElement('text', 'phone', get_lang('PhoneNumber'));
 // Picture
 $form->addElement('file', 'picture', get_lang('AddPicture'));
-$allowed_picture_types = array('jpg', 'jpeg', 'png', 'gif');
+$allowed_picture_types = array ('jpg', 'jpeg', 'png', 'gif');
 
-$form->addRule(
-    'picture',
-    get_lang('OnlyImagesAllowed').' ('.implode(',', $allowed_picture_types).')',
-    'filetype',
-    $allowed_picture_types
-);
+$form->addRule('picture', get_lang('OnlyImagesAllowed').' ('.implode(',', $allowed_picture_types).')', 'filetype', $allowed_picture_types);
 
 // Username
 if (api_get_setting('login_is_email') != 'true') {
-    $form->addElement('text', 'username', get_lang('LoginName'), array('maxlength' => USERNAME_MAX_LENGTH));
+    $form->addElement('text', 'username', get_lang('LoginName'), array('id'=> 'username', 'maxlength' => USERNAME_MAX_LENGTH));
     $form->addRule('username', get_lang('ThisFieldIsRequired'), 'required');
-    $form->addRule(
-        'username',
-        sprintf(get_lang('UsernameMaxXCharacters'), (string)USERNAME_MAX_LENGTH),
-        'maxlength',
-        USERNAME_MAX_LENGTH
-    );
+    $form->addRule('username', sprintf(get_lang('UsernameMaxXCharacters'), (string)USERNAME_MAX_LENGTH), 'maxlength', USERNAME_MAX_LENGTH);
     $form->addRule('username', get_lang('OnlyLettersAndNumbersAllowed'), 'username');
     $form->addRule('username', get_lang('UserTaken'), 'username_available');
 }
@@ -153,39 +160,31 @@ $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 (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_edit.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) {
-        $group[] = $form->createElement('radio', 'password_auto', null, get_lang('ExternalAuthentication').' ', 2);
-        $group[] = $form->createElement('select', 'auth_source', null, $auth_sources);
-        $group[] = $form->createElement('static', '', '', '<br />');
+	$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_edit.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) {
+    	$group[] = $form->createElement('radio', 'password_auto', null, get_lang('ExternalAuthentication').' ', 2);
+    	$group[] = $form->createElement('select', 'auth_source', null, $auth_sources);
+    	$group[] = $form->createElement('static', '', '', '<br />');
     }
 }
-$group[] = $form->createElement(
-    'radio',
-    'password_auto',
-    get_lang('Password'),
-    get_lang('AutoGeneratePassword').'<br />',
-    1
-);
+$group[] = $form->createElement('radio', 'password_auto', get_lang('Password'), get_lang('AutoGeneratePassword').'<br />', 1);
 $group[] = $form->createElement('radio', 'password_auto', 'id="radio_user_password"', null, 0);
-$group[] = $form->createElement(
-    'password',
-    'password',
-    null,
-    array('onkeydown' => 'javascript: password_switch_radio_button();')
-);
+$group[] = $form->createElement('password', 'password', null, array('id'=> 'password', 'onkeydown' => 'javascript: password_switch_radio_button();'));
 $form->addGroup($group, 'password', get_lang('Password'), '');
 
+if (isset($_configuration['allow_strength_pass_checker']) && $_configuration['allow_strength_pass_checker']) {
+    $form->addElement('label', null, '<div id="password_progress" style="display:none"></div>');
+}
 // Status
 $status = api_get_user_roles();
 
@@ -198,15 +197,15 @@ $form->addElement(
 );
 
 //drh list (display only if student)
-$display = isset($_POST['status']) && $_POST['status'] == STUDENT || !isset($_POST['status']) ? 'block' : 'none';
+$display = isset($_POST['status']) && $_POST['status'] == STUDENT  || !isset($_POST['status']) ? 'block' : 'none';
 
 //@todo remove the drh list here. This code is unused
 $form->addElement('html', '<div id="drh_list" style="display:'.$display.';">');
 
 if (isset($drh_list) && is_array($drh_list)) {
-    foreach ($drh_list as $drh) {
-        $drh_select->addOption(api_get_person_name($drh['firstname'], $drh['lastname']), $drh['user_id']);
-    }
+	foreach ($drh_list as $drh) {
+		$drh_select->addOption(api_get_person_name($drh['firstname'], $drh['lastname']), $drh['user_id']);
+	}
 }
 $form->addElement('html', '</div>');
 
@@ -231,7 +230,7 @@ $group[] = $form->createElement('radio', 'send_mail', null, get_lang('No'), 0);
 $form->addGroup($group, 'mail', get_lang('SendMailToNewUser'), '&nbsp;');
 // Expiration Date
 $form->addElement('radio', 'radio_expiration_date', get_lang('ExpirationDate'), get_lang('NeverExpires'), 0);
-$group = array();
+$group = array ();
 $group[] = $form->createElement('radio', 'radio_expiration_date', null, get_lang('On'), 1);
 $group[] = $form->createElement(
     'datepicker',
@@ -245,12 +244,13 @@ $form->addElement('radio', 'active', get_lang('ActiveAccount'), get_lang('Active
 $form->addElement('radio', 'active', '', get_lang('Inactive'), 0);
 
 $extra_data = UserManager::get_extra_user_data(0, true);
+
 $extraField = new ExtraField('user');
 $return_params = $extraField->set_extra_fields_in_form($form, $extra_data, 'user_add', false, null);
 $jquery_ready_content = $return_params['jquery_ready_content'];
 
 // the $jquery_ready_content variable collects all functions that will be load in the $(document).ready javascript function
-$htmlHeadXtra[] = '<script>
+$htmlHeadXtra[] ='<script>
 $(document).ready(function(){
 	'.$jquery_ready_content.'
 });
@@ -258,7 +258,7 @@ $(document).ready(function(){
 
 // Set default values
 $defaults['admin']['platform_admin'] = 0;
-$defaults['mail']['send_mail'] = 1;
+$defaults['mail']['send_mail'] = 0;
 $defaults['password']['password_auto'] = 1;
 $defaults['active'] = 1;
 $defaults['expiration_date'] = array();
@@ -273,49 +273,43 @@ $defaults = array_merge($defaults, $extra_data);
 $form->setDefaults($defaults);
 
 // Submit button
-$html_results_enabled[] = $form->createElement(
-    'style_submit_button',
-    'submit_plus',
-    get_lang('Add').'+',
-    'class="add"'
-);
-$html_results_enabled[] = $form->createElement('style_submit_button', 'submit', get_lang('Add'), 'class="add"');
+$html_results_enabled[] = $form-> createElement ('style_submit_button', 'submit_plus', get_lang('Add').'+', 'class="add"');
+$html_results_enabled[] = $form-> createElement ('style_submit_button', 'submit', get_lang('Add'), 'class="add"');
 $form->addGroup($html_results_enabled);
 
 // Validate form
-if ($form->validate()) {
-    $check = Security::check_token('post');
-    if ($check) {
-        $user = $form->exportValues();
-        $lastname = $user['lastname'];
-        $firstname = $user['firstname'];
-        $official_code = $user['official_code'];
-        $email = $user['email'];
-        $phone = $user['phone'];
-        $username = $user['username'];
-        $status = intval($user['status']);
-        $language = $user['language'];
-        $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']);
-
-        if (count($extAuthSource) > 0 && $user['password']['password_auto'] == '2') {
-            $auth_source = $user['password']['auth_source'];
-            $password = 'PLACEHOLDER';
-        } else {
-            $auth_source = PLATFORM_AUTH_SOURCE;
-            $password = $user['password']['password_auto'] == '1' ? api_generate_password(
-            ) : $user['password']['password'];
-        }
+if( $form->validate()) {
+	$check = Security::check_token('post');
+	if ($check) {
+		$user = $form->exportValues();
+		$lastname       = $user['lastname'];
+		$firstname      = $user['firstname'];
+		$official_code  = $user['official_code'];
+		$email          = $user['email'];
+		$phone          = $user['phone'];
+		$username       = $user['username'];
+		$status         = intval($user['status']);
+		$language       = $user['language'];
+		$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']);
+
+		if (count($extAuthSource) > 0 && $user['password']['password_auto'] == '2') {
+			$auth_source = $user['password']['auth_source'];
+			$password = 'PLACEHOLDER';
+		} else {
+			$auth_source = PLATFORM_AUTH_SOURCE;
+			$password = $user['password']['password_auto'] == '1' ? api_generate_password() : $user['password']['password'];
+		}
 
-        if ($user['radio_expiration_date'] == '1') {
-            $expiration_date = $user['expiration_date'];
-        } else {
-            $expiration_date = '0000-00-00 00:00:00';
-        }
+		if ($user['radio_expiration_date'] == '1') {
+			$expiration_date = $user['expiration_date'];
+		} else {
+			$expiration_date = '0000-00-00 00:00:00';
+		}
 
-        $active = intval($user['active']);
+		$active = intval($user['active']);
 
         if (api_get_setting('login_is_email') == 'true') {
             $username = $email;
@@ -341,18 +335,18 @@ if ($form->validate()) {
             $send_mail
         );
 
-        Security::clear_token();
-        $tok = Security::get_token();
-        if ($user_id === false) {
-            //If any error ocurred during user creation, print it (api_failureList
-            // stores values as separate words, so rework it
-            $message = '';
-            $message_bits = explode(' ', api_get_last_failure());
-            foreach ($message_bits as $bit) {
-                $message .= ucfirst($bit);
-            }
-        } else {
-            if (!empty($picture['name'])) {
+		Security::clear_token();
+		$tok = Security::get_token();
+		if ($user_id === false) {
+			//If any error ocurred during user creation, print it (api_failureList
+			// stores values as separate words, so rework it
+			$message = '';
+			$message_bits = explode(' ',api_get_last_failure());
+			foreach ($message_bits as $bit) {
+				$message .= ucfirst($bit);
+			}
+		} else {
+ 			if (!empty($picture['name'])) {
                 $picture_uri = UserManager::update_user_picture(
                     $user_id,
                     $_FILES['picture']['name'],
@@ -377,37 +371,36 @@ if ($form->validate()) {
                     null,
                     $language
                 );
-            }
-
-            foreach ($user as $key => $value) {
-                if (substr($key, 0, 6) == 'extra_') { //an extra field
-                    UserManager::update_extra_field_value($user_id, substr($key, 6), $value);
-                }
-            }
-
-            $message = get_lang('UserAdded');
-        }
-        if (isset($user['submit_plus'])) {
-            //we want to add more. Prepare report message and redirect to the same page (to clean the form)
-            header('Location: user_add.php?message='.urlencode($message).'&sec_token='.$tok);
-            exit ();
-        } else {
-            $tok = Security::get_token();
-            header('Location: user_list.php?action=show_message&message='.urlencode($message).'&sec_token='.$tok);
-            exit ();
-        }
-    }
+			}
+
+			foreach ($user as $key => $value) {
+				if (substr($key, 0, 6) == 'extra_') { //an extra field
+					UserManager::update_extra_field_value($user_id, substr($key, 6), $value);
+				}
+			}
+			$message = get_lang('UserAdded');
+		}
+		if (isset($user['submit_plus'])) {
+			//we want to add more. Prepare report message and redirect to the same page (to clean the form)
+			header('Location: user_add.php?message='.urlencode($message).'&sec_token='.$tok);
+			exit ();
+		} else {
+			$tok = Security::get_token();
+			header('Location: user_list.php?action=show_message&message='.urlencode($message).'&sec_token='.$tok);
+			exit ();
+		}
+	}
 } else {
-    if (isset($_POST['submit'])) {
-        Security::clear_token();
-    }
-    $token = Security::get_token();
-    $form->addElement('hidden', 'sec_token');
-    $form->setConstants(array('sec_token' => $token));
+	if (isset($_POST['submit'])) {
+		Security::clear_token();
+	}
+	$token = Security::get_token();
+	$form->addElement('hidden', 'sec_token');
+	$form->setConstants(array('sec_token' => $token));
 }
 
-if (!empty($message)) {
-    $message = Display::return_message(stripslashes($message));
+if (!empty($message)){
+	$message = Display::return_message(stripslashes($message));
 }
 $content = $form->return_form();
 

+ 25 - 16
main/admin/user_import.php

@@ -20,6 +20,7 @@ $purification_option_for_usernames = false;
 
 function validate_data($users) {
 	global $defined_auth_sources;
+    global $time;
 	$errors = array();
 	$usernames = array();
 
@@ -83,6 +84,7 @@ function validate_data($users) {
  */
 function complete_missing_data($user) {
 	global $purification_option_for_usernames;
+    global $time;
 	// 1. Create a username if necessary.
 	if (UserManager::is_username_empty($user['UserName'])) {
 		$user['UserName'] = UserManager::create_unique_username($user['FirstName'], $user['LastName']);
@@ -117,15 +119,16 @@ function save_data($users) {
 		$inserted_in_course = array();
 	}
 	$send_mail = $_POST['sendMail'] ? 1 : 0;
+    $t0 = time();
 	if (is_array($users)) {
-		foreach ($users as $index => $user)	{
+        foreach ($users as $index => $user)	{
 			$user = complete_missing_data($user);
 			$user['Status'] = api_status_key($user['Status']);
-            $user_id = UserManager :: create_user($user['FirstName'], $user['LastName'], $user['Status'], $user['Email'], $user['UserName'], $user['Password'], $user['OfficialCode'], $user['language'], $user['PhoneNumber'], '', $user['AuthSource'], null, 1, 0, null, null, $send_mail);
-			if (!is_array($user['Courses']) && !empty($user['Courses'])) {
+            $user_id = UserManager :: create_user($user['FirstName'], $user['LastName'], $user['Status'], $user['Email'], $user['UserName'], $user['Password'], (isset($user['OfficialCode'])?$user['OfficialCode']:null), (isset($user['language'])?$user['language']:null), (isset($user['PhoneNumber'])?$user['PhoneNumber']:null), '', $user['AuthSource'], null, 1, 0, null, null, $send_mail, true);
+			if (!empty($user['Courses']) && !is_array($user['Courses'])) {
 				$user['Courses'] = array($user['Courses']);
 			}
-			if (is_array($user['Courses'])) {
+			if (isset($user['Courses']) && is_array($user['Courses'])) {
 				foreach ($user['Courses'] as $index => $course) {
 					if (CourseManager :: course_exists($course)) {
 						CourseManager :: subscribe_user($user_id, $course,$user['Status']);
@@ -155,15 +158,19 @@ function save_data($users) {
 			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);
-				}
-			}
+            if (isset($extra_fields) && is_array($extra_fields)) {
+                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);
+                    }
+                }
+            }
 		}
 	}
+    $t1 = time()-$t0;
+    error_log('Total import took '.$t1.'s');
 }
 
 /**
@@ -172,6 +179,8 @@ function save_data($users) {
  * @return array All userinformation read from the file
  */
 function parse_csv_data($file) {
+    global $time;
+    $time = time();
 	$users = Import :: csv_to_array($file);
 	foreach ($users as $index => $user) {
 		if (isset ($user['Courses'])) {
@@ -255,7 +264,7 @@ api_protect_admin_script(true);
 
 
 $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));
 }
 
@@ -267,7 +276,7 @@ $extra_fields = UserManager::get_extra_fields(0, 0, 5, 'ASC', true);
 $user_id_error = array();
 $error_message = '';
 
-if ($_POST['formSent'] AND $_FILES['import_file']['size'] !== 0) {
+if (!empty($_POST['formSent']) AND $_FILES['import_file']['size'] !== 0) {
 	$file_type = $_POST['file_type'];
 	Security::clear_token();
 	$tok = Security::get_token();
@@ -345,15 +354,15 @@ if ($_POST['formSent'] AND $_FILES['import_file']['size'] !== 0) {
 	}
 
 	// if the warning message is too long then we display the warning message trough a session
-	if (api_strlen($warning_message) > 150) {
-		$_SESSION['session_message_import_users'] = $warning_message;
+	if (isset($warning_message) && api_strlen($warning_message) > 150) {
+		$_SESSION['session_message_import_users'] = (isset($warning_message)?$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);
+		header('Location: '.api_get_path(WEB_CODE_PATH).'admin/user_list.php?action=show_message&warn='.(isset($warning_message)?urlencode($warning_message):'').'&message='.urlencode($see_message_import).'&sec_token='.$tok);
 		exit;
 	}
 

+ 11 - 9
main/admin/user_information.php

@@ -87,7 +87,7 @@ $tbl_user                   = Database :: get_main_table(TABLE_MAIN_USER);
 
 $user_id = $user['user_id'];
 
-$sessions = SessionManager::get_sessions_by_user($user_id);
+$sessions = SessionManager::get_sessions_by_user($user_id, true);
 
 $personal_course_list = array();
 if (count($sessions) > 0) {
@@ -103,21 +103,23 @@ if (count($sessions) > 0) {
         $id_session = $session_item['session_id'];
 
         foreach ($session_item['courses'] as $my_course) {
-            $course_info = api_get_course_info($my_course['code']);
+            $courseInfo = api_get_course_info_by_id($my_course['id']);
             $row = array();
-            $row[] = $my_course['code'];
-            $row[] = $course_info['title'];
+            $row[] = $courseInfo['code'];
+            $row[] = $courseInfo['title'];
             //$row[] = $my_course['status'] == STUDENT ? get_lang('Student') : get_lang('Teacher');
 
-            $roles = api_detect_user_roles($user['user_id'], $my_course['real_id'], $id_session);
+            $roles = api_detect_user_roles($user['user_id'], $courseInfo['real_id'], $id_session);
             $row[] = api_get_roles_to_string($roles);
-            $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>';
 
             $row[] = $tools;
             $data[] = $row;
         }
-        echo Display::page_subheader($session_item['session_name']);
+        $dates = SessionManager::parse_session_dates($session_item);
+        echo Display::page_subheader($session_item['session_name'], ' '.$dates);
+
         Display :: display_sortable_table($header, $data, array (), array(), array ('user_id' => intval($_GET['user_id'])));
     }
 } else {
@@ -213,4 +215,4 @@ if (api_is_multiple_url_enabled()) {
 }
 
 /* FOOTER */
-Display::display_footer();
+Display::display_footer();

+ 66 - 15
main/admin/user_list.php

@@ -17,10 +17,10 @@ $current_access_url_id = api_get_current_access_url_id();
 // Blocks the possibility to delete a user
 $delete_user_available = true;
 if (isset($_configuration['deny_delete_users']) &&  $_configuration['deny_delete_users']) {
-    $delete_user_available = false;
+	$delete_user_available = false;
 }
-
 $url = api_get_path(WEB_AJAX_PATH).'course.ajax.php?a=get_user_courses';
+$urlSession = api_get_path(WEB_AJAX_PATH).'session.ajax.php?a=get_user_sessions';
 
 $htmlHeadXtra[] = '<script>
 function load_course_list (div_course,my_user_id) {
@@ -38,6 +38,21 @@ function load_course_list (div_course,my_user_id) {
 		}
 	});
 }
+function load_session_list (div_session,my_user_id) {
+	 $.ajax({
+		contentType: "application/x-www-form-urlencoded",
+		beforeSend: function(objeto) {
+            $("div#"+div_session).html("<img src=\'../inc/lib/javascript/indicator.gif\' />"); },
+		type: "POST",
+		url: "'.$urlSession.'",
+		data: "user_id="+my_user_id,
+		success: function(datos) {
+			$("div#"+div_session).html(datos);
+			$("div#div_s_"+my_user_id).attr("class","blackboard_show");
+			$("div#div_s_"+my_user_id).attr("style","");
+		}
+	});
+}
 
 function active_user(element_div) {
 	id_image=$(element_div).attr("id");
@@ -80,6 +95,10 @@ function clear_course_list (div_course) {
 	$("div#"+div_course).html("&nbsp;");
 	$("div#"+div_course).hide("");
 }
+function clear_session_list (div_session) {
+	$("div#"+div_session).html("&nbsp;");
+	$("div#"+div_session).hide("");
+}
 
 function display_advanced_search_form () {
         if ($("#advanced_search_form").css("display") == "none") {
@@ -129,8 +148,7 @@ $(document).ready(function() {
 //Load user calendar
 function load_calendar(user_id, month, year) {
  	var url = "'.api_get_path(WEB_AJAX_PATH).'agenda.ajax.php?a=get_user_agenda&user_id=" +user_id + "&month="+month+"&year="+year;
-	$("#dialog").load( url
-	);
+	$("#dialog").load(url);
 }
 </script>';
 
@@ -289,8 +307,10 @@ function get_user_data($from, $number_of_items, $column, $direction, $get_count
                  u.status				AS col7,
                  u.active				AS col8,
                  u.user_id				AS col9,
-                 u.registration_date    AS col10 ".
-                 ", u.expiration_date   AS exp            ";
+                 u.registration_date    AS col10,
+                 u.expiration_date      AS exp,
+                 u.password
+    ";
 
     if ($get_count) {
         $select = "SELECT count(u.user_id) as total_rows";
@@ -380,6 +400,16 @@ function get_user_data($from, $number_of_items, $column, $direction, $get_count
 		$sql.= " AND url_rel_user.access_url_id=".api_get_current_access_url_id();
     }
 
+    $checkPassStrength = isset($_GET['check_easy_passwords']) && $_GET['check_easy_passwords'] == 1 ? true : false;
+
+    if ($checkPassStrength) {
+        $easyPasswordList = api_get_easy_password_list();
+        $easyPasswordList = array_map('api_get_encrypted_password', $easyPasswordList);
+        $easyPasswordList = array_map(array('Database', 'escape_string'), $easyPasswordList);
+        $easyPassword = implode("' OR password LIKE '", $easyPasswordList);
+
+        $sql .= "AND password LIKE '$easyPassword' ";
+    }
     if (!in_array($direction, array('ASC','DESC'))) {
     	$direction = 'ASC';
     }
@@ -388,7 +418,7 @@ function get_user_data($from, $number_of_items, $column, $direction, $get_count
     $from 	= intval($from);
     $number_of_items = intval($number_of_items);
 
-    //Returns counts and exits function
+    // Returns counts and exits function.
     if ($get_count) {
         $res = Database::query($sql);
         $user = Database::fetch_array($res);
@@ -418,9 +448,8 @@ function get_user_data($from, $number_of_items, $column, $direction, $get_count
         	   $user[7] = '-1';
             }
         }
-
         // forget about the expiration date field
-        $users[] = array($user[0], $photo, $user[1],$user[2], $user[3], $user[4], $user[5], $roles[$user[6]], $user[7], api_get_local_time($user[9]), $user[0]);
+        $users[] = array($user[0], $photo, $user[1],$user[2], $user[3], $user[4], $user[5], $user[6], $user[7], api_get_local_time($user[9]), $user[0]);
 	}
 	return $users;
 }
@@ -463,16 +492,22 @@ function modify_filter($user_id, $url_params, $row) {
 	if ($current_user_status_label == $statusname[ANONYMOUS]) {
 		$user_is_anonymous =true;
 	}
-
 	$result = '';
 	if (!$user_is_anonymous) {
-        $icon = Display::return_icon('course.gif', get_lang('Courses'), array('onmouseout' =>'"clear_course_list (\'div_'.$user_id.'\')" '));
+        $icon = Display::return_icon('course.png', get_lang('Courses'), array('onmouseout' => 'clear_course_list (\'div_'.$user_id.'\')'));
 		$result .= '<a href="javascript:void(0)" onclick="load_course_list(\'div_'.$user_id.'\','.$user_id.')" >
-					'.$icon.'
+			        '.$icon.'
 					<div class="blackboard_hide" id="div_'.$user_id.'">&nbsp;&nbsp;</div>
-					</a>&nbsp;&nbsp;';
+					</a>';
+
+        $icon = Display::return_icon('session.png', get_lang('Sessions'), array('onmouseout' => 'clear_session_list (\'div_s_'.$user_id.'\')'));
+		$result .= '<a href="javascript:void(0)" onclick="load_session_list(\'div_s_'.$user_id.'\','.$user_id.')" >
+					'.$icon.'
+					<div class="blackboard_hide" id="div_s_'.$user_id.'">&nbsp;&nbsp;</div>
+					</a>';
 	} else {
-		$result .= Display::return_icon('course_na.gif',get_lang('Courses')).'&nbsp;&nbsp;';
+		$result .= Display::return_icon('course_na.png',get_lang('Courses')).'&nbsp;&nbsp;';
+		$result .= Display::return_icon('course_na.png',get_lang('Sessions')).'&nbsp;&nbsp;';
 	}
 
 	if (api_is_platform_admin()) {
@@ -603,6 +638,20 @@ function active_filter($active, $url_params, $row) {
 	return $result;
 }
 
+/**
+ * Instead of displaying the integer of the status, we give a translation for the status
+ *
+ * @param integer $status
+ * @return string translation
+ *
+ * @version march 2008
+ * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University, Belgium
+ */
+function status_filter($status) {
+	$statusname = api_get_status_langvars();
+	return $statusname[$status];
+}
+
 $action = isset($_REQUEST["action"]) ? $_REQUEST["action"] : null;
 
 if (isset($_GET['keyword']) || isset($_GET['keyword_firstname'])) {
@@ -769,10 +818,12 @@ $active_group[] = $form->createElement('checkbox','keyword_inactive','', get_lan
 $form->addGroup($active_group,'',get_lang('ActiveAccount'),'<br/>',false);
 $form->addElement('html', '</td><td>');
 
+$form->addElement('checkbox', 'check_easy_passwords', null, get_lang('CheckEasyPasswords'));
 
 /*
  * @todo fix this code
 $extra_data = UserManager::get_extra_fields( 0,10,5, 'ASC', true, 1);
+var_dump($extra_data);
 $extra_options = array();
 if (!empty($extra_data)) {
     $extra_options[0] = get_lang('All');
@@ -829,7 +880,7 @@ $table->set_header(10, get_lang('Action'), false, 'width="220px"');
 $table->set_column_filter(3, 'user_filter');
 $table->set_column_filter(4, 'user_filter');
 $table->set_column_filter(6, 'email_filter');
-//$table->set_column_filter(7, 'status_filter');
+$table->set_column_filter(7, 'status_filter');
 $table->set_column_filter(8, 'active_filter');
 $table->set_column_filter(10, 'modify_filter');
 

+ 18 - 18
main/auth/courses.php

@@ -28,23 +28,23 @@ if (api_get_setting('show_courses_descriptions_in_catalog') == 'true') {
 	            if ($("#dialog").length == 0) {
 	                dialog  = $(\'<div id="dialog" style="display:hidden"></div>\').appendTo(\'body\');
 	            }
-
+	            
 	            // load remote content
 	            dialog.load(
-	                    url,
+	                    url,                    
 	                    {},
 	                    function(responseText, textStatus, XMLHttpRequest) {
 	                        dialog.dialog({
-	                            modal	: true,
-	            				width	: 540,
-	            				height	: 400,
-	                        });
+	                            modal	: true, 
+	            				width	: 540, 
+	            				height	: 400,              
+	                        });	                    
 				});
 	            //prevent the browser to follow the link
 	            return false;
 	        });
         });
-
+        
     </script>';
 }
 
@@ -78,7 +78,7 @@ if (isset($_GET['action']) && in_array($_GET['action'],$actions)) {
 	$action = $_GET['action'];
 }
 
-if ($action == 'createcoursecategory') {
+if ($action == 'createcoursecategory') {	
 	$nameTools = get_lang('CreateCourseCategory');
 }
 if ($action == 'subscribe') {
@@ -99,13 +99,13 @@ $interbreadcrumb[] = array('url' => api_get_path(WEB_PATH).'user_portal.php', 'n
 if (empty($nameTools)) {
 	$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'));
-	}
+	} 
     $interbreadcrumb[] = array('url' => '#', 'name' => $nameTools);
 }
 
@@ -155,7 +155,7 @@ if ($action == 'deletecoursecategory' && isset($_GET['id'])) {
 // 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']) {
-        $courses_controller->add_course_category($_POST['title_course_category']);
+        $courses_controller->add_course_category($_POST['title_course_category']);        
 	}
 }
 
@@ -168,9 +168,9 @@ if (isset($_REQUEST['search_course'])) {
 }
 
 // Subscribe user to course
-if (isset($_REQUEST['subscribe_course'])) {
+if (isset($_REQUEST['subscribe_course'])) {    
     if ($ctok == $_GET['sec_token']) {
-        $courses_controller->subscribe_user($_GET['subscribe_course'], $_GET['search_term'], $_GET['category_code']);
+        $courses_controller->subscribe_user($_GET['subscribe_course'], $_GET['search_term'], $_GET['category_code']);                
     }
 }
 // We are unsubscribing from a course (=Unsubscribe from course).
@@ -188,8 +188,8 @@ if (isset($_POST['unsubscribe'])) {
 	}
 }
 switch ($action) {
-    case 'subscribe_user_with_password':
-        $courses_controller->subscribe_user($_POST['subscribe_user_with_password'], $_POST['search_term'], $_POST['category_code']);
+    case 'subscribe_user_with_password':        
+        $courses_controller->subscribe_user($_POST['subscribe_user_with_password'], $_POST['search_term'], $_POST['category_code']);                       
         exit;
         break;
     case 'createcoursecategory':
@@ -198,16 +198,16 @@ switch ($action) {
     case 'deletecoursecategory':
         $courses_controller->courses_list($action);
         break;
-    case 'sortmycourses':
+    case 'sortmycourses':        
         $courses_controller->courses_list($action);
         break;
-    case 'subscribe':
+    case 'subscribe':                
     case 'display_random_courses':
         if ($user_can_view_page) {
             $courses_controller->courses_categories($action);
         } else {
             api_not_allowed();
-        }
+        }            
         break;
     case 'display_courses':
         $courses_controller->courses_categories($action, $_GET['category_code']);

+ 26 - 18
main/auth/courses_controller.php

@@ -11,6 +11,7 @@
  */
 class CoursesController
 {
+
     private $toolname;
     private $view;
     private $model;
@@ -18,7 +19,7 @@ class CoursesController
     /**
      * 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);
@@ -34,7 +35,7 @@ class CoursesController
     public function courses_list($action, $message = '') {
         $data = array();
         $user_id = api_get_user_id();
-
+        
         $data['user_courses']             = $this->model->get_courses_of_user($user_id);
         $data['user_course_categories']   = $this->model->get_user_course_categories();
         $data['courses_in_category']      = $this->model->get_courses_in_category();
@@ -60,7 +61,7 @@ class CoursesController
      * @param string    error message(optional)
      */
     public function categories_list($action, $message='', $error='') {
-        $data = array();
+        $data = array();            
         $data['user_course_categories'] = $this->model->get_user_course_categories();
         $data['action'] = $action;
         $data['message'] = $message;
@@ -81,24 +82,23 @@ class CoursesController
      */
     public function courses_categories($action, $category_code = null, $message = '', $error = '', $content = null) {
         $data = array();
-        $browse_course_categories = $this->model->browse_course_categories();
-
+        $browse_course_categories = $this->model->browse_course_categories();        
+        
         if ($action == 'display_random_courses') {
             $data['browse_courses_in_category'] = $this->model->browse_courses_in_category(null, 10);
-
         } 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);
         }
-
+        
         $data['browse_course_categories'] = $browse_course_categories;
         $data['code'] = Security::remove_XSS($category_code);
 
         // getting all the courses to which the user is subscribed to
         $curr_user_id = api_get_user_id();
-        $user_courses = $this->model->get_courses_of_user($curr_user_id);
+        $user_courses = $this->model->get_courses_of_user($curr_user_id);            
         $user_coursecodes = array();
 
         // we need only the course codes as these will be used to match against the courses of the category
@@ -107,14 +107,14 @@ class CoursesController
                 $user_coursecodes[] = $value['code'];
             }
         }
-
+        
         if (api_is_drh()) {
             $courses = CourseManager::get_courses_followed_by_drh(api_get_user_id());
             foreach ($courses as $course) {
                 $user_coursecodes[] = $course['code'];
-            }
+            }            
         }
-
+        
         $data['user_coursecodes'] = $user_coursecodes;
         $data['action']           = $action;
         $data['message']          = $message;
@@ -168,18 +168,26 @@ class CoursesController
     }
 
     /**
-     *
+     * Auto user subcription to a course
      */
     public function subscribe_user($course_code, $search_term, $category_code) {
+        $data = array();
+        $courseInfo = api_get_course_info($course_code);
+        // The course must be open in order to access the auto subscription
+        if (in_array($courseInfo['visibility'], array(COURSE_VISIBILITY_CLOSED, COURSE_VISIBILITY_REGISTERED, COURSE_VISIBILITY_HIDDEN))) {
+            $error = get_lang('SubscribingNotAllowed');
+            //$message = get_lang('SubscribingNotAllowed');
+        } else {
         $result = $this->model->subscribe_user($course_code);
         if (!$result) {
             $error = get_lang('CourseRegistrationCodeIncorrect');
         } else {
-            //Redirect directly to the course after subscription
-            $message = $result['message'];
-            $content = $result['content'];
+                //Redirect directly to the course after subscription
+                $message = $result['message'];
+                $content = $result['content'];
+            }
         }
-
+        
         if (!empty($search_term)) {
             $this->search_courses($search_term, $message, $error);
         } else {
@@ -205,7 +213,7 @@ class CoursesController
     /**
      * Change course category
      * render to listing view
-     * @param int Course id
+     * @param string    Course code
      * @param int    Category id
      */
     public function change_course_category($courseId, $category_id) {

+ 12 - 8
main/auth/inscription.php

@@ -19,6 +19,7 @@ if (api_get_setting('allow_registration') === 'false') {
     api_not_allowed(true);
 }
 
+$htmlHeadXtra[] = api_get_password_checker_js('#username', '#pass1');
 if (!empty($_SESSION['user_language_choice'])) {
     $user_selected_language = $_SESSION['user_language_choice'];
 } elseif (!empty($_SESSION['_user']['language'])) {
@@ -40,7 +41,7 @@ $course_code_redirect = isset($_REQUEST['c']) && !empty($_REQUEST['c']) ? $_REQU
 $exercise_redirect = isset($_REQUEST['e']) && !empty($_REQUEST['e']) ? $_REQUEST['e'] : null;
 
 if (!empty($course_code_redirect)) {
-    Session::write('course_redirect', $course_code_redirect);
+    Session::write('course_redirect',   $course_code_redirect);
     Session::write('exercise_redirect', $exercise_redirect);
 }
 
@@ -61,7 +62,6 @@ if ($user_already_registered_show_terms == false) {
 
     //	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');
     }
@@ -99,19 +99,23 @@ if ($user_already_registered_show_terms == false) {
     }
 
     //	PASSWORD
-    $form->addElement('password', 'pass1', get_lang('Password'), array('size' => 20, 'autocomplete' => 'off'));
-    $form->addElement('password', 'pass2', get_lang('Confirmation'), array('size' => 20, 'autocomplete' => 'off'));
+    $form->addElement('password', 'pass1', get_lang('Password'), array('id' => 'pass1', 'size' => 20, 'autocomplete' => 'off'));
+    global $_configuration;
+
+    if (isset($_configuration['allow_strength_pass_checker']) && $_configuration['allow_strength_pass_checker']) {
+        $form->addElement('label', null, '<div id="password_progress"></div>');
+    }
+
+    $form->addElement('password', 'pass2', get_lang('Confirmation'), array('id' => 'pass2', 'size' => 20, 'autocomplete' => 'off'));
     $form->addRule('pass1', get_lang('ThisFieldIsRequired'), 'required');
     $form->addRule('pass2', get_lang('ThisFieldIsRequired'), 'required');
     $form->addRule(array('pass1', 'pass2'), get_lang('PassTwo'), 'compare');
 
-    //if (CHECK_PASS_EASY_TO_FIND) {
-        //$form->addRule('pass1', get_lang('PassTooEasy').': '.api_generate_password(), 'callback', 'api_check_password');
-    //}
+    if (CHECK_PASS_EASY_TO_FIND)
+        $form->addRule('password1', get_lang('PassTooEasy').': '.api_generate_password(), 'callback', 'api_check_password');
 
     //	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');
     }

+ 12 - 21
main/auth/profile.php

@@ -17,12 +17,17 @@ $language_file = array('registration', 'messages', 'userInfo');
 $cidReset = true;
 require_once '../inc/global.inc.php';
 
+if (api_is_profile_readable() == false) {
+    api_not_allowed(true);
+}
+
 if (api_get_setting('allow_social_tool') == 'true') {
     $this_section = SECTION_SOCIAL;
 } else {
     $this_section = SECTION_MYPROFILE;
 }
 
+$htmlHeadXtra[] = api_get_password_checker_js('#username', '#password1');
 $_SESSION['this_section'] = $this_section;
 
 if (!(isset($_user['user_id']) && $_user['user_id']) || api_is_anonymous($_user['user_id'], true)) {
@@ -30,9 +35,7 @@ if (!(isset($_user['user_id']) && $_user['user_id']) || api_is_anonymous($_user[
 }
 
 $htmlHeadXtra[] = '<script src="../inc/lib/javascript/tag/jquery.fcbkcomplete.js" type="text/javascript" language="javascript"></script>';
-$htmlHeadXtra[] = '<link href="'.api_get_path(
-    WEB_LIBRARY_PATH
-).'javascript/tag/style.css" rel="stylesheet" type="text/css" />';
+$htmlHeadXtra[] = '<link href="'.api_get_path(WEB_LIBRARY_PATH).'javascript/tag/style.css" rel="stylesheet" type="text/css" />';
 
 $htmlHeadXtra[] = '<script>
 function confirmation(name) {
@@ -72,7 +75,6 @@ function show_icon_edit(element_html) {
 }
 </script>';
 
-//$interbreadcrumb[] = array('url' => '../auth/profile.php', 'name' => get_lang('ModifyProfile'));
 if (!empty ($_GET['coursePath'])) {
     $course_url = api_get_path(WEB_COURSE_PATH).htmlentities(strip_tags($_GET['coursePath'])).'/index.php';
     $interbreadcrumb[] = array('url' => $course_url, 'name' => Security::remove_XSS($_GET['courseCode']));
@@ -95,7 +97,7 @@ EOF;
 }
 
 // Libraries
-$tool_name = is_profile_editable() ? get_lang('ModifProfile') : get_lang('ViewProfile');
+$tool_name = api_is_profile_editable() ? get_lang('ModifProfile') : get_lang('ViewProfile');
 $table_user = Database :: get_main_table(TABLE_MAIN_USER);
 
 /*	Form	*/
@@ -188,7 +190,7 @@ if (api_get_setting('registration', 'email') == 'true' && api_get_setting('profi
 }
 
 // OPENID URL
-if (is_profile_editable() && api_get_setting('openid_authentication') == 'true') {
+if (api_is_profile_editable() && api_get_setting('openid_authentication') == 'true') {
     $form->addElement('text', 'openid', get_lang('OpenIDURL'), array('size' => 40));
     if (api_get_setting('profile', 'openid') !== 'true') {
         $form->freeze('openid');
@@ -212,7 +214,7 @@ $form->applyFilter('phone', 'trim');
 $form->addRule('phone', get_lang('EmailWrong'), 'email');*/
 
 //	PICTURE
-if (is_profile_editable() && api_get_setting('profile', 'picture') == 'true') {
+if (api_is_profile_editable() && api_get_setting('profile', 'picture') == 'true') {
     $form->addElement(
         'file',
         'picture',
@@ -238,7 +240,7 @@ if (api_get_setting('profile', 'language') !== 'true') {
 }
 
 //THEME
-if (is_profile_editable() && api_get_setting('user_selected_theme') == 'true') {
+if (api_is_profile_editable() && api_get_setting('user_selected_theme') == 'true') {
     $form->addElement('select_theme', 'theme', get_lang('Theme'));
     if (api_get_setting('profile', 'theme') !== 'true') {
         $form->freeze('theme');
@@ -298,7 +300,7 @@ if (api_get_setting('extended_profile') == 'true') {
 }
 
 //	PASSWORD, if auth_source is platform
-if (is_platform_authentication() && is_profile_editable() && api_get_setting('profile', 'password') == 'true') {
+if (is_platform_authentication() && api_is_profile_editable() && api_get_setting('profile', 'password') == 'true') {
     $form->addElement(
         'password',
         'password0',
@@ -344,7 +346,7 @@ if (api_get_setting('profile', 'apikeys') == 'true') {
     ); //generate_open_id_form()
 }
 //	SUBMIT
-if (is_profile_editable()) {
+if (api_is_profile_editable()) {
     $form->addElement('style_submit_button', 'apply_change', get_lang('SaveSettings'), 'class="save"');
 } else {
     $form->freeze();
@@ -368,17 +370,6 @@ function is_platform_authentication()
     return $tab_user_info['auth_source'] == PLATFORM_AUTH_SOURCE;
 }
 
-/**
- * Returns whether a user can edit his/her profile. Defaults to false if
- * profileIsEditable is not set in $GLOBALS.
- *
- * @return    boolean    Editability of the profile
- */
-function is_profile_editable()
-{
-    return isset($GLOBALS['profileIsEditable']) ? $GLOBALS['profileIsEditable'] : false;
-}
-
 /*
 	PRODUCTIONS FUNCTIONS
 */

File diff suppressed because it is too large
+ 192 - 354
main/calendar/agenda.inc.php


+ 945 - 0
main/calendar/agenda.lib.php

@@ -0,0 +1,945 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+/**
+ *  @author: Julio Montoya <gugli100@gmail.com> Implementing a real agenda lib
+ */
+class Agenda
+{
+    var $events = array();
+    var $type = 'personal'; // personal, admin or course
+
+    function __construct()
+    {
+        //Table definitions
+        $this->tbl_global_agenda = Database::get_main_table(TABLE_MAIN_SYSTEM_CALENDAR);
+        $this->tbl_personal_agenda = Database::get_user_personal_table(TABLE_PERSONAL_AGENDA);
+        $this->tbl_course_agenda = Database::get_course_table(TABLE_AGENDA);
+
+        //Setting the course object if we are in a course
+        $this->course = null;
+        $course_info = api_get_course_info();
+        if (!empty($course_info)) {
+            $this->course = $course_info;
+        }
+
+        $this->events = array();
+
+        //Event colors
+        $this->event_platform_color = 'red'; //red
+        $this->event_course_color = '#458B00'; //green
+        $this->event_group_color = '#A0522D'; //siena
+        $this->event_session_color = '#00496D'; // kind of green
+        $this->event_personal_color = 'steel blue'; //steel blue
+    }
+
+    function set_course($course_info)
+    {
+        $this->course = $course_info;
+    }
+
+    /**
+     *
+     * Adds an event to the calendar
+     *
+     * @param   string  start datetime format: 2012-06-14 09:00:00
+     * @param   string  end datetime format: 2012-06-14 09:00:00
+     * @param   string  all day (true, false)
+     * @param   string  view agendaDay, agendaWeek, month @todo seems not to be used
+     * @param   string  title
+     * @param   string  content
+     * @param   array   users to send array('everyone') or a list of user ids
+     * @param   bool    add event as a *course* announcement
+     *
+     */
+    function add_event($start, $end, $all_day, $view, $title, $content, $users_to_send = array(), $add_as_announcement = false)
+    {
+        $start = api_get_utc_datetime($start);
+        $end = api_get_utc_datetime($end);
+        $all_day = isset($all_day) && $all_day == 'true' ? 1 : 0;
+
+        $attributes = array();
+        $id = null;
+        switch ($this->type) {
+            case 'personal':
+                $attributes['user'] = api_get_user_id();
+                $attributes['title'] = $title;
+                $attributes['text'] = $content;
+                $attributes['date'] = $start;
+                $attributes['enddate'] = $end;
+                $attributes['all_day'] = $all_day;
+                $id = Database::insert($this->tbl_personal_agenda, $attributes);
+                break;
+            case 'course':
+                $attributes['title'] = $title;
+                $attributes['content'] = $content;
+                $attributes['start_date'] = $start;
+                $attributes['end_date'] = $end;
+                $attributes['all_day'] = $all_day;
+                $attributes['session_id'] = api_get_session_id();
+                $attributes['c_id'] = $this->course['real_id'];
+
+                //simple course event
+                $id = Database::insert($this->tbl_course_agenda, $attributes);
+
+                if ($id) {
+                    $group_id = api_get_group_id();
+
+                    if ((!is_null($users_to_send)) or (!empty($group_id))) {
+                        $send_to = self::separate_users_groups($users_to_send);
+                        if (isset($send_to['everyone']) && $send_to['everyone']) {
+                            api_item_property_update($this->course, TOOL_CALENDAR_EVENT, $id, "AgendaAdded", api_get_user_id(), $group_id, '', $start, $end);
+                        } else {
+                            // storing the selected groups
+                            if (isset($send_to['groups']) && is_array($send_to['groups'])) {
+                                foreach ($send_to['groups'] as $group) {
+                                    api_item_property_update($this->course, TOOL_CALENDAR_EVENT, $id, "AgendaAdded", api_get_user_id(), $group, 0, $start, $end);
+                                }
+                            }
+
+                            // storing the selected users
+                            if (isset($send_to['groups']) && is_array($send_to['users'])) {
+                                foreach ($send_to['users'] as $to_user_id) {
+                                    api_item_property_update($this->course, TOOL_CALENDAR_EVENT, $id, "AgendaAdded", api_get_user_id(), $group_id, $to_user_id, $start, $end);
+                                }
+                            }
+                        }
+                    }
+
+                    if (isset($add_as_announcement) && !empty($add_as_announcement)) {
+                        self::store_agenda_item_as_announcement($id, $users_to_send);
+                    }
+                }
+                break;
+            case 'admin':
+                if (api_is_platform_admin()) {
+                    $attributes['title'] = $title;
+                    $attributes['content'] = $content;
+                    $attributes['start_date'] = $start;
+                    $attributes['end_date'] = $end;
+                    $attributes['all_day'] = $all_day;
+                    $attributes['access_url_id'] = api_get_current_access_url_id();
+                    $id = Database::insert($this->tbl_global_agenda, $attributes);
+                }
+                break;
+        }
+        return $id;
+    }
+
+    /**
+     * @param agenda_id
+     * @sent agenda event to
+     * */
+    function store_agenda_item_as_announcement($item_id, $sent_to = array())
+    {
+        $table_agenda = Database::get_course_table(TABLE_AGENDA);
+        $course_id = api_get_course_int_id();
+
+        //check params
+        if (empty($item_id) or $item_id != strval(intval($item_id))) {
+            return -1;
+        }
+        //get the agenda item
+
+        $item_id = Database::escape_string($item_id);
+        $sql = "SELECT * FROM $table_agenda WHERE c_id = $course_id AND id = ".$item_id;
+        $res = Database::query($sql);
+
+        if (Database::num_rows($res) > 0) {
+            $row = Database::fetch_array($res, 'ASSOC');
+
+            //Sending announcement
+            if (!empty($sent_to)) {
+                $id = AnnouncementManager::add_announcement($row['title'], $row['content'], $sent_to, null, null, $row['end_date']);
+                AnnouncementManager::send_email($id);
+            }
+            return $id;
+        }
+        return -1;
+    }
+
+    /**
+     * Edits an event
+     *
+     * @param int       event id
+     * @param string    start datetime format: 2012-06-14 09:00:00
+     * @param string    end datetime format: 2012-06-14 09:00:00
+     * @param int       event is all day? 1|0
+     * @param string    view
+     * @param string    event title
+     * @param string    event content
+     */
+    function edit_event($id, $start, $end, $all_day, $view, $title, $content)
+    {
+        $start = api_get_utc_datetime($start);
+
+        if ($all_day == '0') {
+            $end = api_get_utc_datetime($end);
+        }
+        $all_day = isset($all_day) && $all_day == '1' ? 1 : 0;
+
+        $attributes = array();
+
+        switch ($this->type) {
+            case 'personal':
+                $eventInfo = $this->get_event($id);
+                if ($eventInfo['user'] != api_get_user_id()) {
+                    break;
+                }
+                $attributes['title'] = $title;
+                $attributes['text'] = $content;
+                $attributes['date'] = $start;
+                $attributes['enddate'] = $end;
+                Database::update($this->tbl_personal_agenda, $attributes, array('id = ?' => $id));
+                break;
+            case 'course':
+                $course_id = api_get_course_int_id();
+                if (!empty($course_id) && api_is_allowed_to_edit(null, true)) {
+                    $attributes['title'] = $title;
+                    $attributes['content'] = $content;
+                    $attributes['start_date'] = $start;
+                    $attributes['end_date'] = $end;
+                    $attributes['all_day'] = $all_day;
+                    Database::update($this->tbl_course_agenda, $attributes, array('id = ? AND c_id = ?' => array($id, $course_id)));
+                }
+                break;
+            case 'admin':
+                if (api_is_platform_admin()) {
+                    $attributes['title'] = $title;
+                    $attributes['content'] = $content;
+                    $attributes['start_date'] = $start;
+                    $attributes['end_date'] = $end;
+                    Database::update($this->tbl_global_agenda, $attributes, array('id = ?' => $id));
+                }
+                break;
+        }
+    }
+
+    function delete_event($id)
+    {
+        switch ($this->type) {
+            case 'personal':
+                $eventInfo = $this->get_event($id);
+                if ($eventInfo['user'] == api_get_user_id()) {
+                    Database::delete($this->tbl_personal_agenda, array('id = ?' => $id));
+                }
+                break;
+            case 'course':
+                $course_id = api_get_course_int_id();
+                if (!empty($course_id) && api_is_allowed_to_edit(null, true)) {
+                    Database::delete($this->tbl_course_agenda, array('id = ? AND c_id = ?' => array($id, $course_id)));
+                }
+                break;
+            case 'admin':
+                if (api_is_platform_admin()) {
+                    Database::delete($this->tbl_global_agenda, array('id = ?' => $id));
+                }
+                break;
+        }
+    }
+
+    /**
+     *
+     * Get agenda events
+     * @param	int		start tms
+     * @param	int		end tms
+     * @param	int		course id *integer* not the course code
+     * @param   int     user id
+     *
+     */
+    function get_events($start, $end, $course_id = null, $group_id = null, $user_id = 0)
+    {
+
+        switch ($this->type) {
+            case 'admin':
+                $this->get_platform_events($start, $end);
+                break;
+            case 'course':
+                $session_id = api_get_session_id();
+                $course_info = api_get_course_info_by_id($course_id);
+                $this->get_course_events($start, $end, $course_info, $group_id, $session_id, $user_id);
+                break;
+            case 'personal':
+            default:
+                //Getting personal events
+                $this->get_personal_events($start, $end);
+
+                //Getting platform/admin events
+                $this->get_platform_events($start, $end);
+
+                //Getting course events
+                $my_course_list = array();
+
+                if (!api_is_anonymous()) {
+                    $session_list = SessionManager::get_sessions_by_user(api_get_user_id());
+                    $my_course_list = CourseManager::get_courses_list_by_user_id(api_get_user_id(), true);
+                }
+
+                if (!empty($session_list)) {
+                    foreach ($session_list as $session_item) {
+                        $my_courses = $session_item['courses'];
+                        $my_session_id = $session_item['session_id'];
+                        if (!empty($my_courses)) {
+                            foreach ($my_courses as $course_item) {
+                                $course_info = api_get_course_info($course_item['code']);
+                                $this->get_course_events($start, $end, $course_info, 0, $my_session_id);
+                            }
+                        }
+                    }
+                }
+
+                if (!empty($my_course_list)) {
+                    foreach ($my_course_list as $course_info_item) {
+                        if (isset($course_id) && !empty($course_id)) {
+                            if ($course_info_item['real_id'] == $course_id) {
+                                $this->get_course_events($start, $end, $course_info_item);
+                            }
+                        } else {
+                            $this->get_course_events($start, $end, $course_info_item);
+                        }
+                    }
+                }
+                break;
+        }
+        if (!empty($this->events)) {
+            return json_encode($this->events);
+        }
+        return '';
+    }
+
+    function resize_event($id, $day_delta, $minute_delta)
+    {
+        // we convert the hour delta into minutes and add the minute delta
+        $delta = ($day_delta * 60 * 24) + $minute_delta;
+        $delta = intval($delta);
+
+        $event = $this->get_event($id);
+        if (!empty($event)) {
+            switch ($this->type) {
+                case 'personal':
+                    $sql = "UPDATE $this->tbl_personal_agenda SET all_day = 0, enddate = DATE_ADD(enddate, INTERVAL $delta MINUTE)
+							WHERE id=".intval($id);
+                    $result = Database::query($sql);
+                    break;
+                case 'course':
+                    $sql = "UPDATE $this->tbl_course_agenda SET all_day = 0,  end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
+							WHERE c_id = ".$this->course['real_id']." AND id=".intval($id);
+                    $result = Database::query($sql);
+                    break;
+                case 'admin':
+                    $sql = "UPDATE $this->tbl_global_agenda SET all_day = 0, end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
+							WHERE id=".intval($id);
+                    $result = Database::query($sql);
+                    break;
+            }
+        }
+        return 1;
+    }
+
+    function move_event($id, $day_delta, $minute_delta)
+    {
+        // we convert the hour delta into minutes and add the minute delta
+        $delta = ($day_delta * 60 * 24) + $minute_delta;
+        $delta = intval($delta);
+
+        $event = $this->get_event($id);
+
+        $all_day = 0;
+        if ($day_delta == 0 && $minute_delta == 0) {
+            $all_day = 1;
+        }
+
+        if (!empty($event)) {
+            switch ($this->type) {
+                case 'personal':
+                    $sql = "UPDATE $this->tbl_personal_agenda SET all_day = $all_day, date = DATE_ADD(date, INTERVAL $delta MINUTE), enddate = DATE_ADD(enddate, INTERVAL $delta MINUTE)
+							WHERE id=".intval($id);
+                    $result = Database::query($sql);
+                    break;
+                case 'course':
+                    $sql = "UPDATE $this->tbl_course_agenda SET all_day = $all_day, start_date = DATE_ADD(start_date,INTERVAL $delta MINUTE), end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
+							WHERE c_id = ".$this->course['real_id']." AND id=".intval($id);
+                    $result = Database::query($sql);
+                    break;
+                case 'admin':
+                    $sql = "UPDATE $this->tbl_global_agenda SET all_day = $all_day, start_date = DATE_ADD(start_date,INTERVAL $delta MINUTE), end_date = DATE_ADD(end_date, INTERVAL $delta MINUTE)
+							WHERE id=".intval($id);
+                    $result = Database::query($sql);
+                    break;
+            }
+        }
+        return 1;
+    }
+
+    /**
+     * Gets a single event
+     *
+     * @param int event id
+     * @return array
+     */
+    function get_event($id)
+    {
+        // make sure events of the personal agenda can only be seen by the user himself
+        $id = intval($id);
+        $event = null;
+        switch ($this->type) {
+            case 'personal':
+                $sql = " SELECT * FROM ".$this->tbl_personal_agenda." WHERE id = $id AND user = ".api_get_user_id();
+                $result = Database::query($sql);
+                if (Database::num_rows($result)) {
+                    $event = Database::fetch_array($result, 'ASSOC');
+                    $event['description'] = $event['text'];
+                    $event['start_date'] = $event['date'];
+                    $event['end_date'] = $event['enddate'];
+                }
+                break;
+            case 'course':
+                if (!empty($this->course['real_id'])) {
+                    $sql = " SELECT * FROM ".$this->tbl_course_agenda." WHERE c_id = ".$this->course['real_id']." AND id = ".$id;
+                    $result = Database::query($sql);
+                    if (Database::num_rows($result)) {
+                        $event = Database::fetch_array($result, 'ASSOC');
+                        $event['description'] = $event['content'];
+                    }
+                }
+                break;
+            case 'admin':
+            case 'platform':
+                $sql = " SELECT * FROM ".$this->tbl_global_agenda." WHERE id=".$id;
+                $result = Database::query($sql);
+                if (Database::num_rows($result)) {
+                    $event = Database::fetch_array($result, 'ASSOC');
+                    $event['description'] = $event['content'];
+                }
+                break;
+        }
+        return $event;
+    }
+
+    /**
+     *
+     * Gets personal events
+     * @param int 	start date tms
+     * @param int	end   date tms
+     */
+    function get_personal_events($start, $end)
+    {
+        $start = intval($start);
+        $end = intval($end);
+        $start = api_get_utc_datetime($start);
+        $end = api_get_utc_datetime($end);
+        $user_id = api_get_user_id();
+
+        $sql = "SELECT * FROM ".$this->tbl_personal_agenda."
+				   WHERE date >= '".$start."' AND (enddate <='".$end."' OR enddate IS NULL) AND user = $user_id";
+
+        $result = Database::query($sql);
+        $my_events = array();
+        if (Database::num_rows($result)) {
+            while ($row = Database::fetch_array($result, 'ASSOC')) {
+                $event = array();
+                $event['id'] = 'personal_'.$row['id'];
+                $event['title'] = $row['title'];
+                $event['className'] = 'personal';
+                $event['borderColor'] = $event['backgroundColor'] = $this->event_personal_color;
+                $event['editable'] = true;
+
+                $event['sent_to'] = get_lang('Me');
+                $event['type'] = 'personal';
+
+                if (!empty($row['date']) && $row['date'] != '0000-00-00 00:00:00') {
+                    $event['start'] = $this->format_event_date($row['date']);
+                }
+
+                if (!empty($row['enddate']) && $row['enddate'] != '0000-00-00 00:00:00') {
+                    $event['end'] = $this->format_event_date($row['enddate']);
+                }
+                $event['description'] = $row['text'];
+                $event['allDay'] = isset($row['all_day']) && $row['all_day'] == 1 ? $row['all_day'] : 0;
+                $my_events[] = $event;
+                $this->events[] = $event;
+            }
+        }
+        return $my_events;
+    }
+
+    function get_course_events($start, $end, $course_info, $group_id = 0, $session_id = 0, $user_id = 0)
+    {
+        $course_id = $course_info['real_id'];
+        $user_id = intval($user_id);
+
+        $group_list = GroupManager::get_group_list(null, $course_info['code']);
+
+        $group_name_list = array();
+        if (!empty($group_list)) {
+            foreach ($group_list as $group) {
+                $group_name_list[$group['id']] = $group['name'];
+            }
+        }
+
+        if (!api_is_allowed_to_edit()) {
+            $group_memberships = GroupManager::get_group_ids($course_id, api_get_user_id());
+            $user_id = api_get_user_id();
+        } else {
+            $group_memberships = GroupManager::get_group_ids($course_id, $user_id);
+        }
+
+        $tlb_course_agenda = Database::get_course_table(TABLE_AGENDA);
+        $tbl_property = Database::get_course_table(TABLE_ITEM_PROPERTY);
+
+        if (!empty($group_id)) {
+            $group_memberships = array($group_id);
+        }
+
+        $session_id = intval($session_id);
+       
+        if (is_array($group_memberships) && count($group_memberships) > 0) {
+            if (api_is_allowed_to_edit()) {
+                if (!empty($group_id)){
+                    $where_condition = "( ip.to_group_id IN (0, ".implode(", ", $group_memberships).") ) "; 
+                } else {
+                    if (!empty($user_id)) {
+                        $where_condition = "( ip.to_user_id = $user_id OR ip.to_group_id IN (0, ".implode(", ", $group_memberships).") ) ";
+                    } else {
+                        $where_condition = "( ip.to_group_id is null OR ip.to_group_id IN (0, ".implode(", ", $group_memberships).") ) ";
+                    }
+                }
+            } else {
+                $where_condition = "( ip.to_user_id = $user_id OR ip.to_group_id IN (0, ".implode(", ", $group_memberships).") ) ";
+            }
+
+            $sql = "SELECT DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref, to_user_id
+                    FROM ".$tlb_course_agenda." agenda, ".$tbl_property." ip
+                    WHERE   agenda.id       = ip.ref  AND
+                            ip.tool         ='".TOOL_CALENDAR_EVENT."' AND
+                            $where_condition AND
+                            ip.visibility   = '1' AND
+                            agenda.c_id     = $course_id AND
+                            ip.c_id         = $course_id
+
+                    GROUP BY id";
+        } else {
+            if (api_is_allowed_to_edit()) {
+                if ($user_id == 0) {
+                    $where_condition = "";
+                } else {
+                    $where_condition = "( ip.to_user_id=".$user_id. ") AND ";
+                }
+            } else {
+                $where_condition = "( ip.to_user_id=$user_id OR ip.to_group_id='0') AND ";
+            }
+
+            $sql = "SELECT DISTINCT agenda.*, ip.visibility, ip.to_group_id, ip.insert_user_id, ip.ref, to_user_id
+                    FROM ".$tlb_course_agenda." agenda, ".$tbl_property." ip
+                    WHERE   agenda.id = ip.ref AND
+                            ip.tool='".TOOL_CALENDAR_EVENT."' AND
+                            $where_condition
+                            ip.visibility='1' AND
+                            agenda.c_id = $course_id AND
+                            ip.c_id = $course_id AND
+                            agenda.session_id = $session_id AND
+                            ip.id_session = $session_id
+                    ";
+        }
+
+        $result = Database::query($sql);
+        $events = array();
+        if (Database::num_rows($result)) {
+            $events_added = array();
+            while ($row = Database::fetch_array($result, 'ASSOC')) {
+                //to gather sent_tos
+                $sql = "SELECT to_user_id, to_group_id
+                    FROM ".$tbl_property." ip
+                    WHERE   ip.tool         = '".TOOL_CALENDAR_EVENT."' AND
+                            ref             = {$row['ref']} AND
+                            ip.visibility   = '1' AND
+                            ip.c_id         = $course_id";
+                $sent_to_result = Database::query($sql);
+                $user_to_array = array();
+                $group_to_array = array();
+                while ($row_send_to = Database::fetch_array($sent_to_result, 'ASSOC')) {
+                    if (!empty($row_send_to['to_group_id'])) {
+                        $group_to_array[] = $row_send_to['to_group_id'];
+                    }
+                    if (!empty($row_send_to['to_user_id'])) {
+                        $user_to_array[] = $row_send_to['to_user_id'];
+                    }
+                }
+
+                //Only show events from the session
+                /* if (api_get_course_int_id()) {
+                  if ($row['session_id'] != api_get_session_id()) {
+                  continue;
+                  }
+                  } */
+
+                $event = array();
+
+                $event['id'] = 'course_'.$row['id'];
+
+                //To avoid doubles
+                if (in_array($row['id'], $events_added)) {
+                    continue;
+                }
+
+                $events_added[] = $row['id'];
+
+                $attachment = get_attachment($row['id'], $course_id);
+
+                $has_attachment = '';
+
+                if (!empty($attachment)) {
+                    $has_attachment = Display::return_icon('attachment.gif', get_lang('Attachment'));
+                    $user_filename = $attachment['filename'];
+                    $full_file_name = 'download.php?file='.$attachment['path'].'&course_id='.$course_id;
+                    $event['attachment'] = $has_attachment.Display::url($user_filename, $full_file_name);
+                } else {
+                    $event['attachment'] = '';
+                }
+
+                $event['title'] = $row['title'];
+                $event['className'] = 'course';
+                $event['allDay'] = 'false';
+
+                $event['course_id'] = $course_id;
+
+                $event['borderColor'] = $event['backgroundColor'] = $this->event_course_color;
+                if (isset($row['session_id']) && !empty($row['session_id'])) {
+                    $event['borderColor'] = $event['backgroundColor'] = $this->event_session_color;
+                }
+
+                if (isset($row['to_group_id']) && !empty($row['to_group_id'])) {
+                    $event['borderColor'] = $event['backgroundColor'] = $this->event_group_color;
+                }
+
+                $event['editable'] = false;
+
+                if (api_is_allowed_to_edit() && $this->type == 'course') {
+                    $event['editable'] = true;
+                }
+
+                if (!empty($row['start_date']) && $row['start_date'] != '0000-00-00 00:00:00') {
+                    $event['start'] = $this->format_event_date($row['start_date']);
+                }
+                if (!empty($row['end_date']) && $row['end_date'] != '0000-00-00 00:00:00') {
+                    $event['end'] = $this->format_event_date($row['end_date']);
+                }
+
+                $event['sent_to'] = '';
+                //$event['type']    = $this->type;
+                $event['type'] = 'course';
+                if ($row['session_id'] != 0) {
+                    $event['type'] = 'session';
+                }
+
+                //Event Sent to a group?
+                if (isset($row['to_group_id']) && !empty($row['to_group_id'])) {
+                    $sent_to = array();
+                    if (!empty($group_to_array)) {
+                        foreach ($group_to_array as $group_item) {
+                            $sent_to[] = $group_name_list[$group_item];
+                        }
+                    }
+                    $sent_to = implode('@@', $sent_to);
+                    $sent_to = str_replace('@@', '</div><div class="label_tag notice">', $sent_to);
+                    $event['sent_to'] = '<div class="label_tag notice">'.$sent_to.'</div>';
+                    $event['type'] = 'group';
+                }
+
+                //Event sent to a user?
+                if (isset($row['to_user_id'])) {
+                    $sent_to = array();
+                    if (!empty($user_to_array)) {
+                        foreach ($user_to_array as $item) {
+                            $user_info = api_get_user_info($item);
+                            // add username as tooltip for $event['sent_to'] - ref #4226
+                            $username = api_htmlentities(sprintf(get_lang('LoginX'), $user_info['username']), ENT_QUOTES);
+                            $sent_to[] = "<span title='".$username."'>".$user_info['complete_name']."</span>";
+                        }
+                    }
+                    $sent_to = implode('@@', $sent_to);
+                    $sent_to = str_replace('@@', '</div><div class="label_tag notice">', $sent_to);
+                    $event['sent_to'] = '<div class="label_tag notice">'.$sent_to.'</div>';
+                }
+
+                //Event sent to everyone!
+                if (empty($event['sent_to'])) {
+                    $event['sent_to'] = '<div class="label_tag notice">'.get_lang('Everyone').'</div>';
+                }
+
+                $event['description'] = $row['content'];
+                $event['allDay'] = isset($row['all_day']) && $row['all_day'] == 1 ? $row['all_day'] : 0;
+
+                $this->events[] = $event;
+            }
+        }
+        return $this->events;
+    }
+
+    function get_platform_events($start, $end)
+    {
+        $start = intval($start);
+        $end = intval($end);
+
+        $start = api_get_utc_datetime($start);
+        $end = api_get_utc_datetime($end);
+
+        $access_url_id = api_get_current_access_url_id();
+
+        $sql = "SELECT * FROM ".$this->tbl_global_agenda."
+				   WHERE start_date >= '".$start."' AND end_date <= '".$end."' AND access_url_id = $access_url_id ";
+
+        $result = Database::query($sql);
+        $my_events = array();
+        if (Database::num_rows($result)) {
+            while ($row = Database::fetch_array($result, 'ASSOC')) {
+                $event = array();
+                $event['id'] = 'platform_'.$row['id'];
+                $event['title'] = $row['title'];
+                $event['className'] = 'platform';
+                $event['allDay'] = 'false';
+                $event['borderColor'] = $event['backgroundColor'] = $this->event_platform_color;
+                $event['editable'] = false;
+
+                $event['type'] = 'admin';
+
+                if (api_is_platform_admin() && $this->type == 'admin') {
+                    $event['editable'] = true;
+                }
+
+                if (!empty($row['start_date']) && $row['start_date'] != '0000-00-00 00:00:00') {
+                    $event['start'] = $this->format_event_date($row['start_date']);
+                }
+                if (!empty($row['end_date']) && $row['end_date'] != '0000-00-00 00:00:00') {
+                    $event['end'] = $this->format_event_date($row['end_date']);
+                }
+
+                $event['description'] = $row['content'];
+                $event['allDay'] = isset($row['all_day']) && $row['all_day'] == 1 ? $row['all_day'] : 0;
+
+                $my_events[] = $event;
+                $this->events[] = $event;
+            }
+        }
+        return $my_events;
+    }
+
+    /**
+     * Format needed for the Fullcalendar js lib
+     *  @param string UTC time
+     */
+    function format_event_date($utc_time)
+    {
+        return date('c', api_strtotime(api_get_local_time($utc_time)));
+    }
+
+    /**
+     * this function shows the form with the user that were not selected
+     * @author: Patrick Cool <patrick.cool@UGent.be>, Ghent University
+     * @return html code
+     */
+    static function construct_not_selected_select_form($group_list = null, $user_list = null, $to_already_selected = array())
+    {
+        $html = '<select id="users_to_send_id" data-placeholder="'.get_lang('Select').'" name="users_to_send[]" multiple="multiple" style="width:250px" class="chzn-select">';
+
+
+        if ($to_already_selected == 'everyone') {
+            $html .= '<option value="everyone" checked="checked">'.get_lang('Everyone').'</option>';
+        } else {
+            $html .= '<option value="everyone">'.get_lang('Everyone').'</option>';
+        }
+
+        if (is_array($group_list)) {
+            $html .= '<optgroup label="'.get_lang('Groups').'">';
+            foreach ($group_list as $this_group) {
+                if (!is_array($to_already_selected) || !in_array("GROUP:".$this_group['id'], $to_already_selected)) {
+                    // $to_already_selected is the array containing the groups (and users) that are already selected
+                    $count_users = isset($this_group['count_users']) ? $this_group['count_users'] : $this_group['userNb'];
+                    $count_users = " &ndash; $count_users ".get_lang('Users');
+
+                    $html .= '<option value="GROUP:'.$this_group['id'].'"> '.$this_group['name'].$count_users.'</option>';
+                }
+            }
+            $html .= '</optgroup>';
+        }
+
+        // adding the individual users to the select form
+        if (is_array($group_list)) {
+            $html .= '<optgroup label="'.get_lang('Users').'">';
+        }
+        foreach ($user_list as $this_user) {
+            // $to_already_selected is the array containing the users (and groups) that are already selected
+            if (!is_array($to_already_selected) || !in_array("USER:".$this_user['user_id'], $to_already_selected)) {
+                $username = api_htmlentities(sprintf(get_lang('LoginX'), $this_user['username']), ENT_QUOTES);
+                // @todo : add title attribute $username in the jqdialog window. wait for a chosen version to inherit title attribute
+                $html .= '<option title="'.$username.'" value="USER:'.$this_user['user_id'].'">'.api_get_person_name($this_user['firstname'], $this_user['lastname']).' ('.$this_user['username'].') </option>';
+            }
+        }
+        if (is_array($group_list)) {
+            $html .= '</optgroup>';
+            $html .= "</select>";
+        }
+        return $html;
+    }
+
+    static function construct_not_selected_select_form_validator($form, $group_list = null, $user_list = null, $to_already_selected = array())
+    {
+
+        $params = array(
+            'id' => 'users_to_send_id',
+            'data-placeholder' => get_lang('Select'),
+            'multiple' => 'multiple',
+            'style' => 'width:250px',
+            'class' => 'chzn-select'
+        );
+
+        $select = $form->addElement('select', 'users_to_send', get_lang('To'), null, $params);
+
+        $select->addOption(get_lang('Everyone'), 'everyone');
+
+        $options = array();
+        if (is_array($group_list)) {
+            foreach ($group_list as $this_group) {
+                if (!is_array($to_already_selected) || !in_array("GROUP:".$this_group['id'], $to_already_selected)) {
+                    // $to_already_selected is the array containing the groups (and users) that are already selected
+                    $count_users = isset($this_group['count_users']) ? $this_group['count_users'] : $this_group['userNb'];
+                    $count_users = " &ndash; $count_users ".get_lang('Users');
+                    $options[] = array('text' => $this_group['name'].$count_users, 'value' => "GROUP:".$this_group['id']);
+                }
+            }
+            $select->addOptGroup($options, get_lang('Groups'));
+            $html .= '</optgroup>';
+        }
+
+        // adding the individual users to the select form
+        if (is_array($group_list)) {
+            $options = array();
+            foreach ($user_list as $this_user) {
+                // $to_already_selected is the array containing the users (and groups) that are already selected
+                if (!is_array($to_already_selected) || !in_array("USER:".$this_user['user_id'], $to_already_selected)) {
+                    //$username = api_htmlentities(sprintf(get_lang('LoginX'), $this_user['username']), ENT_QUOTES);
+                    // @todo : add title attribute $username in the jqdialog window. wait for a chosen version to inherit title attribute
+                    // from <option> to <li>
+                    //$html .= '<option title="'.$username.'" value="USER:'.$this_user['user_id'].'">'.api_get_person_name($this_user['firstname'], $this_user['lastname']).' ('.$this_user['username'].') </option>';
+                    $options[] = array('text' => api_get_person_name($this_user['firstname'], $this_user['lastname']).' ('.$this_user['username'].')',
+                        'value' => "USER:".$this_user['user_id']);
+                }
+            }
+            $select->addOptGroup($options, get_lang('Users'));
+        }
+    }
+
+    /**
+     * This function separates the users from the groups
+     * users have a value USER:XXX (with XXX the dokeos id
+     * groups have a value GROUP:YYY (with YYY the group id)
+     * @author: Patrick Cool <patrick.cool@UGent.be>, Ghent University
+     * @return array
+     */
+    function separate_users_groups($to)
+    {
+        $grouplist = array();
+        $userlist = array();
+        $send_to = null;
+
+        $send_to['everyone'] = false;
+        if (is_array($to) && count($to) > 0) {
+            foreach ($to as $to_item) {
+                if ($to_item == 'everyone') {
+                    $send_to['everyone'] = true;
+                } else {
+                    list($type, $id) = explode(':', $to_item);
+                    switch ($type) {
+                        case 'GROUP':
+                            $grouplist[] = $id;
+                            break;
+                        case 'USER':
+                            $userlist[] = $id;
+                            break;
+                    }
+                }
+            }
+            $send_to['groups'] = $grouplist;
+            $send_to['users'] = $userlist;
+        }
+        return $send_to;
+    }
+
+    static function show_form($params = array())
+    {
+        $form = new FormValidator('add_event', 'POST', api_get_self().'?'.api_get_cidreq(), null, array('enctype' => 'multipart/form-data'));
+        $id = isset($params['id']) ? $params['id'] : null;
+
+        if ($id) {
+            $form_title = get_lang('ModifyCalendarItem');
+            $button = get_lang('ModifyEvent');
+        } else {
+            $form_title = get_lang('AddCalendarItem');
+            $button = get_lang('AgendaAdd');
+        }
+
+        $form->addElement('header', $form_title);
+        $form->addElement('hidden', 'id', $id);
+        $form->addElement('hidden', 'action', $params['action']);
+        $form->addElement('hidden', 'id_attach', $params['id_attach']);
+
+        $form->addElement('text', 'title', get_lang('ItemTitle'));
+
+        $group_id = api_get_group_id();
+
+        if (isset($group_id) && !empty($group_id)) {
+            $form->addElement('hidden', 'selected_form[0]', "GROUP:'.$group_id.'");
+            $form->addElement('hidden', 'to', 'true');
+        } else {
+            self::show_to_form($form, $to);
+        }
+
+        $form->addElement('text', 'start_date', get_lang('StartDate'));
+        $form->addElement('text', 'end_date', get_lang('EndDate'));
+
+        if (empty($id)) {
+            $form->addElement('advanced_settings', '<a href="javascript://" onclick="return plus_repeated_event();"><span id="plus2">
+                                   <img style="vertical-align:middle;" src="../img/div_show.gif" alt="" />&nbsp;'.get_lang('RepeatEvent').'</span>
+                                </a>');
+            $form->addElement('html', '<div style="display:block">');
+
+            $form->addElement('checkbox', 'repeat', null, get_lang('RepeatEvent'));
+
+            $repeat_events = array(
+                'daily' => get_lang('RepeatDaily'),
+                'weekly' => get_lang('RepeatWeekly'),
+                'monthlyByDate' => get_lang('RepeatMonthlyByDate'),
+                'yearly' => get_lang('RepeatYearly')
+            );
+
+            $form->addElement('select', 'repeat_type', get_lang('RepeatType'), $repeat_events);
+            $form->addElement('text', 'repeat_end_day', get_lang('RepeatEnd'));
+            $form->addElement('html', '</div>');
+
+            if (!api_is_allowed_to_edit(null, true)) {
+                $toolbar = 'AgendaStudent';
+            } else {
+                $toolbar = 'Agenda';
+            }
+            //$form->addElement('html_editor', 'content', get_lang('Description'), null, array('ToolbarSet' => $toolbar, 'Width' => '100%', 'Height' => '200'));
+
+            $form->addElement('file', 'user_upload', get_lang('AddAnAttachment'));
+            $form->addElement('text', 'file_comment', get_lang('Comment'));
+        }
+
+        $form->addElement('button', 'submit', $button);
+        $form->display();
+    }
+
+    static function show_to_form($form, $to_already_selected)
+    {
+        $order = 'lastname';
+        if (api_is_western_name_order()) {
+            $order = 'firstname';
+        }
+        $user_list = CourseManager::get_user_list_from_course_code(api_get_course_id(), api_get_session_id(), null, $order);
+        $group_list = CourseManager::get_group_list_of_course(api_get_course_id(), api_get_session_id());
+
+        self::construct_not_selected_select_form_validator($form, $group_list, $user_list, $to_already_selected);
+    }
+}

+ 2 - 1
main/course_home/activity.php

@@ -54,7 +54,8 @@ if (api_is_platform_admin()) {
 //	COURSE ADMIN ONLY VIEW
 
 // Start of tools for CourseAdmins (teachers/tutors)
-if (api_is_allowed_to_edit(null, true) && !api_is_coach()) {
+
+if ($session_id == 0 && api_is_course_admin() && api_is_allowed_to_edit(null, true)) {
 	$content .=  '<div class="courseadminview" style="border:0px; margin-top: 0px;padding:0px;">
 		<div class="normal-message" id="id_normal_message" style="display:none">';
 			$content .=  '<img src="'.api_get_path(WEB_PATH).'main/inc/lib/javascript/indicator.gif"/>&nbsp;&nbsp;';

+ 78 - 59
main/course_home/vertical_activity.php

@@ -4,66 +4,70 @@
 /**
  *   HOME PAGE FOR EACH COURSE
  *
- *	This page, included in every course's index.php is the home
- *	page. To make administration simple, the teacher edits his
- *	course from the home page. Only the login detects that the
- *	visitor is allowed to activate, deactivate home page links,
- *	access to the teachers tools (statistics, edit forums...).
+ *    This page, included in every course's index.php is the home
+ *    page. To make administration simple, the teacher edits his
+ *    course from the home page. Only the login detects that the
+ *    visitor is allowed to activate, deactivate home page links,
+ *    access to the teachers tools (statistics, edit forums...).
  *
- *	@package chamilo.course_home
+ * @package chamilo.course_home
  */
 
 //	MAIN CODE
-$id = isset($_GET['id']) ? intval($_GET['id']) : null;
-$course_id = api_get_course_int_id();
+$id         = isset($_GET['id']) ? intval($_GET['id']) : null;
+$course_id  = api_get_course_int_id();
 $session_id = api_get_session_id();
 
 if (api_is_allowed_to_edit(null, true)) {
-	// HIDE
-	if (!empty($_GET['hide'])) { // visibility 1 -> 0
-		$sql = "UPDATE $tool_table SET visibility=0 WHERE c_id = $course_id AND id='".$id."'";
-		Database::query($sql);
-		$show_message = Display::return_message(get_lang('ToolIsNowHidden'), 'confirmation');
-	} elseif (!empty($_GET['restore'])) {
-		// visibility 0,2 -> 1
-		// REACTIVATE
-		$sql = "UPDATE $tool_table SET visibility=1  WHERE c_id = $course_id AND id='".$id."'";
-		Database::query($sql);
-		$show_message = Display::return_message(get_lang('ToolIsNowVisible'), 'confirmation');
-	}
+    // HIDE
+    if (!empty($_GET['hide'])) { // visibility 1 -> 0
+        $sql = "UPDATE $tool_table SET visibility=0 WHERE c_id = $course_id AND id='".$id."'";
+        Database::query($sql);
+        $show_message = Display::return_message(get_lang('ToolIsNowHidden'), 'confirmation');
+    } elseif (!empty($_GET['restore'])) {
+        // visibility 0,2 -> 1
+        // REACTIVATE
+        $sql = "UPDATE $tool_table SET visibility=1  WHERE c_id = $course_id AND id='".$id."'";
+        Database::query($sql);
+        $show_message = Display::return_message(get_lang('ToolIsNowVisible'), 'confirmation');
+    }
 }
 
 // Work with data post askable by admin of course
 if (api_is_platform_admin()) {
-	// Show message to confirm that a tool it to be hidden from available tools
-	// visibility 0,1->2
-	if (!empty($_GET['askDelete'])) {
-        $content .='<div id="toolhide">'.get_lang('DelLk').'<br />&nbsp;&nbsp;&nbsp;
+    // Show message to confirm that a tool it to be hidden from available tools
+    // visibility 0,1->2
+    if (!empty($_GET['askDelete'])) {
+        $content .= '<div id="toolhide">'.get_lang('DelLk').'<br />&nbsp;&nbsp;&nbsp;
             <a href="'.api_get_self().'">'.get_lang('No').'</a>&nbsp;|&nbsp;
             <a href="'.api_get_self().'?delete=yes&id='.$id.'">'.get_lang('Yes').'</a>
         </div>';
-	} elseif (isset($_GET['delete']) && $_GET['delete']) {
+    } elseif (isset($_GET['delete']) && $_GET['delete']) {
         /*
         * Process hiding a tools from available tools.
         */
-		//where $id is set?
-		$id = intval($id);
-		Database::query("DELETE FROM $tool_table WHERE c_id = $course_id AND id='$id' AND added_tool=1");
-	}
+        //where $id is set?
+        $id = intval($id);
+        Database::query("DELETE FROM $tool_table WHERE c_id = $course_id AND id='$id' AND added_tool=1");
+    }
 }
 
 //	COURSE ADMIN ONLY VIEW
 
 // Start of tools for CourseAdmins (teachers/tutors)
-if (api_is_allowed_to_edit(null, true) && !api_is_coach()) {   
+if (api_is_allowed_to_edit(null, true) && !api_is_coach()) {
+<<<<<<< HEAD
     $content .=  '<div class="courseadminview" style="border:0px; margin-top: 0px;padding:5px;">
+=======
+    $content .= '<div class="courseadminview" style="border:0px; margin-top: 0px;padding:5px;">
+>>>>>>> master
     <div class="normal-message" id="id_normal_message" style="display:none">';
-        $content .=  '<img src="'.api_get_path(WEB_PATH).'main/inc/lib/javascript/indicator.gif"/>&nbsp;&nbsp;';
-        $content .=  get_lang('PleaseStandBy');
+    $content .= '<img src="'.api_get_path(WEB_PATH).'main/inc/lib/javascript/indicator.gif"/>&nbsp;&nbsp;';
+    $content .= get_lang('PleaseStandBy');
 
-    $content .=  '</div>
+    $content .= '</div>
         <div class="confirmation-message" id="id_confirmation_message" style="display:none"></div></div>';
-    $content .=  '<div id="activity-3col">';
+    $content .= '<div id="activity-3col">';
 
     if (api_get_setting('show_session_data') == 'true' && $session_id > 0) {
         $content .= '<div class="courseadminview-activity-3col"><span class="viewcaption">'.get_lang('SessionData').'</span>
@@ -72,12 +76,12 @@ if (api_is_allowed_to_edit(null, true) && !api_is_coach()) {
     }
 
     $content .= '<div class="courseadminview-activity-3col"><span class="viewcaption">'.get_lang('Authoring').'</span>';
-    $my_list  = CourseHome::get_tools_category(TOOL_AUTHORING);
+    $my_list = CourseHome::get_tools_category(TOOL_AUTHORING);
     $content .= CourseHome::show_tools_category($my_list);
     $content .= '</div>';
 
     $content .= '<div class="courseadminview-activity-3col"><span class="viewcaption">'.get_lang('Interaction').'</span>';
-    $my_list  = CourseHome::get_tools_category(TOOL_INTERACTION);
+    $my_list = CourseHome::get_tools_category(TOOL_INTERACTION);
     $content .= CourseHome::show_tools_category($my_list);
     $content .= '</div>';
 
@@ -87,48 +91,63 @@ if (api_is_allowed_to_edit(null, true) && !api_is_coach()) {
     $content .= '</div>';
 
 } elseif (api_is_coach()) {
-	if (api_get_setting('show_session_data') == 'true' && $session_id > 0) {
+    if (api_get_setting('show_session_data') == 'true' && $session_id > 0) {
         $content .= '<div class="courseadminview-activity-3col"><span class="viewcaption">'.get_lang('SessionData').'</span>
 			<table width="100%">';
-				$content .= CourseHome::show_session_data($session_id);
-             $content .=  '</table></div>';
-	}
+        $content .= CourseHome::show_session_data($session_id);
+        $content .= '</table></div>';
+    }
 
-    $content .=  '<div class="Authoringview">';
-				$my_list = CourseHome::get_tools_category(TOOL_STUDENT_VIEW);
-				$content .= CourseHome::show_tools_category($my_list);
+    $content .= '<div class="Authoringview">';
+    $my_list = CourseHome::get_tools_category(TOOL_STUDENT_VIEW);
+    $content .= CourseHome::show_tools_category($my_list);
     $content .= '</div>';
     //	TOOLS AUTHORING
 
 } else {
-	$my_list = CourseHome::get_tools_category(TOOL_STUDENT_VIEW);
-	if (count($my_list) > 0) {
+    $my_list = CourseHome::get_tools_category(TOOL_STUDENT_VIEW);
+    if (count($my_list) > 0) {
         $content .= '<div class="course-student-view-activity-3col">';
+<<<<<<< HEAD
 		//ordering by get_lang name
 		$order_tool_list = array();
 		foreach($my_list as $key=>$new_tool) {
 			$tool_name = CourseHome::translate_tool_name($new_tool);
 			$order_tool_list [$key]= $tool_name;
-		}		
-		natsort($order_tool_list);		
+		}
+		natsort($order_tool_list);
 		$my_temp_tool_array = array();
 		foreach($order_tool_list as $key=>$new_tool) {
 			$my_temp_tool_array[] = $my_list[$key];
 		}
 		$my_list = $my_temp_tool_array;
+=======
+        //ordering by get_lang name
+        $order_tool_list = array();
+        foreach ($my_list as $key => $new_tool) {
+            $tool_name              = CourseHome::translate_tool_name($new_tool);
+            $order_tool_list [$key] = $tool_name;
+        }
+        natsort($order_tool_list);
+        $my_temp_tool_array = array();
+        foreach ($order_tool_list as $key => $new_tool) {
+            $my_temp_tool_array[] = $my_list[$key];
+        }
+        $my_list = $my_temp_tool_array;
+>>>>>>> master
 
-		$i = 0;
-		foreach($my_list as $new_tool) {
-			if ($i >= 10) {
-				$my_list2[] = $new_tool;
-			} else {
-				$my_list1[] = $new_tool;
-			}
-			$i++;
-		}
-		$content .=CourseHome::show_tools_category($my_list1);
-		$content .=CourseHome::show_tools_category($my_list2);
+        $i = 0;
+        foreach ($my_list as $new_tool) {
+            if ($i >= 10) {
+                $my_list2[] = $new_tool;
+            } else {
+                $my_list1[] = $new_tool;
+            }
+            $i++;
+        }
+        $content .= CourseHome::show_tools_category($my_list1);
+        $content .= CourseHome::show_tools_category($my_list2);
         $content .= '</div>';
-	}
+    }
 }
 $content .= '</div>';

+ 7 - 1
main/course_info/infocours.php

@@ -136,7 +136,7 @@ $form->addElement('html', $image_html);
 
 
 $form->add_textfield('title', get_lang('Title'), true, array('class' => 'span6'));
-//$form->applyFilter('title', 'html_filter');
+$form->applyFilter('title', 'html_filter');
 $form->applyFilter('title', 'trim');
 
 //$form->add_textfield('tutor_name', get_lang('Professors'), true, array ('size' => '60'));
@@ -156,9 +156,11 @@ $form->addElement('select', 'category_code', get_lang('Fac'), $categories, array
 $form->addElement('select_language', 'course_language', array(get_lang('Ln'), get_lang('TipLang')));
 
 $form->add_textfield('department_name', get_lang('Department'), false, array('class' => 'span5'));
+$form->applyFilter('department_name', 'html_filter');
 $form->applyFilter('department_name', 'trim');
 
 $form->add_textfield('department_url', get_lang('DepartmentUrl'), false, array('class' => 'span5'));
+$form->applyFilter('department_url', 'html_filter');
 //$form->addRule('tutor_name', get_lang('ThisFieldIsRequired'), 'required');
 
 // Picture
@@ -195,6 +197,10 @@ $group[]= $form->createElement('radio', 'visibility', get_lang("CourseAccess"),
 $group[]= $form->createElement('radio', 'visibility', null, get_lang('OpenToThePlatform'), COURSE_VISIBILITY_OPEN_PLATFORM);
 $group[]= $form->createElement('radio', 'visibility', null, get_lang('Private'), COURSE_VISIBILITY_REGISTERED);
 $group[]= $form->createElement('radio', 'visibility', null, get_lang('CourseVisibilityClosed'), COURSE_VISIBILITY_CLOSED);
+// The "hidden" visibility is only available to portal admins
+if (api_is_platform_admin()) {
+    $group[]= $form->createElement('radio', 'visibility', null, get_lang('CourseVisibilityHidden'), COURSE_VISIBILITY_HIDDEN);
+}
 $form->addGroup($group, '', array(get_lang("CourseAccess"), get_lang("CourseAccessConfigTip")), '');
 
 $url = api_get_path(WEB_CODE_PATH)."auth/inscription.php?c=$course_code&e=1";

+ 50 - 50
main/coursecopy/classes/Announcement.class.php

@@ -10,65 +10,65 @@ require_once 'Resource.class.php';
  */
 class Announcement extends Resource
 {
-    /**
-     * The title of the announcement
-     */
+	/**
+	 * The title of the announcement
+	 */
     public $title;
-    /**
-     * The content of the announcement
-     */
+	/**
+	 * The content of the announcement
+	 */
     public $content;
-    /**
-     * The date on which this announcement was made
-     */
+	/**
+	 * The date on which this announcement was made
+	 */
     public $date;
-    /**
-     * The display order of this announcement
-     */
+	/**
+	 * The display order of this announcement
+	 */
     public $display_order;
-    /**
-     * Has the e-mail been sent?
-     */
+	/**
+	 * Has the e-mail been sent?
+	 */
     public $email_sent;
-
+	
     public $attachment_path;
-
+	
     public $attachment_filename;
-
+	
     public $attachment_size;
-
+	
     public $attachment_comment;
-
-    /**
-     * Create a new announcement
-     * @param int $id
-     * @param string $title
-     * @param string $content
-     * @param string $date
-     * @param int display_order
-     */
+	
+	/**
+	 * Create a new announcement
+	 * @param int $id
+	 * @param string $title
+	 * @param string $content
+	 * @param string $date
+	 * @param int display_order
+	 */
     function Announcement($id, $title, $content, $date, $display_order, $email_sent, $path, $filename, $size, $comment)
     {
-        parent::Resource($id, RESOURCE_ANNOUNCEMENT);
-
-        $this->content       = $content;
-        $this->title         = $title;
-        $this->date          = $date;
-        $this->display_order = $display_order;
-        $this->email_sent    = $email_sent;
-
-        $this->attachment_path     = $path;
-        $this->attachment_filename = $filename;
-        $this->attachment_size     = $size;
-        $this->attachment_comment  = $comment;
-    }
-
-    /**
-     * Show this announcement
-     */
-    function show()
-    {
-        parent::show();
-        echo $this->date.': '.$this->title;
-    }
+		parent::Resource($id,RESOURCE_ANNOUNCEMENT);
+		
+		$this->content	= $content;
+		$this->title 	= $title;
+		$this->date 	= $date;
+		$this->display_order	= $display_order;
+		$this->email_sent	 	= $email_sent;		
+		
+		$this->attachment_path 	= $path;
+		$this->attachment_filename = $filename;
+		$this->attachment_size 	= $size;
+		$this->attachment_comment 	= $comment;		
+	}
+	
+	/**
+	 * Show this announcement
+	 */
+	function show()
+	{
+		parent::show();
+		echo $this->date.': '.$this->title;
+	}
 }

+ 18 - 17
main/coursecopy/classes/Attendance.class.php

@@ -8,29 +8,30 @@ require_once 'Resource.class.php';
 
 class CourseCopyAttendance extends Resource
 {
-
+		
     public $params = array();
     public $attendance_calendar = array();
-
-    /**
-     * Create a new Thematic
-     *
-     * @param array parameters
-     */
+	
+	
+	/**
+	 * Create a new Thematic
+	 * 
+	 * @param array parameters	
+	 */
     public function __construct($params)
     {
-        parent::Resource($params['id'], RESOURCE_ATTENDANCE);
-        $this->params = $params;
-    }
+		parent::Resource($params['id'], RESOURCE_ATTENDANCE);
+		$this->params = $params;
+	}
 
     public function show()
     {
-        parent::show();
-        echo $this->params['name'];
-    }
-
+		parent::show();
+		echo $this->params['name'];
+	}
+	
     public function add_attendance_calendar($data)
     {
-        $this->attendance_calendar[] = $data;
-    }
-}
+		$this->attendance_calendar[] = $data;
+	}	
+}

+ 299 - 297
main/coursecopy/classes/Course.class.php

@@ -19,345 +19,347 @@ class Course
     public $destination_db;
     public $encoding;
 
-    /**
-     * Create a new Course-object
-     */
+	/**
+	 * Create a new Course-object
+	 */
     function __construct()
     {
-        $this->resources   = array();
-        $this->code        = '';
-        $this->path        = '';
-        $this->backup_path = '';
-        $this->encoding    = api_get_system_encoding();
-    }
+		$this->resources    = array();
+		$this->code         = '';
+		$this->path         = '';
+		$this->backup_path  = '';
+		$this->encoding     = api_get_system_encoding();
+	}
 
-    /**
-     * Check if a resource links to the given resource
-     */
+	/**
+	 * Check if a resource links to the given resource
+	 */
     function is_linked_resource(& $resource_to_check)
     {
-        foreach ($this->resources as $type => $resources) {
-            if (is_array($resources)) {
-                foreach ($resources as $id => $resource) {
-                    if ($resource->links_to($resource_to_check)) {
-
-                        return true;
-                    }
-                    if ($type == RESOURCE_LEARNPATH && get_class($resource) == 'CourseCopyLearnpath') {
-                        if ($resource->has_item($resource_to_check)) {
-
-                            return true;
-                        }
-                    }
-                }
-            }
-        }
+		foreach($this->resources as $type => $resources) {
+			if (is_array($resources)) {
+				foreach($resources as $id => $resource) {
+					if( $resource->links_to($resource_to_check) ) {
+						return true;
+					}
+					if ($type == RESOURCE_LEARNPATH && get_class($resource)=='CourseCopyLearnpath') {
+						if($resource->has_item($resource_to_check)) {
+							return true;
+						}
+					}
+				}
+			}
+		}
+		return false;
+	}
 
-        return false;
-    }
-
-    /**
-     * Add a resource from a given type to this course
-     */
+	/**
+	 * Add a resource from a given type to this course
+	 */
     function add_resource(& $resource)
     {
-        $this->resources[$resource->get_type()][$resource->get_id()] = $resource;
-    }
+		$this->resources[$resource->get_type()][$resource->get_id()] = $resource;
+	}
 
-    /**
-     * Does this course has resources?
-     * @param const $resource_type Check if this course has resources of the
-     * given type. If no type is given, check if course has resources of any
-     * type.
-     */
+	/**
+	 * Does this course has resources?
+	 * @param const $resource_type Check if this course has resources of the
+	 * given type. If no type is given, check if course has resources of any
+	 * type.
+	 */
     function has_resources($resource_type = null)
     {
-        if ($resource_type != null) {
+		if( $resource_type != null) {
             return isset($this->resources[$resource_type]) && is_array($this->resources[$resource_type]) && (count(
                     $this->resources[$resource_type]
                 ) > 0);
-        }
-
-        return (count($this->resources) > 0);
-    }
-
-    /**
-     * Show this course resources
-     */
+		}
+		return (count($this->resources) > 0);
+	}
+	/**
+	 * Show this course resources
+	 */
     function show()
     { /*
 		echo '<pre>';
 		print_r($this);
 		echo '</pre>';*/
-    }
+	}
 
-    /**
-     * Returns sample text based on the imported course content.
-     * This sample text is to be used for course language or encoding detection if there is missing (meta)data in the archive.
-     * @return string    The resulting sample text extracted from some common resources' data fields.
-     */
+	/**
+	 * Returns sample text based on the imported course content.
+	 * This sample text is to be used for course language or encoding detection if there is missing (meta)data in the archive.
+	 * @return string	The resulting sample text extracted from some common resources' data fields.
+	 */
     public function get_sample_text()
     {
 
-        $sample_text = '';
-        foreach ($this->resources as $type => & $resources) {
-            if (count($resources) > 0) {
-                foreach ($resources as $id => & $resource) {
-                    $title       = '';
-                    $description = '';
-
-                    switch ($type) {
-                        case RESOURCE_ANNOUNCEMENT:
-                            $title       = $resource->title;
-                            $description = $resource->content;
-                            break;
-                        case RESOURCE_DOCUMENT:
-                            $title       = $resource->title;
-                            $description = $resource->comment;
-                            break;
-                        case RESOURCE_EVENT:
-                            $title       = $resource->title;
-                            $description = $resource->content;
-                            break;
-                        case RESOURCE_FORUM:
-                            $title       = $resource->title;
-                            $description = $resource->description;
-                            break;
-                        case RESOURCE_FORUMCATEGORY:
-                            $title       = $resource->title;
-                            $description = $resource->description;
-                            break;
-                        case RESOURCE_FORUMPOST:
-                            $title       = $resource->title;
-                            $description = $resource->text;
-                            break;
-                        case RESOURCE_FORUMTOPIC:
+		$sample_text = '';
+		foreach ($this->resources as $type => & $resources) {
+			if (count($resources) > 0) {
+				foreach ($resources as $id => & $resource) {
+					$title = '';
+					$description = '';
+
+					switch ($type) {
+						case RESOURCE_ANNOUNCEMENT:
+							$title = $resource->title;
+							$description = $resource->content;
+							break;
+						case RESOURCE_DOCUMENT:
+							$title = $resource->title;
+							$description = $resource->comment;
+							break;
+						case RESOURCE_EVENT:
+							$title = $resource->title;
+							$description = $resource->content;
+							break;
+						case RESOURCE_FORUM:
+							$title = $resource->title;
+							$description = $resource->description;
+							break;
+
+						case RESOURCE_FORUMCATEGORY:
+							$title = $resource->title;
+							$description = $resource->description;
+							break;
+						case RESOURCE_FORUMPOST:
+							$title = $resource->title;
+							$description = $resource->text;
+							break;
+						case RESOURCE_FORUMTOPIC:
+							$title = $resource->title;
+							break;
+						case RESOURCE_GLOSSARY:
+							$title = $resource->name;
+							$description = $resource->description;
+							break;
+						case RESOURCE_LEARNPATH:
+							$title = $resource->name;
+							$description = $resource->description;
+							break;
+						case RESOURCE_LINK:
+							$title = $resource->title;
+							$description = $resource->description;
+							break;
+						case RESOURCE_LINKCATEGORY:
+							$title = $resource->title;
+							$description = $resource->description;
+							break;
+						case RESOURCE_QUIZ:
+							$title = $resource->title;
+							$description = $resource->description;
+							break;
+						case RESOURCE_QUIZQUESTION:
+							$title = $resource->question;
+							$description = $resource->description;
+							break;
+						case RESOURCE_SCORM:
+							$title = $resource->title;
+							break;
+						case RESOURCE_SURVEY:
+							$title = $resource->title;
+							$description = $resource->subtitle;
+							break;
+						case RESOURCE_SURVEYQUESTION:
+							$title = $resource->survey_question;
+							$description = $resource->survey_question_comment;
+							break;
+						case RESOURCE_TOOL_INTRO:
+							$description = $resource->intro_text;
+							break;
+						case RESOURCE_WIKI:
+							$title = $resource->title;
+							$description = $resource->content;
+							break;
+						case RESOURCE_THEMATIC:
+							$title 			= $resource->title;
+							$description 	= $resource->content;
+							break;
+						case RESOURCE_ATTENDANCE:
+							$title 			= $resource->params['name'];
+							$description 	= $resource->params['description'];
+							break;
+                        case RESOURCE_WORK:
                             $title = $resource->title;
-                            break;
-                        case RESOURCE_GLOSSARY:
-                            $title       = $resource->name;
-                            $description = $resource->description;
-                            break;
-                        case RESOURCE_LEARNPATH:
-                            $title       = $resource->name;
                             $description = $resource->description;
-                            break;
-                        case RESOURCE_LINK:
-                            $title       = $resource->title;
-                            $description = $resource->description;
-                            break;
-                        case RESOURCE_LINKCATEGORY:
-                            $title       = $resource->title;
-                            $description = $resource->description;
-                            break;
-                        case RESOURCE_QUIZ:
-                            $title       = $resource->title;
-                            $description = $resource->description;
-                            break;
-                        case RESOURCE_QUIZQUESTION:
-                            $title       = $resource->question;
-                            $description = $resource->description;
-                            break;
-                        case RESOURCE_SCORM:
-                            $title = $resource->title;
-                            break;
-                        case RESOURCE_SURVEY:
-                            $title       = $resource->title;
-                            $description = $resource->subtitle;
-                            break;
-                        case RESOURCE_SURVEYQUESTION:
-                            $title       = $resource->survey_question;
-                            $description = $resource->survey_question_comment;
-                            break;
-                        case RESOURCE_TOOL_INTRO:
-                            $description = $resource->intro_text;
-                            break;
-                        case RESOURCE_WIKI:
-                            $title       = $resource->title;
-                            $description = $resource->content;
-                            break;
-                        case RESOURCE_THEMATIC:
-                            $title       = $resource->title;
-                            $description = $resource->content;
-                            break;
-                        case RESOURCE_ATTENDANCE:
-                            $title       = $resource->params['name'];
-                            $description = $resource->params['description'];
-                            break;
-                        default:
-                            break;
-                    }
+							break;
+						default:
+							break;
+					}
 
                     $title       = Text::api_html_to_text($title);
                     $description = Text::api_html_to_text($description);
 
-                    if (!empty($title)) {
-                        $sample_text .= $title."\n";
-                    }
-                    if (!empty($description)) {
-                        $sample_text .= $description."\n";
-                    }
-                    if (!empty($title) || !empty($description)) {
-                        $sample_text .= "\n";
-                    }
-                }
-            }
-        }
-
-        return $sample_text;
-    }
+					if (!empty($title)) {
+						$sample_text .= $title."\n";
+					}
+					if (!empty($description)) {
+						$sample_text .= $description."\n";
+					}
+					if (!empty($title) || !empty($description)) {
+						$sample_text .= "\n";
+					}
+				}
+			}
+		}
+		return $sample_text;
+	}
 
-    /**
-     * Converts to the system encoding all the language-sensitive fields in the imported course.
-     */
+	/**
+	 * Converts to the system encoding all the language-sensitive fields in the imported course.
+	 */
     public function to_system_encoding()
     {
 
-        if (api_equal_encodings($this->encoding, api_get_system_encoding())) {
-            return;
-        }
+		if (api_equal_encodings($this->encoding, api_get_system_encoding())) {
+			return;
+		}
 
-        foreach ($this->resources as $type => & $resources) {
-            if (count($resources) > 0) {
-                foreach ($resources as $id => & $resource) {
+		foreach ($this->resources as $type => & $resources) {
+			if (count($resources) > 0) {
+				foreach ($resources as $id => & $resource) {
 
-                    switch ($type) {
-                        case RESOURCE_ANNOUNCEMENT:
-                            $resource->title   = api_to_system_encoding($resource->title, $this->encoding);
-                            $resource->content = api_to_system_encoding($resource->content, $this->encoding);
-                            break;
-                        case RESOURCE_DOCUMENT:
-                            $resource->title   = api_to_system_encoding($resource->title, $this->encoding);
-                            $resource->comment = api_to_system_encoding($resource->comment, $this->encoding);
-                            break;
-                        case RESOURCE_EVENT:
-                            $resource->title   = api_to_system_encoding($resource->title, $this->encoding);
-                            $resource->content = api_to_system_encoding($resource->content, $this->encoding);
-                            break;
-                        case RESOURCE_FORUM:
-                            $resource->title       = api_to_system_encoding($resource->title, $this->encoding);
-                            $resource->description = api_to_system_encoding($resource->description, $this->encoding);
-                            break;
-                        case RESOURCE_FORUMCATEGORY:
-                            $resource->title       = api_to_system_encoding($resource->title, $this->encoding);
-                            $resource->description = api_to_system_encoding($resource->description, $this->encoding);
-                            break;
-                        case RESOURCE_FORUMPOST:
-                            $resource->title       = api_to_system_encoding($resource->title, $this->encoding);
-                            $resource->text        = api_to_system_encoding($resource->text, $this->encoding);
-                            $resource->poster_name = api_to_system_encoding($resource->poster_name, $this->encoding);
-                            break;
-                        case RESOURCE_FORUMTOPIC:
-                            $resource->title             = api_to_system_encoding($resource->title, $this->encoding);
-                            $resource->topic_poster_name = api_to_system_encoding(
-                                $resource->topic_poster_name,
-                                $this->encoding
-                            );
-                            $resource->title_qualify     = api_to_system_encoding(
-                                $resource->title_qualify,
-                                $this->encoding
-                            );
-                            break;
-                        case RESOURCE_GLOSSARY:
-                            $resource->name        = api_to_system_encoding($resource->name, $this->encoding);
-                            $resource->description = api_to_system_encoding($resource->description, $this->encoding);
-                            break;
-                        case RESOURCE_LEARNPATH:
-                            $resource->name            = api_to_system_encoding($resource->name, $this->encoding);
-                            $resource->description     = api_to_system_encoding(
-                                $resource->description,
-                                $this->encoding
-                            );
-                            $resource->content_maker   = api_to_system_encoding(
-                                $resource->content_maker,
-                                $this->encoding
-                            );
-                            $resource->content_license = api_to_system_encoding(
-                                $resource->content_license,
-                                $this->encoding
-                            );
-                            //$resource->author = api_to_system_encoding($resource->author, $this->encoding);  // Needs implamantation.
-                            break;
-                        case RESOURCE_LINK:
-                            $resource->title       = api_to_system_encoding($resource->title, $this->encoding);
-                            $resource->description = api_to_system_encoding($resource->description, $this->encoding);
-                            break;
-                        case RESOURCE_LINKCATEGORY:
-                            $resource->title       = api_to_system_encoding($resource->title, $this->encoding);
-                            $resource->description = api_to_system_encoding($resource->description, $this->encoding);
-                            break;
-                        case RESOURCE_QUIZ:
-                            $resource->title       = api_to_system_encoding($resource->title, $this->encoding);
-                            $resource->description = api_to_system_encoding($resource->description, $this->encoding);
-                            break;
-                        case RESOURCE_QUIZQUESTION:
-                            $resource->question    = api_to_system_encoding($resource->question, $this->encoding);
-                            $resource->description = api_to_system_encoding($resource->description, $this->encoding);
-                            if (is_array($resource->answers) && count($resource->answers) > 0) {
-                                foreach ($resource->answers as $index => & $answer) {
-                                    $answer['answer']  = api_to_system_encoding($answer['answer'], $this->encoding);
-                                    $answer['comment'] = api_to_system_encoding($answer['comment'], $this->encoding);
-                                }
-                            }
-                            break;
-                        case RESOURCE_SCORM:
+					switch ($type) {
+
+						case RESOURCE_ANNOUNCEMENT:
+							$resource->title = api_to_system_encoding($resource->title, $this->encoding);
+							$resource->content = api_to_system_encoding($resource->content, $this->encoding);
+							break;
+
+						case RESOURCE_DOCUMENT:
+							$resource->title = api_to_system_encoding($resource->title, $this->encoding);
+							$resource->comment = api_to_system_encoding($resource->comment, $this->encoding);
+							break;
+
+						case RESOURCE_EVENT:
+							$resource->title = api_to_system_encoding($resource->title, $this->encoding);
+							$resource->content = api_to_system_encoding($resource->content, $this->encoding);
+							break;
+
+						case RESOURCE_FORUM:
+							$resource->title = api_to_system_encoding($resource->title, $this->encoding);
+							$resource->description = api_to_system_encoding($resource->description, $this->encoding);
+							break;
+
+						case RESOURCE_FORUMCATEGORY:
+							$resource->title = api_to_system_encoding($resource->title, $this->encoding);
+							$resource->description = api_to_system_encoding($resource->description, $this->encoding);
+							break;
+
+						case RESOURCE_FORUMPOST:
+							$resource->title = api_to_system_encoding($resource->title, $this->encoding);
+							$resource->text = api_to_system_encoding($resource->text, $this->encoding);
+							$resource->poster_name = api_to_system_encoding($resource->poster_name, $this->encoding);
+							break;
+
+						case RESOURCE_FORUMTOPIC:
+							$resource->title = api_to_system_encoding($resource->title, $this->encoding);
+							$resource->topic_poster_name = api_to_system_encoding($resource->topic_poster_name, $this->encoding);
+							$resource->title_qualify = api_to_system_encoding($resource->title_qualify, $this->encoding);
+							break;
+
+						case RESOURCE_GLOSSARY:
+							$resource->name = api_to_system_encoding($resource->name, $this->encoding);
+							$resource->description = api_to_system_encoding($resource->description, $this->encoding);
+							break;
+
+						case RESOURCE_LEARNPATH:
+							$resource->name = api_to_system_encoding($resource->name, $this->encoding);
+							$resource->description = api_to_system_encoding($resource->description, $this->encoding);
+							$resource->content_maker = api_to_system_encoding($resource->content_maker, $this->encoding);
+							$resource->content_license = api_to_system_encoding($resource->content_license, $this->encoding);
+							//$resource->author = api_to_system_encoding($resource->author, $this->encoding);  // Needs implamantation.
+							break;
+
+						case RESOURCE_LINK:
+							$resource->title = api_to_system_encoding($resource->title, $this->encoding);
+							$resource->description = api_to_system_encoding($resource->description, $this->encoding);
+							break;
+
+						case RESOURCE_LINKCATEGORY:
+							$resource->title = api_to_system_encoding($resource->title, $this->encoding);
+							$resource->description = api_to_system_encoding($resource->description, $this->encoding);
+							break;
+
+						case RESOURCE_QUIZ:
+							$resource->title = api_to_system_encoding($resource->title, $this->encoding);
+							$resource->description = api_to_system_encoding($resource->description, $this->encoding);
+							break;
+
+						case RESOURCE_QUIZQUESTION:
+							$resource->question = api_to_system_encoding($resource->question, $this->encoding);
+							$resource->description = api_to_system_encoding($resource->description, $this->encoding);
+							if (is_array($resource->answers) && count($resource->answers) > 0) {
+								foreach ($resource->answers as $index => & $answer) {
+									$answer['answer'] = api_to_system_encoding($answer['answer'], $this->encoding);
+									$answer['comment'] = api_to_system_encoding($answer['comment'], $this->encoding);
+								}
+							}
+							break;
+
+						case RESOURCE_SCORM:
+							$resource->title = api_to_system_encoding($resource->title, $this->encoding);
+							break;
+
+						case RESOURCE_SURVEY:
+							$resource->title = api_to_system_encoding($resource->title, $this->encoding);
+							$resource->subtitle = api_to_system_encoding($resource->subtitle, $this->encoding);
+							$resource->author = api_to_system_encoding($resource->author, $this->encoding);
+							$resource->intro = api_to_system_encoding($resource->intro, $this->encoding);
+							$resource->surveythanks = api_to_system_encoding($resource->surveythanks, $this->encoding);
+							break;
+
+						case RESOURCE_SURVEYQUESTION:
+							$resource->survey_question = api_to_system_encoding($resource->survey_question, $this->encoding);
+							$resource->survey_question_comment = api_to_system_encoding($resource->survey_question_comment, $this->encoding);
+							break;
+
+						case RESOURCE_TOOL_INTRO:
+							$resource->intro_text = api_to_system_encoding($resource->intro_text, $this->encoding);
+							break;
+
+						case RESOURCE_WIKI:
+							$resource->title = api_to_system_encoding($resource->title, $this->encoding);
+							$resource->content = api_to_system_encoding($resource->content, $this->encoding);
+							$resource->reflink = api_to_system_encoding($resource->reflink, $this->encoding);
+							break;
+
+                        case RESOURCE_WORK:
+                            $resource->url = api_to_system_encoding($resource->url, $this->encoding);
                             $resource->title = api_to_system_encoding($resource->title, $this->encoding);
+                            $resource->description = api_to_system_encoding($resource->description, $this->encoding);
                             break;
-                        case RESOURCE_SURVEY:
-                            $resource->title        = api_to_system_encoding($resource->title, $this->encoding);
-                            $resource->subtitle     = api_to_system_encoding($resource->subtitle, $this->encoding);
-                            $resource->author       = api_to_system_encoding($resource->author, $this->encoding);
-                            $resource->intro        = api_to_system_encoding($resource->intro, $this->encoding);
-                            $resource->surveythanks = api_to_system_encoding($resource->surveythanks, $this->encoding);
-                            break;
-                        case RESOURCE_SURVEYQUESTION:
-                            $resource->survey_question         = api_to_system_encoding(
-                                $resource->survey_question,
-                                $this->encoding
-                            );
-                            $resource->survey_question_comment = api_to_system_encoding(
-                                $resource->survey_question_comment,
-                                $this->encoding
-                            );
-                            break;
-                        case RESOURCE_TOOL_INTRO:
-                            $resource->intro_text = api_to_system_encoding($resource->intro_text, $this->encoding);
-                            break;
-                        case RESOURCE_WIKI:
-                            $resource->title   = api_to_system_encoding($resource->title, $this->encoding);
-                            $resource->content = api_to_system_encoding($resource->content, $this->encoding);
-                            $resource->reflink = api_to_system_encoding($resource->reflink, $this->encoding);
-                            break;
-                        default:
-                            break;
-                    }
-                }
-            }
-        }
-        $this->encoding = api_get_system_encoding();
-    }
+						default:
+							break;
+					}
+				}
+			}
+		}
+		$this->encoding = api_get_system_encoding();
+	}
 
     /**
-     * Serialize the course with the best serializer available
-     */
+	* Serialize the course with the best serializer available
+	*/
     public static function serialize($course)
     {
-        if (extension_loaded('igbinary')) {
-            return igbinary_serialize($course);
-        } else {
-            return serialize($course);
+		if (extension_loaded('igbinary')) {
+			return igbinary_serialize($course);
+		} else {
+			return serialize($course);
         }
-    }
+	}
 
-    /**
-     * Unserialize the course with the best serializer available
-     */
+	/**
+	* Unserialize the course with the best serializer available
+	*/
     public static function unserialize($course)
     {
-        if (extension_loaded('igbinary')) {
-            return igbinary_unserialize($course);
-        } else {
-            return unserialize($course);
-        }
-    }
-}
+		if (extension_loaded('igbinary')) {
+			return igbinary_unserialize($course);
+		} else {
+			return unserialize($course);
+		}
+	}
+}

+ 16 - 6
main/coursecopy/classes/CourseArchiver.class.php

@@ -41,11 +41,11 @@ class CourseArchiver
         CourseArchiver::clean_backup_dir();
 
         // Create a temp directory
-        $tmp_dir_name = 'CourseArchiver_' . api_get_unique_id();
-        $backup_dir = api_get_path(SYS_ARCHIVE_PATH) . $tmp_dir_name . '/';
+        $tmp_dir_name = 'CourseArchiver_'.api_get_unique_id();
+        $backup_dir = api_get_path(SYS_ARCHIVE_PATH).$tmp_dir_name . '/';
 
         // All course-information will be stored in course_info.dat
-        $course_info_file = $backup_dir . 'course_info.dat';
+        $course_info_file = $backup_dir.'course_info.dat';
         $zip_dir = api_get_path(SYS_ARCHIVE_PATH);
         $user = api_get_user_info();
         $date = new DateTime(api_get_local_time());
@@ -72,7 +72,6 @@ class CourseArchiver
             error_log(__FILE__ . ' line ' . __LINE__ . ': ' . (ini_get('track_errors') != false ? $php_errormsg : 'error not recorded because track_errors is off in your php.ini'), 0);
         }
 
-
         // Copy all documents to the temp-dir
         if (isset($course->resources[RESOURCE_DOCUMENT]) && is_array($course->resources[RESOURCE_DOCUMENT])) {
             foreach ($course->resources[RESOURCE_DOCUMENT] as $document) {
@@ -120,6 +119,14 @@ class CourseArchiver
             FileManager::copyDirTo($course->path . 'upload/announcements/', $doc_dir, false);
         }
 
+        // Copy work folders (only folders)
+        if (isset($course->resources[RESOURCE_WORK]) && is_array($course->resources[RESOURCE_WORK])) {
+            $doc_dir = dirname($backup_dir . '/upload/work/');
+            @mkdir($doc_dir, $perm_dirs, true);
+            // @todo: adjust to only create subdirs, but not copy files
+            FileManager::copyDirTo($course->path . 'upload/work/', $doc_dir, false);
+        }
+
         // Zip the course-contents
         $zip = new PclZip($zip_dir . $zip_file);
         $zip->create($zip_dir . $tmp_dir_name, PCLZIP_OPT_REMOVE_PATH, $zip_dir . $tmp_dir_name . '/');
@@ -183,7 +190,8 @@ class CourseArchiver
         mkdir($unzip_dir, api_get_permissions_for_new_directories(), true);
         copy(api_get_path(SYS_ARCHIVE_PATH).$filename, $unzip_dir.'/backup.zip');
         // unzip the archive
-        $zip = new PclZip($unzip_dir . '/backup.zip');
+
+        $zip = new PclZip($unzip_dir.'/backup.zip');
         chdir($unzip_dir);
         $list = $zip->extract(PCLZIP_OPT_TEMP_FILE_ON);
 
@@ -192,17 +200,19 @@ class CourseArchiver
             $errorMessage = $zip->errorInfo(true);
             $app['session']->getFlashBag()->add('warning', $errorMessage);*/
         }
+
         // remove the archive-file
         if ($delete) {
             if (file_exists(api_get_path(SYS_ARCHIVE_PATH).$filename)) {
                 unlink(api_get_path(SYS_ARCHIVE_PATH).$filename);
-        }
+            }
         }
 
         // Read the course
         if (!is_file('course_info.dat')) {
             return new Course();
         }
+
         $contents = file_get_contents('course_info.dat');
         // CourseCopyLearnpath class appeared in Chamilo 1.8.7, it is the former Learnpath class in the "Copy course" tool.
         // For backward comaptibility with archives created on Chamilo 1.8.6.2 or older systems, we have to do the following:

File diff suppressed because it is too large
+ 622 - 662
main/coursecopy/classes/CourseBuilder.class.php


+ 37 - 22
main/coursecopy/classes/CourseRecycler.class.php

@@ -56,6 +56,7 @@ class CourseRecycler
         $this->recycle_glossary();
         $this->recycle_thematic();
         $this->recycle_attendance();
+        $this->recycle_work();
 
         foreach ($this->course->resources as $type => $resources) {
             foreach ($resources as $id => $resource) {
@@ -311,7 +312,7 @@ class CourseRecycler
             $table_qui 	   = Database :: get_course_table(TABLE_QUIZ_TEST);
             $table_rel 	   = Database :: get_course_table(TABLE_QUIZ_TEST_QUESTION);
             $table_qui_que_opt = Database :: get_course_table(TABLE_QUIZ_QUESTION_OPTION);
-            $table_qui_que_cat = Database :: get_course_table(TABLE_QUIZ_CATEGORY);
+            $table_qui_que_cat = Database :: get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
             $table_qui_que_rel_cat = Database :: get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
 
             $ids = array_keys($this->course->resources[RESOURCE_QUIZ]);
@@ -321,7 +322,7 @@ class CourseRecycler
             // This value is set in CourseBuilder::quiz_build_questions()
             $delete_orphan_questions = in_array(-1, $ids);
             $ids = implode(',', $ids);
-
+            
             if (!empty($ids)) {
                 // Deletion of the tests first. Questions in these tests are
                 //   not deleted and become orphan at this point
@@ -333,21 +334,7 @@ class CourseRecycler
 
             // Identifying again and deletion of the orphan questions, if it was desired.
             if ($delete_orphan_questions) {
-
-                /*$sql = 'SELECT questions.id '.
-                       ' FROM '.$table_qui_que.' as questions '.
-                       ' LEFT JOIN '.$table_rel.' as quizz_questions '.
-                       '   ON questions.id=quizz_questions.question_id '.
-                       ' LEFT JOIN '.$table_qui.' as exercices '.
-                       '   ON exercice_id=exercices.id '.
-                       ' WHERE '.
-                       '   questions.c_id = '.$this->course_id.' AND '.
-                       '   quizz_questions.c_id = '.$this->course_id.' AND '.
-                       '   exercices.c_id = '.$this->course_id.' AND '.
-                       '   quizz_questions.exercice_id IS NULL OR '.
-                       '   exercices.active = -1';
-                       // active = -1 means "deleted" test.
-                */
+               
 
                 //@todo fix query in order to use iid
                 $sql = " (
@@ -370,9 +357,8 @@ class CourseRecycler
                     SELECT q.iid FROM $table_qui_que q
                     INNER JOIN $table_rel r
                     ON (q.c_id = r.c_id AND q.iid = r.question_id)
-                    WHERE r.c_id = ".$this->course_id." AND r.exercice_id = '-1' OR r.exercice_id = '0'
+                    WHERE r.c_id = ".$this->course_id." AND (r.exercice_id = '-1' OR r.exercice_id = '0')
                 )";
-
                 $db_result = Database::query($sql);
                 if (Database::num_rows($db_result) > 0) {
                     $orphan_ids = array();
@@ -405,7 +391,8 @@ class CourseRecycler
     /**
      * Recycle surveys - removes everything
      */
-    function recycle_surveys() {
+    function recycle_surveys() 
+    {
         if ($this->course->has_resources(RESOURCE_SURVEY)) {
             $table_survey = Database :: get_course_table(TABLE_SURVEY);
             $table_survey_q = Database :: get_course_table(TABLE_SURVEY_QUESTION);
@@ -428,7 +415,8 @@ class CourseRecycler
     /**
      * Recycle learnpaths
      */
-    function recycle_learnpaths() {
+    function recycle_learnpaths() 
+    {
         if ($this->course->has_resources(RESOURCE_LEARNPATH)) {
             $table_main = Database :: get_course_table(TABLE_LP_MAIN);
             $table_item = Database :: get_course_table(TABLE_LP_ITEM);
@@ -527,7 +515,8 @@ class CourseRecycler
     /**
     * Recycle Attendances
     */
-    function recycle_attendance($session_id = 0) {
+    function recycle_attendance($session_id = 0) 
+    {
         if ($this->course->has_resources(RESOURCE_ATTENDANCE)) {
             $table_attendance          = Database :: get_course_table(TABLE_ATTENDANCE);
             $table_attendance_calendar = Database :: get_course_table(TABLE_ATTENDANCE_CALENDAR);
@@ -546,4 +535,30 @@ class CourseRecycler
             }
         }
     }
+
+    /**
+     * Recycle Works
+     */
+    function recycle_work($session_id = 0) 
+    {
+        if ($this->course->has_resources(RESOURCE_WORK)) {
+            $table_work          = Database :: get_course_table(TABLE_STUDENT_PUBLICATION);
+            $table_work_assignment = Database :: get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
+
+            $resources = $this->course->resources;
+            foreach ($resources[RESOURCE_WORK] as $last_id => $obj) {
+                if (is_numeric($last_id)) {
+                    $cond = array('publication_id = ? AND c_id = ? '=>array($last_id, $this->course_id));
+                    Database::delete($table_work_assignment, $cond);
+                    // The following also deletes student tasks
+                    $cond = array('parent_id = ? AND c_id = ?'=>array($last_id, $this->course_id));
+                    Database::delete($table_work, $cond);
+                    // Finally, delete the main task registry
+                    $cond = array('id = ? AND c_id = ?'=>array($last_id, $this->course_id));
+                    Database::delete($table_work, $cond);
+                    api_item_property_update($this->course_info, TOOL_STUDENTPUBLICATION, $last_id,'StudentPublicationDeleted', api_get_user_id());
+                }
+            }
+        }
+    }
 }

File diff suppressed because it is too large
+ 337 - 453
main/coursecopy/classes/CourseRestorer.class.php


+ 4 - 3
main/coursecopy/classes/CourseSelectForm.class.php

@@ -35,9 +35,10 @@ class CourseSelectForm
 		$resource_titles[RESOURCE_WIKI]                 = get_lang('Wiki');
 		$resource_titles[RESOURCE_THEMATIC]             = get_lang('Thematic');
 		$resource_titles[RESOURCE_ATTENDANCE]           = get_lang('Attendance');
+        $resource_titles[RESOURCE_WORK]                 = get_lang('ToolStudentPublication');
 
         $iconPath = api_get_path(WEB_IMG_PATH);
-        ?>
+?>
 		<script>
 			function exp(item) {
 				el = document.getElementById('div_'+item);
@@ -489,7 +490,7 @@ class CourseSelectForm
 							}
 					default :
 						if (!empty($resources) && is_array($resources)) {
-							foreach($resources as $id => $obj) {
+							foreach ($resources as $id => $obj) {
 								$resource_is_used_elsewhere = $course->is_linked_resource($obj);
                                 //var_dump($obj, $resource_is_used_elsewhere);
 								// check if document is in a quiz (audio/video)
@@ -563,7 +564,7 @@ class CourseSelectForm
 		<?php
 
 		//get destination course title
-		if (!empty($hidden_fields['destination_course'])) {
+		if(!empty($hidden_fields['destination_course'])) {
 			$course_infos = CourseManager::get_course_information($hidden_fields['destination_course']);
 			echo '<h3>';
 				echo get_lang('DestinationCourse').' : '.$course_infos['title'];

+ 4 - 1
main/coursecopy/classes/Resource.class.php

@@ -30,6 +30,7 @@ define('RESOURCE_SURVEYINVITATION', 'survey_invitation');
 define('RESOURCE_WIKI', 'wiki');
 define('RESOURCE_THEMATIC', 'thematic');
 define('RESOURCE_ATTENDANCE', 'attendance');
+define('RESOURCE_WORK', 'work');
 
 /**
  * Representation of a resource in a Chamilo-course.
@@ -190,6 +191,8 @@ class Resource
                 return TOOL_COURSE_PROGRESS;
             case RESOURCE_ATTENDANCE:
                 return TOOL_ATTENDANCE;
+            case RESOURCE_WORK:
+                return TOOL_STUDENTPUBLICATION;
             default:
                 return null;
         }
@@ -220,4 +223,4 @@ class Resource
     {
         //echo 'RESOURCE: '.$this->get_id().' '.$type[$this->get_type()].' ';
     }
-}
+}

+ 36 - 0
main/coursecopy/classes/Work.class.php

@@ -0,0 +1,36 @@
+<?php
+/* For licensing terms, see /license.txt */
+/**
+ * Work/Assignment/Student publication backup script
+ * @package chamilo.backup
+ */
+/**
+ * Code
+ */
+require_once 'Resource.class.php';
+/**
+ * An event
+ * @author Yannick Warnier <yannick.warnier@beeznest.com>
+ * @package chamilo.backup
+ */
+class Work extends Resource
+{
+    public $params = array();
+
+    /**
+     * Create a new Work
+     *
+     * @param array parameters
+     */
+    public function __construct($params)
+    {
+        parent::Resource($params['id'], RESOURCE_WORK);
+        $this->params = $params;
+    }
+
+    public function show()
+    {
+        parent::show();
+        echo $this->params['title'];
+    }
+}

+ 5 - 29
main/create_course/add_course.php

@@ -15,15 +15,9 @@
  * Code
  */
 
-// Name of the language file that needs to be included.
-$language_file = array('create_course', 'registration', 'admin', 'exercice', 'course_description', 'course_info');
-
 // Flag forcing the "current course" reset.
 $cidReset = true;
 
-// Including the global initialization file.
-require_once '../inc/global.inc.php';
-
 // Section for the tabs.
 $this_section = SECTION_COURSES;
 
@@ -36,23 +30,12 @@ $htmlHeadXtra[] = '<script>
     function setFocus(){
         $("#title").focus();
     }
+
     $(window).load(function () {
         setFocus();
+        $("#advanced_params_options").hide();
     });
 
-    function advanced_parameters() {
-        if(document.getElementById(\'options\').style.display == \'none\') {
-            document.getElementById(\'options\').style.display = \'block\';
-            document.getElementById(\'img_plus_and_minus\').innerHTML=\'&nbsp;'.Display::return_icon('div_hide.gif').'&nbsp;'.get_lang(
-    'AdvancedParameters'
-).'\';
-        } else {
-            document.getElementById(\'options\').style.display = \'none\';
-            document.getElementById(\'img_plus_and_minus\').innerHTML=\'&nbsp;'.Display::return_icon('div_show.gif').'&nbsp;'.get_lang(
-    'AdvancedParameters'
-).'\';
-        }
-    }
 </script>';
 
 $interbreadcrumb[] = array('url' => api_get_path(WEB_PATH).'user_portal.php', 'name' => get_lang('MyCourses'));
@@ -87,11 +70,9 @@ $form->addElement(
 $form->applyFilter('title', 'html_filter');
 $form->addRule('title', get_lang('ThisFieldIsRequired'), 'required');
 
-$advanced = '<a href="javascript://" onclick=" return advanced_parameters()"><span id="img_plus_and_minus"><div style="vertical-align:top;" >'.Display::return_icon('div_show.gif').'&nbsp;'.get_lang(
-    'AdvancedParameters'
-).'</div></span></a>';
-$form->addElement('advanced_settings', $advanced);
-$form->addElement('html', '<div id="options" style="display:none">');
+$form->addElement('advanced_settings', '<a class="btn btn-show advanced_parameters" id="advanced_params" href="javascript://">'.get_lang('AdvancedParameters').'</a>');
+
+$form->addElement('html', '<div id="advanced_params_options">');
 
 // Course category.
 $categories_select = $form->addElement(
@@ -115,10 +96,6 @@ $form->add_textfield(
 $form->applyFilter('wanted_code', 'html_filter');
 $form->addRule('wanted_code', get_lang('Max'), 'maxlength', CourseManager::MAX_COURSE_LENGTH_CODE);
 
-/*if ($course_validation_feature) {
-    $form->addRule('wanted_code', get_lang('ThisFieldIsRequired'), 'required');
-}*/
-
 // The teacher
 //get_lang('ExplicationTrainers')
 $titular = & $form->addElement(
@@ -213,7 +190,6 @@ if ($form->validate()) {
     $course_values = $form->exportValues();
 
     $wanted_code = $course_values['wanted_code'];
-    //$tutor_name         = $course_values['tutor_name'];
     $category_code = $course_values['category_code'];
     $title = $course_values['title'];
     $course_language = $course_values['course_language'];

+ 680 - 0
main/cron/import_csv.php

@@ -0,0 +1,680 @@
+<?php
+
+if (PHP_SAPI !='cli') {
+    die('Run this script through the command line or comment this line in the code');
+}
+
+//$_SERVER['SERVER_NAME'] = '';
+//$_SERVER['HTTP_HOST'] = '';
+
+require_once __DIR__.'/../inc/global.inc.php';
+require_once api_get_path(LIBRARY_PATH).'log.class.php';
+
+/**
+ * Class ImportCsv
+ */
+class ImportCsv
+{
+    private $logger;
+    private $dumpValues;
+    public $test;
+    public $defaultLanguage = 'dutch';
+    public $extraFieldIdNameList = array(
+        'session' => 'external_session_id',
+        'course' => 'external_course_id',
+        'user' => 'external_user_id',
+    );
+    public $defaultAdminId = 1;
+    public $defaultSessionVisibility = 1;
+
+    /**
+     * When creating a user the expiration date is set to registration date + this value
+     * @var int number of years
+     */
+    public $expirationDateInUserCreation = 1;
+
+    /**
+     * When updating a user the expiration date is set to update date + this value
+     * @var int number of years
+     */
+    public $expirationDateInUserUpdate = 1;
+    public $daysCoachAccessBeforeBeginning = 30;
+    public $daysCoachAccessAfterBeginning = 60;
+    public $conditions;
+
+    /**
+     * @param Logger $logger
+     */
+    public function __construct($logger, $conditions)
+    {
+        $this->logger = $logger;
+        $this->conditions = $conditions;
+    }
+
+    /**
+     * @param bool $dump
+     */
+    function setDumpValues($dump)
+    {
+        $this->dumpValues = $dump;
+    }
+
+    /**
+     * @return mixed
+     */
+    function getDumpValues()
+    {
+        return $this->dumpValues;
+    }
+
+    /**
+     * Runs the import process
+     */
+    public function run()
+    {
+        $path = api_get_path(SYS_CODE_PATH).'cron/incoming/';
+        if (!is_dir($path)) {
+            echo "The folder! $path does not exits";
+            exit;
+        }
+
+        if ($this->getDumpValues()) {
+            $this->dumpDatabaseTables();
+        }
+
+        echo "Starting with reading the files: ".PHP_EOL.PHP_EOL;
+
+        $files = scandir($path);
+        $fileToProcess = array();
+
+        if (!empty($files)) {
+            foreach ($files as $file) {
+                $fileInfo = pathinfo($file);
+                if ($fileInfo['extension'] == 'csv') {
+                    // teachers_yyyymmdd.csv, courses_yyyymmdd.csv, students_yyyymmdd.csv and sessions_yyyymmdd.csv
+                    $parts = explode('_', $fileInfo['filename']);
+                    $method = 'import'.ucwords($parts[1]);
+
+                    if (method_exists($this, $method)) {
+                         $fileToProcess[$parts[1]][] = array(
+                            'method' => $method,
+                            'file' => $path.$fileInfo['basename']
+                        );
+                        //$this->$method($path.$fileInfo['basename']);
+                    } else {
+                        echo "Error - This file '$file' can't be processed.".PHP_EOL;
+                        echo "The file have to has this format:".PHP_EOL;
+                        echo "prefix_students_ddmmyyyy.csv, prefix_teachers_ddmmyyyy.csv, prefix_courses_ddmmyyyy.csv, prefix_sessions_ddmmyyyy.csv ".PHP_EOL;
+                        exit;
+                    }
+                }
+            }
+
+            if (empty($fileToProcess)) {
+                echo 'Error - no files to process.';
+                exit;
+            }
+
+            $sections = array('students', 'teachers', 'courses', 'sessions');
+
+            $this->prepareImport();
+
+            foreach ($sections as $section) {
+                $this->logger->addInfo("-- Import $section --");
+
+                if (isset($fileToProcess[$section]) && !empty($fileToProcess[$section])) {
+                    $files = $fileToProcess[$section];
+                    foreach ($files as $fileInfo) {
+                        $method = $fileInfo['method'];
+                        $file = $fileInfo['file'];
+
+                        echo 'Reading file: '.$file.PHP_EOL;
+                        $this->logger->addInfo("Reading file: $file");
+
+                        $this->$method($file);
+                    }
+
+                }
+            }
+        }
+    }
+
+    private function prepareImport()
+    {
+        // Create user extra field: extra_external_user_id
+        UserManager::create_extra_field($this->extraFieldIdNameList['user'], 1, 'External user id', null);
+
+        // Create course extra field: extra_external_course_id
+        CourseManager::create_course_extra_field($this->extraFieldIdNameList['course'], 1, 'External course id');
+        // Create session extra field extra_external_session_id
+        SessionManager::create_session_extra_field($this->extraFieldIdNameList['session'], 1, 'External session id');
+    }
+
+    /**
+     * @param string $file
+     */
+    function moveFile($file)
+    {
+        $moved = str_replace('incoming', 'treated', $file);
+
+        if ($this->test) {
+            $result = 1;
+        } else {
+            $result = rename($file, $moved);
+        }
+
+        if ($result) {
+            $this->logger->addInfo("Moving file to the treated folder: $file");
+        } else {
+            $this->logger->addError("Error - Cant move file to the treated folder: $file");
+        }
+    }
+
+    /**
+     * @param array $row
+     *
+     * @return array
+     */
+    private function cleanUserRow($row)
+    {
+        $row['lastname'] = $row['LastName'];
+        $row['firstname'] = $row['FirstName'];
+        $row['email'] = $row['Email'];
+        $row['username'] = $row['UserName'];
+        $row['password'] = $row['Password'];
+        $row['auth_source'] = $row['AuthSource'];
+        $row['official_code'] = $row['OfficialCode'];
+        $row['phone'] = $row['PhoneNumber'];
+
+        if (isset($row['StudentID'])) {
+            $row['extra_'.$this->extraFieldIdNameList['user']] = $row['StudentID'];
+        }
+
+        if (isset($row['TeacherID'])) {
+            $row['extra_'.$this->extraFieldIdNameList['user']] = $row['TeacherID'];
+        }
+
+        //$row['lastname'] =  Status
+        return $row;
+    }
+
+    /**
+     * @param array $row
+     * @return array
+     */
+    private function cleanCourseRow($row)
+    {
+        $row['title'] = $row['Title'];
+        $row['course_code'] = $row['Code'];
+        $row['course_category'] = $row['CourseCategory'];
+        $row['email'] = $row['Teacher'];
+        $row['language'] = $row['Language'];
+
+        $row['teachers'] = array();
+        if (isset($row['Teacher']) && !empty($row['Teacher'])) {
+            $userInfo = api_get_user_info_from_username($row['Teacher']);
+            if (!empty($userInfo)) {
+                $row['teachers'] = $userInfo['user_id'];
+            }
+        }
+
+        if (isset($row['CourseID'])) {
+            $row['extra_'.$this->extraFieldIdNameList['course']] = $row['CourseID'];
+        }
+        return $row;
+    }
+
+    /**
+     * File to import
+     * @param string $file
+     */
+    private function importTeachers($file)
+    {
+        $data = Import::csv_to_array($file);
+
+        /* Unique identifier: official-code username.
+        Email address and password should never get updated. *ok
+        The only fields that I can think of that should update if the data changes in the csv file are FirstName and LastName. *ok
+        A slight edit of these fields should be taken into account. ???
+        Adding teachers is no problem, but deleting them shouldn’t be automated, but we should get a log of “to delete teachers”.
+        We’ll handle that manually if applicable.
+        No delete!
+        */
+        $language = $this->defaultLanguage;
+
+        if (!empty($data)) {
+            $this->logger->addInfo(count($data)." records found.");
+            foreach ($data as $row) {
+                $row = $this->cleanUserRow($row);
+
+                $user_id = UserManager::get_user_id_from_original_id($row['extra_'.$this->extraFieldIdNameList['user']], $this->extraFieldIdNameList['user']);
+                $userInfo  = array();
+                $userInfoByOfficialCode  = null;
+
+                if (!empty($user_id)) {
+                    $userInfo = api_get_user_info($user_id);
+                    //$userInfo = api_get_user_info_from_username($row['username']);
+                    $userInfoByOfficialCode = api_get_user_info_from_official_code($row['official_code']);
+                }
+
+                $expirationDate = api_get_utc_datetime(strtotime("+".intval($this->expirationDateInUserCreation)."years"));
+
+                if (empty($userInfo) && empty($userInfoByOfficialCode)) {
+                    // Create user
+                    $userId = UserManager::create_user(
+                        $row['firstname'],
+                        $row['lastname'],
+                        COURSEMANAGER,
+                        $row['email'],
+                        $row['username'],
+                        $row['password'],
+                        $row['official_code'],
+                        $language, //$row['language'],
+                        $row['phone'],
+                        null, //$row['picture'], //picture
+                        PLATFORM_AUTH_SOURCE, // ?
+                        $expirationDate, //'0000-00-00 00:00:00', //$row['expiration_date'], //$expiration_date = '0000-00-00 00:00:00',
+                        1, //active
+                        0,
+                        null, // extra
+                        null, //$encrypt_method = '',
+                        false //$send_mail = false
+                    );
+
+                    if ($userId) {
+                        foreach ($row as $key => $value) {
+                            if (substr($key, 0, 6) == 'extra_') { //an extra field
+                                UserManager::update_extra_field_value($userId, substr($key, 6), $value);
+                            }
+                        }
+                        $this->logger->addInfo("Teachers - User created: ".$row['username']);
+                    } else {
+                        $this->logger->addError("Teachers - User NOT created: ".$row['username']." ".$row['firstname']." ".$row['lastname']);
+                    }
+                } else {
+                    if (empty($userInfo)) {
+                        $this->logger->addError("Teachers - Can't update user :".$row['username']);
+                        continue;
+                    }
+
+                    $expirationDate = api_get_utc_datetime(strtotime("+".intval($this->expirationDateInUserUpdate)."years"));
+
+                    // Update user
+                    $result = UserManager::update_user(
+                        $userInfo['user_id'],
+                        $row['firstname'], // <<-- changed
+                        $row['lastname'],  // <<-- changed
+                        $userInfo['username'],
+                        null, //$password = null,
+                        $auth_source = null,
+                        $userInfo['email'],
+                        COURSEMANAGER,
+                        $userInfo['official_code'],
+                        $userInfo['phone'],
+                        $userInfo['picture_uri'],
+                        $expirationDate,
+                        $userInfo['active'],
+                        null, //$creator_id = null,
+                        0, //$hr_dept_id = 0,
+                        null, // $extra = null,
+                        null, //$language = 'english',
+                        null, //$encrypt_method = '',
+                        false, //$send_email = false,
+                        0 //$reset_password = 0
+                    );
+
+                    if ($result) {
+                        foreach ($row as $key => $value) {
+                            if (substr($key, 0, 6) == 'extra_') { //an extra field
+                                UserManager::update_extra_field_value($userInfo['user_id'], substr($key, 6), $value);
+                            }
+                        }
+                        $this->logger->addInfo("Teachers - User updated: ".$row['username']);
+                    } else {
+                        $this->logger->addError("Teachers - User not updated: ".$row['username']);
+                    }
+                }
+            }
+        }
+        $this->moveFile($file);
+    }
+
+    /**
+     * @param string $file
+     */
+    private function importStudents($file)
+    {
+        $data = Import::csv_to_array($file);
+
+        /*
+         * Another users import.
+        Unique identifier: official code and username . ok
+        Username and password should never get updated. ok
+        If an update should need to occur (because it changed in the .csv), we’ll want that logged. We will handle this manually in that case.
+        All other fields should be updateable, though passwords should of course not get updated. ok
+        If a user gets deleted (not there anymore),
+        He should be set inactive one year after the current date. So I presume you’ll just update the expiration date. We want to grant access to courses up to a year after deletion.
+         */
+
+        if (!empty($data)) {
+            $language = $this->defaultLanguage;
+            $this->logger->addInfo(count($data)." records found.");
+            foreach ($data as $row) {
+                $row = $this->cleanUserRow($row);
+                //$userInfo = api_get_user_info_from_username($row['username']);
+                $user_id = UserManager::get_user_id_from_original_id($row['extra_'.$this->extraFieldIdNameList['user']], $this->extraFieldIdNameList['user']);
+
+                $userInfo = array();
+                $userInfoByOfficialCode = null;
+                if (!empty($user_id)) {
+                    $userInfo = api_get_user_info($user_id);
+                    $userInfoByOfficialCode = api_get_user_info_from_official_code($row['official_code']);
+                }
+
+                $expirationDate = api_get_utc_datetime(strtotime("+".intval($this->expirationDateInUserCreation)."years"));
+
+                if (empty($userInfo) && empty($userInfoByOfficialCode)) {
+                    // Create user
+                    $result = UserManager::create_user(
+                        $row['firstname'],
+                        $row['lastname'],
+                        STUDENT,
+                        $row['email'],
+                        $row['username'],
+                        $row['password'],
+                        $row['official_code'],
+                        $language, //$row['language'],
+                        $row['phone'],
+                        null, //$row['picture'], //picture
+                        PLATFORM_AUTH_SOURCE, // ?
+                        $expirationDate, //'0000-00-00 00:00:00', //$row['expiration_date'], //$expiration_date = '0000-00-00 00:00:00',
+                        1, //active
+                        0,
+                        null, // extra
+                        null, //$encrypt_method = '',
+                        false //$send_mail = false
+                    );
+
+                    if ($result) {
+                        foreach ($row as $key => $value) {
+                            if (substr($key, 0, 6) == 'extra_') { //an extra field
+                                UserManager::update_extra_field_value($result, substr($key, 6), $value);
+                            }
+                        }
+                        $this->logger->addInfo("Students - User created: ".$row['username']);
+                    } else {
+                        $this->logger->addError("Students - User NOT created: ".$row['username']." ".$row['firstname']." ".$row['lastname']);
+                    }
+                } else {
+                    if (empty($userInfo)) {
+                        $this->logger->addError("Students - Can't update user :".$row['username']);
+                        continue;
+                    }
+
+                    if ($row['action'] == 'delete') {
+                        // INactive one year later
+                        $userInfo['expiration_date'] = api_get_utc_datetime(api_strtotime(time() + 365*24*60*60));
+                    }
+
+                    if (isset($this->conditions['importStudents'])) {
+                        if (isset($this->conditions['importStudents']['update']) && isset($this->conditions['importStudents']['update']['avoid'])) {
+                            $avoidUsersWithEmail = $this->conditions['importStudents']['update']['avoid']['email'];
+                            if ($userInfo['email'] != $row['email'] && in_array($row['email'], $avoidUsersWithEmail)) {
+                                $this->logger->addInfo("Students - User skipped: ".$row['username']." because the avoid conditions (email).");
+                                continue;
+                            }
+
+                            $avoidUsersWithPassword = $this->conditions['importStudents']['update']['avoid']['password'];
+
+                            if ($userInfo['password'] != api_get_encrypted_password($row['password']) && in_array($row['password'], $avoidUsersWithPassword)) {
+                                $this->logger->addInfo("Students - User skipped: ".$row['username']." because the avoid conditions (password).");
+                                continue;
+                            }
+                        }
+                    }
+
+                    $expirationDate = api_get_utc_datetime(strtotime("+".intval($this->expirationDateInUserUpdate)."years"));
+
+                    // Update user
+                    $result = UserManager::update_user(
+                        $userInfo['user_id'],
+                        $row['firstname'], // <<-- changed
+                        $row['lastname'],  // <<-- changed
+                        $userInfo['username'],
+                        null, //$password = null,
+                        $auth_source = null,
+                        $userInfo['email'],
+                        STUDENT,
+                        $userInfo['official_code'],
+                        $userInfo['phone'],
+                        $userInfo['picture_uri'],
+                        $expirationDate,
+                        $userInfo['active'],
+                        null, //$creator_id = null,
+                        0, //$hr_dept_id = 0,
+                        null, // $extra = null,
+                        null, //$language = 'english',
+                        null, //$encrypt_method = '',
+                        false, //$send_email = false,
+                        0 //$reset_password = 0
+                    );
+
+                    if ($result) {
+                        foreach ($row as $key => $value) {
+                            if (substr($key, 0, 6) == 'extra_') { //an extra field
+                                UserManager::update_extra_field_value($userInfo['user_id'], substr($key, 6), $value);
+                            }
+                        }
+
+                        $this->logger->addInfo("Students - User updated: ".$row['username']);
+                    } else {
+                        $this->logger->addError("Students - User NOT updated: ".$row['username']." ".$row['firstname']." ".$row['lastname']);
+                    }
+                }
+            }
+        }
+
+        $this->moveFile($file);
+    }
+
+    /**
+     * @param string $file
+     */
+    private function importCourses($file)
+    {
+        $data = Import::csv_to_array($file);
+
+        //$language = $this->defaultLanguage;
+
+        if (!empty($data)) {
+            $this->logger->addInfo(count($data)." records found.");
+
+            foreach ($data as $row) {
+                $row = $this->cleanCourseRow($row);
+                $courseCode = CourseManager::get_course_id_from_original_id($row['extra_'.$this->extraFieldIdNameList['course']], $this->extraFieldIdNameList['course']);
+
+                //$courseInfo = api_get_course_info($row['course_code']);
+                $courseInfo = api_get_course_info($courseCode);
+                if (empty($courseInfo)) {
+                    // Create
+                    $params = array();
+                    $params['title']                = $row['title'];
+                    $params['exemplary_content']    = false;
+                    $params['wanted_code']          = $row['course_code'];
+                    $params['course_category']      = $row['course_category'];
+                    $params['course_language']      = $row['language'];
+                    $params['teachers']             = $row['teachers'];
+
+                    $courseInfo = CourseManager::create_course($params);
+
+                    if (!empty($courseInfo)) {
+                        CourseManager::update_course_extra_field_value($courseInfo['code'], 'external_course_id', $row['extra_'.$this->extraFieldIdNameList['course']]);
+                        $this->logger->addInfo("Courses - Course created ".$courseInfo['code']);
+                    } else {
+                        $this->logger->addError("Courses - Can't create course:".$row['title']);
+                    }
+                } else {
+                    // Update
+                    $params = array(
+                        'title' => $row['title'],
+                    );
+                    $result = CourseManager::update_attributes($courseInfo['real_id'], $params);
+
+                    //CourseManager::updateTeachers($courseInfo['id'], $row['teachers']);
+
+                    if ($result) {
+                        $this->logger->addInfo("Courses - Course updated ".$courseInfo['code']);
+                    } else {
+                        $this->logger->addError("Courses - Course NOT updated ".$courseInfo['code']);
+                    }
+                }
+            }
+        }
+        $this->moveFile($file);
+    }
+
+    /**
+     * @param string $file
+     */
+    private function importSessions($file)
+    {
+        $result = SessionManager::importCSV(
+            $file,
+            true,
+            $this->defaultAdminId,
+            $this->logger,
+            array('SessionID' => 'extra_'.$this->extraFieldIdNameList['session']),
+            $this->extraFieldIdNameList['session'],
+            $this->daysCoachAccessBeforeBeginning,
+            $this->daysCoachAccessAfterBeginning,
+            $this->defaultSessionVisibility
+        );
+
+        if (!empty($result['error_message'])) {
+            $this->logger->addError($result['error_message']);
+        }
+        $this->logger->addInfo("Sessions - Sessions parsed: ".$result['session_counter']);
+        $this->moveFile($file);
+    }
+
+    private function dumpDatabaseTables()
+    {
+        echo 'Dumping tables'.PHP_EOL;
+
+        // User
+        $table = Database::get_main_table(TABLE_MAIN_USER);
+        $tableAdmin = Database::get_main_table(TABLE_MAIN_ADMIN);
+        //$sql = "DELETE FROM $table WHERE username NOT IN ('admin') AND lastname <> 'Anonymous' ";
+        $sql = "DELETE FROM $table WHERE user_id not in (select user_id from $tableAdmin) and status <> ".ANONYMOUS;
+        Database::query($sql);
+        echo $sql.PHP_EOL;
+
+        // Course
+        $table = Database::get_main_table(TABLE_MAIN_COURSE);
+        $sql = "DELETE FROM $table";
+        Database::query($sql);
+        echo $sql.PHP_EOL;
+
+        $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
+        $sql = "DELETE FROM $table";
+        Database::query($sql);
+        echo $sql.PHP_EOL;
+
+        $table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
+        $sql = "DELETE FROM $table";
+        Database::query($sql);
+        echo $sql.PHP_EOL;
+
+        $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
+        $sql = "DELETE FROM $table";
+        Database::query($sql);
+        echo $sql.PHP_EOL;
+
+        // Sessions
+        $table = Database::get_main_table(TABLE_MAIN_SESSION);
+        $sql = "DELETE FROM $table";
+        Database::query($sql);
+        echo $sql.PHP_EOL;
+
+        $table = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
+        $sql = "DELETE FROM $table";
+        Database::query($sql);
+        echo $sql.PHP_EOL;
+
+        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
+        $sql = "DELETE FROM $table";
+        Database::query($sql);
+        echo $sql.PHP_EOL;
+
+        $table = Database::get_main_table(TABLE_MAIN_SESSION_USER);
+        $sql = "DELETE FROM $table";
+        Database::query($sql);
+        echo $sql.PHP_EOL;
+
+        $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
+        $sql = "DELETE FROM $table";
+        Database::query($sql);
+        echo $sql.PHP_EOL;
+
+        // Extra fields
+        $table = Database::get_main_table(TABLE_MAIN_SESSION_FIELD_VALUES);
+        $sql = "DELETE FROM $table";
+        Database::query($sql);
+        echo $sql.PHP_EOL;
+
+        $table = Database::get_main_table(TABLE_MAIN_COURSE_FIELD_VALUES);
+        $sql = "DELETE FROM $table";
+        Database::query($sql);
+        echo $sql.PHP_EOL;
+
+        $table = Database::get_main_table(TABLE_MAIN_USER_FIELD_VALUES);
+        $sql = "DELETE FROM $table";
+        Database::query($sql);
+        echo $sql.PHP_EOL;
+    }
+}
+
+use Monolog\Logger;
+use Monolog\Handler\StreamHandler;
+use Monolog\Handler\NativeMailerHandler;
+use Monolog\Handler\RotatingFileHandler;
+use Monolog\Handler\BufferHandler;
+
+$logger = new Logger('cron');
+$emails = isset($_configuration['cron_notification_mails']) ? $_configuration['cron_notification_mails'] : null;
+
+$minLevel = Logger::DEBUG;
+
+if (!is_array($emails)) {
+    $emails = array($emails);
+}
+$subject = "Cron main/cron/import_csv.php ".date('Y-m-d h:i:s');
+$from = api_get_setting('emailAdministrator');
+
+if (!empty($emails)) {
+    foreach ($emails as $email) {
+        $stream = new NativeMailerHandler($email, $subject, $from, $minLevel);
+        $logger->pushHandler(new BufferHandler($stream, 0, $minLevel));
+    }
+}
+
+$stream = new StreamHandler(api_get_path(SYS_ARCHIVE_PATH).'import_csv.log', $minLevel);
+$logger->pushHandler(new BufferHandler($stream, 0, $minLevel));
+$logger->pushHandler(new RotatingFileHandler('import_csv', 5, $minLevel));
+
+$import = new ImportCsv($logger, $_configuration['cron_import_csv_conditions']);
+
+if (isset($_configuration['default_admin_user_id_for_cron'])) {
+    $import->defaultAdminId = $_configuration['default_admin_user_id_for_cron'];
+}
+// @todo in production disable the dump option
+$dump = false;
+
+if (isset($argv[1]) && $argv[1] = '--dump') {
+    $dump = true;
+}
+
+$import->setDumpValues($dump);
+// Do not moves the files to treated
+$import->test = true;
+$import->run();

+ 118 - 26
main/css/base.css

@@ -53,8 +53,6 @@ header #logo {
 }
 
 .subnav {
-    /*font-size: 11px;
-    font-weight: bold;*/
 }
 
 .subnav .btn-navbar {
@@ -541,6 +539,15 @@ a.tag {
     margin:0px 0px 10px 0px;    */
 }
 
+#course_category li,
+#hot_courses h5,
+.course_item h5,
+.course-box h5 {
+    font-size: 12px;
+    overflow-y : auto;
+    max-height:70px;
+    padding: 5px;
+}
 .session_box_title {
     margin-bottom: 7px;
 }
@@ -2127,28 +2134,6 @@ div.image-social-content center.friend {
     margin-right: 4px;
 }
 
-/*
-textarea {
-    border:1px solid #CCCCCC;
-    padding:5px;
-    -moz-border-radius:5px;
-    -webkit-border-radius:5px;
-    border-radius:5px;
-    color:#666666;
-}
-*/
-/*
-select {
-    color:#555;
-    border: 1px solid #CCC;
-    padding: 4px;
-    background-color: #F3F3F3;
-    font-size: 12px;
-
-    -moz-border-radius:5px;
-    -webkit-border-radius:5px;
-    border-radius:5px;
-}*/
 
 /* Fixes the FB input*/
 input.maininput:focus {
@@ -2887,7 +2872,11 @@ div.admin_section h4 {
 
 .question_options input {
     /* margin-right:10px; */
+}
 
+.question_options input[type="text"] {
+    padding:0px;
+    margin:2px 2px 2px 0px;
 }
 
 .question_description {
@@ -3805,6 +3794,20 @@ a:active {
     margin-right: 4px;
 }
 
+.send_msg_in_text {
+    background: url("send_msg.png") no-repeat scroll right center transparent;
+    height: 16px;
+    width: 17px;
+    display: inline-block;
+    margin-right: 4px;
+}
+.send_inv_in_text {
+    background: url("send_inv.png") no-repeat scroll right center transparent;
+    height: 16px;
+    width: 17px;
+    display: inline-block;
+    margin-right: 4px;
+}
 .teacher_online {
     background: url("teacher.png") no-repeat scroll right center transparent;
     height: 16px;
@@ -5310,12 +5313,101 @@ i.size-32.icon-new-work {
     padding: 7px 9px;
 }
 
+.question_no_title {
+    text-align: center;
+    font-size: larger;
+}
 
-.table td div.success {
-    background-color: #98E57F;
+.main_question .media .media-object {
+    font-weight: bold;
+    background-color: #ccc;
+    width:32px;
+    height:32px;
+    padding:8px 2px 0px 2px;
+    border-radius: 5px;
 }
 
+.main_question .media .question_description {
+    padding-top: 5px;
+}
+
+
+.btn-invitations {
+    margin-left: 110px;
+}
+.btn-msg {
+  background: url("send_msg.png") no-repeat left center;
+  background-position: 3px;
+  padding: 2px 4px;
+  padding-left: 22px;
+  margin-bottom: 10px;
+  font-size: 11px;
+  line-height: 14px;
+  background-color: #e6e6e6;
+}
+.btn-inv {
+  background: url("send_inv.png") no-repeat left center;
+  background-position: 3px;
+  padding: 2px 4px;
+  padding-left: 22px;
+  margin-bottom: 10px;
+  font-size: 11px;
+  line-height: 14px;
+  background-color: #e6e6e6;
+}
+.btn-inv-off {
+  background: url("send_inv_off.png") no-repeat left center;
+  background-position: 3px;
+  padding: 2px 4px;
+  padding-left: 22px;
+  margin-bottom: 10px;
+  font-size: 11px;
+  line-height: 14px;
+  background-color: #e6e6e6;
+}
+
+.password-verdict {
+    padding-left:5px;
+}
+#password_progress {
+    width: 220px;
+}
 
+.table td div.success {
+    background-color: #98E57F;
+}
 .table td.hover {
     background-color: rgba(255, 153, 0, 0.5);
 }
+
+.trajectory .control-group .btn-danger {
+    margin-top: -10px;
+    margin-left: 5px;
+}
+
+.trajectory ul {
+    margin-left: 0px;
+    list-style-type: none;
+}
+.trajectory .control-group {
+    /* margin-left: 25px; */
+}
+
+.trajectory .control-group label {
+}
+
+.trajectory .btn-group {
+    margin-top: -50px;
+    margin-right: -10px;
+    float: right;
+}
+
+#saveQuestionBar {
+    width:150px;
+    bottom:140px;
+    position:fixed;
+}
+
+.jqgrid_whitespace {
+    white-space: normal !important;
+}

BIN
main/css/chamilo_electric_blue/images/header-logo.png


BIN
main/css/chamilo_green/images/header-logo.png


BIN
main/css/chamilo_orange/images/header-logo.png


BIN
main/css/chamilo_red/images/header-logo.png


+ 538 - 0
main/css/digedd/dataTable.css

@@ -0,0 +1,538 @@
+/*
+ *  File:         demo_table.css
+ *  CVS:          $Id$
+ *  Description:  CSS descriptions for DataTables demo pages
+ *  Author:       Allan Jardine
+ *  Created:      Tue May 12 06:47:22 BST 2009
+ *  Modified:     $Date$ by $Author$
+ *  Language:     CSS
+ *  Project:      DataTables
+ *
+ *  Copyright 2009 Allan Jardine. All Rights Reserved.
+ *
+ * ***************************************************************************
+ * DESCRIPTION
+ *
+ * The styles given here are suitable for the demos that are used with the standard DataTables
+ * distribution (see www.datatables.net). You will most likely wish to modify these styles to
+ * meet the layout requirements of your site.
+ *
+ * Common issues:
+ *   'full_numbers' pagination - I use an extra selector on the body tag to ensure that there is
+ *     no conflict between the two pagination types. If you want to use full_numbers pagination
+ *     ensure that you either have "example_alt_pagination" as a body class name, or better yet,
+ *     modify that selector.
+ *   Note that the path used for Images is relative. All images are by default located in
+ *     images/dataTable/ - relative to this CSS file.
+ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * DataTables features
+ */
+
+.dataTables_wrapper {
+	position: relative;
+	min-height: 302px;
+	clear: both;
+	_height: 302px;
+	zoom: 1; /* Feeling sorry for IE */
+}
+
+.dataTables_processing {
+	position: absolute;
+	top: 50%;
+	left: 50%;
+	width: 250px;
+	height: 30px;
+	margin-left: -125px;
+	margin-top: -15px;
+	padding: 14px 0 2px 0;
+	border: 1px solid #ddd;
+	text-align: center;
+	color: #999;
+	font-size: 14px;
+	background-color: white;
+}
+
+.dataTables_length {
+	width: 40%;
+	float: left;
+}
+
+.dataTables_filter {
+	width: 50%;
+	float: right;
+	text-align: right;
+}
+
+.dataTables_info {
+	width: 60%;
+	float: left;
+}
+
+.dataTables_paginate {
+	width: 44px;
+	* width: 50px;
+	float: right;
+	text-align: right;
+}
+
+/* Pagination nested */
+.paginate_disabled_previous, .paginate_enabled_previous, .paginate_disabled_next, .paginate_enabled_next {
+	height: 19px;
+	width: 19px;
+	margin-left: 3px;
+	float: left;
+}
+
+.paginate_disabled_previous {
+	background-image: url('images/dataTale/back_disabled.jpg');
+}
+
+.paginate_enabled_previous {
+	background-image: url('images/dataTable/back_enabled.jpg');
+}
+
+.paginate_disabled_next {
+	background-image: url('images/dataTable/forward_disabled.jpg');
+}
+
+.paginate_enabled_next {
+	background-image: url('images/dataTable/forward_enabled.jpg');
+}
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * DataTables display
+ */
+table.display {
+	margin: 0 auto;
+	clear: both;
+	width: 100%;
+	
+	/* Note Firefox 3.5 and before have a bug with border-collapse
+	 * ( https://bugzilla.mozilla.org/show%5Fbug.cgi?id=155955 ) 
+	 * border-spacing: 0; is one possible option. Conditional-css.com is
+	 * useful for this kind of thing
+	 *
+	 * Further note IE 6/7 has problems when calculating widths with border width.
+	 * It subtracts one px relative to the other browsers from the first column, and
+	 * adds one to the end...
+	 *
+	 * If you want that effect I'd suggest setting a border-top/left on th/td's and 
+	 * then filling in the gaps with other borders.
+	 */
+}
+
+table.display thead th {
+	padding: 3px 18px 3px 10px;
+	border-bottom: 1px solid black;
+	font-weight: bold;
+	cursor: pointer;
+	* cursor: hand;
+}
+
+table.display tfoot th {
+	padding: 3px 18px 3px 10px;
+	border-top: 1px solid black;
+	font-weight: bold;
+}
+
+table.display tr.heading2 td {
+	border-bottom: 1px solid #aaa;
+}
+
+table.display td {
+	padding: 3px 10px;
+}
+
+table.display td.center {
+	text-align: center;
+}
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * DataTables sorting
+ */
+
+.sorting_asc {
+	background: url('images/dataTable/sort_asc.png') no-repeat center right;
+}
+
+.sorting_desc {
+	background: url('images/dataTable/sort_desc.png') no-repeat center right;
+}
+
+.sorting {
+	background: url('images/dataTable/sort_both.png') no-repeat center right;
+}
+
+.sorting_asc_disabled {
+	background: url('images/dataTable/sort_asc_disabled.png') no-repeat center right;
+}
+
+.sorting_desc_disabled {
+	background: url('images/dataTable/sort_desc_disabled.png') no-repeat center right;
+}
+
+
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * DataTables row classes
+ */
+table.display tr.odd.gradeA {
+	background-color: #ddffdd;
+}
+
+table.display tr.even.gradeA {
+	background-color: #eeffee;
+}
+
+table.display tr.odd.gradeC {
+	background-color: #ddddff;
+}
+
+table.display tr.even.gradeC {
+	background-color: #eeeeff;
+}
+
+table.display tr.odd.gradeX {
+	background-color: #ffdddd;
+}
+
+table.display tr.even.gradeX {
+	background-color: #ffeeee;
+}
+
+table.display tr.odd.gradeU {
+	background-color: #ddd;
+}
+
+table.display tr.even.gradeU {
+	background-color: #eee;
+}
+
+
+tr.odd {
+	background-color: #E2E4FF;
+}
+
+tr.even {
+	background-color: white;
+}
+
+
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Misc
+ */
+.dataTables_scroll {
+	clear: both;
+}
+
+.dataTables_scrollBody {
+	*margin-top: -1px;
+}
+
+.top, .bottom {
+	padding: 15px;
+	background-color: #F5F5F5;
+	border: 1px solid #CCCCCC;
+}
+
+.top .dataTables_info {
+	float: none;
+}
+
+.clear {
+	clear: both;
+}
+
+.dataTables_empty {
+	text-align: center;
+}
+
+tfoot input {
+	margin: 0.5em 0;
+	width: 100%;
+	color: #444;
+}
+
+tfoot input.search_init {
+	color: #999;
+}
+
+td.group {
+	background-color: #d1cfd0;
+	border-bottom: 2px solid #A19B9E;
+	border-top: 2px solid #A19B9E;
+}
+
+td.details {
+	background-color: #d1cfd0;
+	border: 2px solid #A19B9E;
+}
+
+
+.example_alt_pagination div.dataTables_info {
+	width: 40%;
+}
+
+.paging_full_numbers {
+	width: 400px;
+	height: 22px;
+	line-height: 22px;
+}
+
+.paging_full_numbers span.paginate_button,
+ 	.paging_full_numbers span.paginate_active {
+	border: 1px solid #aaa;
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	padding: 2px 5px;
+	margin: 0 3px;
+	cursor: pointer;
+	*cursor: hand;
+}
+
+.paging_full_numbers span.paginate_button {
+	background-color: #ddd;
+}
+
+.paging_full_numbers span.paginate_button:hover {
+	background-color: #ccc;
+}
+
+.paging_full_numbers span.paginate_active {
+	background-color: #99B3FF;
+}
+
+table.display tr.even.row_selected td {
+	background-color: #B0BED9;
+}
+
+table.display tr.odd.row_selected td {
+	background-color: #9FAFD1;
+}
+
+
+/*
+ * Sorting classes for columns
+ */
+/* For the standard odd/even */
+tr.odd td.sorting_1 {
+	background-color: #D3D6FF;
+}
+
+tr.odd td.sorting_2 {
+	background-color: #DADCFF;
+}
+
+tr.odd td.sorting_3 {
+	background-color: #E0E2FF;
+}
+
+tr.even td.sorting_1 {
+	background-color: #EAEBFF;
+}
+
+tr.even td.sorting_2 {
+	background-color: #F2F3FF;
+}
+
+tr.even td.sorting_3 {
+	background-color: #F9F9FF;
+}
+
+
+/* For the Conditional-CSS grading rows */
+/*
+ 	Colour calculations (based off the main row colours)
+  Level 1:
+		dd > c4
+		ee > d5
+	Level 2:
+	  dd > d1
+	  ee > e2
+ */
+tr.odd.gradeA td.sorting_1 {
+	background-color: #c4ffc4;
+}
+
+tr.odd.gradeA td.sorting_2 {
+	background-color: #d1ffd1;
+}
+
+tr.odd.gradeA td.sorting_3 {
+	background-color: #d1ffd1;
+}
+
+tr.even.gradeA td.sorting_1 {
+	background-color: #d5ffd5;
+}
+
+tr.even.gradeA td.sorting_2 {
+	background-color: #e2ffe2;
+}
+
+tr.even.gradeA td.sorting_3 {
+	background-color: #e2ffe2;
+}
+
+tr.odd.gradeC td.sorting_1 {
+	background-color: #c4c4ff;
+}
+
+tr.odd.gradeC td.sorting_2 {
+	background-color: #d1d1ff;
+}
+
+tr.odd.gradeC td.sorting_3 {
+	background-color: #d1d1ff;
+}
+
+tr.even.gradeC td.sorting_1 {
+	background-color: #d5d5ff;
+}
+
+tr.even.gradeC td.sorting_2 {
+	background-color: #e2e2ff;
+}
+
+tr.even.gradeC td.sorting_3 {
+	background-color: #e2e2ff;
+}
+
+tr.odd.gradeX td.sorting_1 {
+	background-color: #ffc4c4;
+}
+
+tr.odd.gradeX td.sorting_2 {
+	background-color: #ffd1d1;
+}
+
+tr.odd.gradeX td.sorting_3 {
+	background-color: #ffd1d1;
+}
+
+tr.even.gradeX td.sorting_1 {
+	background-color: #ffd5d5;
+}
+
+tr.even.gradeX td.sorting_2 {
+	background-color: #ffe2e2;
+}
+
+tr.even.gradeX td.sorting_3 {
+	background-color: #ffe2e2;
+}
+
+tr.odd.gradeU td.sorting_1 {
+	background-color: #c4c4c4;
+}
+
+tr.odd.gradeU td.sorting_2 {
+	background-color: #d1d1d1;
+}
+
+tr.odd.gradeU td.sorting_3 {
+	background-color: #d1d1d1;
+}
+
+tr.even.gradeU td.sorting_1 {
+	background-color: #d5d5d5;
+}
+
+tr.even.gradeU td.sorting_2 {
+	background-color: #e2e2e2;
+}
+
+tr.even.gradeU td.sorting_3 {
+	background-color: #e2e2e2;
+}
+
+
+/*
+ * Row highlighting example
+ */
+.ex_highlight #example tbody tr.even:hover, #example tbody tr.even td.highlighted {
+	background-color: #ECFFB3;
+}
+
+.ex_highlight #example tbody tr.odd:hover, #example tbody tr.odd td.highlighted {
+	background-color: #E6FF99;
+}
+
+.ex_highlight_row #example tr.even:hover {
+	background-color: #ECFFB3;
+}
+
+.ex_highlight_row #example tr.even:hover td.sorting_1 {
+	background-color: #DDFF75;
+}
+
+.ex_highlight_row #example tr.even:hover td.sorting_2 {
+	background-color: #E7FF9E;
+}
+
+.ex_highlight_row #example tr.even:hover td.sorting_3 {
+	background-color: #E2FF89;
+}
+
+.ex_highlight_row #example tr.odd:hover {
+	background-color: #E6FF99;
+}
+
+.ex_highlight_row #example tr.odd:hover td.sorting_1 {
+	background-color: #D6FF5C;
+}
+
+.ex_highlight_row #example tr.odd:hover td.sorting_2 {
+	background-color: #E0FF84;
+}
+
+.ex_highlight_row #example tr.odd:hover td.sorting_3 {
+	background-color: #DBFF70;
+}
+
+
+/*
+ * KeyTable
+ */
+table.KeyTable td {
+	border: 3px solid transparent;
+}
+
+table.KeyTable td.focus {
+	border: 3px solid #3366FF;
+}
+
+table.display tr.gradeA {
+	background-color: #eeffee;
+}
+
+table.display tr.gradeC {
+	background-color: #ddddff;
+}
+
+table.display tr.gradeX {
+	background-color: #ffdddd;
+}
+
+table.display tr.gradeU {
+	background-color: #ddd;
+}
+
+div.box {
+	height: 100px;
+	padding: 10px;
+	overflow: auto;
+	border: 1px solid #8080FF;
+	background-color: #E5E5FF;
+}

+ 201 - 0
main/css/digedd/default.css

@@ -0,0 +1,201 @@
+/*****************************************************
+ *  MAIN  - CHAMILO CSS
+ *****************************************************/
+
+/* Adding default style for the chamilo_X themes */
+@import url('../base_chamilo.css');
+
+/* the following for regular <a> elements */
+a {
+    text-decoration: none;
+    color :#3757f7
+}
+a:visited {
+    text-decoration: none;    
+}
+a:hover {
+    text-decoration: none;
+    color: #f3840d;
+}
+a:active {
+    text-decoration: none;
+    color : #3757f7;
+}
+
+.subnav .navbar-inner {
+    background-color: #00AAE3; /* Old browsers */
+    background-repeat: repeat-x; /* Repeat the gradient */
+    background-image: -moz-linear-gradient(top, #028DC2 0%, #00AAE3 100%); /* FF3.6+ */  
+    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#028DC2), color-stop(100%,#00AAE3)); /* Chrome,Safari4+ */
+    background-image: -webkit-linear-gradient(top, #028DC2 0%, #00AAE3 100%); /* Chrome 10+,Safari 5.1+ */
+    background-image: -ms-linear-gradient(top, #028DC2 0%,#00AAE3 100%); /* IE10+ */
+    background-image: -o-linear-gradient(top, #028DC2 0%,#00AAE3 100%); /* Opera 11.10+ */
+    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#028DC2', endColorstr='#00AAE3',GradientType=0 ); /* IE6-9 */
+    background-image: linear-gradient(top, #028DC2 0%,#00AAE3 100%); /* W3C */    
+}
+
+.subnav .nav > li > a {
+    border-left: 1px solid #0EA0D4;
+    border-right: 1px solid #0EA0D4;
+    color: white;
+}
+
+.subnav .nav > #current > a,
+.subnav .nav > #current > a:hover {  
+    color: #fff;
+    background-color: #028DC2;
+    border-right-color: #028DC2;  
+}
+
+.subnav li a {
+    color:#fff;
+}
+
+/* Green hover */
+.subnav .navbar-inner li a:hover {
+    background: none repeat scroll 0 0 #8ECB50;
+    color: #fff;
+}
+
+/*****************************************************
+ *  FOOTER STYLES                                    *
+ *****************************************************/
+footer {    
+    background-color: #037fb2;
+    background-image: url(images/bg-footer.gif);
+    background-repeat:repeat-x;    
+    color:#ffffff;    
+}
+
+/*****************************************************
+ *  DISPLAY MESSAGES	                             *
+ *****************************************************/
+.normal-message {
+    color: #00407F;
+    border: 1px solid #CDE6F5;
+    background: url("images/background_message.png") repeat-x scroll 0 0 #EAF8FE;
+}
+.warning-message {
+    border: 1px solid #FFB30F;
+    color: #000;
+	background: url("images/background_message.png") repeat-x scroll 0 0 #FFEFA7;
+}
+.confirmation-message {
+	border: 1px solid #1F8323;
+    color:#1F8323;
+	background: url("images/background_message.png") repeat-x scroll 0 0 #CAF0C7;
+}
+.error-message {
+    border: 1px solid #FF0000;
+    color: #440000;
+	background: url("images/background_message.png") repeat-x scroll 0 0 #FFD1D1;
+}
+
+.social-menu-title {
+	background-color:#00AAE3;
+}
+
+#social-content-online {
+    background-color:#00AAE3;
+}
+		
+.admin_section li {
+    background-image:url(images/bullet.gif);
+}
+
+.system_announcements {
+    background: transparent url('images/systemenouvelles.jpg') no-repeat top  left;
+}
+
+.topa {
+    background:transparent url('images/logoa4.gif') no-repeat;
+}
+.topb {
+    background:transparent url('images/logob4.gif') no-repeat;
+}
+
+#bottomhellomindfactory {    
+    background:transparent url('images/textologo.jpg') no-repeat;
+}
+
+/*including "login" image*/
+button.login {
+    background-image:url(images/bg-button.gif);
+}
+
+button.login:hover {
+}
+
+/*including "save" image*/
+button.save {
+    background-image:url(images/button_accept.gif);
+}
+/*including "add" image*/
+button.add {
+    background-image:url(images/button_add.gif);
+}
+/*including "cancel" image*/
+button.cancel {
+    background-image:url(images/button_delete.gif);
+}
+/*including "search" image*/
+button.search {
+    background-image:url(images/bg-button.gif);
+}
+/*including "plus" image*/
+button.plus {
+    background-image:url(images/button_plus.gif);
+}
+/*including "minus" image*/
+button.minus {
+    background-image:url(images/button_minus.gif);
+}
+/*including "next" image*/
+button.next {
+    background-image:url(images/button_next.gif) !important;
+}
+/*including "back" image*/
+button.back {
+    background-image:url(images/button_back.gif);
+}
+/*including "refresh" image*/
+button.refresh {
+    background-image:url(images/button_refresh.gif);
+}
+/*including "upload" image*/
+button.upload {
+    background-image:url(images/button_upload.gif);
+}
+
+button.arrowr, input.arrowr {
+	background-image:url(images/2rightarrow.gif);	
+}
+button.arrowl, input.arrowl {
+    background-image:url(images/2leftarrow.gif);	
+}
+.refresh {
+    background-image:url(images/refresh.png);
+}
+
+.portal {
+    background-image:url(images/portal.png);
+}
+#logo img {
+    max-width: 180%;
+}
+.exercise_progress_bars_cat {
+    width: 220px !important;
+}
+.exercise_progress_bars_cat_items {
+    width: 710px !important;
+}
+#exercise_progress_legend {
+  width:97%;
+  margin-top:20px;
+}
+#exercise_progress_legend .legend_static {
+  float:right;
+} 
+#exercise_progress_legend .legend_dynamic {
+  float:left;
+}

+ 983 - 0
main/css/digedd/frames.css

@@ -0,0 +1,983 @@
+body {
+	font-family: verdana, arial, helvetica, sans-serif;
+	font-size: 12px;
+	color: #000;
+	margin: 10px;
+	padding: 0;
+	background-color: #fff;
+}
+img {
+	border: none;
+}
+#outerframe {
+	position: relative;  /* do not remove, fixes a bug in IE */
+	border: 1px solid #fff;
+	background-color: #fff;
+}
+/* Hides from IE5-mac \*/
+* html #outerframe {
+	height: 1%;
+}
+/* End hide from IE5-mac */
+
+/***************************************************** 
+ *  HEADER STYLES                                    *
+ *****************************************************/
+#header {
+	width: 100%;
+	padding: 0;
+	margin: 0;
+}
+/* Header 1: Containing title, portal and organization */
+#header1 {
+	font-size: 12px;
+	padding: 4px;
+	background-color: #264269;
+	color: #fff;
+	border-bottom: 1px solid white;
+}
+#header1 a {
+	color: #ffffff;
+	text-decoration: none;
+}
+#header1 a:hover {
+	text-decoration: underline;
+}
+#sitename {
+	margin: 0;
+	font-weight: bold;
+}
+#institution {
+	float: left;
+	font-weight: bold;
+}
+#my_courses {
+	float: right;
+	font-weight: bold;
+}
+#logout {
+	float: right;
+	width:20%;
+	text-align:right;
+}
+
+/* The tool shortcuts */
+#toolshortcuts {
+	text-align: right;
+}
+/***************************************************** 
+ *  FOOTER STYLES                                    *
+ *****************************************************/
+#footer {
+	padding: 8px;
+	border-top: 1px solid #4171B5;
+	background-color: #E5EDF9;
+	font-size: 12px;
+}
+#footer .copyright {
+	float: right;
+}
+/***************************************************** 
+ *  MAIN STYLES                                      *
+ *****************************************************/
+#main {
+	position: relative; /* to avoid the IE peekabo bug*/
+	margin: 0px auto;
+	margin-top: 10px;
+	width: 98%;
+	padding: 0px 10px 10px 10px;
+	background-color: #fff;
+	min-height: 320px;
+}
+/* for content section in main index.php file */
+.maincontent {
+	float: left;
+	width: 78%;
+	padding: 4px;
+	background-color: #fff;
+}
+/* "menu" classes for menu/navigation section in main index.php  */
+.menu {
+	float: right;
+	width: 20%;
+	padding: 0 0 6px 0;
+	background-color: #E5EDF9;
+	border: 1px solid #4171B5;
+}
+.menucaption {
+	font-size: 12px;
+	font-weight: bold;
+	padding-left: 12px;
+}
+.menusection {
+	width: auto;
+	margin: 24px 6px 0 6px;
+	padding-left: 10px;
+	border: 1px solid #4171B5;
+}
+.menusectioncaption {
+	position: relative;
+	top: -9px;
+	background-color: #E5EDF9;
+	font-size: 12px;
+	padding: 0 8px 0 4px;
+}
+.menulist {
+	list-style: none;
+	margin: 0 0 12px 0;
+	padding: 0;
+}
+#lang_form {
+	text-align: left;
+	font-size: 12px;
+	margin: 2px 0 10px 0;
+	padding: 2px;
+}
+#lang_form input, #lang_form select {
+	font-size: 12px;
+}
+#loginform label {
+	font-size: 12px;
+	margin: 4px 6px;
+}
+#loginform input {
+	display: block;
+	font-size: 13px;
+	margin: 4px 6px;
+}
+#login_fail {
+	margin: 0 6px 6px 6px;
+	padding: 4px;
+	border: 1px solid #f00;
+	background-color: #fff;
+	font-size: 12px;
+	color: #f00;
+}
+/*** layout divs for course and tool pages (being tested in some pages) ****/  
+#contentfloatholder {/* also makes the right "sliding" tab  */
+	/*background: url(../pics/sidebar-r.gif) repeat-y 100% 0;
+background: url(../pics/bg_fountain.jpg) no-repeat 100% 0; */
+float: left;
+	width: 100%;
+	position: relative;
+}
+#contentfloatholder:after {
+	/* this is for NN6 to clear floats */
+content: ".";
+	display: block;
+	height: 0px;
+	clear: both;
+	visibility: hidden;
+}
+#centerwrap {
+	float: left;
+	width: 100%;
+	margin-right: -95%;/* this needs to be less than 100% for Moz/Mac which thinks 
+         it's empty otherwise. The difference is made up by putting a 
+         negative left margin on the left float:
+	   Note IE/Mac doesn't like this method ~ it wants the 100% so it can 
+	   be fed in using IE only CSS below becasue IE/Win also works with the 100% method.  
+	*/
+}
+#center {
+	margin: 0 0 0 180px;
+	padding: 10px 0 40px 0;
+	min-height: 300px;
+}
+#left {
+	float: left;
+	width: 180px;
+	padding: 20px 0 0 0;
+	margin-left: -5%; /* the difference to make the left colum appear flush left */
+}
+/* --- left navigation box menu as a definition list  --- */
+#leftnavbox {
+	margin: 0;
+	padding: 0;
+	float:left;
+}
+#leftnavbox dl {
+	width: 160px;
+	margin: 12px auto 4px auto;
+	padding: 0 0 10px 0;
+	background: transparent;
+	font-size: 12px;
+	text-align: center;
+}
+#leftnavbox dt {
+	margin: 0;
+	padding: 1px 2px;
+	font-weight: bold;
+	font-size: 12px;
+	text-align: center;
+	color: #000;
+	border-bottom: 1px solid #fff;
+	background: transparent;
+}
+#leftnavbox dd {
+	margin: 0;
+	padding: 0;
+	color: #009;
+	text-align: left;
+	border-bottom:1px solid #fff;
+	background: #ccf;
+}
+#leftnavlist a, #leftnavlist a:link {
+	display: block;
+	color: #fff;
+	text-decoration: none;
+	padding: 2px 5px 2px 10px;
+	background: #4171B5;
+	width:140px;
+	border: 1px solid #009;
+}
+#leftnavlist a:visited {
+	color:#eee;
+	text-decoration: none;
+	display: block;
+	padding: 2px 5px 2px 10px;
+	background: #4171B5;
+	color: #eee;
+	width:140px;
+}
+#leftnavlist a:hover {
+	background: #fff;
+	color:#4171B5;
+	display: block;
+}
+/* --- end of left side definition list menu section  --- */ 
+
+
+ 
+/* various sections in course-home.php file  */
+#toolremove {
+	width: 40%;
+	color: #f00;
+	font-weight: bold;
+	margin: 10px auto;
+	padding: 10px;
+	border: 2px solid #f00;
+}
+#courseintro {
+	clear: both;
+	width: 80%;
+	margin: 10px auto;
+	padding: 10px;
+	border-bottom: 1px solid #4171B5;
+}
+#courseintro_icons {
+	clear: both;
+	width: 80%;
+	margin: 10px auto;
+}
+.everybodyview {
+	position: relative; /* to avoid the IE peekabo bug ?*/
+	width: 80%;
+	margin: 10px auto;
+	padding: 10px;
+}
+.courseadminview, .platformadminview {
+	position: relative;
+	width: 80%;
+	margin: 25px auto 10px;
+	padding: 10px;
+	border: 1px solid #4171B5;
+}
+.viewcaption {
+	position: relative;
+	top: -20px;
+	font-size: 12px;
+	font-weight: bold;
+	color: #4171B5;
+	background-color: #fff;
+	padding: 0 4px;
+}
+/***********************************/
+
+/* ===================================================
+					AGENDA STYLES
+===================================================*/
+
+/* ---------------------------------------------------
+	check if these are still used or not
+-----------------------------------------------------*/
+#agenda {
+	width: 100%;
+	margin: 0 auto;
+	border: 1px solid #4171B5;
+	border-collapse: collapse;
+}
+.agenda_month_divider {
+	background-color: #4171B5;
+	font-weight: bold;
+	font-size: 12px;
+	color: #fff;
+	text-align: center;
+}
+#agenda #title a {
+	color: #fff;
+}
+#agenda .agendaitem {
+	font-size: 12px;
+}
+#smallcalendar #title {
+	background-color: #4171B5;
+	font-weight: bold;
+	padding: 2px;
+	color: #fff;
+	text-align: center;
+	font-size: 11px;
+}
+#smallcalendar #title a {
+	color: #fff;
+}
+#agenda_select {
+	list-style: none;
+	border: 0px solid green;
+	margin: 30px 0 0 0;
+	padding: 0 0 0 10px;
+}
+/* ---------------------------------------------------
+	styles for the agenda (day, week, month view)
+-----------------------------------------------------*/
+#agenda_list {
+	width: 100%;
+	margin: 0 auto;
+	border: 1px solid #fff;
+	border-collapse: collapse;
+}
+/*The caption of the calendar (displays the month and the << and >> links*/ 
+#agenda_list #title {
+	background-color: #4171B5;
+	font-weight: bold;
+	font-size: 12px;
+	color: #fff;
+	text-align: left;
+	padding: 2px 10px;
+	text-align: center;
+	border: 1px solid #264269;
+}
+#agenda_list #title a:link, #agenda_list #title a:visited {
+	background-color: #4171B5;
+	font-weight: bold;
+	font-size: 12px;
+	color: #fff;
+	text-align: left;
+	padding: 2px 10px;
+	text-align: center;
+}
+#agenda_list #title a:hover {
+	background-color: #4171B5;
+	font-weight: bold;
+	font-size: 12px;
+	color: #ff0000;
+	text-align: left;
+	padding: 2px 10px;
+	text-align: center;
+}
+/* The cells with the name of the days of the weeks (mon->sun)*/
+#agenda_list .weekdays {
+	background-color: #D3DFF1;
+	text-align: center;
+	font-weight: bold;
+	border: 1px solid #264269;
+	border-collapse: collapse;
+}
+/* The cells for the days (1->31) */ 
+#agenda_list .days_week {
+	height: 40px;
+	width: 12%;
+	text-align: left;
+	vertical-align: top;
+	border: 1px solid #264269;
+	border-collapse: collapse;
+	background-color: #f5f5f5;
+}
+#agenda_list .days_weekend {
+	height: 40px;
+	width: 12%;
+	text-align: left;
+	vertical-align: top;
+	border: 1px solid #264269;
+	border-collapse: collapse;
+	background-color: #e6e6e6;
+}
+#agenda_list .days_today {
+	height: 40px;
+	width: 12%;
+	text-align: left;
+	vertical-align: top;
+	border: 1px solid #264269;
+	border-collapse: collapse;
+	background-color: #FFCA8D;
+	color: #CC3300;
+	font-weight: bold;
+}
+/* text in the cells: display of agenda items (visible)*/
+#agenda_list .data {
+	background-color: #eee;
+	text-align: left;
+	padding: 2px 10px;
+	font-weight: bold;
+	border: 0px solid #4171B5;
+	border-collapse: collapse;
+}
+#agenda_list .datanotbold {
+	background-color: #eee;
+	text-align: left;
+	padding: 2px 10px;
+	font-weight: normal;
+	border: 0px solid #4171B5;
+	border-collapse: collapse;
+}
+#agenda_list .text {
+	background-color: #fff;
+	text-align: left;
+	padding: 2px 10px;
+	font-weight: normal;
+	border: 0px solid #4171B5;
+	border-collapse: collapse;
+}
+/*text in the cells: display of agenda items (invisible)*/   
+#agenda_list .data_hidden {
+	background-color: #eee;
+	text-align: left;
+	padding: 2px 10px;
+	font-weight: bold;
+	border: 0px solid #4171B5;
+	border-collapse: collapse;
+	color: #999999;
+}
+#agenda_list .datanotbold_hidden {
+	background-color: #eee;
+	text-align: left;
+	padding: 2px 10px;
+	font-weight: normal;
+	border: 0px solid #4171B5;
+	border-collapse: collapse;
+	color: #999999;
+}
+#agenda_list .text_hidden {
+	background-color: #fff;
+	text-align: left;
+	padding: 2px 10px;
+	font-weight: normal;
+	border: 0px solid #4171B5;
+	border-collapse: collapse;
+	color: #999999;
+}
+/*text in the cells: display of agenda items (highlighted)*/    
+#agenda_list .datanow {
+	background-color: #FFCC00;
+	text-align: left;
+	padding: 2px 10px;
+	font-weight: bold;
+	border: 0px solid #4171B5;
+	border-collapse: collapse;
+}
+#agenda_list .datanotboldnow {
+	background-color: #FFCC00;
+	text-align: left;
+	padding: 2px 10px;
+	font-weight: normal;
+	border: 0px solid #4171B5;
+	border-collapse: collapse;
+}
+#agenda_list .textnow {
+	background-color: #fff;
+	text-align: left;
+	padding: 2px 10px;
+	font-weight: normal;
+	border: 0px solid #4171B5;
+	border-collapse: collapse;
+}
+/* ---------------------------------------------------
+	styles for the mini agenda
+-----------------------------------------------------*/ 
+#smallcalendar {
+	width: 100%;
+	margin: 0 auto;
+	border: 1px solid #fff;
+	border-collapse: collapse;
+}
+#smallcalendar .weekdays {
+	background-color: #D3DFF1;
+	text-align: center;
+	font-size: 11px;
+	font-weight: bold;
+	border: 1px solid #fff;
+	border-collapse: collapse;
+}
+#smallcalendar .days_week {
+	background-color: #f5f5f5;
+	text-align: center;
+	font-size: 11px;
+	border-collapse: collapse;
+}
+#smallcalendar .days_weekend {
+	background-color: #e6e6e6;
+	text-align: center;
+	font-size: 11px;
+	border: 1px solid #fff;
+	border-collapse: collapse;
+}
+#smallcalendar .days_today {
+	width: 12%;
+	text-align: center;
+	font-size: 11px;
+	border: 1px solid #FA8500;
+	border-collapse: collapse;
+	background-color: #FFCA8D;
+}
+/* ---------------------------------------------------
+	styles for the personal agenda
+-----------------------------------------------------*/
+.personal_agenda {
+	color: #008000;
+}
+.personal_agenda a:link, .personal_agenda a:visited {
+	color: #008000;
+}
+a.personal_agenda:link, a.personal_agenda:visited {
+	color: #008000;
+}
+.personal_agenda a:hover, .personal_agenda a:hover {
+	color: #666666;
+}
+a.personal_agenda:hover, a.personal_agenda:hover {
+	color: #666666;
+}
+/* normal and erro message-box */
+.normal-message, .error-message {
+	position: relative;
+	margin: 10px auto;
+	margin-left: -250px;
+	width: 500px;
+	left: 50%;
+	right: 50%;
+	border-width: 1px;
+	border-style: solid;
+	padding: 5px;
+}
+.normal-message {
+	border: 1px solid #FF8001;
+	color: #000;
+	background-color: #FDC77E;
+}
+.error-message {
+	border: 1px solid #3F70AC;
+	color: #000;
+	background-color: #FDC273;
+}
+#message {
+	margin: 0 auto;
+	text-align: center;
+}
+#message select {
+	margin: 10px 0;
+	width: 220px;
+}
+#message textarea {
+	margin: 10px 0;
+}
+#message td {
+	padding: 4px;
+}
+/* styles from the document.php file */
+.comment {
+	margin-left: 30px;
+}
+.invisible {
+	color: #999;
+}
+.invisible a:link, .invisible a:visited {
+	color: #999;
+}
+a.invisible:link, a.invisible:visited {
+	color: #999;
+}
+/* styles from the upload.php file */
+dl.upload_option {
+	margin: 1em 0;
+	padding: 0;
+}
+.upload_option dt {
+	font-weight:bold;
+	margin:0;
+}
+.upload_option dd {
+	margin:0;
+}
+/* styles from dropbox.php file */
+.dropbox_detail {
+	font-size: small
+}
+.dropbox_date {
+	font-style: italic
+}
+.dropbox_person {
+	font-weight: bold
+}
+.dropbox_listTitle {
+	color: #000000;
+}
+.dropbox_feedback {
+	font-size: x-small;
+	height: 50px;
+	width: 200px;
+	overflow: auto
+}
+.dropbox_feedbacks {
+	height: 250px;
+	width: 100%;
+	overflow: auto
+}
+/* styles for chat / conference tools */
+#chat_entermessage {
+	background-color: #D6E5FA;
+	border-top: 1px solid #4171B5;
+	padding: 5px;
+	margin: 0;
+}
+/* styles for general formatting */
+.clear {
+	clear: both;
+	line-height: 0;
+	height: 0;
+}
+p, blockquote, ol, ul {
+	font-size: 12px;
+}
+h1 {
+	font-size: 21px;
+}
+h2 {
+	font-size: 18px;
+}
+h3 {
+	font-size: 15px;
+	margin-top:0px;
+	padding-top:0px;
+}
+h4 {
+	font-size: 12px;
+}
+h5, h6 {
+	font-family: verdana, arial, helvetica, sans-serif;
+}
+/* the following for regular <a> elements */
+a:link {
+	text-decoration: none;
+	font-weight : bold;
+	color : #4171b5;
+}
+a:visited {
+	text-decoration: none;
+	font-weight : bold;
+	color : #4171b5;
+}
+a:hover {
+	text-decoration: none;
+	color: red;
+	font-weight: bold
+}
+a:active {
+	text-decoration: none;
+	font-weight : bold;
+	color : #f00;
+}
+input.link_alike {
+	background-color: #FFFFFF;
+	border-width: 0px;
+	color: #4171b5;
+	font-weight: bold;
+	text-align: left;
+	padding: 0px;
+	margin: 0px;
+}
+input.link_alike:hover {
+	background-color: #FFFFFF;
+	border-width: 0px;
+	color: #FF0000;
+	font-weight: bold;
+	text-align: left;
+	padding: 0px;
+	margin: 0px;
+}
+/* the following for the greyed out elements */
+a.nobold:link, a.nobold:visited, a.nobold:active {
+	font-weight: normal;
+	color: #999;
+	margin: 0 0 0 25px;
+}
+a.nobold:hover {
+	font-weight: normal;
+	color: #999;
+	text-decoration: underline;
+	margin: 0 0 0 25px;
+}
+.note {
+	margin: 6px;
+	font-size: 12px;
+	line-height: 14px;
+	font-family: verdana, arial, helvetica, sans-serif;
+	background-color: #FFF089;
+	color: #4171B5;
+	border: 1px solid #4171B5;
+	padding: 4px;
+}
+.alternativeBgLight {
+	background-color: #f5f5f5;
+	border: 1px solid #4171B5;
+	border-collapse: collapse;
+}
+.alternativeBgDark {
+	background-color: #ccf;
+	border: 1px solid #4171B5;
+	border-collapse: collapse;
+}
+.myagendatoday {
+	background-color: #FFCA8D;
+	border-collapse: collapse;
+	font-family: verdana, arial, helvetica, sans-serif;
+	color: #CC3300;
+	font-weight: bold;
+}
+/* Form elements - some general styling*/
+select, textarea {
+	color : #000;
+	border: 1px solid #000;
+}
+input.checkbox {
+	border-width: 0;
+}
+input.mainoption {
+	font-weight : bold;
+}   /* Main submit button      */
+input.liteoption {
+	font-weight : normal;
+} /* None-bold submit button */
+select, input[type=checkbox], input[type=radio], input[type=button], input[type=submit] {
+	cursor:	pointer;
+	font-size: 12px;
+}
+input[text] {
+	font-size: 12px;
+}
+/************************************************************
+  styles below here are not necessarily used in the current
+	release and the CVS files, they are from earlier versions,
+	and have been left untouched for anyone needing them in
+	their own platform ...
+*************************************************************/
+.topBanner a:link, .topBanner a:active, .topBanner a:visited {
+	text-decoration:none;
+	color:white;
+}
+.topBanner table {
+	text-decoration:none;
+}
+.topBanner a:hover {
+	text-decoration:underline;
+}
+.topBanner td {
+	border-top: solid White 1px;
+}
+.alternativeBgLight {
+	background-color: #f5f5f5;
+}
+.alternativeBgDark {
+	background-color: #e6e6e6
+}
+.forms {
+	letter-spacing: normal;
+	text-align: justify;
+	text-indent: 3pt;
+	word-spacing: normal;
+	padding: 2px 5px;
+}
+.formsTips {
+	text-align: justify;
+	text-indent: 15pt;
+	word-spacing: normal;
+}
+/*
+input.forms	{ letter-spacing: normal; text-align: justify; text-indent: 3pt;	word-spacing: normal;
+padding-top: 0px;	padding-right: 0px;	padding-bottom: 0px;	padding-left: 0px;}
+*/
+.warn {
+	border: thin double Silver;
+	margin-left: 15px;
+	margin-right: 15px;
+	font-family: serif;
+	color: Red;
+	padding-left: 25px;
+}
+.small {
+	font-family: Verdana, Arial, Helvetica, sans-serif;
+	font-size: 11px
+}
+.xsmall {
+	font-family: Verdana, Arial, Helvetica, sans-serif;
+	font-size: 11px
+}
+.xxsmall {
+	font-family: Verdana, Arial, Helvetica, sans-serif;
+	font-size: 9px
+}
+/***************************************************** 
+ *  DATA TABLE STYLES                                *
+ *****************************************************/
+.cell_header {
+	background-color: #EEEEFF;
+	font-weight:bold;
+	text-align:left;
+	padding-left:5px;
+}   /* header cell in data table in tools */
+.data_table {
+	border-collapse: collapse;
+	width: 100%;
+	padding: 5px;
+}
+.data_table th {
+	padding-right: 20px;
+	border: 1px solid gray;
+	background-color: #E5EDF9;
+}
+.data_table tr.row_odd {
+	background-color: #fafafa;
+}
+.data_table tr.row_odd:hover, .data_table tr.row_even:hover {
+	background-color: #f0f0f0;
+}
+.data_table tr.row_even {
+	background-color: #fff;
+}
+.data_table td {
+	padding: 5px;
+	vertical-align: top;
+	border-bottom: 1px solid #b0b0b0;
+	border-right: 1px dotted #e1e1e1;
+	border-left: 1px dotted #e1e1e1;
+}
+/* admin page tool list definitions */
+.tool_list dt {
+	font-weight: bold;
+}
+.tool_list dd {
+	margin: 0;
+	padding: 4px 0 0 10px;
+}
+/* divs for category list / platform news on home page */
+.home_cats {
+	width: 45%;
+	float: left;
+	margin: 0;
+	padding: 0px;
+	padding-top: 8px;
+	background: #fff;
+}
+.home_news {
+	width: 45%;
+	float: right;
+	margin: 0;
+	padding: 0px;
+	padding-top: 8px;
+	background: #fff;
+}
+label.left {
+	float: left;
+	width: 15em;
+	margin: 0 0 0.5em 0;
+}
+form br {
+	clear: both;
+}
+/* Fix for alignment problem in IE-Win browsers  */
+/*  Hide from IE5-mac. Only IE-win sees this. \*/
+* html .label {
+	margin-right: 10px;
+}
+* html .data {
+	height: 1%;
+	margin-left: 0;
+}
+/* End hide from IE5/mac */
+
+.radio, .checkbox {
+	margin: 0;
+	padding: 0;
+	border: none;
+	background-color: transparent;
+}
+.required {
+	color: #f00;
+	font-weight: bold;
+}
+/* Admin section */
+div.admin_section {
+	width: 40%;
+	float: left;
+	padding: 5px;
+	margin: 10px 20px;
+}
+div.admin_section h4 {
+	margin: 0;
+	border-bottom: 1px solid gray;
+	width: 100%;
+}
+.user_course_category {
+	background-color: #efefef;
+	border: 1px solid #666;
+	font-weight: bold;
+	color: #666;
+	list-style-type: none;
+	margin: 5px;
+	padding: 5px;
+}
+/* Styles for the Dokeos Config Settings of the platform admin section*/
+.sectiontitle {
+	background-color: #EFEFEF;
+	border: 1px solid #cccccc;
+	font-weight: bold;
+	color: #666666;
+	list-style-type: none;
+	margin: 5px;
+	padding: 5px;
+	font-size: 11px;
+}
+.sectioncomment {
+	color: #000000;
+	margin: 5px;
+	padding: 5px;
+	font-size: 11px;
+}
+.sectionvalue {
+	list-style-type: none;
+	margin: 5px;
+	padding: 5px;
+}
+/* New Announcements Tool */
+.announcements_datum {
+	font-size: 12px;
+	font-weight: italic;
+	color: #666666;
+}
+/* System announcements on homepage */
+div.system_announcements {
+}
+div.system_announcements h3 {
+}
+div.system_announcements ul {
+	list-style-type: none;
+}
+div.system_announcement {
+	margin: 5px;
+}
+div.system_announcement_title {
+}
+div.system_announcement_content {
+	margin-left: 20px;
+	border-left: 1px solid gray;
+	padding-left: 5px;
+}

BIN
main/css/digedd/images/2leftarrow.gif


BIN
main/css/digedd/images/2rightarrow.gif


BIN
main/css/digedd/images/background_message.png


BIN
main/css/digedd/images/bar_1.gif


BIN
main/css/digedd/images/bar_1m.gif


BIN
main/css/digedd/images/bar_1r.gif


BIN
main/css/digedd/images/bar_1u.gif


BIN
main/css/digedd/images/bg-button.gif


BIN
main/css/digedd/images/bg-footer.gif


BIN
main/css/digedd/images/bg-header1.gif


BIN
main/css/digedd/images/bg-header4.png


BIN
main/css/digedd/images/bg-main.png


BIN
main/css/digedd/images/bg-menu.png


BIN
main/css/digedd/images/bgmenusup.png


BIN
main/css/digedd/images/bullet.gif


BIN
main/css/digedd/images/button_accept.gif


BIN
main/css/digedd/images/button_add.gif


BIN
main/css/digedd/images/button_back.gif


BIN
main/css/digedd/images/button_back.jpg


BIN
main/css/digedd/images/button_delete.gif


BIN
main/css/digedd/images/button_login.gif


BIN
main/css/digedd/images/button_minus.gif


BIN
main/css/digedd/images/button_next.gif


BIN
main/css/digedd/images/button_plus.gif


BIN
main/css/digedd/images/button_refresh.gif


BIN
main/css/digedd/images/button_search.gif


BIN
main/css/digedd/images/button_upload.gif


BIN
main/css/digedd/images/dataTable/Sorting icons.psd


BIN
main/css/digedd/images/dataTable/back_disabled.jpg


BIN
main/css/digedd/images/dataTable/back_enabled.jpg


BIN
main/css/digedd/images/dataTable/favicon.ico


BIN
main/css/digedd/images/dataTable/forward_disabled.jpg


BIN
main/css/digedd/images/dataTable/forward_enabled.jpg


BIN
main/css/digedd/images/dataTable/sort_asc.png


BIN
main/css/digedd/images/dataTable/sort_asc_disabled.png


BIN
main/css/digedd/images/dataTable/sort_both.png


BIN
main/css/digedd/images/dataTable/sort_desc.png


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