Forráskód Böngészése

Merge branch 'master' of git.beeznest.com:minedu-chamilo

Yannick Warnier 11 éve
szülő
commit
6455e7107d
100 módosított fájl, 2687 hozzáadás és 1100 törlés
  1. 3 2
      composer.json
  2. 338 286
      composer.lock
  3. 1 0
      config/profile.conf.dist.php
  4. 13 0
      config/routing.yml
  5. 14 22
      main/auth/profile.php
  6. 70 70
      main/course_home/vertical_activity.php
  7. 67 1
      main/css/base.css
  8. 47 9
      main/exercice/exercise.class.php
  9. 2 2
      main/exercice/exercise_show.php
  10. 2 2
      main/exercice/exercise_submit.php
  11. 17 15
      main/exercice/testcategory.class.php
  12. 4 2
      main/exercice/tests_category.php
  13. BIN
      main/img/icons/128/cv.png
  14. BIN
      main/img/icons/32/cv.png
  15. BIN
      main/img/icons/32/cv_na.png
  16. BIN
      main/img/icons/64/cv.png
  17. BIN
      main/img/icons/64/cv_na.png
  18. 32 7
      main/inc/Entity/CQuizCategory.php
  19. 6 4
      main/inc/ajax/exercise.ajax.php
  20. 5 2
      main/inc/global.inc.php
  21. 6 1
      main/inc/lib/announcements.inc.php
  22. 144 53
      main/inc/lib/api.lib.php
  23. 1 0
      main/inc/lib/course.lib.php
  24. 68 52
      main/inc/lib/course_home.lib.php
  25. 1 1
      main/inc/lib/online.inc.php
  26. 4 1
      main/inc/lib/page.lib.php
  27. 2 2
      main/inc/lib/social.lib.php
  28. 16 12
      main/inc/lib/template.lib.php
  29. 2 1
      main/inc/lib/usermanager.lib.php
  30. 3 22
      main/inc/routes.php
  31. 38 13
      main/inc/services.php
  32. 1 0
      main/install/1.10.0/db_course.sql
  33. 1 1
      main/template/default/admin/administrator/branches/add.tpl
  34. 1 1
      main/template/default/admin/administrator/juries/add.tpl
  35. 1 1
      main/template/default/admin/administrator/juries/edit.tpl
  36. 1 1
      main/template/default/admin/administrator/question_score/add.tpl
  37. 1 1
      main/template/default/admin/administrator/question_score/edit.tpl
  38. 1 1
      main/template/default/admin/administrator/question_score_name/add.tpl
  39. 1 1
      main/template/default/admin/administrator/question_score_name/edit.tpl
  40. 1 1
      main/template/default/admin/administrator/question_score_name/list.tpl
  41. 1 1
      main/template/default/admin/administrator/question_score_name/read.tpl
  42. 1 1
      main/template/default/admin/administrator/role/add.tpl
  43. 1 1
      main/template/default/admin/administrator/role/edit.tpl
  44. 1 1
      main/template/default/admin/administrator/role/list.tpl
  45. 1 1
      main/template/default/admin/administrator/role/read.tpl
  46. 51 0
      main/template/default/crud_macros/course_crud.tpl
  47. 0 0
      main/template/default/crud_macros/simple_crud.tpl
  48. 2 2
      main/template/default/layout/error.tpl
  49. 21 12
      main/template/default/layout/menu.tpl
  50. 2 2
      main/template/default/tool/curriculum/category/add.tpl
  51. 2 2
      main/template/default/tool/curriculum/category/add_from_parent.tpl
  52. 2 2
      main/template/default/tool/curriculum/category/edit.tpl
  53. 1 1
      main/template/default/tool/curriculum/category/list.tpl
  54. 4 2
      main/template/default/tool/curriculum/category/read.tpl
  55. 2 2
      main/template/default/tool/curriculum/item/add.tpl
  56. 2 2
      main/template/default/tool/curriculum/item/add_from_category.tpl
  57. 2 2
      main/template/default/tool/curriculum/item/edit.tpl
  58. 4 4
      main/template/default/tool/curriculum/item/list.tpl
  59. 4 2
      main/template/default/tool/curriculum/item/read.tpl
  60. 2 2
      main/template/default/tool/curriculum/user/add.tpl
  61. 2 2
      main/template/default/tool/curriculum/user/add_from_category.tpl
  62. 2 2
      main/template/default/tool/curriculum/user/edit.tpl
  63. 14 10
      main/template/default/tool/curriculum/user/list.tpl
  64. 4 2
      main/template/default/tool/curriculum/user/read.tpl
  65. 3 3
      src/ChamiloLMS/Controller/Admin/Administrator/BranchController.php
  66. 4 4
      src/ChamiloLMS/Controller/Admin/Administrator/JuryController.php
  67. 2 2
      src/ChamiloLMS/Controller/Admin/Administrator/QuestionScoreController.php
  68. 3 3
      src/ChamiloLMS/Controller/Admin/Administrator/QuestionScoreNameController.php
  69. 3 3
      src/ChamiloLMS/Controller/Admin/Administrator/RoleController.php
  70. 1 1
      src/ChamiloLMS/Controller/Admin/Director/BranchDirectorController.php
  71. 14 23
      src/ChamiloLMS/Controller/BaseController.php
  72. 2 10
      src/ChamiloLMS/Controller/CommonController.php
  73. 3 3
      src/ChamiloLMS/Controller/IndexController.php
  74. 18 18
      src/ChamiloLMS/Controller/Tool/Curriculum/CurriculumCategoryController.php
  75. 3 6
      src/ChamiloLMS/Controller/Tool/Curriculum/CurriculumItemController.php
  76. 3 3
      src/ChamiloLMS/Controller/Tool/Curriculum/CurriculumUserController.php
  77. 1 1
      src/ChamiloLMS/Form/CurriculumItemRelUserType.php
  78. 34 15
      src/ChamiloLMS/Provider/ReflectionControllerProvider.php
  79. 3 0
      src/ChamiloLMS/Resources/config/route_example.yml
  80. 1 1
      vendor/autoload.php
  81. 13 0
      vendor/composer/autoload_files.php
  82. 1 0
      vendor/composer/autoload_namespaces.php
  83. 6 7
      vendor/composer/autoload_real.php
  84. 384 349
      vendor/composer/installed.json
  85. 77 0
      vendor/flint/flint/CHANGELOG.md
  86. 19 0
      vendor/flint/flint/LICENSE
  87. 12 0
      vendor/flint/flint/README.md
  88. 37 0
      vendor/flint/flint/composer.json
  89. BIN
      vendor/flint/flint/doc/_static/peytzco.jpg
  90. 253 0
      vendor/flint/flint/doc/conf.py
  91. 304 0
      vendor/flint/flint/doc/index.rst
  92. 55 0
      vendor/flint/flint/src/Flint/Application.php
  93. 80 0
      vendor/flint/flint/src/Flint/Config/Configurator.php
  94. 77 0
      vendor/flint/flint/src/Flint/Config/Loader/JsonFileLoader.php
  95. 39 0
      vendor/flint/flint/src/Flint/Config/Normalizer/ChainNormalizer.php
  96. 33 0
      vendor/flint/flint/src/Flint/Config/Normalizer/EnvironmentNormalizer.php
  97. 15 0
      vendor/flint/flint/src/Flint/Config/Normalizer/NormalizerInterface.php
  98. 62 0
      vendor/flint/flint/src/Flint/Config/Normalizer/PimpleAwareNormalizer.php
  99. 40 0
      vendor/flint/flint/src/Flint/Config/ResourceCollection.php
  100. 39 0
      vendor/flint/flint/src/Flint/Console/Application.php

+ 3 - 2
composer.json

@@ -39,7 +39,7 @@
     ],
     "require": {
         "php": ">=5.3.2",
-        "silex/silex": "~1.0",
+        "silex/silex": "1.*",
         "symfony/console"  : "~2.3",
         "symfony/twig-bridge": "~2.3",
         "symfony/doctrine-bridge": "2.3.*@dev",
@@ -76,7 +76,8 @@
         "bt51/gaufrette-serviceprovider": "dev-master",
         "neutron/silex-filesystem-provider": "dev-master",
         "jbroadway/urlify": "dev-master",
-        "sensio/framework-extra-bundle": "2.3.*@dev"
+        "sensio/framework-extra-bundle": "2.3.*@dev",
+        "flint/flint" : "~1.4"
     },
     "require-dev": {
         "symfony/browser-kit": "2.3.*@dev",

+ 338 - 286
composer.lock

@@ -3,7 +3,7 @@
         "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",
+    "hash": "4a9f7f6b12b57b152e87183d9cf86a50",
     "packages": [
         {
             "name": "bt51/gaufrette-serviceprovider",
@@ -447,6 +447,57 @@
             ],
             "time": "2013-02-18 00:04:08"
         },
+        {
+            "name": "flint/flint",
+            "version": "1.4.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/henrikbjorn/Flint.git",
+                "reference": "1.4.1"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/henrikbjorn/Flint/zipball/1.4.1",
+                "reference": "1.4.1",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3",
+                "silex/silex": "~1.0",
+                "symfony/config": "~2.2",
+                "twig/twig": "~1.10"
+            },
+            "replace": {
+                "henrikbjorn/flint": "self.version"
+            },
+            "require-dev": {
+                "symfony/console": "~2.2"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.4.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Flint": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Henrik Bjornskov",
+                    "email": "henrik@bjrnskov.dk",
+                    "homepage": "http://henrik.bjrnskov.dk"
+                }
+            ],
+            "description": "Enhanced Silex",
+            "time": "2013-07-04 09:26:29"
+        },
         {
             "name": "franmomu/silex-pagerfanta-provider",
             "version": "2.3.x-dev",
@@ -1391,18 +1442,65 @@
             "description": "A fork of the popular pChart library.",
             "time": "2013-03-18 08:23:38"
         },
+        {
+            "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/silex",
-            "version": "v1.0.0",
+            "version": "v1.0.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/fabpot/Silex.git",
-                "reference": "v1.0.0"
+                "reference": "v1.0.1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/fabpot/Silex/zipball/v1.0.0",
-                "reference": "v1.0.0",
+                "url": "https://api.github.com/repos/fabpot/Silex/zipball/v1.0.1",
+                "reference": "v1.0.1",
                 "shasum": ""
             },
             "require": {
@@ -1415,7 +1513,7 @@
             },
             "require-dev": {
                 "doctrine/dbal": ">=2.2.0,<2.4.0-dev",
-                "monolog/monolog": ">=1.4,<2.0,>=1.4.1",
+                "monolog/monolog": "~1.4,>=1.4.1",
                 "swiftmailer/swiftmailer": "5.*",
                 "symfony/browser-kit": ">=2.1,<2.4-dev",
                 "symfony/config": ">=2.1,<2.4-dev",
@@ -1471,7 +1569,7 @@
             "keywords": [
                 "microframework"
             ],
-            "time": "2013-05-03 16:49:57"
+            "time": "2013-07-04 06:25:40"
         },
         {
             "name": "swiftmailer/swiftmailer",
@@ -1625,25 +1723,25 @@
         },
         {
             "name": "symfony/debug",
-            "version": "v2.3.1",
+            "version": "v2.3.3",
             "target-dir": "Symfony/Component/Debug",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/Debug.git",
-                "reference": "v2.3.1"
+                "reference": "v2.3.3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Debug/zipball/v2.3.1",
-                "reference": "v2.3.1",
+                "url": "https://api.github.com/repos/symfony/Debug/zipball/v2.3.3",
+                "reference": "v2.3.3",
                 "shasum": ""
             },
             "require": {
                 "php": ">=5.3.3"
             },
             "require-dev": {
-                "symfony/http-foundation": ">=2.1,<3.0",
-                "symfony/http-kernel": ">=2.1,<3.0"
+                "symfony/http-foundation": "~2.1",
+                "symfony/http-kernel": "~2.1"
             },
             "suggest": {
                 "symfony/class-loader": "",
@@ -1677,7 +1775,7 @@
             ],
             "description": "Symfony Debug Component",
             "homepage": "http://symfony.com",
-            "time": "2013-06-02 11:58:44"
+            "time": "2013-07-01 12:24:43"
         },
         {
             "name": "symfony/dependency-injection",
@@ -1803,24 +1901,24 @@
         },
         {
             "name": "symfony/event-dispatcher",
-            "version": "v2.3.1",
+            "version": "v2.3.3",
             "target-dir": "Symfony/Component/EventDispatcher",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/EventDispatcher.git",
-                "reference": "v2.3.1"
+                "reference": "v2.3.3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/v2.3.1",
-                "reference": "v2.3.1",
+                "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/v2.3.3",
+                "reference": "v2.3.3",
                 "shasum": ""
             },
             "require": {
                 "php": ">=5.3.3"
             },
             "require-dev": {
-                "symfony/dependency-injection": ">=2.0,<3.0"
+                "symfony/dependency-injection": "~2.0"
             },
             "suggest": {
                 "symfony/dependency-injection": "",
@@ -1853,7 +1951,7 @@
             ],
             "description": "Symfony EventDispatcher Component",
             "homepage": "http://symfony.com",
-            "time": "2013-05-13 14:36:40"
+            "time": "2013-07-21 12:12:18"
         },
         {
             "name": "symfony/filesystem",
@@ -1962,20 +2060,90 @@
             "time": "2013-06-02 12:05:51"
         },
         {
-            "name": "symfony/http-foundation",
+            "name": "symfony/framework-bundle",
             "version": "v2.3.1",
-            "target-dir": "Symfony/Component/HttpFoundation",
+            "target-dir": "Symfony/Bundle/FrameworkBundle",
             "source": {
                 "type": "git",
-                "url": "https://github.com/symfony/HttpFoundation.git",
+                "url": "https://github.com/symfony/FrameworkBundle.git",
                 "reference": "v2.3.1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/v2.3.1",
+                "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/http-foundation",
+            "version": "v2.3.3",
+            "target-dir": "Symfony/Component/HttpFoundation",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/HttpFoundation.git",
+                "reference": "v2.3.3"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/v2.3.3",
+                "reference": "v2.3.3",
+                "shasum": ""
+            },
             "require": {
                 "php": ">=5.3.3"
             },
@@ -2009,40 +2177,41 @@
             ],
             "description": "Symfony HttpFoundation Component",
             "homepage": "http://symfony.com",
-            "time": "2013-05-10 06:00:03"
+            "time": "2013-08-07 14:02:06"
         },
         {
             "name": "symfony/http-kernel",
-            "version": "v2.3.1",
+            "version": "v2.3.3",
             "target-dir": "Symfony/Component/HttpKernel",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/HttpKernel.git",
-                "reference": "v2.3.1"
+                "reference": "v2.3.3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/HttpKernel/zipball/v2.3.1",
-                "reference": "v2.3.1",
+                "url": "https://api.github.com/repos/symfony/HttpKernel/zipball/v2.3.3",
+                "reference": "v2.3.3",
                 "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"
+                "psr/log": "~1.0",
+                "symfony/debug": "~2.3",
+                "symfony/event-dispatcher": "~2.1",
+                "symfony/http-foundation": "~2.2"
             },
             "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"
+                "symfony/browser-kit": "~2.2",
+                "symfony/class-loader": "~2.1",
+                "symfony/config": "~2.0",
+                "symfony/console": "~2.2",
+                "symfony/dependency-injection": "~2.0",
+                "symfony/finder": "~2.0",
+                "symfony/process": "~2.0",
+                "symfony/routing": "~2.2",
+                "symfony/stopwatch": "~2.2",
+                "symfony/templating": "~2.2"
             },
             "suggest": {
                 "symfony/browser-kit": "",
@@ -2079,7 +2248,7 @@
             ],
             "description": "Symfony HttpKernel Component",
             "homepage": "http://symfony.com",
-            "time": "2013-06-11 11:46:38"
+            "time": "2013-08-07 17:11:16"
         },
         {
             "name": "symfony/icu",
@@ -2305,17 +2474,17 @@
         },
         {
             "name": "symfony/options-resolver",
-            "version": "v2.3.1",
+            "version": "v2.3.3",
             "target-dir": "Symfony/Component/OptionsResolver",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/OptionsResolver.git",
-                "reference": "v2.3.1"
+                "reference": "v2.3.3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/OptionsResolver/zipball/v2.3.1",
-                "reference": "v2.3.1",
+                "url": "https://api.github.com/repos/symfony/OptionsResolver/zipball/v2.3.3",
+                "reference": "v2.3.3",
                 "shasum": ""
             },
             "require": {
@@ -2353,7 +2522,7 @@
                 "configuration",
                 "options"
             ],
-            "time": "2013-04-11 06:50:46"
+            "time": "2013-07-21 12:12:18"
         },
         {
             "name": "symfony/property-access",
@@ -2415,27 +2584,27 @@
         },
         {
             "name": "symfony/routing",
-            "version": "v2.3.1",
+            "version": "v2.3.3",
             "target-dir": "Symfony/Component/Routing",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/Routing.git",
-                "reference": "v2.3.1"
+                "reference": "v2.3.3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Routing/zipball/v2.3.1",
-                "reference": "v2.3.1",
+                "url": "https://api.github.com/repos/symfony/Routing/zipball/v2.3.3",
+                "reference": "v2.3.3",
                 "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"
+                "doctrine/common": "~2.2",
+                "psr/log": "~1.0",
+                "symfony/config": "~2.2",
+                "symfony/yaml": "~2.0"
             },
             "suggest": {
                 "doctrine/common": "",
@@ -2469,7 +2638,7 @@
             ],
             "description": "Symfony Routing Component",
             "homepage": "http://symfony.com",
-            "time": "2013-05-20 08:57:26"
+            "time": "2013-08-02 20:53:38"
         },
         {
             "name": "symfony/security",
@@ -2539,6 +2708,100 @@
             "homepage": "http://symfony.com",
             "time": "2013-06-02 22:50:02"
         },
+        {
+            "name": "symfony/stopwatch",
+            "version": "v2.3.3",
+            "target-dir": "Symfony/Component/Stopwatch",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/Stopwatch.git",
+                "reference": "v2.3.3"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/v2.3.3",
+                "reference": "v2.3.3",
+                "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-07-21 12:12:18"
+        },
+        {
+            "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/translation",
             "version": "v2.3.1",
@@ -3086,53 +3349,6 @@
             ],
             "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",
@@ -3235,24 +3451,24 @@
         },
         {
             "name": "symfony/dom-crawler",
-            "version": "v2.3.1",
+            "version": "v2.3.3",
             "target-dir": "Symfony/Component/DomCrawler",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/DomCrawler.git",
-                "reference": "v2.3.1"
+                "reference": "v2.3.3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/DomCrawler/zipball/v2.3.1",
-                "reference": "v2.3.1",
+                "url": "https://api.github.com/repos/symfony/DomCrawler/zipball/v2.3.3",
+                "reference": "v2.3.3",
                 "shasum": ""
             },
             "require": {
                 "php": ">=5.3.3"
             },
             "require-dev": {
-                "symfony/css-selector": ">=2.0,<3.0"
+                "symfony/css-selector": "~2.0"
             },
             "suggest": {
                 "symfony/css-selector": ""
@@ -3284,21 +3500,21 @@
             ],
             "description": "Symfony DomCrawler Component",
             "homepage": "http://symfony.com",
-            "time": "2013-06-11 07:15:14"
+            "time": "2013-07-21 12:12:18"
         },
         {
             "name": "symfony/finder",
-            "version": "v2.2.3",
+            "version": "v2.2.5",
             "target-dir": "Symfony/Component/Finder",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/Finder.git",
-                "reference": "v2.2.3"
+                "reference": "v2.2.5"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Finder/zipball/v2.2.3",
-                "reference": "v2.2.3",
+                "url": "https://api.github.com/repos/symfony/Finder/zipball/v2.2.5",
+                "reference": "v2.2.5",
                 "shasum": ""
             },
             "require": {
@@ -3331,91 +3547,21 @@
             ],
             "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"
+            "time": "2013-07-01 12:15:46"
         },
         {
             "name": "symfony/process",
-            "version": "v2.3.1",
+            "version": "v2.3.3",
             "target-dir": "Symfony/Component/Process",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/Process.git",
-                "reference": "v2.3.1"
+                "reference": "v2.3.3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Process/zipball/v2.3.1",
-                "reference": "v2.3.1",
+                "url": "https://api.github.com/repos/symfony/Process/zipball/v2.3.3",
+                "reference": "v2.3.3",
                 "shasum": ""
             },
             "require": {
@@ -3448,101 +3594,7 @@
             ],
             "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"
+            "time": "2013-08-02 21:51:01"
         },
         {
             "name": "symfony/web-profiler-bundle",
@@ -3625,13 +3677,13 @@
         "bt51/gaufrette-serviceprovider": 20,
         "neutron/silex-filesystem-provider": 20,
         "jbroadway/urlify": 20,
+        "sensio/framework-extra-bundle": 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
+        "filp/whoops": 20
     },
     "platform": {
         "php": ">=5.3.2"

+ 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.

+ 13 - 0
config/routing.yml

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

+ 14 - 22
main/auth/profile.php

@@ -17,6 +17,10 @@ $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 {
@@ -72,7 +76,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']));
@@ -87,15 +90,15 @@ if (!empty($_GET['fe'])) {
 $jquery_ready_content = '';
 if (api_get_setting('allow_message_tool') == 'true') {
     $jquery_ready_content = <<<EOF
-			$(".message-content .message-delete").click(function(){
-				$(this).parents(".message-content").animate({ opacity: "hide" }, "slow");
-				$(".message-view").animate({ opacity: "show" }, "slow");
-			});
+    $(".message-content .message-delete").click(function(){
+        $(this).parents(".message-content").animate({ opacity: "hide" }, "slow");
+        $(".message-view").animate({ opacity: "show" }, "slow");
+    });
 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 +191,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 +215,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 +241,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 +301,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 +347,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 +371,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
 */

+ 70 - 70
main/course_home/vertical_activity.php

@@ -4,66 +4,66 @@
 /**
  *   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()) {   
-    $content .=  '<div class="courseadminview" style="border:0px; margin-top: 0px;padding:5px;">
+if (api_is_allowed_to_edit(null, true) && !api_is_coach()) {
+    $content .= '<div class="courseadminview" style="border:0px; margin-top: 0px;padding:5px;">
     <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 +72,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 +87,48 @@ 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">';
-		//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;
+        //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;
 
-		$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>';

+ 67 - 1
main/css/base.css

@@ -5310,6 +5310,66 @@ i.size-32.icon-new-work {
     padding: 7px 9px;
 }
 
+.question_no_title {
+    text-align: center;
+}
+
+.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;
@@ -5330,15 +5390,21 @@ i.size-32.icon-new-work {
     list-style-type: none;
 }
 .trajectory .control-group {
-    margin-left: 25px;
+    /* 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;
 }
+

+ 47 - 9
main/exercice/exercise.class.php

@@ -775,7 +775,7 @@ class Exercise
                     }
                 }
             }
-            }
+        }
 
         if (!empty($questions_by_category)) {
             $temp_question_list = array();
@@ -795,7 +795,7 @@ class Exercise
 
                 if (!empty($numberOfQuestions)) {
                     $elements = Testcategory::getNElementsFromArray($categoryQuestionList, $numberOfQuestions, $randomizeQuestions);
-                if (!empty($elements)) {
+                    if (!empty($elements)) {
                         $temp_question_list[$category_id] = $elements;
                         $categoryQuestionList = $elements;
                     }
@@ -832,6 +832,7 @@ class Exercise
         $cat = new Testcategory();
 
         // Setting category order.
+
         switch ($questionSelectionType) {
             case EX_Q_SELECTION_ORDERED: // 1
             case EX_Q_SELECTION_RANDOM:  // 2
@@ -864,12 +865,12 @@ class Exercise
             case EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_RANDOM_NO_GROUPED: // 8
                 break;
             case EX_Q_SELECTION_CATEGORIES_ORDERED_BY_PARENT_QUESTIONS_ORDERED: // 9
-                $categoriesAddedInExercise = $cat->getCategoryExerciseTree($this->id, $this->course['real_id'], 'root ASC', false, true);
+                $categoriesAddedInExercise = $cat->getCategoryExerciseTree($this->id, $this->course['real_id'], 'root ASC, lft ASC', false, true);
                 $questions_by_category = Testcategory::getQuestionsByCat($this->id, $question_list, $categoriesAddedInExercise);
                 $question_list = $this->pickQuestionsPerCategory($categoriesAddedInExercise, $question_list, $questions_by_category, true, false);
                 break;
             case EX_Q_SELECTION_CATEGORIES_ORDERED_BY_PARENT_QUESTIONS_RANDOM: // 10
-                $categoriesAddedInExercise = $cat->getCategoryExerciseTree($this->id, $this->course['real_id'], 'root ASC', false, true);
+                $categoriesAddedInExercise = $cat->getCategoryExerciseTree($this->id, $this->course['real_id'], 'root, lft ASC', false, true);
                 $questions_by_category = Testcategory::getQuestionsByCat($this->id, $question_list, $categoriesAddedInExercise);
                 $question_list = $this->pickQuestionsPerCategory($categoriesAddedInExercise, $question_list, $questions_by_category, true, true);
                 break;
@@ -903,11 +904,39 @@ class Exercise
                     } else {
                         $categoryEntity = $parentsLoaded[$cat['parent_id']];
                     }
+
                     $path = $repo->getPath($categoryEntity);
+
                     $index = 0;
                     if ($this->categoryMinusOne) {
-                        $index = 1;
+                        //$index = 1;
                     }
+                    /** @var Entity\CQuizCategory $categoryParent*/
+
+                    foreach ($path as $categoryParent) {
+                        $visibility = $categoryParent->getVisibility();
+
+                        if ($visibility == 0) {
+                            $categoryParentId = $categoryId;
+                            $categoryTitle = $cat['title'];
+                            if (count($path) > 1) {
+                                continue;
+                            }
+                        } else {
+                            $categoryParentId = $categoryParent->getIid();
+                            $categoryTitle = $categoryParent->getTitle();
+                        }
+
+                        $categoryParentInfo['id'] = $categoryParentId;
+                        $categoryParentInfo['iid'] = $categoryParentId;
+                        $categoryParentInfo['parent_path'] = null;
+                        $categoryParentInfo['title'] = $categoryTitle;
+                        $categoryParentInfo['name'] = $categoryTitle;
+                        $categoryParentInfo['parent_id'] = null;
+                        break;
+                    }
+
+                    /*
                     if (isset($path) && isset($path[$index])) {
                         $categoryParentId = $path[$index]->getIid();
 
@@ -917,7 +946,7 @@ class Exercise
                         $categoryParentInfo['title'] = $path[$index]->getTitle();
                         $categoryParentInfo['name'] = $path[$index]->getTitle();
                         $categoryParentInfo['parent_id'] = null;
-                    }
+                    }*/
                 }
                 $cat['parent_info'] = $categoryParentInfo;
                 $newCategoryList[$categoryId] = array(
@@ -2592,7 +2621,6 @@ class Exercise
 
             $original_exercise->copy_exercise_categories($exercise_obj);
 
-            //$question_list = $exercise_obj->selectQuestionList(true);
             $question_list = $exercise_obj->getQuestionListWithMediasUncompressed();
 
             if (!empty($question_list)) {
@@ -5988,6 +6016,8 @@ class Exercise
             $selectionType = $this->getQuestionSelectionType();
             $useRootAsCategoryTitle = false;
 
+            // Grouping questions per parent category see BT#6540
+
             if (in_array(
                 $selectionType,
                 array(
@@ -6007,11 +6037,19 @@ class Exercise
                 // The new categories list starts empty
                 $newCategoryList = array();
                 foreach ($categories as $category) {
-                    if ($this->categoryMinusOne) {
+                    /*if ($this->categoryMinusOne) {
                         $rootElement = $category['id'];
                     } else {
-                        $rootElement = $category['root'];
+
+                    }*/
+
+                    $rootElement = $category['root'];
+
+                    if (isset($category['parent_info'])) {
+                        $rootElement = $category['parent_info']['id'];
                     }
+
+                    //$rootElement = $category['id'];
                     // If the current category's ancestor was never seen
                     // before, then declare it and assign the current
                     // category to it.

+ 2 - 2
main/exercice/exercise_show.php

@@ -501,7 +501,7 @@ foreach ($questionList as $questionId) {
                 echo '<p>'.$comment.'</p>';
             }
 
-            // Showing the score
+            // Showing the score.
             $queryfree = "select marks from ".$TBL_TRACK_ATTEMPT." WHERE exe_id = '".Database::escape_string($id)."' and question_id= '".Database::escape_string($questionId)."'";
             $resfree = Database::query($queryfree);
             $questionScore= Database::result($resfree,0,"marks");
@@ -725,7 +725,7 @@ if (!empty($category_list) && ($show_results || $show_only_total_score)) {
         'score' => $my_total_score_temp,
         'total' => $totalWeighting
     );
-    echo Testcategory::get_stats_table_by_attempt($objExercise->id, $category_list);
+    echo Testcategory::get_stats_table_by_attempt($objExercise->id, $category_list, $objExercise->categoryMinusOne);
 }
 
 echo $total_score_text;

+ 2 - 2
main/exercice/exercise_submit.php

@@ -362,7 +362,7 @@ if (!isset($exerciseInSession) || isset($exerciseInSession) && ($exerciseInSessi
 
     // if the specified exercise doesn't exist or is disabled
     if (!$objExercise->read($exerciseId) || (!$objExercise->selectStatus() && !$is_allowedToEdit && ($origin != 'learnpath'))) {
-    	if ($debug) {
+        if ($debug) {
             error_log('1.1. Error while reading the exercise');
         }
         unset ($objExercise);
@@ -376,7 +376,7 @@ if (!isset($exerciseInSession) || isset($exerciseInSession) && ($exerciseInSessi
     }
 }
 
-// $objExercise = new Exercise(); $objExercise->read($exerciseId);
+//$objExercise = new Exercise(); $objExercise->read($exerciseId);
 
 //2. Checking if $objExercise is set
 if (!isset($objExercise) && isset($exerciseInSession)) {

+ 17 - 15
main/exercice/testcategory.class.php

@@ -16,6 +16,7 @@ class Testcategory
     public $course_id;
     public $c_id; // from db
     public $root;
+    public $visibility;
 
     /**
      * Constructor of the class Category
@@ -31,7 +32,7 @@ class Testcategory
      * @param string $type
      * @param int $course_id
      */
-    public function Testcategory($in_id = 0, $in_name = '', $in_description = "", $parent_id = 0, $type = 'simple', $course_id = null)
+    public function Testcategory($in_id = 0, $in_name = '', $in_description = "", $parent_id = 0, $type = 'simple', $course_id = null, $visibility = 1)
     {
 		if ($in_id != 0 && $in_name == "") {
 			$tmpobj = new Testcategory();
@@ -44,6 +45,7 @@ class Testcategory
             $this->parent_path = $this->name;
             $this->c_id = $tmpobj->c_id;
             $this->root = $tmpobj->root;
+            $this->visibility = $tmpobj->visibility;
 
             if (!empty($tmpobj->parent_id)) {
                 $category = new Testcategory($tmpobj->parent_id);
@@ -54,10 +56,11 @@ class Testcategory
 			$this->name = $in_name;
 			$this->description = $in_description;
             $this->parent_id = $parent_id;
+            $this->visibility = $visibility;
         }
         $this->type = $type;
 
-        if (!empty($course_id))  {
+        if (!empty($course_id)) {
             $this->course_id = $course_id;
 		} else {
             $this->course_id = api_get_course_int_id();
@@ -89,6 +92,7 @@ class Testcategory
             $this->parent_id = $row['parent_id'];
             $this->c_id = $row['c_id'];
             $this->root = $row['root'];
+            $this->visibility = $row['visibility'];
 
         } else {
             return false;
@@ -169,6 +173,7 @@ class Testcategory
 
         $category->setTitle($this->name);
         $category->setDescription($this->description);
+        $category->setVisibility($this->visibility);
 
         if (!empty($this->parent_id)) {
             foreach ($this->parent_id as $parentId) {
@@ -690,8 +695,7 @@ class Testcategory
                 WHERE   exercice_id = $exerciseId AND
                         qrc.c_id = ".api_get_course_int_id()."
                 ";
-
-		$res = Database::query($sql);
+        $res = Database::query($sql);
         $categories = array();
 
 		while ($data = Database::fetch_array($res)) {
@@ -715,7 +719,6 @@ class Testcategory
                 $newCategoryList[$categoryId] = $categories[$categoryId];
             }
         }
-
         return $newCategoryList;
     }
 
@@ -956,8 +959,6 @@ class Testcategory
         $em = $app['orm.em'];
         $repo = $em->getRepository('Entity\CQuizCategory');
 
-        $redefineCategoryList = array();
-
         if (!empty($category_list) && count($category_list) > 1) {
             $globalCategoryScore = array();
 
@@ -1054,27 +1055,21 @@ class Testcategory
                 WHERE exercise_id = {$exercise_id} ";
 
         if (!empty($order)) {
-            $sql .= "ORDER BY $order";
+            $sql .= " ORDER BY $order";
         }
-
         $categories = array();
         $result = Database::query($sql);
         if (Database::num_rows($result)) {
              while ($row = Database::fetch_array($result, 'ASSOC')) {
                 if ($excludeCategoryWithNoQuestions) {
-                    //if ($row['count_questions'] == 0 || $row['count_questions'] == -1) {
-                    /*0 means no questions selected this options is also filtered in the function:
-                    Exercise::pickQuestionsPerCategory() */
                     if ($row['count_questions'] == 0) {
                        continue;
                     }
                 }
                 $categories[$row['category_id']] = $row;
             }
-            if (!empty($list)) {
-                //$categories = $this->sort_tree_array($list);
-            }
         }
+
         if ($shuffle) {
             ArrayClass::shuffle_assoc($categories);
         }
@@ -1163,6 +1158,12 @@ class Testcategory
         $form->add_html_editor('category_description', get_lang('CategoryDescription'), false, false, array('ToolbarSet' => 'test_category', 'Width' => '90%', 'Height' => '200'));
         $category_parent_list = array();
 
+        $options = array(
+            '1' => get_lang('Visible'),
+            '0' => get_lang('Hidden')
+        );
+        $form->addElement('select', 'visibility', get_lang('Visibility'), $options);
+
         $script = null;
         if (!empty($this->parent_id)) {
             $parent_cat = new Testcategory($this->parent_id);
@@ -1180,6 +1181,7 @@ class Testcategory
         $defaults["category_name"] = $this->name;
         $defaults["category_description"] = $this->description;
         $defaults["parent_id"] = $this->parent_id;
+        $defaults["visibility"] = $this->visibility;
         $form->setDefaults($defaults);
 
         // setting the rules

+ 4 - 2
main/exercice/tests_category.php

@@ -129,7 +129,8 @@ function edit_category_form($in_action, $type = 'simple') {
                 $v_name = $values['category_name'];
                 $v_description = $values['category_description'];
                 $parent_id = isset($values['parent_id']) ? $values['parent_id'] : null;
-                $objcat = new Testcategory($v_id, $v_name, $v_description, $parent_id, $type);
+                $visibility = isset($values['visibility']) ? $values['visibility'] : 1;
+                $objcat = new Testcategory($v_id, $v_name, $v_description, $parent_id, $type, null, $visibility);
                 if ($objcat->modifyCategory()) {
                     Display::display_confirmation_message(get_lang('MofidfyCategoryDone'));
                 } else {
@@ -153,7 +154,8 @@ function edit_category_form($in_action, $type = 'simple') {
 }
 
 // process to delete a category
-function delete_category_form($in_action, $type = 'simple') {
+function delete_category_form($in_action, $type = 'simple')
+{
     $in_action = Security::remove_XSS($in_action);
     if (isset($_GET['category_id']) && is_numeric($_GET['category_id'])) {
         $category_id = Security::remove_XSS($_GET['category_id']);

BIN
main/img/icons/128/cv.png


BIN
main/img/icons/32/cv.png


BIN
main/img/icons/32/cv_na.png


BIN
main/img/icons/64/cv.png


BIN
main/img/icons/64/cv_na.png


+ 32 - 7
main/inc/Entity/CQuizCategory.php

@@ -89,6 +89,12 @@ class CQuizCategory
      */
     private $children;
 
+    /**
+     *
+     * @ORM\Column(name="visibility", type="integer")
+     */
+    private $visibility;
+
     /**
      * @ORM\OneToMany(targetEntity="CQuizQuestionRelCategory", mappedBy="category")
      **/
@@ -217,20 +223,39 @@ class CQuizCategory
     * @param integer $cId
     * @return CQuizQuestionCategory
     */
-   public function setParentId($id)
-   {
+    public function setParentId($id)
+    {
        $this->parentId = $id;
 
        return $this;
-   }
+    }
 
-   /**
+    /**
     * Get cId
     *
     * @return integer
     */
-   public function getParentId()
-   {
+    public function getParentId()
+    {
        return $this->parentId;
-   }
+    }
+
+    /**
+     * @return integer
+     */
+    public function getVisibility()
+    {
+        return $this->visibility;
+    }
+
+    /**
+     * @param $visibility
+     * @return $this
+     */
+    public function setVisibility($visibility)
+    {
+        $this->visibility = $visibility;
+
+        return $this;
+    }
 }

+ 6 - 4
main/inc/ajax/exercise.ajax.php

@@ -446,12 +446,14 @@ switch ($action) {
                 }
 
                 // Creates a temporary Question object
-            	$objQuestionTmp = Question::read($my_question_id, $course_id);
+                $objQuestionTmp = Question::read($my_question_id, $course_id);
 
                 if ($objExercise->type == ONE_PER_PAGE && $objQuestionTmp->type == UNIQUE_ANSWER) {
-                    if (empty($my_choice)) {
-                        echo 'answer_required';
-                        exit;
+                    if (in_array($my_question_id, $remind_list)) {
+                        if (empty($my_choice)) {
+                            echo 'answer_required';
+                            exit;
+                        }
                     }
                 }
 

+ 5 - 2
main/inc/global.inc.php

@@ -4,7 +4,7 @@
 /**
  * This is a bootstrap file that loads all Chamilo dependencies including:
  *
- * - Chamilo settings in main/inc/configuration.php or main/inc/configuration.yml
+ * - Chamilo settings in main/inc/conf/configuration.php or config/configuration.yml or config/configuration.php (in this order, using what if finds first)
  * - Database (Using Doctrine DBAL/ORM)
  * - Templates (Using Twig)
  * - Loading language files (Using Symfony component)
@@ -259,6 +259,8 @@ $app->error(
         if ($app['debug']) {
             //return;
         }
+        $message = null;
+
         if (isset($code)) {
             switch ($code) {
                 case 401:
@@ -273,8 +275,8 @@ $app->error(
             }
         } else {
             $code = null;
-            $message = null;
         }
+        //$code = ($e instanceof HttpException) ? $e->getStatusCode() : 500;
 
         // It seems that error() is executed first than the before() middleware
         // @ŧodo check this one
@@ -285,6 +287,7 @@ $app->error(
         // Default layout.
         $app['default_layout'] = $app['template_style'].'/layout/layout_1_col.tpl';
 
+        $app['template']->assign('error', array('code' => $code, 'message' => $message));
 
         $response = $app['template']->render_layout('error.tpl');
 

+ 6 - 1
main/inc/lib/announcements.inc.php

@@ -279,6 +279,11 @@ class AnnouncementManager
         }
     }
 
+    /**
+     * Get last announcement order in the list (by max display_order)
+     * @return int 0 or the integer display_order of the last announcement
+     * @assert () === 0 
+     */
     public static function get_last_announcement_order()
     {
         $tbl_announcement = Database::get_course_table(TABLE_ANNOUNCEMENT);
@@ -397,7 +402,7 @@ class AnnouncementManager
     }
 
     /*
-      STORE ANNOUNCEMENT  GROUP ITEM
+     * STORE ANNOUNCEMENT  GROUP ITEM
      */
 
     public static function add_group_announcement(

+ 144 - 53
main/inc/lib/api.lib.php

@@ -82,7 +82,7 @@ define('UNSUBSCRIBE_NOT_ALLOWED', 0);
 
 // CONSTANTS defining all tools, using the english version
 /* When you add a new tool you must add it into function api_get_tools_lists() too */
-define('TOOL_DOCUMENT','document');
+define('TOOL_DOCUMENT', 'document');
 define('TOOL_THUMBNAIL', 'thumbnail');
 define('TOOL_HOTPOTATOES', 'hotpotatoes');
 define('TOOL_CALENDAR_EVENT', 'calendar_event');
@@ -92,11 +92,11 @@ define('TOOL_SEARCH', 'search');
 define('TOOL_LEARNPATH', 'learnpath');
 define('TOOL_ANNOUNCEMENT', 'announcement');
 define('TOOL_FORUM', 'forum');
-define('TOOL_FORUM_CATEGORY','forum_category');
-define('TOOL_FORUM_THREAD','forum_thread');
-define('TOOL_FORUM_POST','forum_post');
-define('TOOL_FORUM_ATTACH','forum_attachment');
-define('TOOL_FORUM_THREAD_QUALIFY','forum_thread_qualify');
+define('TOOL_FORUM_CATEGORY', 'forum_category');
+define('TOOL_FORUM_THREAD', 'forum_thread');
+define('TOOL_FORUM_POST', 'forum_post');
+define('TOOL_FORUM_ATTACH', 'forum_attachment');
+define('TOOL_FORUM_THREAD_QUALIFY', 'forum_thread_qualify');
 define('TOOL_THREAD', 'thread');
 define('TOOL_POST', 'post');
 define('TOOL_DROPBOX', 'dropbox');
@@ -115,18 +115,19 @@ define('TOOL_COPY_COURSE_CONTENT', 'copy_course_content');
 define('TOOL_RECYCLE_COURSE', 'recycle_course');
 define('TOOL_COURSE_HOMEPAGE', 'course_homepage');
 define('TOOL_COURSE_RIGHTS_OVERVIEW', 'course_rights');
-define('TOOL_UPLOAD','file_upload');
-define('TOOL_COURSE_MAINTENANCE','course_maintenance');
-define('TOOL_VISIO','visio');
-define('TOOL_VISIO_CONFERENCE','visio_conference');
-define('TOOL_VISIO_CLASSROOM','visio_classroom');
-define('TOOL_SURVEY','survey');
-define('TOOL_WIKI','wiki');
-define('TOOL_GLOSSARY','glossary');
-define('TOOL_GRADEBOOK','gradebook');
-define('TOOL_NOTEBOOK','notebook');
-define('TOOL_ATTENDANCE','attendance');
-define('TOOL_COURSE_PROGRESS','course_progress');
+define('TOOL_UPLOAD', 'file_upload');
+define('TOOL_COURSE_MAINTENANCE', 'course_maintenance');
+define('TOOL_VISIO', 'visio');
+define('TOOL_VISIO_CONFERENCE', 'visio_conference');
+define('TOOL_VISIO_CLASSROOM', 'visio_classroom');
+define('TOOL_SURVEY', 'survey');
+define('TOOL_WIKI', 'wiki');
+define('TOOL_GLOSSARY', 'glossary');
+define('TOOL_GRADEBOOK', 'gradebook');
+define('TOOL_NOTEBOOK', 'notebook');
+define('TOOL_ATTENDANCE', 'attendance');
+define('TOOL_COURSE_PROGRESS', 'course_progress');
+define('TOOL_CURRICULUM', 'curriculum');
 
 // CONSTANTS defining Chamilo interface sections
 define('SECTION_CAMPUS', 'mycampus');
@@ -136,7 +137,7 @@ define('SECTION_MYAGENDA', 'myagenda');
 define('SECTION_COURSE_ADMIN', 'course_admin');
 define('SECTION_PLATFORM_ADMIN', 'platform_admin');
 define('SECTION_MYGRADEBOOK', 'mygradebook');
-define('SECTION_TRACKING','session_my_space');
+define('SECTION_TRACKING', 'session_my_space');
 define('SECTION_SOCIAL', 'social');
 define('SECTION_DASHBOARD', 'dashboard');
 define('SECTION_REPORTS', 'reports');
@@ -148,7 +149,7 @@ define('CAS_AUTH_SOURCE', 'cas');
 define('LDAP_AUTH_SOURCE', 'extldap');
 
 // CONSTANT defining the default HotPotatoes files directory
-define('DIR_HOTPOTATOES','/HotPotatoes_files');
+define('DIR_HOTPOTATOES', '/HotPotatoes_files');
 
 // Event logs types
 define('LOG_COURSE_DELETE',                     'course_deleted');
@@ -847,7 +848,7 @@ function api_get_path($path_type, $path = null) {
 function api_get_cdn_path($web_path) {
     global $_configuration;
     $web_root = api_get_path(WEB_PATH);
-    $ext = substr($web_path,strrpos($web_path,'.'));
+    $ext = substr($web_path,strrpos($web_path, '.'));
     if (isset($ext[2])) { // faster version of strlen to check if len>2
         // Check for CDN definitions
         if (!empty($_configuration['cdn_enable']) && !empty($ext)) {
@@ -1174,7 +1175,7 @@ function api_get_user_id() {
  * Gets the list of courses a specific user is subscribed to
  * @param int       User ID
  * @param boolean   Whether to get session courses or not - NOT YET IMPLEMENTED
- * @return array    Array of courses in the form [0]=>('code'=>xxx,'db'=>xxx,'dir'=>xxx,'status'=>d)
+ * @return array    Array of courses in the form [0]=>('code'=>xxx, 'db'=>xxx, 'dir'=>xxx, 'status'=>d)
  * @deprecated use the UserManager or CourseManager class
  */
 function api_get_user_courses($userid, $fetch_session = true) {
@@ -2267,14 +2268,18 @@ function api_get_self() {
 function api_is_platform_admin($allow_sessions_admins = false)
 {
     global $app;
-    if ($app['security']->isGranted('ROLE_ADMIN')) {
-        return true;
-    }
+    $token = $app['security']->getToken();
 
-    if ($allow_sessions_admins) {
-        if ($app['security']->isGranted('ROLE_SESSION_MANAGER')) {
+    if (!empty($token)) {
+        if ($app['security']->isGranted('ROLE_ADMIN')) {
             return true;
         }
+
+        if ($allow_sessions_admins) {
+            if ($app['security']->isGranted('ROLE_SESSION_MANAGER')) {
+                return true;
+            }
+        }
     }
     return false;
 }
@@ -2282,8 +2287,12 @@ function api_is_platform_admin($allow_sessions_admins = false)
 function api_is_question_manager()
 {
     global $app;
-    if ($app['security']->isGranted('ROLE_QUESTION_MANAGER')) {
-        return true;
+    $token = $app['security']->getToken();
+
+    if (!empty($token)) {
+        if ($app['security']->isGranted('ROLE_QUESTION_MANAGER')) {
+            return true;
+        }
     }
     return false;
 }
@@ -2296,8 +2305,12 @@ function api_is_question_manager()
 function api_is_session_admin()
 {
     global $app;
-    if ($app['security']->isGranted('ROLE_SESSION_MANAGER')) {
-        return true;
+    $token = $app['security']->getToken();
+
+    if (!empty($token)) {
+        if ($app['security']->isGranted('ROLE_SESSION_MANAGER')) {
+            return true;
+        }
     }
     return false;
 }
@@ -2308,8 +2321,12 @@ function api_is_session_admin()
  */
 function api_is_drh() {
     global $app;
-    if ($app['security']->isGranted('ROLE_RRHH')) {
-        return true;
+    $token = $app['security']->getToken();
+
+    if (!empty($token)) {
+        if ($app['security']->isGranted('ROLE_RRHH')) {
+            return true;
+        }
     }
     return false;
 }
@@ -2320,8 +2337,12 @@ function api_is_drh() {
  */
 function api_is_student() {
     global $app;
-    if ($app['security']->isGranted('ROLE_STUDENT')) {
-        return true;
+    $token = $app['security']->getToken();
+
+    if (!empty($token)) {
+        if ($app['security']->isGranted('ROLE_STUDENT')) {
+            return true;
+        }
     }
     return false;
 }
@@ -3317,7 +3338,7 @@ function api_item_property_update($_course, $tool, $item_id, $lastedit_type, $us
                             WHERE $filter";
                 } else {
                     $sql = "INSERT INTO $TABLE_ITEMPROPERTY (c_id, tool, ref, insert_date, insert_user_id, lastedit_date, lastedit_type, lastedit_user_id, to_user_id, to_group_id, visibility, start_visible, end_visible, id_session)
-                            VALUES ($course_id, '$tool','$item_id','$time', '$user_id', '$time', '$lastedit_type','$user_id', '$to_user_id', '$to_group_id', '$visibility', '$start_visible','$end_visible', '$session_id')";
+                            VALUES ($course_id, '$tool', '$item_id', '$time', '$user_id', '$time', '$lastedit_type', '$user_id', '$to_user_id', '$to_group_id', '$visibility', '$start_visible', '$end_visible', '$session_id')";
                 }
 
             } else {
@@ -3479,7 +3500,7 @@ function api_get_track_item_property_history($tool, $ref) {
     $item_property_id = api_get_item_property_id($course_code, $tool, $ref);
     $sql = "SELECT * FROM $tbl_stats_item_property WHERE item_property_id = $item_property_id AND course_id = $course_id ORDER BY lastedit_date DESC";
     $result = Database::query($sql);
-    $result = Database::store_result($result,'ASSOC');
+    $result = Database::store_result($result, 'ASSOC');
     return $result;
 }
 
@@ -3513,7 +3534,7 @@ function api_get_item_property_info($course_id, $tool, $ref, $session_id = 0) {
     $rs  = Database::query($sql);
     $row = array();
     if (Database::num_rows($rs) > 0) {
-        $row = Database::fetch_array($rs,'ASSOC');
+        $row = Database::fetch_array($rs, 'ASSOC');
     }
     return $row;
 }
@@ -3685,7 +3706,7 @@ function api_get_language_info($language_id) {
     $rs = Database::query($sql);
     $language_info = array();
     if (Database::num_rows($rs)) {
-        $language_info = Database::fetch_array($rs,'ASSOC');
+        $language_info = Database::fetch_array($rs, 'ASSOC');
     }
     return $language_info;
 }
@@ -4108,7 +4129,7 @@ function api_copy_folder_course_session($pathname, $base_path_document, $session
 
     $course_id	 = $course_info['real_id'];
 
-    $folders = explode(DIRECTORY_SEPARATOR,str_replace($base_path_document.DIRECTORY_SEPARATOR,'',$pathname));
+    $folders = explode(DIRECTORY_SEPARATOR,str_replace($base_path_document.DIRECTORY_SEPARATOR, '',$pathname));
 
     $new_pathname = $base_path_document;
     $path = '';
@@ -4138,7 +4159,7 @@ function api_copy_folder_course_session($pathname, $base_path_document, $session
                 		session_id = '$session_id'";
                 Database::query($sql);
                 $document_id = Database::insert_id();
-                api_item_property_update($course_info,TOOL_DOCUMENT,$document_id,'FolderCreated',api_get_user_id(),0,0,null,null,$session_id);
+                api_item_property_update($course_info,TOOL_DOCUMENT,$document_id, 'FolderCreated',api_get_user_id(),0,0,null,null,$session_id);
             }
         }
 
@@ -4469,8 +4490,8 @@ function api_set_setting($var, $value, $subvar = null, $cat = null, $access_url
                         "subkeytext,access_url)" .
                         " VALUES " .
                         "('".$row['variable']."',".(!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL")."," .
-                        "'".$row['type']."','".$row['category']."'," .
-                        "'$value','".$row['title']."'," .
+                        "'".$row['type']."', '".$row['category']."'," .
+                        "'$value', '".$row['title']."'," .
                         "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".(!empty($row['scope']) ? "'".$row['scope']."'" : "NULL")."," .
                         "".(!empty($row['subkeytext'])?"'".$row['subkeytext']."'":"NULL").",$access_url)";
                 $res = Database::query($insert);
@@ -4499,8 +4520,8 @@ function api_set_setting($var, $value, $subvar = null, $cat = null, $access_url
                             " VALUES " .
                             "('".$row['variable']."',".
                             (!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL")."," .
-                            "'".$row['type']."','".$row['category']."'," .
-                            "'$value','".$row['title']."'," .
+                            "'".$row['type']."', '".$row['category']."'," .
+                            "'$value', '".$row['title']."'," .
                             "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".
                             (!empty($row['scope']) ? "'".$row['scope']."'" : "NULL")."," .
                             "".(!empty($row['subkeytext']) ? "'".$row['subkeytext']."'" : "NULL").",$access_url,".$row['access_url_changeable'].")";
@@ -4590,7 +4611,7 @@ function api_get_access_url($id)
 {
     $id = intval($id);
     $table_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
-    $sql = "SELECT url, description, active, created_by, tms FROM $table_access_url WHERE id = '$id' ";
+    $sql = "SELECT id, url, description, active, created_by, tms FROM $table_access_url WHERE id = '$id' ";
     $res = Database::query($sql);
     $result = Database::fetch_array($res);
     return $result;
@@ -4629,7 +4650,7 @@ function api_add_access_url($u, $d = '', $a = 1) {
     }
     $ui = api_get_user_id();
 
-    $sql = "INSERT INTO $t_au (url,description,active,created_by,tms) VALUES ('$u','$d',$a,$ui,'')";
+    $sql = "INSERT INTO $t_au (url,description,active,created_by,tms) VALUES ('$u', '$d',$a,$ui, '')";
     $res = Database::query($sql);
     return ($res === false) ? false : Database::insert_id();
 }
@@ -4676,7 +4697,7 @@ function & api_get_settings_categories($exceptions = array(), $access_url = 1) {
     $t_cs = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
     $list = "'".implode("','",$exceptions)."'";
     $sql = "SELECT DISTINCT category FROM $t_cs WHERE category is NOT NULL ";
-    if ($list != "'',''" and $list != "''" and !empty($list)) {
+    if ($list != "'', ''" and $list != "''" and !empty($list)) {
         $sql .= " AND category NOT IN ($list) ";
     }
     $result = Database::store_result(Database::query($sql));
@@ -4771,7 +4792,7 @@ function api_add_setting($val, $var, $sk = null, $type = 'textfield', $c = null,
                 "subkey,title," .
                 "comment,scope," .
                 "subkeytext,access_url,access_url_changeable)" .
-                " VALUES ('$var','$val',";
+                " VALUES ('$var', '$val',";
     if (isset($type)) {
         $type = Database::escape_string($type);
         $insert .= "'$type',";
@@ -5879,7 +5900,7 @@ function api_get_jquery_libraries_js($libraries) {
         $platform_isocode = strtolower(api_get_language_isocode());
 
         //languages supported by jqgrid see files in main/inc/lib/javascript/jqgrid/js/i18n
-        $jqgrid_langs = array('bg', 'bg1251', 'cat','cn','cs','da','de','el','en','es','fa','fi','fr','gl','he','hu','is','it','ja','nl','no','pl','pt-br','pt','ro','ru','sk','sr','sv','tr','ua');
+        $jqgrid_langs = array('bg', 'bg1251', 'cat', 'cn', 'cs', 'da', 'de', 'el', 'en', 'es', 'fa', 'fi', 'fr', 'gl', 'he', 'hu', 'is', 'it', 'ja', 'nl', 'no', 'pl', 'pt-br', 'pt', 'ro', 'ru', 'sk', 'sr', 'sv', 'tr', 'ua');
 
         if (in_array($platform_isocode, $jqgrid_langs)) {
             $languaje = $platform_isocode;
@@ -6049,7 +6070,7 @@ function api_check_php_version() {
  */
 function api_check_archive_dir() {
     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');
+        $message = Display::return_message(get_lang('ArchivesDirectoryNotWriteableContactAdmin'), 'warning');
         api_not_allowed(true, $message);
     }
 }
@@ -6145,7 +6166,7 @@ function api_check_ip_in_range($ip,$range) {
     $ip_ip = ip2long ($ip);
     $ranges = array();
     // divide range param into array of elements
-    if (strpos($range,',')!==false) {
+    if (strpos($range, ',')!==false) {
         $ranges = explode(',',$range);
     } else {
         $ranges = array($range);
@@ -6153,7 +6174,7 @@ function api_check_ip_in_range($ip,$range) {
     foreach ($ranges as $range) {
         $range = trim($range);
         if (empty($range)) { continue; }
-        if (strpos($range,'/')===false) {
+        if (strpos($range, '/')===false) {
             if (strcmp($ip,$range)===0) {
                 return true; // there is a direct IP match, return OK
             }
@@ -6927,3 +6948,73 @@ function api_get_user_roles()
     $status[QUESTION_MANAGER] = get_lang('QuestionManager');
     return $status;
 }
+/**
+ *
+ * @param string $inputId the jquery id example: #password
+ * @return string
+ */
+function api_get_password_checker_js($inputId)
+{
+    global $_configuration;
+    $useStrengthPassChecker = isset($_configuration['allow_strength_pass_checker']) ? $_configuration['allow_strength_pass_checker'] : false;
+
+    if ($useStrengthPassChecker == false) {
+        return null;
+    }
+
+    $verdicts = array(get_lang('Weak'), get_lang('Normal'), get_lang('Medium'), get_lang('Strong'), get_lang('VeryStrong'));
+    $js = api_get_js('strength/strength.js');
+    $js .=  "<script>
+
+    var verdicts = ['".implode("','", $verdicts)."'];
+    var errorMessages = {
+        password_to_short : '".get_lang('PasswordIsTooShort')."'
+    };
+
+    $(document).ready(function() {
+        var options = {
+            verdicts: verdicts,
+            onLoad : function () {
+                //$('#messages').text('Start typing password');
+            },
+            onKeyUp: function (evt) {
+                $(evt.target).pwstrength('outputErrorList');
+            },
+            errorMessages : errorMessages,
+            viewports: {
+              progress: '#password_progress',
+              //verdict: undefined,
+              //errors: undefined
+          }
+        };
+        $('".$inputId."').pwstrength(options);
+    });
+    </script>";
+    return $js;
+}
+
+/**
+ * Gets an array with "easy" passwords
+ * @return array
+ */
+function api_get_easy_password_list()
+{
+    $passwordList = array('123', '1234', '123456', 'admin', 'user', 'student', 'teacher');
+    $file = api_get_path(CONFIGURATION_PATH).'easy_password_list.php';
+    if (file_exists($file)) {
+        $passwordList = require_once $file;
+    }
+    return $passwordList;
+}
+
+function api_is_profile_editable()
+{
+    global $profileIsEditable;
+    return isset($profileIsEditable) ? $profileIsEditable : false;
+}
+
+function api_is_profile_readable()
+{
+    global $profileIsReadable;
+    return isset($profileIsReadable) ? $profileIsReadable : true;
+}

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

@@ -4279,6 +4279,7 @@ class CourseManager
         Database::query("INSERT INTO $tbl_course_homepage VALUES ($course_id, NULL, '" . TOOL_NOTEBOOK."','notebook/index.php','notebook.gif','".Text::string2binary(api_get_setting('course_create_active_tools', 'notebook'))."','0','squaregrey.gif','NO','_self','interaction','0')");
         Database::query("INSERT INTO $tbl_course_homepage VALUES ($course_id, NULL, '" . TOOL_ATTENDANCE."','attendance/index.php','attendance.gif','".Text::string2binary(api_get_setting('course_create_active_tools', 'attendances'))."','0','squaregrey.gif','NO','_self','authoring','0')");
         Database::query("INSERT INTO $tbl_course_homepage VALUES ($course_id, NULL, '" . TOOL_COURSE_PROGRESS."','course_progress/index.php','course_progress.gif','".Text::string2binary(api_get_setting('course_create_active_tools', 'course_progress'))."','0','squaregrey.gif','NO','_self','authoring','0')");
+        Database::query("INSERT INTO $tbl_course_homepage VALUES ($course_id, NULL, '" . TOOL_CURRICULUM."','curriculum','cv.png','".Text::string2binary(api_get_setting('course_create_active_tools', 'curriculum'))."','0','squaregrey.gif','NO','_self','authoring','0')");
 
         if (api_get_setting('service_visio', 'active') == 'true') {
             $mycheck = api_get_setting('service_visio', 'visio_host');

+ 68 - 52
main/inc/lib/course_home.lib.php

@@ -1,7 +1,8 @@
 <?php
 /* For licensing terms, see /license.txt */
 
-class CourseHome {
+class CourseHome
+{
 
     /**
      * Gets the html content to show in the 3 column view
@@ -18,7 +19,7 @@ class CourseHome {
         $course_id = api_get_course_int_id();
 
         switch ($cat) {
-            case 'Basic' :
+            case 'Basic':
                 $condition_display_tools = ' WHERE a.c_id = '.$course_id.' AND  a.link=t.link AND t.position="basic" ';
                 if ((api_is_coach() || api_is_course_tutor()) && $_SESSION['studentview'] != 'studentview') {
                     $condition_display_tools = ' WHERE a.c_id = '.$course_id.' AND a.link=t.link AND (t.position="basic" OR a.name = "'.TOOL_TRACKING.'") ';
@@ -27,7 +28,7 @@ class CourseHome {
                 $sql = "SELECT a.*, t.image img, t.row_module, t.column_module  FROM $TBL_ACCUEIL a, $TABLE_TOOLS t
                         $condition_display_tools ORDER BY t.row_module, t.column_module";
                 break;
-            case 'External' :
+            case 'External':
                 if (api_is_allowed_to_edit()) {
                     $sql = "SELECT a.*, t.image img FROM $TBL_ACCUEIL a, $TABLE_TOOLS t
                             WHERE a.c_id = $course_id AND ((a.link=t.link AND t.position='external')
@@ -40,12 +41,12 @@ class CourseHome {
                             ORDER BY a.id";
                 }
                 break;
-            case 'courseAdmin' :
+            case 'courseAdmin':
                 $sql = "SELECT a.*, t.image img, t.row_module, t.column_module  FROM $TBL_ACCUEIL a, $TABLE_TOOLS t
                         WHERE a.c_id = $course_id AND admin=1 AND a.link=t.link ORDER BY t.row_module, t.column_module";
                 break;
 
-            case 'platformAdmin' :
+            case 'platformAdmin':
                $sql = "SELECT *, image img FROM $TBL_ACCUEIL WHERE c_id = $course_id AND visibility = 2 ORDER BY id";
         }
         $result = Database::query($sql);
@@ -205,7 +206,8 @@ class CourseHome {
      * @param string $course_tool_category	contains the category of tools to display:
      * "Public", "PublicButHide", "courseAdmin", "claroAdmin"
      */
-    public static function show_tool_2column($course_tool_category) {
+    public static function show_tool_2column($course_tool_category)
+    {
         $html = '';
         $web_code_path = api_get_path(WEB_CODE_PATH);
         $course_tool_table = Database::get_course_table(TABLE_TOOL_LIST);
@@ -249,13 +251,13 @@ class CourseHome {
 
         switch ($course_tool_category)  {
             case TOOL_PUBLIC:
-                $sql_links="SELECT tl.*, tip.visibility
+                $sql_links = "SELECT tl.*, tip.visibility
                         FROM $course_link_table tl
                         LEFT JOIN $course_item_property_table tip ON tip.tool='link' AND tl.c_id = tip.c_id AND tl.c_id = $course_id AND tip.ref=tl.id
                         WHERE tl.on_homepage='1' AND tip.visibility = 1";
                 break;
             case TOOL_PUBLIC_BUT_HIDDEN:
-                $sql_links="SELECT tl.*, tip.visibility
+                $sql_links = "SELECT tl.*, tip.visibility
                     FROM $course_link_table tl
                     LEFT JOIN $course_item_property_table tip ON tip.tool='link' AND tl.c_id = tip.c_id AND tl.c_id = $course_id AND tip.ref=tl.id
                     WHERE tl.on_homepage='1' AND tip.visibility = 0";
@@ -403,7 +405,8 @@ class CourseHome {
      * @return array
      */
 
-    public static function get_tools_category($course_tool_category) {
+    public static function get_tools_category($course_tool_category)
+    {
         $course_tool_table  = Database::get_course_table(TABLE_TOOL_LIST);
         $is_platform_admin  = api_is_platform_admin();
         $all_tools_list = array();
@@ -415,46 +418,46 @@ class CourseHome {
 
         switch ($course_tool_category) {
             case TOOL_STUDENT_VIEW:
-                    $condition_display_tools = ' WHERE visibility = 1 AND (category = "authoring" OR category = "interaction" OR category = "plugin") ';
-                    if ((api_is_coach() || api_is_course_tutor()) && $_SESSION['studentview'] != 'studentview') {
-                        $condition_display_tools = ' WHERE (visibility = 1 AND (category = "authoring" OR category = "interaction" OR category = "plugin") OR (name = "'.TOOL_TRACKING.'") )   ';
-                    }
-                    $sql = "SELECT * FROM $course_tool_table  $condition_display_tools AND c_id = $course_id $condition_session ORDER BY id";
-                    $result = Database::query($sql);
-                    $col_link ="##003399";
-                    break;
+                $condition_display_tools = ' WHERE visibility = 1 AND (category = "authoring" OR category = "interaction" OR category = "plugin") ';
+                if ((api_is_coach() || api_is_course_tutor()) && $_SESSION['studentview'] != 'studentview') {
+                    $condition_display_tools = ' WHERE (visibility = 1 AND (category = "authoring" OR category = "interaction" OR category = "plugin") OR (name = "'.TOOL_TRACKING.'") )   ';
+                }
+                $sql = "SELECT * FROM $course_tool_table  $condition_display_tools AND c_id = $course_id $condition_session ORDER BY id";
+                $result = Database::query($sql);
+                $col_link ="##003399";
+                break;
             case TOOL_AUTHORING:
-                    $sql = "SELECT * FROM $course_tool_table WHERE category = 'authoring' AND c_id = $course_id $condition_session ORDER BY id";
-                    $result = Database::query($sql);
-                    $col_link ="##003399";
-                    break;
+                $sql = "SELECT * FROM $course_tool_table WHERE category = 'authoring' AND c_id = $course_id $condition_session ORDER BY id";
+                $result = Database::query($sql);
+                $col_link ="##003399";
+                break;
             case TOOL_INTERACTION:
-                    $sql = "SELECT * FROM $course_tool_table WHERE category = 'interaction' AND c_id = $course_id $condition_session ORDER BY id";
-                    $result = Database::query($sql);
-                    $col_link ="##003399";
-                    break;
+                $sql = "SELECT * FROM $course_tool_table WHERE category = 'interaction' AND c_id = $course_id $condition_session ORDER BY id";
+                $result = Database::query($sql);
+                $col_link ="##003399";
+                break;
             case TOOL_ADMIN_VISIBLE:
-                    $sql = "SELECT * FROM $course_tool_table WHERE category = 'admin' AND visibility ='1' AND c_id = $course_id $condition_session ORDER BY id";
-                    $result = Database::query($sql);
-                    $col_link ="##003399";
-                    break;
+                $sql = "SELECT * FROM $course_tool_table WHERE category = 'admin' AND visibility ='1' AND c_id = $course_id $condition_session ORDER BY id";
+                $result = Database::query($sql);
+                $col_link ="##003399";
+                break;
             case TOOL_ADMIN_PLATFORM:
-                    $sql = "SELECT * FROM $course_tool_table WHERE category = 'admin' AND c_id = $course_id $condition_session ORDER BY id";
-                    $result = Database::query($sql);
-                    $col_link ="##003399";
-                    break;
+                $sql = "SELECT * FROM $course_tool_table WHERE category = 'admin' AND c_id = $course_id $condition_session ORDER BY id";
+                $result = Database::query($sql);
+                $col_link ="##003399";
+                break;
             case TOOL_COURSE_PLUGIN:
-                    //Other queries recover id, name, link, image, visibility, admin, address, added_tool, target, category and session_id
-                    // but plugins are not present in the tool table, only globally and inside the course_settings table once configured
-                    $sql = "SELECT * FROM $course_tool_table WHERE category = 'plugin' AND c_id = $course_id $condition_session ORDER BY id";
-                    $result = Database::query($sql);
-                    break;
+                //Other queries recover id, name, link, image, visibility, admin, address, added_tool, target, category and session_id
+                // but plugins are not present in the tool table, only globally and inside the course_settings table once configured
+                $sql = "SELECT * FROM $course_tool_table WHERE category = 'plugin' AND c_id = $course_id $condition_session ORDER BY id";
+                $result = Database::query($sql);
+                break;
         }
 
         //Get the list of hidden tools - this might imply performance slowdowns
         // if the course homepage is loaded many times, so the list of hidden
         // tools might benefit from a shared memory storage later on
-        $list = api_get_settings('Tools','list', api_get_current_access_url_id());
+        $list = api_get_settings('Tools', 'list', api_get_current_access_url_id());
         $hide_list = array();
         $check = false;
 
@@ -575,20 +578,21 @@ class CourseHome {
      * @param   int rows
      * @return void
      */
-    public static function show_tools_category($all_tools_list, $rows = false) {
+    public static function show_tools_category($all_tools_list, $rows = false)
+    {
         $rowDiv =  '<div class="row-fluid">';
         $theme = api_get_setting('homepage_view');
         if ($theme == 'vertical_activity') {
             //ordering by get_lang name
             $order_tool_list = array();
             if (is_array($all_tools_list) && count($all_tools_list)>0) {
-                foreach($all_tools_list as $key=>$new_tool) {
+                foreach ($all_tools_list as $key => $new_tool) {
                     $tool_name = self::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) {
+                foreach ($order_tool_list as $key => $new_tool) {
                     $my_temp_tool_array[] = $all_tools_list[$key];
                 }
                 $all_tools_list = $my_temp_tool_array;
@@ -596,6 +600,7 @@ class CourseHome {
                 $all_tools_list = array();
             }
         }
+        $courseInfo = api_get_course_info();
         $web_code_path      = api_get_path(WEB_CODE_PATH);
         $is_allowed_to_edit = api_is_allowed_to_edit(null, true);
         $is_platform_admin  = api_is_platform_admin();
@@ -613,6 +618,14 @@ class CourseHome {
 
                 $tool['original_link'] = $tool['link'];
 
+                // Re-writing URL for new tools
+                $newTools = array(TOOL_CURRICULUM);
+
+                $toolName = isset($tool['name']) ? $tool['name'] : null;
+                if (in_array($toolName, $newTools)) {
+                    $tool['link'] = $courseInfo['course_web_public_url'].$tool['name'].'/';
+                }
+
                 if ($tool['image'] == 'scormbuilder.gif') {
                     // display links to lp only for current session
                     /*if ($session_id != $tool['session_id']) {
@@ -620,7 +633,7 @@ class CourseHome {
                     }*/
                     // check if the published learnpath is visible for student
                     $published_lp_id = self::get_published_lp_id_from_link($tool['link']);
-                    if (!api_is_allowed_to_edit(null, true) && !learnpath::is_lp_visible_for_student($published_lp_id,api_get_user_id())) {
+                    if (!api_is_allowed_to_edit(null, true) && !learnpath::is_lp_visible_for_student($published_lp_id, api_get_user_id())) {
                         continue;
                     }
                 }
@@ -678,9 +691,9 @@ class CourseHome {
                     $tool['link'] = $web_code_path.$tool['link'];
                 }
                 if ($tool['visibility'] == '0' && $tool['admin'] != '1') {
-                      $class = 'invisible';
-                      $info = pathinfo($tool['image']);
-                      $basename = basename($tool['image'], '.'.$info['extension']); // $file is set to "index"
+                    $class = 'invisible';
+                    $info = pathinfo($tool['image']);
+                    $basename = basename($tool['image'], '.'.$info['extension']); // $file is set to "index"
                     $tool['image'] = $basename.'_na.'.$info['extension'];
                 } else {
                     $class = '';
@@ -698,7 +711,7 @@ class CourseHome {
 
                 //$tool['link'] = htmlspecialchars($tool['link']) ;
                 //@todo this visio stuff should be removed
-                if (strpos($tool['name'],'visio_') !== false) {
+                if (strpos($tool['name'], 'visio_') !== false) {
                     $tool_link_params = array(
                         'id'      => 'tooldesc_'.$tool["id"],
                         'href'    => '"javascript: void(0);"',
@@ -720,6 +733,8 @@ class CourseHome {
                             'class'   => $class,
                             'target'  =>  '_blank');
                     } else {
+
+
                         $tool_link_params = array(
                             'id'      => 'tooldesc_'.$tool["id"],
                             'href'    => $tool['link'],
@@ -800,7 +815,7 @@ class CourseHome {
                                 $image = $original_image;
                         }
 
-                        $data .= Display::url($image , $item['url_params']['href'], $item['url_params']);
+                        $data .= Display::url($image, $item['url_params']['href'], $item['url_params']);
                         $html .= Display::div($data, array('class'=>'big_icon')); //box-image reflection
                         $html .= Display::div('<h4>'.$item['visibility'].$item['extra'].$item['link'].'</h4>', array('class'=>'content'));
                         $html .=  '</div>';
@@ -813,7 +828,6 @@ class CourseHome {
 
                         break;
                     case 'activity':
-
                         if ($counter == 0) {
                             $html .=  $rowDiv;
                         }
@@ -860,7 +874,8 @@ class CourseHome {
      * @param id	session id
      * @return string	session data
      */
-    public static function show_session_data($id_session) {
+    public static function show_session_data($id_session)
+    {
 
         if ($id_session != strval(intval($id_session))) {
             return '';
@@ -884,7 +899,7 @@ class CourseHome {
 
         $output  = '';
         if (!empty($session_category)) {
-            $output .= '<tr><td>'. get_lang('SessionCategory') . ': ' . '<b>' . $session_category_name .'</b></td></tr>';
+            $output .= '<tr><td>'. get_lang('SessionCategory').': '.'<b>'.$session_category_name.'</b></td></tr>';
         }
         $output .= '<tr>
                         <td style="width:50%">'. get_lang('SessionName') . ': ' . '<b>' . $session_info['name'] .'</b></td>
@@ -900,7 +915,8 @@ class CourseHome {
      * @param array $tool		The input record.
      * @return string			Returns the name of the corresponding tool.
      */
-    public static function translate_tool_name(& $tool) {
+    public static function translate_tool_name(& $tool)
+    {
         static $already_translated_icons = array(
             'file_html.gif',
             'file_html_na.gif',

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

@@ -101,7 +101,7 @@ class Online
         // (using *authent_name*_logout as the function name) and the following code
         // will find and execute it
         $uinfo = api_get_user_info($user_id);
-        if (($uinfo['auth_source'] != PLATFORM_AUTH_SOURCE) && is_array($extAuthSource)) {
+        if ((isset($uinfo['auth_source']) && $uinfo['auth_source'] != PLATFORM_AUTH_SOURCE) && is_array($extAuthSource)) {
             if (is_array($extAuthSource[$uinfo['auth_source']])) {
                 $subarray = $extAuthSource[$uinfo['auth_source']];
                 if (!empty($subarray['logout']) && file_exists($subarray['logout'])) {

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

@@ -58,7 +58,10 @@ class PageController
                                     <img title="'.get_lang('EditProfile').'" src="'.$img_array['file'].'"></a>';
             }
         }
-        $this->show_right_block(null, null, 'user_image_block', array('content' => $profile_content));
+
+        if (!empty($profile_content)) {
+            $this->show_right_block(null, null, 'user_image_block', array('content' => $profile_content));
+        }
     }
 
     /**

+ 2 - 2
main/inc/lib/social.lib.php

@@ -928,13 +928,13 @@ class SocialManager extends UserManager {
         }
 
         if (!empty($courseCode)) {
-            //return api_get_path(WEB_PUBLIC_PATH).'users/online-in-course/'.$courseCode;
             return api_get_path(WEB_PATH).'whoisonline.php?cidReq='.$courseCode;
+            //return api_get_path(WEB_PUBLIC_PATH).'users/online/course/'.$courseCode;
         }
 
         if (!empty($sessionId)) {
-            //return api_get_path(WEB_PUBLIC_PATH).'users/online-in-session/'.$courseCode;
             return api_get_path(WEB_PATH).'whoisonlinesession.php?session_id='.$sessionId;
+            //return api_get_path(WEB_PUBLIC_PATH).'users/online/session/'.$sessionId;
         }
     }
 }

+ 16 - 12
main/inc/lib/template.lib.php

@@ -635,16 +635,19 @@ class Template
 
         // Preparing values for the menu
 
-        // Logout link
-        // See the SecurityServiceProvider definition
-        $this->assign('logout_link', $this->app['url_generator']->generate('admin_logout'));
+        // Profile link.
 
-        //Profile link
+        $this->assign('is_profile_editable', api_is_profile_readable());
+
+        $profile_link = null;
         if (api_get_setting('allow_social_tool') == 'true') {
             $profile_link = '<a href="'.api_get_path(WEB_CODE_PATH).'social/home.php">'.get_lang('Profile').'</a>';
         } else {
-            $profile_link = '<a href="'.api_get_path(WEB_CODE_PATH).'auth/profile.php">'.get_lang('Profile').'</a>';
+            if (api_is_profile_readable()) {
+                $profile_link = '<a href="'.api_get_path(WEB_CODE_PATH).'auth/profile.php">'.get_lang('Profile').'</a>';
+            }
         }
+
         $this->assign('profile_link', $profile_link);
 
         // Message link.
@@ -960,8 +963,10 @@ class Template
         $navigation['mycourses']['title'] = get_lang('MyCourses');
 
         // My Profile
-        $navigation['myprofile']['url'] = api_get_path(WEB_CODE_PATH).'auth/profile.php'.(!empty($_course['path']) ? '?coursePath='.$_course['path'].'&amp;courseCode='.$_course['official_code'] : '');
-        $navigation['myprofile']['title'] = get_lang('ModifyProfile');
+        if (api_is_profile_readable()) {
+            $navigation['myprofile']['url'] = api_get_path(WEB_CODE_PATH).'auth/profile.php'.(!empty($_course['path']) ? '?coursePath='.$_course['path'].'&amp;courseCode='.$_course['official_code'] : '');
+            $navigation['myprofile']['title'] = get_lang('ModifyProfile');
+        }
 
         // Link to my agenda
         $navigation['myagenda']['url'] = api_get_path(WEB_CODE_PATH).'calendar/agenda_js.php?type=personal';
@@ -1188,11 +1193,10 @@ class Template
             }
 
             // My Profile
-            if (api_get_setting('show_tabs', 'my_profile') == 'true' && api_get_setting(
-                'allow_social_tool'
-            ) != 'true'
-            ) {
-                $navigation['myprofile'] = $possible_tabs['myprofile'];
+            if (api_get_setting('show_tabs', 'my_profile') == 'true' && api_get_setting('allow_social_tool') != 'true') {
+                if (isset($possible_tabs['myprofile'])) {
+                    $navigation['myprofile'] = $possible_tabs['myprofile'];
+                }
             } else {
                 $menu_navigation['myprofile'] = $possible_tabs['myprofile'];
             }

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

@@ -71,7 +71,8 @@ class UserManager
      * @param array Array of user details (array('status'=>...,'username'=>..., ...))
      * @return mixed Array of user information
      */
-    public static function add($params) {
+    public static function add($params)
+    {
         global $_configuration;
 
         $access_url_id = 1;

+ 3 - 22
main/inc/routes.php

@@ -444,19 +444,10 @@ $app->match('/main/{file}', 'legacy.controller:classicAction', 'GET|POST')
     ->assert('file', '.+')
     ->assert('type', '.+');
 
-/** Logout already implemented by the the security service provider */
-
-/* $app->get('/logout', 'index.controller:logoutAction')
-    ->bind('logout')
-    ->after($cleanCourseSession);*/
-
 /** Login form */
 $app->match('/login', 'index.controller:loginAction', 'GET|POST')
     ->bind('login');
 
-/*$app->match('/admin/login-check', 'index.controller:checkLoginAction', 'GET|POST')
-->bind('login_check');*/
-
 /** Course home instead of courses/MATHS the new URL is web/courses/MATHS  */
 $app->match('/courses/{cidReq}/{id_session}/', 'course_home.controller:indexAction', 'GET|POST')
     ->assert('id_session', '\d+')
@@ -537,7 +528,6 @@ $app->get('/data/upload/groups/{groupId}/{file}', 'index.controller:getGroupFile
     ->assert('type', '.+');
 
 /** Admin */
-
 $app->get('/admin/dashboard', 'index.controller:dashboardAction')
     ->assert('type', '.+')
     ->bind('admin_dashboard');
@@ -659,24 +649,16 @@ $app->match('/admin/administrator/', 'admin.controller:indexAction', 'GET')
     ->assert('type', '.+')
     ->bind('admin_administrator');
 
-
-
 $app->match('/ajax', 'model_ajax.controller:indexAction', 'GET')
     ->assert('type', '.+')
     ->bind('model_ajax');
 
-
-// Roles
-// @todo improve route creation. Use mount() to write less
-
 if ($alreadyInstalled) {
-    // Takes a some time to load @todo improve this calls
     $app->mount('/admin/administrator/roles', new ChamiloLMS\Provider\ReflectionControllerProvider('role.controller'));
     $app->mount('/admin/administrator/question_scores', new ChamiloLMS\Provider\ReflectionControllerProvider('question_score.controller'));
     $app->mount('/admin/administrator/question_score_names', new ChamiloLMS\Provider\ReflectionControllerProvider('question_score_name.controller'));
 
     // Ministerio routes:
-
     $app->mount('/admin/administrator/branches', new ChamiloLMS\Provider\ReflectionControllerProvider('branch.controller'));
     $app->mount('/admin/administrator/juries', new ChamiloLMS\Provider\ReflectionControllerProvider('jury.controller'));
 
@@ -684,10 +666,9 @@ if ($alreadyInstalled) {
     $app->mount('/admin/jury_president', new ChamiloLMS\Provider\ReflectionControllerProvider('jury_president.controller'));
     $app->mount('/admin/jury_member', new ChamiloLMS\Provider\ReflectionControllerProvider('jury_member.controller'));
 
-    $app->mount('/tool/curriculum/category', new ChamiloLMS\Provider\ReflectionControllerProvider('curriculum_category.controller'));
-    $app->mount('/tool/curriculum/item', new ChamiloLMS\Provider\ReflectionControllerProvider('curriculum_item.controller'));
-    $app->mount('/tool/curriculum/user', new ChamiloLMS\Provider\ReflectionControllerProvider('curriculum_user.controller'));
+    $app->mount('/courses/{courseCode}/curriculum/category', new ChamiloLMS\Provider\ReflectionControllerProvider('curriculum_category.controller'));
+    $app->mount('/courses/{courseCode}/curriculum/item', new ChamiloLMS\Provider\ReflectionControllerProvider('curriculum_item.controller'));
+    $app->mount('/courses/{courseCode}/curriculum/user', new ChamiloLMS\Provider\ReflectionControllerProvider('curriculum_user.controller'));
 
 }
 
-

+ 38 - 13
main/inc/services.php

@@ -7,6 +7,19 @@
  * @package chamilo.services
  */
 
+
+// Flint
+$app->register(new Flint\Provider\ConfigServiceProvider());
+$app['root_dir'] = $app['root_sys'];
+
+$app->register(new Flint\Provider\RoutingServiceProvider(), array(
+    'routing.resource' => $app['sys_config_path'].'routing.yml',
+    'routing.options' => array(
+        'cache_dir' => $app['debug'] == true ? null : $app['sys_temp_path']
+        //'cache_dir' => $app['sys_temp_path']
+    ),
+));
+
 // Monolog.
 use Doctrine\Common\Persistence\AbstractManagerRegistry;
 use FranMoreno\Silex\Provider\PagerfantaServiceProvider;
@@ -35,6 +48,7 @@ if (is_writable($app['sys_temp_path'])) {
     }
 }
 
+
 //Setting HttpCacheService provider in order to use do: $app['http_cache']->run();
 /*
 $app->register(new Silex\Provider\HttpCacheServiceProvider(), array(
@@ -43,7 +57,15 @@ $app->register(new Silex\Provider\HttpCacheServiceProvider(), array(
 
 // http://symfony.com/doc/master/reference/configuration/security.html
 
-$app->register(new Silex\Provider\SecurityServiceProvider(), array(
+class SecurityServiceProvider extends \Silex\Provider\SecurityServiceProvider
+{
+    public function addFakeRoute($method, $pattern, $name)
+    {
+        // Don't do anything otherwise the closures will be dumped and that leads to fatal errors.
+    }
+}
+
+$app->register(new SecurityServiceProvider, array(
     'security.firewalls' => array(
         'login' => array(
             'pattern' => '^/login$',
@@ -67,15 +89,12 @@ $app->register(new Silex\Provider\SecurityServiceProvider(), array(
                 return $app['orm.em']->getRepository('Entity\User');
             }),
             'anonymous' => true
-        ),/*
-        'classic' => array(
-            'pattern' => '^/.*$'
-        )*/
+        )
     )
 ));
 
-// Registering Password encoder.
 
+// Registering Password encoder.
 $app['security.encoder.digest'] = $app->share(function($app) {
     // use the sha1 algorithm
     // don't base64 encode the password
@@ -83,6 +102,7 @@ $app['security.encoder.digest'] = $app->share(function($app) {
     return new MessageDigestPasswordEncoder($app['configuration']['password_encryption'], false, 1);
 });
 
+
 // What to do when login success?
 $app['security.authentication.success_handler.admin'] = $app->share(function($app) {
     return new ChamiloLMS\Component\Auth\LoginSuccessHandler($app['url_generator'], $app['security']);
@@ -95,13 +115,21 @@ $app['security.authentication.logout_handler.admin'] = $app->share(function($app
 
 // Role hierarchy
 $app['security.role_hierarchy'] = array(
-    'ROLE_ADMIN' => array('ROLE_QUESTION_MANAGER', 'ROLE_SESSION_MANAGER', 'ROLE_TEACHER', 'ROLE_ALLOWED_TO_SWITCH', 'ROLE_DIRECTOR'),
+    'ROLE_ADMIN' => array(
+        'ROLE_QUESTION_MANAGER',
+        'ROLE_SESSION_MANAGER',
+        'ROLE_TEACHER',
+        'ROLE_ALLOWED_TO_SWITCH',
+        'ROLE_DIRECTOR',
+        'ROLE_JURY_PRESIDENT'
+    ),
     'ROLE_RRHH' => array('ROLE_TEACHER'),
     'ROLE_TEACHER' => array('ROLE_STUDENT'),
     'ROLE_QUESTION_MANAGER' => array('ROLE_STUDENT', 'ROLE_QUESTION_MANAGER'),
     'ROLE_SESSION_MANAGER' => array('ROLE_STUDENT', 'ROLE_SESSION_MANAGER'),
     'ROLE_STUDENT' => array('ROLE_STUDENT'),
     'ROLE_ANONYMOUS' => array('ROLE_ANONYMOUS'),
+
     // Ministerio
     'ROLE_JURY_PRESIDENT' => array('ROLE_JURY_PRESIDENT', 'ROLE_JURY_MEMBER', 'ROLE_JURY_SUBSTITUTE'),
     'ROLE_JURY_SUBSTITUTE' => array('ROLE_JURY_SUBSTITUTE', 'ROLE_JURY_MEMBER'),
@@ -118,6 +146,8 @@ $app['security.access_rules'] = array(
     //array('^/main/admin/extra_field_workflow.php', 'ROLE_QUESTION_MANAGER'),
     array('^/main/admin/.*', 'ROLE_ADMIN'),
     array('^/admin/questionmanager', 'ROLE_QUESTION_MANAGER'),
+    array('^/main/auth/inscription.php', 'IS_AUTHENTICATED_ANONYMOUSLY'),
+    array('^/main/auth/lostPassword.php', 'IS_AUTHENTICATED_ANONYMOUSLY'),
     array('^/main/.*', array('ROLE_STUDENT')),
 
     // Ministerio routes
@@ -153,7 +183,7 @@ $app->register(new Silex\Provider\TranslationServiceProvider(), array(
 $app->register(new Silex\Provider\FormServiceProvider());
 
 // URL generator provider
-$app->register(new Silex\Provider\UrlGeneratorServiceProvider());
+//$app->register(new Silex\Provider\UrlGeneratorServiceProvider());
 
 // Needed to use the "entity" option in symfony forms
 
@@ -445,7 +475,6 @@ if ($app['assetic.enabled']) {
     );
 }
 
-
 // Gaufrette service provider (to manage files/dirs) (not used yet)
 /*
 use Bt51\Silex\Provider\GaufretteServiceProvider\GaufretteServiceProvider;
@@ -680,7 +709,3 @@ $app['curriculum_user.controller'] = $app->share(
         return new ChamiloLMS\Controller\Tool\Curriculum\CurriculumUserController($app);
     }
 );
-
-
-
-

+ 1 - 0
main/install/1.10.0/db_course.sql

@@ -1398,6 +1398,7 @@ CREATE TABLE c_quiz_category (
   lft int default NULL,
   rgt int default NULL,
   root int default NULL,
+  visibility INT default 1,
   PRIMARY KEY (iid)
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
 /*!40101 SET character_set_client = @saved_cs_client */;

+ 1 - 1
main/template/default/admin/administrator/branches/add.tpl

@@ -1,5 +1,5 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    {% import app.template_style ~ "/default_actions/settings.tpl" as actions %}
+    {% import app.template_style ~ "/crud_macros/simple_crud.tpl" as actions %}
     {{ actions.add(form, links) }}
 {% endblock %}

+ 1 - 1
main/template/default/admin/administrator/juries/add.tpl

@@ -1,5 +1,5 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    {% import app.template_style ~ "/default_actions/settings.tpl" as actions %}
+    {% import app.template_style ~ "/crud_macros/simple_crud.tpl" as actions %}
     {{ actions.add(form, links) }}
 {% endblock %}

+ 1 - 1
main/template/default/admin/administrator/juries/edit.tpl

@@ -1,5 +1,5 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    {% import app.template_style ~ "/default_actions/settings.tpl" as actions %}
+    {% import app.template_style ~ "/crud_macros/simple_crud.tpl" as actions %}
     {{ actions.edit(form, links) }}
 {% endblock %}

+ 1 - 1
main/template/default/admin/administrator/question_score/add.tpl

@@ -1,5 +1,5 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    {% import app.template_style ~ "/default_actions/settings.tpl" as actions %}
+    {% import app.template_style ~ "/crud_macros/simple_crud.tpl" as actions %}
     {{ actions.add(form, links) }}
 {% endblock %}

+ 1 - 1
main/template/default/admin/administrator/question_score/edit.tpl

@@ -1,5 +1,5 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    {% import app.template_style ~ "/default_actions/settings.tpl" as actions %}
+    {% import app.template_style ~ "/crud_macros/simple_crud.tpl" as actions %}
     {{ actions.edit(form, links) }}
 {% endblock %}

+ 1 - 1
main/template/default/admin/administrator/question_score_name/add.tpl

@@ -1,5 +1,5 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    {% import app.template_style ~ "/default_actions/settings.tpl" as actions %}
+    {% import app.template_style ~ "/crud_macros/simple_crud.tpl" as actions %}
     {{ actions.add(form, links) }}
 {% endblock %}

+ 1 - 1
main/template/default/admin/administrator/question_score_name/edit.tpl

@@ -1,5 +1,5 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    {% import app.template_style ~ "/default_actions/settings.tpl" as actions %}
+    {% import app.template_style ~ "/crud_macros/simple_crud.tpl" as actions %}
     {{ actions.edit(form, links) }}
 {% endblock %}

+ 1 - 1
main/template/default/admin/administrator/question_score_name/list.tpl

@@ -1,5 +1,5 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    {% import app.template_style ~ "/default_actions/settings.tpl" as actions %}
+    {% import app.template_style ~ "/crud_macros/simple_crud.tpl" as actions %}
     {{ actions.list(items, links) }}
 {% endblock %}

+ 1 - 1
main/template/default/admin/administrator/question_score_name/read.tpl

@@ -1,5 +1,5 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    {% import app.template_style ~ "/default_actions/settings.tpl" as actions %}
+    {% import app.template_style ~ "/crud_macros/simple_crud.tpl" as actions %}
     {{ actions.read(item, links) }}
 {% endblock %}

+ 1 - 1
main/template/default/admin/administrator/role/add.tpl

@@ -1,5 +1,5 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    {% import app.template_style ~ "/default_actions/settings.tpl" as actions %}
+    {% import app.template_style ~ "/crud_macros/simple_crud.tpl" as actions %}
     {{ actions.add(form, links) }}
 {% endblock %}

+ 1 - 1
main/template/default/admin/administrator/role/edit.tpl

@@ -1,5 +1,5 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    {% import app.template_style ~ "/default_actions/settings.tpl" as actions %}
+    {% import app.template_style ~ "/crud_macros/simple_crud.tpl" as actions %}
     {{ actions.edit(form, links) }}
 {% endblock %}

+ 1 - 1
main/template/default/admin/administrator/role/list.tpl

@@ -1,5 +1,5 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    {% import app.template_style ~ "/default_actions/settings.tpl" as actions %}
+    {% import app.template_style ~ "/crud_macros/simple_crud.tpl" as actions %}
     {{ actions.list(items, links) }}
 {% endblock %}

+ 1 - 1
main/template/default/admin/administrator/role/read.tpl

@@ -1,5 +1,5 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    {% import app.template_style ~ "/default_actions/settings.tpl" as actions %}
+    {% import app.template_style ~ "/crud_macros/simple_crud.tpl" as actions %}
     {{ actions.read(item, links) }}
 {% endblock %}

+ 51 - 0
main/template/default/crud_macros/course_crud.tpl

@@ -0,0 +1,51 @@
+{% macro list(items, links, courseCode) %}
+    <a href="{{ url(links.create_link, {'courseCode': courseCode }) }}">
+        {{ 'Add' |trans }}
+    </a>
+    <table class="table">
+    {% for item in items %}
+        <tr>
+            <td>
+                <a href="{{ url(links.read_link, {'courseCode': courseCode, id: item.id }) }}">
+                {{ item.name }}
+                </a>
+            </td>
+            <td>
+                <a class="btn" href="{{ url(links.update_link, {'courseCode': courseCode, id: item.id }) }}"> {{ 'Edit' |trans }}</a>
+                <a class="btn" href="{{ url(links.delete_link, {'courseCode': courseCode, id: item.id }) }}"> {{ 'Delete' |trans }}</a>
+            </td>
+        </tr>
+    {% endfor %}
+    </table>
+{% endmacro %}
+
+{% macro add(form, links, courseCode) %}
+    <a href="{{ url(links.list_link, {'courseCode': courseCode }) }}">
+        {{ 'List' |trans }}
+    </a>
+    <hr />
+    <form action="{{ url(links.create_link, {'courseCode': courseCode} ) }}" method="post" {{ form_enctype(form) }}>
+        {{ form_widget(form) }}
+    </form>
+{% endmacro %}
+
+{% macro edit(form, links, courseCode) %}
+    <a href="{{ url(links.list_link, {'courseCode': courseCode}) }}">
+        {{ 'List' |trans }}
+    </a>
+    <form action="{{ url(links.update_link, {'courseCode': courseCode, id : item.id}) }}" method = "post" {{ form_enctype(form) }}>
+        {{ form_widget(form) }}
+    </form>
+{% endmacro %}
+
+{% macro read(item, links, courseCode) %}
+    <a href="{{ url(links.list_link, {'courseCode': courseCode}) }}">
+        {{ 'List' |trans }}
+    </a>
+    <a href="{{ url(links.update_link, {'courseCode': courseCode, id : item.id}) }}">
+        {{ 'Edit' |trans }}
+    </a>
+    <h2>{{ item.id }}</h2>
+    <p>{{ item.name }}</p>
+{% endmacro %}
+

+ 0 - 0
main/template/default/default_actions/settings.tpl → main/template/default/crud_macros/simple_crud.tpl


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

@@ -1,5 +1,5 @@
 {% extends app.template_style ~ '/layout/layout_1_col.tpl' %}
 {% block content %}
-    {{ error_code }} - {{ error_message }}
+    {{ error.code }} - {{ error.message }}
     {{ content }}
-{% endblock %}
+{% endblock %}

+ 21 - 12
main/template/default/layout/menu.tpl

@@ -1,5 +1,4 @@
 {% if menu is not null %}
-
 <div class="navbar subnav">
     <div class="navbar-inner">
         {% if app.full_width == 1 %}
@@ -27,20 +26,30 @@
                     </li>
                     {% endif %}
 
-                    <li class="dropdown">
-                        <a class="dropdown-toggle" data-toggle="dropdown" href="#">
+                    {% if is_profile_editable == true %}
+                        <li class="dropdown">
+                            <a class="dropdown-toggle" data-toggle="dropdown" href="#">
+                                {{ _u.messages_count }}  <img src="{{ _u.avatar_small }}"/>
+                                {{ _u.complete_name }}
+                                <b class="caret"></b>
+                            </a>
+                            <ul class="dropdown-menu">
+                                <li>
+                                    {{ profile_link }}
+                                    {{ message_link }}
+                                </li>
+                            </ul>
+                        </li>
+                    {% else %}
+                        <li>
+                            <a>
                             {{ _u.messages_count }}  <img src="{{ _u.avatar_small }}"/>
                             {{ _u.complete_name }}
-                            <b class="caret"></b>
-                        </a>
-                        <ul class="dropdown-menu">
-                            <li>
-                                {{ profile_link }}
-                                {{ message_link }}
-                            </li>
-                        </ul>
+                            </a>
+                        </li>
+                    {% endif %}
                     <li>
-                        <a id="logout_button" class="logout" title="{{ "Logout"|get_lang }}" href="{{ logout_link }}" >
+                        <a id="logout_button" class="logout" title="{{ "Logout"|get_lang }}" href="{{ url('admin_logout') }}" >
                             <img src="{{ "exit.png"|icon(22) }}">
                         </a>
                     </li>

+ 2 - 2
main/template/default/tool/curriculum/category/add.tpl

@@ -1,5 +1,5 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    {% import app.template_style ~ "/default_actions/settings.tpl" as actions %}
-    {{ actions.add(form, links) }}
+    {% import app.template_style ~ "/crud_macros/course_crud.tpl" as actions %}
+    {{ actions.add(form, links, app.request.get('courseCode')) }}
 {% endblock %}

+ 2 - 2
main/template/default/tool/curriculum/category/add_from_parent.tpl

@@ -1,10 +1,10 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    <a href="{{ url(links.list_link) }}">
+    <a href="{{ url(links.list_link, {'courseCode' : app.request.get('courseCode')}) }}">
         List
     </a>
     <hr />
-    <form action="{{ url(links.add_from_parent_link, { "id" : parent_id }) }}" method="post" {{ form_enctype(form) }}>
+    <form action="{{ url(links.add_from_parent_link, {'courseCode' : app.request.get('courseCode'), "id" : parent_id }) }}" method="post" {{ form_enctype(form) }}>
         {{ form_widget(form) }}
     </form>
 {% endblock %}

+ 2 - 2
main/template/default/tool/curriculum/category/edit.tpl

@@ -1,5 +1,5 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    {% import app.template_style ~ "/default_actions/settings.tpl" as actions %}
-    {{ actions.edit(form, links) }}
+    {% import app.template_style ~ "/crud_macros/course_crud.tpl" as actions %}
+    {{ actions.edit(form, links, app.request.get('courseCode')) }}
 {% endblock %}

+ 1 - 1
main/template/default/tool/curriculum/category/list.tpl

@@ -1,6 +1,6 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    <a href="{{ url(links.create_link) }}">
+    <a href="{{ url(links.create_link, {'courseCode' : app.request.get('courseCode') }) }}">
         Add
     </a>
     {{ tree }}

+ 4 - 2
main/template/default/tool/curriculum/category/read.tpl

@@ -1,11 +1,13 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    {{ item.id }} {{ item.name  }}
+    {{ item.id }} {{ item.name }}
     <hr />
     <ul>
     {% for subitem in subitems %}
         <li>
-            <a href="{{ url(links.question_score_name_read_link, { id: subitem.id} ) }}">{{ subitem.name }}</a>
+            <a href="{{ url(links.question_score_name_read_link, {'courseCode' : app.request.get('courseCode'), id: subitem.id} ) }}">
+                {{ subitem.name }}
+            </a>
         </li>
     {% endfor %}
     </ul>

+ 2 - 2
main/template/default/tool/curriculum/item/add.tpl

@@ -1,5 +1,5 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    {% import app.template_style ~ "/default_actions/settings.tpl" as actions %}
-    {{ actions.add(form, links) }}
+    {% import app.template_style ~ "/crud_macros/course_crud.tpl" as actions %}
+    {{ actions.add(form, links, app.request.get('courseCode')) }}
 {% endblock %}

+ 2 - 2
main/template/default/tool/curriculum/item/add_from_category.tpl

@@ -1,10 +1,10 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    <a href="{{ url(links.list_link) }}">
+    <a href="{{ url(links.list_link, {'courseCode' : app.request.get('courseCode')}) }}">
         List
     </a>
     <hr />
-    <form action="{{ url(links.add_from_category, { "id" : parent_id }) }}" method="post" {{ form_enctype(form) }}>
+    <form action="{{ url(links.add_from_category, {'courseCode' : app.request.get('courseCode'), "id" : parent_id }) }}" method="post" {{ form_enctype(form) }}>
         {{ form_widget(form) }}
     </form>
 {% endblock %}

+ 2 - 2
main/template/default/tool/curriculum/item/edit.tpl

@@ -1,5 +1,5 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    {% import app.template_style ~ "/default_actions/settings.tpl" as actions %}
-    {{ actions.edit(form, links) }}
+    {% import app.template_style ~ "/crud_macros/course_crud.tpl" as actions %}
+    {{ actions.edit(form, links, app.request.get('courseCode')) }}
 {% endblock %}

+ 4 - 4
main/template/default/tool/curriculum/item/list.tpl

@@ -1,19 +1,19 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    <a href="{{ url(links.create_link) }}">
+    <a href="{{ url(links.create_link, {'courseCode' : app.request.get('courseCode')}) }}">
         {{ 'Add' |trans }}
     </a>
     <table class="table">
     {% for item in items %}
         <tr>
             <td>
-                <a href="{{ url(links.read_link, { id: item.id }) }}">
+                <a href="{{ url(links.read_link, {'courseCode' : app.request.get('courseCode'), id: item.id }) }}">
                 {{ item.title }}
                 </a>
             </td>
             <td>
-                <a class="btn" href="{{ url(links.update_link, { id: item.id }) }}"> {{ 'Edit' |trans }}</a>
-                <a class="btn" href="{{ url(links.delete_link, { id: item.id }) }}"> {{ 'Delete' |trans }}</a>
+                <a class="btn" href="{{ url(links.update_link, {'courseCode' : app.request.get('courseCode'), id: item.id }) }}"> {{ 'Edit' |trans }}</a>
+                <a class="btn" href="{{ url(links.delete_link, {'courseCode' : app.request.get('courseCode'), id: item.id }) }}"> {{ 'Delete' |trans }}</a>
             </td>
         </tr>
     {% endfor %}

+ 4 - 2
main/template/default/tool/curriculum/item/read.tpl

@@ -1,11 +1,13 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    {{ item.id }} {{ item.name  }}
+    {{ item.id }} {{ item.name }}
     <hr />
     <ul>
     {% for subitem in subitems %}
         <li>
-            <a href="{{ url(links.question_score_name_read_link, { id: subitem.id} ) }}">{{ subitem.name }}</a>
+            <a href="{{ url(links.question_score_name_read_link, {'courseCode' : app.request.get('courseCode'), id: subitem.id} ) }}">
+                {{ subitem.name }}
+            </a>
         </li>
     {% endfor %}
     </ul>

+ 2 - 2
main/template/default/tool/curriculum/user/add.tpl

@@ -1,5 +1,5 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    {% import app.template_style ~ "/default_actions/settings.tpl" as actions %}
-    {{ actions.add(form, links) }}
+    {% import app.template_style ~ "/crud_macros/course_crud.tpl" as actions %}
+    {{ actions.add(form, links, app.request.get('courseCode')) }}
 {% endblock %}

+ 2 - 2
main/template/default/tool/curriculum/user/add_from_category.tpl

@@ -1,10 +1,10 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    <a href="{{ url(links.list_link) }}">
+    <a href="{{ url(links.list_link, {'courseCode' : app.request.get('courseCode')) }}">
         List
     </a>
     <hr />
-    <form action="{{ url(links.add_from_category, { "id" : parent_id }) }}" method="post" {{ form_enctype(form) }}>
+    <form action="{{ url(links.add_from_category, {'courseCode' : app.request.get('courseCode'), "id" : parent_id }) }}" method="post" {{ form_enctype(form) }}>
         {{ form_widget(form) }}
     </form>
 {% endblock %}

+ 2 - 2
main/template/default/tool/curriculum/user/edit.tpl

@@ -1,5 +1,5 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    {% import app.template_style ~ "/default_actions/settings.tpl" as actions %}
-    {{ actions.edit(form, links) }}
+    {% import app.template_style ~ "/crud_macros/course_crud.tpl" as actions %}
+    {{ actions.edit(form, links, {'courseCode' : app.request.get('courseCode'))} }}
 {% endblock %}

+ 14 - 10
main/template/default/tool/curriculum/user/list.tpl

@@ -83,7 +83,7 @@ function addTagFormDeleteLink($tagFormLi) {
 function save(itemId) {
     var form = $("#"+itemId).parent();
     var serializedForm = form.serialize();
-    $.post('{{ url('curriculum_user.controller:saveUserItemAction') }}', serializedForm);
+    $.post('{{ url('curriculum_user.controller:saveUserItemAction', {'courseCode' : app.request.get('courseCode')) }}', serializedForm);
     return false;
 }
 
@@ -113,9 +113,10 @@ function saveAll() {
 
                 {% for item in subcategory.items %}
                     <h5> {{ item.title }} (item) - Max {{ item.maxRepeat }}</h5>
-
+                    <div class="row">
                     {{ form_start(form_list[item.id]) }}
-                        <div id="items_{{ item.id }}" class="items" data-max="{{ item.maxRepeat }}" data-prototype="{{ form_widget(form_list[item.id].userItems.vars.prototype)|e }}" >
+
+                        <div id="items_{{ item.id }}" class="items span8" data-max="{{ item.maxRepeat }}" data-prototype="{{ form_widget(form_list[item.id].userItems.vars.prototype)|e }}" >
                             {% for widget in form_list[item.id].userItems.children %}
                                 {{ _self.widget_prototype(widget, 'Remove item') }}
                             {% endfor %}
@@ -124,16 +125,19 @@ function saveAll() {
                             </ul>
                         </div>
 
-                        <div class="btn-group">
-                            {# form_widget(form_list[item.id].submit) #}
-                            <!-- <a class="btn btn-success" onclick="save('items_{{ item.id }}');" data-target="items_{{ item.id }}">{{ 'Save items' | get_lang }}</a> -->
-                            {% if item.maxRepeat > 1 %}
-                                <a class="btn-add btn btn-primary" data-target="items_{{ item.id }}"><i class="icon-plus-sign icon-large"></i></a>
-                            {% endif %}
+                        <div class="span8">
+                            <div class="btn-group">
+                                {# form_widget(form_list[item.id].submit) #}
+                                <!-- <a class="btn btn-success" onclick="save('items_{{ item.id }}');" data-target="items_{{ item.id }}">{{ 'Save items' | get_lang }}</a> -->
+                                {% if item.maxRepeat > 1 %}
+                                    <a class="btn-add btn btn-primary" data-target="items_{{ item.id }}"><i class="icon-plus-sign icon-large"></i></a>
+                                {% endif %}
+                            </div>
                         </div>
-
                     {{ form_end(form_list[item.id]) }}
+                    </div>
                 {% endfor %}
+
             {% endfor %}
         </div>
     </div>

+ 4 - 2
main/template/default/tool/curriculum/user/read.tpl

@@ -1,11 +1,13 @@
 {% extends app.template_style ~ "/layout/layout_1_col.tpl" %}
 {% block content %}
-    {{ item.id }} {{ item.name  }}
+    {{ item.id }} {{ item.name }}
     <hr />
     <ul>
     {% for subitem in subitems %}
         <li>
-            <a href="{{ url(links.question_score_name_read_link, { id: subitem.id} ) }}">{{ subitem.name }}</a>
+            <a href="{{ url(links.question_score_name_read_link, {'courseCode' : app.request.get('courseCode'), id: subitem.id} ) }}">
+                {{ subitem.name }}
+            </a>
         </li>
     {% endfor %}
     </ul>

+ 3 - 3
src/ChamiloLMS/Controller/Admin/Administrator/BranchController.php

@@ -65,7 +65,7 @@ class BranchController extends CommonController
 
     /**
     *
-    * @Route("/{id}", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
     public function readAction($id)
@@ -132,7 +132,7 @@ class BranchController extends CommonController
 
     /**
     *
-    * @Route("/{id}/edit", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}/edit", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
     public function editAction($id)
@@ -142,7 +142,7 @@ class BranchController extends CommonController
 
     /**
     *
-    * @Route("/{id}/delete", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}/delete", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
     public function deleteAction($id)

+ 4 - 4
src/ChamiloLMS/Controller/Admin/Administrator/JuryController.php

@@ -36,7 +36,7 @@ class JuryController extends CommonController
 
     /**
     *
-    * @Route("/{id}", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
     public function readAction($id)
@@ -62,7 +62,7 @@ class JuryController extends CommonController
 
     /**
     *
-    * @Route("/{id}/edit", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}/edit", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
     public function editAction($id)
@@ -71,7 +71,7 @@ class JuryController extends CommonController
     }
 
     /**
-    * @Route("/{id}/delete", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}/delete", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
     public function deleteAction($id)
@@ -80,7 +80,7 @@ class JuryController extends CommonController
     }
 
      /**
-    * @Route("/{id}/remove-member", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}/remove-member", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
     public function removeMemberAction($id)

+ 2 - 2
src/ChamiloLMS/Controller/Admin/Administrator/QuestionScoreController.php

@@ -59,7 +59,7 @@ class QuestionScoreController extends CommonController
 
     /**
     *
-    * @Route("/{id}/edit", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}/edit", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
     public function editAction($id)
@@ -69,7 +69,7 @@ class QuestionScoreController extends CommonController
 
     /**
     *
-    * @Route("/{id}/delete", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}/delete", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
     public function deleteAction($id)

+ 3 - 3
src/ChamiloLMS/Controller/Admin/Administrator/QuestionScoreNameController.php

@@ -31,7 +31,7 @@ class QuestionScoreNameController extends CommonController
 
     /**
     *
-    * @Route("/{id}", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
     public function readAction($id)
@@ -50,7 +50,7 @@ class QuestionScoreNameController extends CommonController
 
     /**
     *
-    * @Route("/{id}/edit", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}/edit", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
     public function editAction($id)
@@ -60,7 +60,7 @@ class QuestionScoreNameController extends CommonController
 
     /**
     *
-    * @Route("/{id}/delete", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}/delete", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
     public function deleteAction($id)

+ 3 - 3
src/ChamiloLMS/Controller/Admin/Administrator/RoleController.php

@@ -32,7 +32,7 @@ class RoleController extends CommonController
 
     /**
     *
-    * @Route("/{id}", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
     public function readAction($id)
@@ -51,7 +51,7 @@ class RoleController extends CommonController
 
     /**
     *
-    * @Route("/{id}/edit", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}/edit", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
     public function editAction($id)
@@ -61,7 +61,7 @@ class RoleController extends CommonController
 
     /**
     *
-    * @Route("/{id}/delete", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}/delete", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
     public function deleteAction($id)

+ 1 - 1
src/ChamiloLMS/Controller/Admin/Director/BranchDirectorController.php

@@ -69,7 +69,7 @@ class BranchDirectorController extends CommonController
 
     /**
     *
-    * @Route("/{id}", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
     public function readAction($id)

+ 14 - 23
src/ChamiloLMS/Controller/BaseController.php

@@ -12,6 +12,7 @@ use Symfony\Component\HttpFoundation\Request;
 use Doctrine\ORM\Query;
 use Doctrine\ORM\NoResultException;
 use Silex\Application;
+use Flint\Controller\Controller as FlintController;
 
 use Symfony\Component\Routing\Annotation\Route;
 use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
@@ -21,9 +22,10 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
  *
  * @abstract
  */
-abstract class BaseController
+abstract class BaseController extends FlintController
 {
     protected $app;
+    protected $pimple;
 
     /**
      * @param Application $app
@@ -31,6 +33,8 @@ abstract class BaseController
     public function __construct(Application $app)
     {
         $this->app = $app;
+        // In order to use the Flint Controller
+        $this->pimple = $app;
     }
 
     /**
@@ -81,28 +85,14 @@ abstract class BaseController
         return $this->get('request');
     }
 
-    protected function redirect($redirect)
-    {
-        return $this->app->redirect($redirect);
-    }
-
     protected function createNotFoundException($message = 'Not Found', \Exception $previous = null)
     {
         return $this->app->abort(404, $message);
     }
 
-    /**
-     * @param string $item
-     * @return mixed
-     */
-    protected function get($item)
-    {
-        return $this->app[$item];
-    }
-
     protected function getManager()
     {
-        return $this->app['orm.em'];
+        return $this->get('orm.em');
     }
 
     /**
@@ -114,14 +104,15 @@ abstract class BaseController
     protected function createUrl($label, $params = array())
     {
         $links = $this->generateLinks();
+        $courseCode = $this->getRequest()->get('courseCode');
+        $params['courseCode'] = $courseCode;
         if (isset($links) && is_array($links) && isset($links[$label])) {
-            $url = $this->get('url_generator')->generate($links[$label], $params);
+            $url = $this->generateUrl($links[$label], $params);
             return $url;
         }
-        return $url = $this->get('url_generator')->generate($links['list_link']);
+        return $url = $this->generateUrl($links['list_link']);
     }
 
-
     // CRUD default actions
 
     /**
@@ -154,6 +145,7 @@ abstract class BaseController
                 $item = $form->getData();
                 $this->createAction($item);
                 $this->get('session')->getFlashBag()->add('success', "Added");
+
                 $url = $this->createUrl('list_link');
                 return $this->redirect($url);
             }
@@ -168,7 +160,7 @@ abstract class BaseController
 
     /**
      *
-     * @Route("/{id}", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+     * @Route("/{id}", requirements={"id" = "\d+"})
      * @Method({"GET"})
      */
     public function readAction($id)
@@ -180,7 +172,7 @@ abstract class BaseController
 
     /**
      *
-     * @Route("/{id}/edit", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+     * @Route("/{id}/edit", requirements={"id" = "\d+"}})
      * @Method({"GET"})
      */
     public function editAction($id)
@@ -217,7 +209,7 @@ abstract class BaseController
 
     /**
      *
-     * @Route("/{id/delete}", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+     * @Route("/{id}/delete", requirements={"id" = "\d+"})
      * @Method({"GET"})
      */
     public function deleteAction($id)
@@ -231,7 +223,6 @@ abstract class BaseController
         }
     }
 
-
     /**
      * Base "read" action.
      *

+ 2 - 10
src/ChamiloLMS/Controller/CommonController.php

@@ -12,12 +12,6 @@ use ChamiloLMS\Controller\BaseController;
  */
 class CommonController extends BaseController
 {
-    public $languageFiles = array();
-
-    public function __construct(Application $app)
-    {
-        parent::__construct($app);
-    }
 
     /**
      * {@inheritdoc}
@@ -43,8 +37,8 @@ class CommonController extends BaseController
     /**
      * {@inheritdoc}
      */
-    protected function getControllerAlias() {
-
+    protected function getControllerAlias()
+    {
     }
 
     /**
@@ -74,7 +68,6 @@ class CommonController extends BaseController
         );
     }
 
-
     /**
      * @param Application $app
      * @param array $breadcrumbs
@@ -129,5 +122,4 @@ class CommonController extends BaseController
         );
         $app['breadcrumbs'] = $bread;
     }
-
 }

+ 3 - 3
src/ChamiloLMS/Controller/IndexController.php

@@ -198,7 +198,6 @@ class IndexController extends CommonController
         $app['template']->assign('error', $app['security.last_error']($request));
         $response = $app['template']->render_template('auth/login.tpl');
         return new Response($response, 200, array('Cache-Control' => 's-maxage=3600, public'));
-        //return new Response($response, 200, array());
     }
 
     /**
@@ -287,8 +286,9 @@ class IndexController extends CommonController
           ->getForm();
           return $app['template']->assign('form', $form->createView());
          */
-
-        $form = new \FormValidator('formLogin', 'POST', $app['url_generator']->generate('admin_login_check'), null, array('class' => 'form-vertical'));
+        $url = $app['url_generator']->generate('admin_login_check');
+        //var_dump($app['router']->generate('admin_login_check'));
+        $form = new \FormValidator('formLogin', 'POST', $url , null, array('class' => 'form-vertical'));
         $form->addElement(
             'text',
             'username',

+ 18 - 18
src/ChamiloLMS/Controller/Tool/Curriculum/CurriculumCategoryController.php

@@ -14,7 +14,6 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
 
 /**
  * Class CurriculumController
- * @todo @route and @method function don't work yet
  * @package ChamiloLMS\Controller
  * @author Julio Montoya <gugli100@gmail.com>
  */
@@ -25,7 +24,7 @@ class CurriculumCategoryController extends CommonController
      * @Route("/")
      * @Method({"GET"})
      */
-    public function indexAction()
+    public function indexAction($courseCode)
     {
         $options = array(
             'decorate' => true,
@@ -33,24 +32,25 @@ class CurriculumCategoryController extends CommonController
             'rootClose' => '</ul>',
             'childOpen' => '<li>',
             'childClose' => '</li>',
-            'nodeDecorator' => function($row) {
+            'nodeDecorator' => function ($row) use ($courseCode) {
                 $addChildren = null;
                 $items = null;
                 if ($row['lvl'] <= 0) {
-                    $addChildren = '<a class="btn" href="'.$this->createUrl('add_from_parent_link', array('id' => $row['id'])).'">Add children</a>';
+
+                    $addChildren = '<a class="btn" href="'.$this->createUrl('add_from_parent_link', array('courseCode' => $courseCode, 'id' => $row['id'])).'">Add children</a>';
                 } else {
-                    $addChildren = '<a class="btn" href="'.$this->createUrl('add_from_category', array('id' => $row['id'])).'">Add items</a>';
+                    $addChildren = '<a class="btn" href="'.$this->createUrl('add_from_category', array('courseCode' => $courseCode, 'id' => $row['id'])).'">Add items</a>';
                     //$items = $row['items'];
                     $items = '<ul>';
                     foreach ($row['items'] as $item) {
-                        $url = ' <a class="btn" href="'.$this->createUrl('edit_item', array('id' => $item['id'])).'">Edit</a>';
+                        $url = ' <a class="btn" href="'.$this->createUrl('edit_item', array('courseCode' => $courseCode, 'id' => $item['id'])).'">Edit</a>';
                         $items.= '<li>'.$item['title']." (item) ".$url.'</li>';
                     }
                     $items .= '</ul>';
                 }
-                $readLink = '<a href="'.$this->createUrl('read_link', array('id' => $row['id'])).'">'.$row['title'].'</a>';
-                $editLink = '<a class="btn" href="'.$this->createUrl('update_link', array('id' => $row['id'])).'">Edit</a>';
-                $deleteLink = '<a class="btn" href="'.$this->createUrl('delete_link', array('id' => $row['id'])).'"/>Delete</a>';
+                $readLink = '<a href="'.$this->createUrl('read_link', array('courseCode' => $courseCode, 'id' => $row['id'])).'">'.$row['title'].'</a>';
+                $editLink = '<a class="btn" href="'.$this->createUrl('update_link', array('courseCode' => $courseCode, 'id' => $row['id'])).'">Edit</a>';
+                $deleteLink = '<a class="btn" href="'.$this->createUrl('delete_link', array('courseCode' => $courseCode, 'id' => $row['id'])).'"/>Delete</a>';
 
                 return $readLink.' '.$addChildren.' '.$editLink.' '.$deleteLink.$items;
             }
@@ -71,19 +71,20 @@ class CurriculumCategoryController extends CommonController
             ->getQuery();
 
         $htmlTree = $repo->buildTree($query->getArrayResult(), $options);
+
         $this->get('template')->assign('tree', $htmlTree);
         $this->get('template')->assign('links', $this->generateLinks());
         $response = $this->get('template')->render_template($this->getTemplatePath().'list.tpl');
-        return new Response($response, 200, array());
 
+        return new Response($response, 200, array());
     }
 
     /**
     *
-    * @Route("/{id}", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}/show", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
-    public function readAction($id)
+    public function readCategoryAction($courseCode, $id)
     {
         return parent::readAction($id);
     }
@@ -92,7 +93,7 @@ class CurriculumCategoryController extends CommonController
     * @Route("/add")
     * @Method({"GET"})
     */
-    public function addAction()
+    public function addCategoryAction($courseCode)
     {
         return parent::addAction();
     }
@@ -137,20 +138,20 @@ class CurriculumCategoryController extends CommonController
 
     /**
     *
-    * @Route("/{id}/edit", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}/edit", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
-    public function editAction($id)
+    public function editCategoryAction($courseCode, $id)
     {
         return parent::editAction($id);
     }
 
     /**
     *
-    * @Route("/{id}/delete", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}/delete", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
-    public function deleteAction($id)
+    public function deleteCategoryAction($courseCode, $id)
     {
         return parent::deleteAction($id);
     }
@@ -167,7 +168,6 @@ class CurriculumCategoryController extends CommonController
         $routes['add_from_category'] = 'curriculum_item.controller:addFromCategoryAction';
         $routes['edit_item'] = 'curriculum_item.controller:editAction';
 
-
         return $routes ;
     }
 

+ 3 - 6
src/ChamiloLMS/Controller/Tool/Curriculum/CurriculumItemController.php

@@ -14,7 +14,6 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
 
 /**
  * Class CurriculumItemController
- * @todo @route and @method function don't work yet
  * @package ChamiloLMS\Controller
  * @author Julio Montoya <gugli100@gmail.com>
  */
@@ -32,7 +31,7 @@ class CurriculumItemController extends CommonController
 
     /**
     *
-    * @Route("/{id}", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
     public function readAction($id)
@@ -91,7 +90,7 @@ class CurriculumItemController extends CommonController
 
     /**
     *
-    * @Route("/{id}/edit", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}/edit", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
     public function editAction($id)
@@ -101,7 +100,7 @@ class CurriculumItemController extends CommonController
 
     /**
     *
-    * @Route("/{id}/delete", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}/delete", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
     public function deleteAction($id)
@@ -118,8 +117,6 @@ class CurriculumItemController extends CommonController
     {
         $routes = parent::generateDefaultCrudRoutes();
         $routes['add_from_category'] = 'curriculum_item.controller:addFromCategoryAction';
-        //$routes['add_items'] = 'curriculum_item.controller:addItemsAction';
-
         return $routes ;
     }
 

+ 3 - 3
src/ChamiloLMS/Controller/Tool/Curriculum/CurriculumUserController.php

@@ -213,7 +213,7 @@ class CurriculumUserController extends CommonController
 
     /**
     *
-    * @Route("/{id}", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
     public function readAction($id)
@@ -232,7 +232,7 @@ class CurriculumUserController extends CommonController
 
     /**
     *
-    * @Route("/{id}/edit", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}/edit", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
     public function editAction($id)
@@ -242,7 +242,7 @@ class CurriculumUserController extends CommonController
 
     /**
     *
-    * @Route("/{id}/delete", requirements={"id" = "\d+"}, defaults={"foo" = "bar"})
+    * @Route("/{id}/delete", requirements={"id" = "\d+"})
     * @Method({"GET"})
     */
     public function deleteAction($id)

+ 1 - 1
src/ChamiloLMS/Form/CurriculumItemRelUserType.php

@@ -17,7 +17,7 @@ class CurriculumItemRelUserType extends AbstractType
 
     public function buildForm(FormBuilderInterface $builder, array $options)
     {
-        $builder->add('description', 'text', array('label' => ' ', 'attr' => array('class' => 'span8')));
+        $builder->add('description', 'text', array('label' => ' ', 'attr' => array('class' => 'span7')));
         $builder->add('item_id', 'hidden', array('attr' => array('value' => $this->itemId)));
     }
 

+ 34 - 15
src/ChamiloLMS/Provider/ReflectionControllerProvider.php

@@ -35,10 +35,14 @@ class ReflectionControllerProvider implements ControllerProviderInterface
         /** @var \Silex\ControllerCollection $controllers */
         $controllers = $app['controllers_factory'];
 
+        // Routes are already cached using Flint
+        if ($app['debug'] == false) {
+            return $controllers;
+        }
+
         $reflection = new \ReflectionClass($app[$this->controllerName]);
 
         $annotationReader = new AnnotationReader();
-        //$classAnnotations = $annotationReader->getClassAnnotations($reflection);
         $routeAnnotation = new Route(array());
         $methodAnnotation = new Method(array());
 
@@ -46,37 +50,52 @@ class ReflectionControllerProvider implements ControllerProviderInterface
 
         foreach ($methods as $method) {
             $methodName = $method->getName();
+
             $controllerName = $this->controllerName.':'.$methodName;
 
-            if (in_array($methodName, array('__construct', 'get', 'getManager'))) {
+            // Parse only function with the "Action" suffix
+
+            if (strpos($methodName, 'Action') === false) {
                 continue;
             }
 
-            /** @var Route $routeObject */
-            $routeObject = $annotationReader->getMethodAnnotation($method, $routeAnnotation);
-            $req = $routeObject->getRequirements();
-            //$routeObject->setMethods();
+            // Getting all annotations
+            $routeObjects = $annotationReader->getMethodAnnotations($method);
 
             /** @var Method $routeObject */
             $methodObject = $annotationReader->getMethodAnnotation($method, $methodAnnotation);
 
             $methodsToString = 'GET';
+
             if ($methodObject) {
                 $methodsToString = implode('|', $methodObject->getMethods());
             }
 
-            if ($routeObject) {
-                $match = $controllers->match($routeObject->getPath(), $controllerName, $methodsToString);
-                //var_dump($controllerName);
-                $match->bind($controllerName);
-                // setRequirements
-                if (!empty($req)) {
-                    foreach ($req as $key => $value) {
-                        $match->assert($key, $value);
+            /** @var Route $routeObject */
+            foreach ($routeObjects as $routeObject) {
+
+                if ($routeObject && is_a($routeObject, 'Symfony\Component\Routing\Annotation\Route')) {
+
+                    $match = $controllers->match($routeObject->getPath(), $controllerName, $methodsToString);
+
+                    // setRequirements
+                    if (!empty($req)) {
+                        foreach ($req as $key => $value) {
+                            $match->assert($key, $value);
+                        }
                     }
+                    $defaults = $routeObject->getDefaults();
+                    //var_dump($routeObject);
+                    //var_dump($defaults);
+                    if (!empty($defaults)) {
+                        foreach ($defaults as $key => $value) {
+                            $match->value($key, $value);
+                        }
+                    }
+
+                    $match->bind($controllerName);
                 }
             }
-
         }
         return $controllers;
     }

+ 3 - 0
src/ChamiloLMS/Resources/config/route_example.yml

@@ -0,0 +1,3 @@
+homepage:
+    path:      /homepage
+    defaults:  { _controller: index.controller:indexAction, culture: en }

+ 1 - 1
vendor/autoload.php

@@ -4,4 +4,4 @@
 
 require_once __DIR__ . '/composer' . '/autoload_real.php';
 
-return ComposerAutoloaderInit6849b8aa9cb29cb82589890fae069cb3::getLoader();
+return ComposerAutoloaderInit1f12a82cc2ba6cc62e0ea30ebe1f1130::getLoader();

+ 13 - 0
vendor/composer/autoload_files.php

@@ -0,0 +1,13 @@
+<?php
+
+// autoload_files.php generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = dirname($vendorDir);
+
+return array(
+    $vendorDir . '/symfony/intl/Symfony/Component/Intl/Resources/stubs/functions.php',
+    $vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php',
+    $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
+    $vendorDir . '/kriswallsmith/assetic/src/functions.php',
+);

+ 1 - 0
vendor/composer/autoload_namespaces.php

@@ -59,6 +59,7 @@ return array(
     'Gedmo' => array($vendorDir . '/gedmo/doctrine-extensions/lib'),
     'Gaufrette' => array($vendorDir . '/knplabs/gaufrette/src'),
     'FranMoreno' => array($vendorDir . '/franmomu/silex-pagerfanta-provider/src'),
+    'Flint' => array($vendorDir . '/flint/flint/src'),
     'Entity' => array($baseDir . '/main/inc'),
     'Doctrine\\ORM' => array($vendorDir . '/doctrine/orm/lib'),
     'Doctrine\\DBAL\\Migrations' => array($vendorDir . '/doctrine/migrations/lib'),

+ 6 - 7
vendor/composer/autoload_real.php

@@ -2,7 +2,7 @@
 
 // autoload_real.php generated by Composer
 
-class ComposerAutoloaderInit6849b8aa9cb29cb82589890fae069cb3
+class ComposerAutoloaderInit1f12a82cc2ba6cc62e0ea30ebe1f1130
 {
     private static $loader;
 
@@ -19,9 +19,9 @@ class ComposerAutoloaderInit6849b8aa9cb29cb82589890fae069cb3
             return self::$loader;
         }
 
-        spl_autoload_register(array('ComposerAutoloaderInit6849b8aa9cb29cb82589890fae069cb3', 'loadClassLoader'), true, true);
+        spl_autoload_register(array('ComposerAutoloaderInit1f12a82cc2ba6cc62e0ea30ebe1f1130', 'loadClassLoader'), true, true);
         self::$loader = $loader = new \Composer\Autoload\ClassLoader();
-        spl_autoload_unregister(array('ComposerAutoloaderInit6849b8aa9cb29cb82589890fae069cb3', 'loadClassLoader'));
+        spl_autoload_unregister(array('ComposerAutoloaderInit1f12a82cc2ba6cc62e0ea30ebe1f1130', 'loadClassLoader'));
 
         $vendorDir = dirname(__DIR__);
         $baseDir = dirname($vendorDir);
@@ -38,10 +38,9 @@ class ComposerAutoloaderInit6849b8aa9cb29cb82589890fae069cb3
 
         $loader->register(true);
 
-        require $vendorDir . '/symfony/intl/Symfony/Component/Intl/Resources/stubs/functions.php';
-        require $vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php';
-        require $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php';
-        require $vendorDir . '/kriswallsmith/assetic/src/functions.php';
+        foreach (require __DIR__ . '/autoload_files.php' as $file) {
+            require $file;
+        }
 
         return $loader;
     }

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 384 - 349
vendor/composer/installed.json


+ 77 - 0
vendor/flint/flint/CHANGELOG.md

@@ -0,0 +1,77 @@
+1.4.0 / 2013-07-04
+==================
+
+ * Configuration cache is now automatically bursted when debug is true and a file have changed.
+ * Introduce a ResourceCollection object that ConfigLoaders must add Resources to when loading. This 
+ caused a BC break in the Configurator constructor arguments.
+ * Debug and cache dir is now setters on the Configurator instead of constructor arguments.
+ * Changed package name to `flint/flint`.
+
+1.3.1 / 2013-06-26
+==================
+
+  * PHP Scalar values are now converted to its string counter part `true` will be `'true'` and so forth.
+  * Replacement for `%placeholder%` and `#PLACEHOLDER#` have been made more robust. Also `%placeholder%` only matches
+  lowercase characters and `#PLACEHOLDER#` only matches uppercase characters.
+
+1.3.0 / 2013-06-26
+==================
+
+  * New documentation in Sphinx which is hosted on readthedocs.org
+  * Configuration with JSON files and caching.
+
+1.2.0 / 2013-05-06
+==================
+
+  * `ApplicationAwareInterface` and `ApplicationAware` was renamed to `PimpleAwareInterface` and `PimpleAware`. This
+  means Controller must use `$this->pimple` instead of `$this->app` when accessing services. The base Controller have
+  been updated.
+  * Add a `Flint\Console\Application` base class that gives access to `pimple` through `PimpleAwareInterface`. It takes
+  a `Pimple` object as the first constructor argument.
+
+1.0.6 / 2013-03-03 
+==================
+
+  * Allow setting parameters in the constructor
+  * Just a small typo fix in README.md
+  * Reshare extended services
+  * allow 5.5 failures
+  * Add section about twig bridge
+  * test the priority of registered service providers
+  * rearrange service providers
+
+1.0.5 / 2013-02-08 
+==================
+
+  * Alias url_generator service to router to be compatible with application using UrlGeneratorServiceProvider
+  * New documentation
+
+1.0.4 / 2013-02-04 
+==================
+
+  * Add test for overriding exception controller
+  * Update documentation
+  * Allow to override the controller used for excetion handling
+
+1.0.3 / 2013-02-03 
+==================
+
+  * %root_dir%/config and %root_dir% are now registered as locations for config locator
+  * Ignore coverage directory
+  * Normalize visibility in Controller
+  * Ignore local phpunit.xml file
+  * Restructure composer file
+  * Add testcase for matcher and matcher_base_class
+  * Add .gitattributes file to make downloads slimmer
+
+1.0.2 / 2013-01-31 
+==================
+
+  * Fix typo in RoutingServiceProvider which previously would use an invalid class for matching.
+  * Add matcher_base_class as a default option for `routing.options` to make the cached matcher extend from the correct class.
+
+1.0.1 / 2013-01-31
+==================
+
+  * Add .gitattributes file to make downloads slimmer
+  * Add CHANGELOG.md

+ 19 - 0
vendor/flint/flint/LICENSE

@@ -0,0 +1,19 @@
+Copyright (c) 2013 Henrik Bjornskov
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 12 - 0
vendor/flint/flint/README.md

@@ -0,0 +1,12 @@
+Flint
+=====
+
+[![Build Status](https://travis-ci.org/henrikbjorn/Flint.png?branch=master)](https://travis-ci.org/henrikbjorn/Flint)
+
+Flint is a microframework build on top of Silex. It brings the full Router, conventions and structure to Silex.
+
+You can read more about [in it documentation](http://flint.rtfd.org).
+
+---
+
+[![Peytz & Co](doc/_static/peytzco.jpg)](http://peytz.dk)

+ 37 - 0
vendor/flint/flint/composer.json

@@ -0,0 +1,37 @@
+{
+    "name"        : "flint/flint",
+    "description" : "Enhanced Silex",
+    "license"     : "MIT",
+
+    "authors" : [{
+        "name"  : "Henrik Bjornskov",
+        "email" : "henrik@bjrnskov.dk"
+    }],
+
+    "autoload" : {
+        "psr-0" : {
+            "Flint" : "src"
+        }
+    },
+
+    "replace" : {
+        "henrikbjorn/flint" : "self.version"
+    },
+
+    "require" : {
+        "php"            : ">=5.3.3",
+        "silex/silex"    : "~1.0",
+        "twig/twig"      : "~1.10",
+        "symfony/config" : "~2.2"
+    },
+
+    "require-dev" : {
+        "symfony/console" : "~2.2"
+    },
+
+    "extra" : {
+        "branch-alias" : {
+            "dev-master" : "1.4.x-dev"
+        }
+    }
+}

BIN
vendor/flint/flint/doc/_static/peytzco.jpg


+ 253 - 0
vendor/flint/flint/doc/conf.py

@@ -0,0 +1,253 @@
+# -*- coding: utf-8 -*-
+#
+# Flint documentation build configuration file, created by
+# sphinx-quickstart on Tue May 21 08:39:31 2013.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+from subprocess import Popen, PIPE
+
+def get_version():
+    """ Returns project version as string from 'git describe' command. """
+    pipe = Popen('git describe --tags --always', stdout=PIPE, shell=True)
+    version = pipe.stdout.read()
+
+    if version:
+        return version
+    else:
+        return 'latest'
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = []
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'Flint'
+copyright = u'2013, Henrik Bjrnskov'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = get_version().lstrip('v')
+# The full version, including alpha/beta/rc tags.
+release = version
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = []
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'Flintdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+  ('index', 'Flint.tex', u'Flint Documentation',
+   u'Henrik Bjrnskov', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    ('index', 'flint', u'Flint Documentation',
+     [u'Henrik Bjrnskov'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+  ('index', 'Flint', u'Flint Documentation',
+   u'Henrik Bjrnskov', 'Flint', 'One line description of project.',
+   'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'

+ 304 - 0
vendor/flint/flint/doc/index.rst

@@ -0,0 +1,304 @@
+Flint
+=====
+
+Flint is a microframework built on top of Silex. It tries to bridge the gap between Silex and
+Symfony by bringing structure and conventions to Silex.
+
+Getting started
+---------------
+
+To start a new project with Flint the easiest way is to use
+`Composer <http://getcomposer.org>`__ and
+`Flint-Skeleton <http://github.com/henrikbjorn/flint-skeleton>`__.
+
+.. code-block:: bash
+
+    $ php composer.phar create-project -s dev henrikbjorn/flint-skeleton my-flint-application
+
+Or if you are migrating from a Silex project you can change your
+``composer.json`` file to require Flint and change the Application class
+that is used.
+
+.. code-block:: bash
+
+    $ php composer.phar require flint/flint:~1.0
+
+.. code-block:: php
+
+    <?php
+
+    use Flint\Application;
+
+    $application = new Application($rootDir, $debug);
+
+It is recommended to subclass ``Flint\Application`` instead of using the
+application class directly.
+
+Controllers
+-----------
+
+Flint tries to make Silex more like Symfony. And by using closures it is
+hard to seperate controllers in a logic way when you have more than a
+couple of them. To make it better it is recommended to use classes and
+methods for controllers. The basics is `explained
+here <http://silex.sensiolabs.org/doc/usage.html#controllers-in-classes>`__
+but Flint takes it further and allows the application to be injected
+into a controller.
+
+The first way to accomplish this is by implementing
+``PimpleAwareInterface`` or extending ``PimpleAware``. This works
+exactly `as described in
+Symfony <http://symfony.com/doc/2.0/book/controller.html#the-base-controller-class>`__.
+With the only exception that the property is called ``$pimple`` instead
+of ``$container``.
+
+.. code-block:: php
+
+    <?php
+
+    namespace Acme\Controller;
+
+    use Flint\PimpleAware;
+
+    class HelloController extends PimpleAware
+    {
+        public function indexAction()
+        {
+            return $this->pimple['twig']->render('Hello/index.html.twig');
+        }
+    }
+
+Another way is to use a base controller which have convenience methods
+for the most frequently used services. Theese methods can be seen in the
+source code if you look at the implementation for
+``Flint\Controller\Controller``.
+
+.. code-block:: php
+
+    <?php
+
+    namespace Acme\Controller;
+
+    use Flint\Controller\Controller;
+
+    class HelloController extends Controller
+    {
+        public function indexAction()
+        {
+            return $this->render('Hello/index.html.twig');
+        }
+    }
+
+Routing
+-------
+
+Because Flint replaces the url matcher used in Symfony with the full
+router implementation a lot of new things is possible.
+
+Caching is one of thoose things. It makes your application faster as it
+does not need to register routes on every request. Together with loading
+your routes from a configuration file like Symfony it will also bring
+more structure to your application.
+
+To enable caching you just need to point the router to the directory you
+want to use and if it should cache or not. By default the ``debug``
+parameter will be used as to determaine if cache should be used or not.
+
+.. code-block:: php
+
+    <?php
+
+    // .. create a $app before this line
+    $app->inject(array(
+        'routing.options' => array(
+            'cache_dir' => '/my/cache/directory/routing',
+        ),
+    ));
+
+Before it is possible to use the full power of caching it is needed to
+use configuration files because Silex will always call add routes via
+its convenience methods ``get|post|delete|put``. Furtunately this is
+baked right in.
+
+.. code-block:: php
+
+    <?php
+
+    // .. create $app
+    $app->inject(array(
+        'routing.resource' => 'config/routing.xml',
+    ));
+
+.. code-block:: xml
+
+    <!-- config/routing.xml -->
+    <?xml version="1.0" encoding="UTF-8" ?>
+    <routes xmlns="http://symfony.com/schema/routing"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
+
+        <route id="homepage" pattern="/">
+            <default key="_controller">Acme\\Controller\\DefaultController::indexAction</default>
+        </route>
+    </routes>
+
+This will make the router load that resource by default. Here xml is
+used as an example but ``php`` is also supported together with ``yml``
+if ``Symfony\Component\Yaml\Yaml`` is autoloadable.
+
+The benefit from doing it this way is of course they can be cached but
+also it allows you to import routing files that are included in
+libraries and even other Symfony bundles such as the
+`WebProfilerBundle <https://github.com/symfony/webprofilerbundle>`__.
+Also it will make it easier to generate routes from inside your views.
+
+.. code-block:: jinja
+
+    <a href="{{ app.router.generate('homepage') }}">Homepage</a>
+
+This is also possible with Silex but with a more verbose syntax. The
+syntax can be even more precise by using the twig functions that is
+available in the Twig bridge for Symfony. To enable thoose add the twig
+bridge to your composer file.
+
+.. code-block:: json
+
+    {
+        "require" : {
+            "symfony/twig-bridge" : "~2.0"
+        }
+    }
+
+Now it is possible to use the functions inside your Twig templates.
+
+.. code-block:: jinja
+
+    <a href="{{ path('homepage') }}">Homepage</a>
+    <a href="{{ url('homepage') }}">Homepage</a>
+
+Default Parameters
+------------------
+
+The two contructor arguments ``$rootDir`` and ``$debug`` are also
+registered on the application as parameters. This makes it easier for
+services to add paths for caching, logs or other directories.
+
+.. code-block:: php
+
+    <?php
+
+    // .. create $app
+    $app->inject(array(
+        'twig.path' => $app['root_dir'] . '/views',
+    ));
+
+Custom Error Pages
+------------------
+
+When finished a project or application it is the small things that
+matter the most. Such as having a custom error page instead of the one
+Silex provides by default. Also it can help a lost user navigate back.
+Flint makes this possible by using the exception handler from Symfony
+and a dedicated controller. Both the views and the controller can be
+overrriden.
+
+This will only work when debug is turned off.
+
+To override the error pages the same logic is used as inside Symfony.
+The logic is very well described `in their
+documentation <http://symfony.com/doc/master/cookbook/controller/error_pages.html>`__.
+
+Only difference from Symfony is the templates must be created inside
+``views/Exception/`` directory. Inside the templates there is access to
+``app`` which in turns gives you access to all of the services defined.
+
+To override the controller used by the exception handler change the
+``exception_controller`` parameter. This parameter will by default be
+set to ``Flint\\Controller\\ExceptionController::showAction``.
+
+.. code-block:: php
+
+    <?php
+
+    // .. create $app
+    $app->inject(array(
+        'exception_controller' => 'Acme\\Controller\\ExceptionController::showAction',
+    ));
+
+To see what parameter the controller action takes look at the one
+provided by default. Normally it should not be overwritten as it already
+gives a lot of flexibilty with the template lookup.
+
+Injecting Configuration Parameters
+----------------------------------
+
+Some times it is more useful to inject an array of parameters instead of
+setting them on the application one-by-one. Flint have a method that
+does this. It does the same thing as the second parameter of Silex
+``register`` method.
+
+.. code-block:: php
+
+    <?php
+
+    // .. $app
+    $app->inject(array(
+        'twig.paths' => '/my/path/to/views',
+    ));
+
+Pimple Console
+--------------
+
+``Flint\Console\Application`` is an extension of the base console
+application shipped with Symfony. It gives access to Pimple in commands.
+
+.. code-block:: php
+
+    <?php
+
+    namespace Application\Command;
+
+    use Symfony\Component\Console\Input\InputInterface;
+    use Symfony\Component\Console\Output\OutputInterface;
+
+    class MyCommand extends \Symfony\Component\Console\Command\Command
+    {
+
+        protected function execute(InputInterface $input, OutputInterface $output)
+        {
+            $pimple = $this->getApplication()->getPimple();
+        }
+    }
+
+Configuration
+-------------
+
+Every application need to have some parameters configured based on environment or other parameters.
+Flint comes with a ``Configurator`` which reads ``json`` files and sets them as parmeters on your application.
+
+It is very easy to use:
+
+.. code-block:: php
+
+    <?php
+
+    use Flint\Application;
+
+    $app = new Application($rootDir, $debug);
+    $app->configure('config.json');
+
+    // Or use the service directly
+    $app['configurator']->configure($app, 'app/config/prod.json');
+
+The Configurator will replace placeholders marked with ``%my_parameter%`` with the corresponding parameter in your
+application which in this instance would be ``$app['my_parameter']``. It will also replace placeholders marked as
+``#my_env#`` with environment variables.
+
+It is possible to inherit from a config file by using a special key ``@import`` and set its value to another file. The
+loaded parameters from ``@import`` will have the lowest priority when merging the two files.
+
+.. warning::
+
+    When using Silex version 1.0.0 or earlier it is not possible to load configurations in the boot method. This is because
+    when adding a listener to the `dispatcher` service it will get the routes and a bunch of other services which means it
+    is too late.

+ 55 - 0
vendor/flint/flint/src/Flint/Application.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace Flint;
+
+use Flint\Provider\ConfigServiceProvider;
+use Flint\Provider\FlintServiceProvider;
+use Flint\Provider\RoutingServiceProvider;
+use Silex\Provider\TwigServiceProvider;
+
+/**
+ * @package Flint
+ */
+class Application extends \Silex\Application
+{
+    /**
+     * Assigns rootDir and debug to the pimple container. Also replaces the
+     * normal resolver with a PimpleAware Resolver.
+     *
+     * @param string  $rootDir
+     * @param boolean $debug
+     * @param array   $parameters
+     */
+    public function __construct($rootDir, $debug = false, array $parameters = array())
+    {
+        parent::__construct($parameters);
+
+        $this['root_dir'] = $rootDir;
+        $this['debug'] = $debug;
+
+        $this->register(new ConfigServiceProvider);
+        $this->register(new RoutingServiceProvider);
+        $this->register(new TwigServiceProvider);
+        $this->register(new FlintServiceProvider);
+    }
+
+    /**
+     * @see Flint\Config\Configurator::configure()
+     * @param string $resource
+     */
+    public function configure($resource)
+    {
+        $this['configurator']->configure($this, $resource);
+    }
+
+    /**
+     * @deprecated
+     * @param array $parameters
+     */
+    public function inject(array $parameters)
+    {
+        foreach ($parameters as $k => $v) {
+            $this[$k] = $v;
+        }
+    }
+}

+ 80 - 0
vendor/flint/flint/src/Flint/Config/Configurator.php

@@ -0,0 +1,80 @@
+<?php
+
+namespace Flint\Config;
+
+use Pimple;
+use Symfony\Component\Config\ConfigCache;
+use Symfony\Component\Config\Loader\LoaderInterface;
+
+/**
+ * @package Flint
+ */
+class Configurator
+{
+    protected $loader;
+    protected $resources;
+    protected $cacheDir;
+    protected $debug = true;
+
+    /**
+     * @param LoaderInterface $resolver
+     * @param ResourceCollection $resources
+     * @param string          $cacheDir
+     * @param boolean         $debug
+     */
+    public function __construct(LoaderInterface $resolver, ResourceCollection $resources)
+    {
+        $this->resources = $resources;
+        $this->loader = $resolver;
+    }
+
+    /**
+     * @param boolean $debug
+     */
+    public function setDebug($debug)
+    {
+        $this->debug = (boolean) $debug;
+    }
+
+    /**
+     * @param string $cacheDir
+     */
+    public function setCacheDir($cacheDir)
+    {
+        $this->cacheDir = $cacheDir;
+    }
+
+    /**
+     * @param Pimple $pimple
+     * @param string $resource
+     */
+    public function configure(Pimple $pimple, $resource)
+    {
+        $cache = new ConfigCache($this->cacheDir . '/' . crc32($resource) . '.php', $this->debug);
+
+        if (!$cache->isFresh()) {
+            $parameters = $this->loader->load($resource);
+        }
+
+        if ($this->cacheDir && isset($parameters)) {
+            $cache->write('<?php $parameters = ' . var_export($parameters, true) . ';', $this->resources->all());
+        }
+
+        if (!isset($parameters)) {
+            require (string) $cache;
+        }
+
+        $this->build($pimple, $parameters);
+    }
+
+    /**
+     * @param Pimple $pimple
+     * @param array  $parameters
+     */
+    protected function build(Pimple $pimple, array $parameters)
+    {
+        foreach ($parameters as $key => $value) {
+            $pimple[$key] = $value;
+        }
+    }
+}

+ 77 - 0
vendor/flint/flint/src/Flint/Config/Loader/JsonFileLoader.php

@@ -0,0 +1,77 @@
+<?php
+
+namespace Flint\Config\Loader;
+
+use Flint\Config\Normalizer\NormalizerInterface;
+use Flint\Config\ResourceCollection;
+use Symfony\Component\Config\FileLocatorInterface;
+use Symfony\Component\Config\Resource\FileResource;
+
+/**
+ * @package Flint
+ */
+class JsonFileLoader extends \Symfony\Component\Config\Loader\FileLoader
+{
+    protected $normalizer;
+    protected $resources;
+
+    /**
+     * @param NormalizerInterface  $normalizer
+     * @param FileLocatorInterface $locator
+     */
+    public function __construct(
+        NormalizerInterface $normalizer,
+        FileLocatorInterface $locator,
+        ResourceCollection $resources
+    ) {
+        parent::__construct($locator);
+
+        $this->normalizer = $normalizer;
+        $this->resources = $resources;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function load($resource, $type = null)
+    {
+        $resource = $this->locator->locate($resource);
+
+        $this->resources->add(new FileResource($resource));
+
+        return $this->parse($this->read($resource), $resource);
+    }
+
+    /**
+     * @param  array  $parameters
+     * @param  string $file
+     * @return array
+     */
+    protected function parse(array $parameters, $file)
+    {
+        if (!isset($parameters['@import'])) {
+            return $parameters;
+        }
+
+        $import = $parameters['@import'];
+
+        unset($parameters['@import']);
+
+        $this->setCurrentDir(dirname($import));
+
+        return array_replace($this->import($import, null, false, $file), $parameters);
+    }
+
+    protected function read($resource)
+    {
+        return json_decode($this->normalizer->normalize(file_get_contents($resource)), true);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function supports($resource, $type = null)
+    {
+        return is_string($resource) && 'json' === pathinfo($resource, PATHINFO_EXTENSION);
+    }
+}

+ 39 - 0
vendor/flint/flint/src/Flint/Config/Normalizer/ChainNormalizer.php

@@ -0,0 +1,39 @@
+<?php
+
+namespace Flint\Config\Normalizer;
+
+/**
+ * @package Flint
+ */
+class ChainNormalizer implements NormalizerInterface
+{
+    protected $normalizers = array();
+
+    /**
+     * @param array $normalizers
+     */
+    public function __construct(array $normalizers = array())
+    {
+        array_map(array($this, 'add'), $normalizers);
+    }
+
+    /**
+     * @param NormalizerInterface $normalizer
+     */
+    public function add(NormalizerInterface $normalizer)
+    {
+        $this->normalizers[] = $normalizer;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function normalize($contents)
+    {
+        foreach ($this->normalizers as $normalizer) {
+            $contents = $normalizer->normalize($contents);
+        }
+
+        return $contents;
+    }
+}

+ 33 - 0
vendor/flint/flint/src/Flint/Config/Normalizer/EnvironmentNormalizer.php

@@ -0,0 +1,33 @@
+<?php
+
+namespace Flint\Config\Normalizer;
+
+/**
+ * @package Flint
+ */
+class EnvironmentNormalizer implements NormalizerInterface
+{
+    const PLACEHOLDER = '{##|#([A-Z0-9_]+)#}';
+
+    /**
+     * @param  string $contents
+     * @return string
+     */
+    public function normalize($contents)
+    {
+        return preg_replace_callback(static::PLACEHOLDER, array($this, 'callback'), $contents);
+    }
+
+    /**
+     * @param  array $matches
+     * @return mixed
+     */
+    protected function callback($matches)
+    {
+        if (!isset($matches[1])) {
+            return '##';
+        }
+
+        return getenv($matches[1]);
+    }
+}

+ 15 - 0
vendor/flint/flint/src/Flint/Config/Normalizer/NormalizerInterface.php

@@ -0,0 +1,15 @@
+<?php
+
+namespace Flint\Config\Normalizer;
+
+/**
+ * @package Flint
+ */
+interface NormalizerInterface
+{
+    /**
+     * @param  string $contents
+     * @return string
+     */
+    public function normalize($contents);
+}

+ 62 - 0
vendor/flint/flint/src/Flint/Config/Normalizer/PimpleAwareNormalizer.php

@@ -0,0 +1,62 @@
+<?php
+
+namespace Flint\Config\Normalizer;
+
+use Pimple;
+
+/**
+ * @package Flint
+ */
+class PimpleAwareNormalizer extends \Flint\PimpleAware implements NormalizerInterface
+{
+    const PLACEHOLDER = '{%%|%([a-z0-9_.]+)%}';
+
+    /**
+     * @param Pimple $pimple
+     */
+    public function __construct(Pimple $pimple = null)
+    {
+        $this->setPimple($pimple);
+    }
+
+    /**
+     * @param  string $contents
+     * @return string
+     */
+    public function normalize($contents)
+    {
+        return preg_replace_callback(static::PLACEHOLDER, array($this, 'callback'), $contents);
+    }
+
+    /**
+     * @param  array $matches
+     * @return mixed
+     */
+    protected function callback($matches)
+    {
+        if (!isset($matches[1])) {
+            return '%%';
+        }
+
+        return $this->scarlarToString($this->pimple[$matches[1]]);
+    }
+
+    /**
+     * @param  mixed $value
+     * @return mixed
+     */
+    protected function scarlarToString($value)
+    {
+        switch (gettype($value)) {
+            case 'resource':
+            case 'object':
+                throw new \RuntimeException('Unable to replace placeholder if its replacement is an object or resource.');
+            case 'boolean':
+                return $value ? 'true' : 'false';
+            case 'NULL':
+                return 'null';
+            default:
+                return (string) $value;
+        }
+    }
+}

+ 40 - 0
vendor/flint/flint/src/Flint/Config/ResourceCollection.php

@@ -0,0 +1,40 @@
+<?php
+
+namespace Flint\Config;
+
+use Symfony\Component\Config\Resource\ResourceInterface;
+
+/**
+ * Collection of Resources that is used to burst the cache for the configs
+ * when in debug.
+ *
+ * @package Flint
+ */
+class ResourceCollection
+{
+    protected $resources = array();
+
+    /**
+     * @param array $resources
+     */
+    public function __construct(array $resources = array())
+    {
+        array_map(array($this, 'add'), $resources);
+    }
+
+    /**
+     * @param ResourceInterface $resource
+     */
+    public function add(ResourceInterface $resource)
+    {
+        $this->resources[] = $resource;
+    }
+
+    /**
+     * @return ResourceInterface[]
+     */
+    public function all()
+    {
+        return $this->resources;
+    }
+}

+ 39 - 0
vendor/flint/flint/src/Flint/Console/Application.php

@@ -0,0 +1,39 @@
+<?php
+
+namespace Flint\Console;
+
+use Flint\PimpleAwareInterface;
+use Symfony\Component\Console\Application as BaseApplication;
+
+class Application extends BaseApplication implements PimpleAwareInterface
+{
+    protected $pimple;
+
+    /**
+     * @param Pimple $pimple
+     * @param string $name
+     * @param string $version
+     */
+    public function __construct(\Pimple $pimple, $name = 'Flint', $version = 'UNKNOWN')
+    {
+        parent::__construct($name, $version);
+
+        $this->setPimple($pimple);
+    }
+
+    /**
+     * @return Pimple
+     */
+    public function getPimple()
+    {
+        return $this->pimple;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function setPimple(\Pimple $pimple = null)
+    {
+        $this->pimple = $pimple;
+    }
+}

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott