Adding missing files.

1.10.x
Julio Montoya 12 years ago
parent 4dc4cbe28a
commit e57ee00c58
  1. 27
      app/Resources/views/Common/topbar.html.twig
  2. 12
      app/Resources/views/Layouts/12.html.twig
  3. 387
      app/Resources/views/Layouts/3-9.html.twig
  4. 2
      app/Resources/views/Themes/page.html.twig
  5. 313
      app/Resources/views/base.html.twig
  6. 1
      app/Resources/views/layout.html.twig
  7. 1
      app/config/config.yml
  8. 32
      cli-config.php
  9. 183
      console-config.php
  10. 93
      console.php
  11. 7
      index.php
  12. 449
      main/calendar/agenda.php
  13. 175
      main/calendar/agenda_js.php
  14. 80
      main/course_home/activity.php
  15. 2280
      main/inc/lib/agenda.lib.php
  16. 7
      main/inc/lib/course_home.lib.php
  17. 57
      main/inc/lib/pear/HTML/QuickForm/select.php
  18. 22
      src/ChamiloLMS/CoreBundle/DependencyInjection/Compiler/DoctrineEntityListenerPass.php
  19. 40
      src/ChamiloLMS/CoreBundle/Doctrine/EntityListenerResolver.php
  20. 60
      src/ChamiloLMS/CoreBundle/EventListener/MenuListener.php
  21. 2
      vendor/autoload.php
  22. 2
      vendor/composer/autoload_namespaces.php
  23. 1
      vendor/composer/autoload_psr4.php
  24. 10
      vendor/composer/autoload_real.php
  25. 1202
      vendor/composer/installed.json
  26. 1
      vendor/doctrine/orm/bin/doctrine.php
  27. 3
      vendor/doctrine/orm/docs/en/index.rst
  28. 2
      vendor/doctrine/orm/docs/en/reference/caching.rst
  29. 2
      vendor/doctrine/orm/docs/en/reference/configuration.rst
  30. 66
      vendor/doctrine/orm/docs/en/reference/events.rst
  31. 2
      vendor/doctrine/orm/docs/en/reference/faq.rst
  32. 12
      vendor/doctrine/orm/docs/en/toc.rst
  33. 14
      vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/HydrationException.php
  34. 8
      vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php
  35. 8
      vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php
  36. 6
      vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
  37. 4
      vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultEntityListenerResolver.php
  38. 5
      vendor/doctrine/orm/lib/Doctrine/ORM/Query/SqlWalker.php
  39. 6
      vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/ConsoleRunner.php
  40. 2
      vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php
  41. 22
      vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryOutputWalker.php
  42. 37
      vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php
  43. 2
      vendor/doctrine/orm/lib/Doctrine/ORM/Version.php
  44. 8
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/CHANGELOG.md
  45. 86
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Configuration/Cache.php
  46. 9
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Configuration/ConfigurationAnnotation.php
  47. 10
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Configuration/ConfigurationInterface.php
  48. 10
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Configuration/Method.php
  49. 16
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Configuration/ParamConverter.php
  50. 16
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Configuration/Route.php
  51. 20
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Configuration/Template.php
  52. 17
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/DependencyInjection/Configuration.php
  53. 35
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/DependencyInjection/SensioFrameworkExtraExtension.php
  54. 70
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/EventListener/CacheListener.php
  55. 18
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/EventListener/ControllerListener.php
  56. 43
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/EventListener/ParamConverterListener.php
  57. 22
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/EventListener/TemplateListener.php
  58. 6
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/README.md
  59. 16
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Request/ParamConverter/DateTimeParamConverter.php
  60. 46
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Request/ParamConverter/DoctrineParamConverter.php
  61. 38
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Request/ParamConverter/ParamConverterInterface.php
  62. 20
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Request/ParamConverter/ParamConverterManager.php
  63. 2
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Resources/config/cache.xml
  64. 1
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Resources/config/converters.xml
  65. 83
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Resources/doc/annotations/cache.rst
  66. 56
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Resources/doc/annotations/converters.rst
  67. 9
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Resources/doc/annotations/routing.rst
  68. 31
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Resources/doc/index.rst
  69. 31
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Routing/AnnotatedRouteControllerLoader.php
  70. 18
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Templating/TemplateGuesser.php
  71. 9
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Tests/Configuration/ConfigurationAnnotationTest.php
  72. 12
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Tests/EventListener/ControllerListenerTest.php
  73. 63
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Tests/EventListener/ParamConverterListenerTest.php
  74. 31
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Tests/Request/ParamConverter/DateTimeParamConverterTest.php
  75. 9
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Tests/Request/ParamConverter/DoctrineParamConverterTest.php
  76. 65
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Tests/Request/ParamConverter/ParamConverterManagerTest.php
  77. 33
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Tests/Routing/AnnotatedRouteControllerLoaderTest.php
  78. 9
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/Tests/Templating/TemplateGuesserTest.php
  79. 12
      vendor/sensio/framework-extra-bundle/Sensio/Bundle/FrameworkExtraBundle/composer.json
  80. 34
      vendor/sensio/generator-bundle/Sensio/Bundle/GeneratorBundle/Command/GenerateControllerCommand.php
  81. 4
      vendor/sensio/generator-bundle/Sensio/Bundle/GeneratorBundle/Command/GenerateDoctrineCommand.php
  82. 3
      vendor/sensio/generator-bundle/Sensio/Bundle/GeneratorBundle/Command/GenerateDoctrineFormCommand.php
  83. 4
      vendor/sensio/generator-bundle/Sensio/Bundle/GeneratorBundle/Generator/ControllerGenerator.php
  84. 5
      vendor/sensio/generator-bundle/Sensio/Bundle/GeneratorBundle/Generator/DoctrineCrudGenerator.php
  85. 19
      vendor/sensio/generator-bundle/Sensio/Bundle/GeneratorBundle/LICENSE
  86. 4
      vendor/sensio/generator-bundle/Sensio/Bundle/GeneratorBundle/Resources/doc/commands/generate_bundle.rst
  87. 4
      vendor/sensio/generator-bundle/Sensio/Bundle/GeneratorBundle/Resources/doc/commands/generate_controller.rst
  88. 8
      vendor/sensio/generator-bundle/Sensio/Bundle/GeneratorBundle/Resources/doc/index.rst
  89. 2
      vendor/sensio/generator-bundle/Sensio/Bundle/GeneratorBundle/Resources/skeleton/bundle/routing.xml.twig
  90. 2
      vendor/sensio/generator-bundle/Sensio/Bundle/GeneratorBundle/Resources/skeleton/bundle/routing.yml.twig
  91. 15
      vendor/sensio/generator-bundle/Sensio/Bundle/GeneratorBundle/Resources/skeleton/controller/Controller.php.twig
  92. 12
      vendor/sensio/generator-bundle/Sensio/Bundle/GeneratorBundle/Resources/skeleton/crud/actions/create.php.twig
  93. 2
      vendor/sensio/generator-bundle/Sensio/Bundle/GeneratorBundle/Resources/skeleton/crud/actions/show.php.twig
  94. 14
      vendor/sensio/generator-bundle/Sensio/Bundle/GeneratorBundle/Resources/skeleton/crud/config/routing.xml.twig
  95. 14
      vendor/sensio/generator-bundle/Sensio/Bundle/GeneratorBundle/Resources/skeleton/crud/config/routing.yml.twig
  96. 2
      vendor/sensio/generator-bundle/Sensio/Bundle/GeneratorBundle/Resources/skeleton/crud/tests/others/full_scenario.php.twig
  97. 5
      vendor/sensio/generator-bundle/Sensio/Bundle/GeneratorBundle/Tests/Generator/ControllerGeneratorTest.php
  98. 16
      web/install.php

@ -0,0 +1,27 @@
{% block topbar %}
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle"
data-toggle="collapse" data-target=".navbar-ex1-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Chamilo</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse navbar-ex1-collapse">
{{ knp_menu_render('ChamiloLMSCoreBundle:Builder:leftMenu', { 'style': 'navbar' }) }}
<form class="navbar-form navbar-left" role="search">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
{{ knp_menu_render('ChamiloLMSCoreBundle:Builder:rightMenu', { 'style': 'navbar-right' }) }}
</div><!-- /.navbar-collapse -->
</nav>
{% endblock %}

@ -0,0 +1,12 @@
{% include '::Common/topbar.html.twig' %}
<br />
<br />
<br />
<div class="container-fluid">
<div class="row">
<div class="col-sm-12">
{% block content %}
{% endblock %}
</div>
</div>
</div>

@ -0,0 +1,387 @@
{% block header %}
<header class="header">
{% block logo %}
<a href="index.html" class="logo">
<!-- Add the class icon to your logo image or logo icon to add the margining -->
AdminLTE
</a>
{% endblock %}
{% block nav %}
<nav class="navbar navbar-static-top" role="navigation">
<!-- Sidebar toggle button-->
<a href="#" class="navbar-btn sidebar-toggle" data-toggle="offcanvas" role="button">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<div class="navbar-left">
{{ sonata_block_render_event('breadcrumb', { 'context': 'default', 'current_uri': app.request.requestUri }) }}
</div>
<div class="navbar-right">
<ul class="nav navbar-nav">
<!-- Messages: style can be found in dropdown.less-->
<li class="dropdown messages-menu">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-envelope"></i>
<span class="label label-success">4</span>
</a>
<ul class="dropdown-menu">
<li class="header">You have 4 messages</li>
<li>
<!-- inner menu: contains the actual data -->
<div class="slimScrollDiv" style="position: relative; overflow: hidden; width: auto; height: 200px;"><ul class="menu" style="overflow: hidden; width: 100%; height: 200px;">
<li><!-- start message -->
<a href="#">
<div class="pull-left">
<img src="img/avatar3.png" class="img-circle" alt="User Image">
</div>
<h4>
Support Team
<small><i class="fa fa-clock-o"></i> 5 mins</small>
</h4>
<p>Why not buy a new awesome theme?</p>
</a>
</li><!-- end message -->
<li>
<a href="#">
<div class="pull-left">
<img src="img/avatar2.png" class="img-circle" alt="user image">
</div>
<h4>
AdminLTE Design Team
<small><i class="fa fa-clock-o"></i> 2 hours</small>
</h4>
<p>Why not buy a new awesome theme?</p>
</a>
</li>
<li>
<a href="#">
<div class="pull-left">
<img src="img/avatar.png" class="img-circle" alt="user image">
</div>
<h4>
Developers
<small><i class="fa fa-clock-o"></i> Today</small>
</h4>
<p>Why not buy a new awesome theme?</p>
</a>
</li>
<li>
<a href="#">
<div class="pull-left">
<img src="img/avatar2.png" class="img-circle" alt="user image">
</div>
<h4>
Sales Department
<small><i class="fa fa-clock-o"></i> Yesterday</small>
</h4>
<p>Why not buy a new awesome theme?</p>
</a>
</li>
<li>
<a href="#">
<div class="pull-left">
<img src="img/avatar.png" class="img-circle" alt="user image">
</div>
<h4>
Reviewers
<small><i class="fa fa-clock-o"></i> 2 days</small>
</h4>
<p>Why not buy a new awesome theme?</p>
</a>
</li>
</ul><div class="slimScrollBar" style="width: 3px; position: absolute; top: 0px; opacity: 0.4; display: block; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; z-index: 99; right: 1px; background: rgb(0, 0, 0);"></div><div class="slimScrollRail" style="width: 3px; height: 100%; position: absolute; top: 0px; display: none; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; opacity: 0.2; z-index: 90; right: 1px; background: rgb(51, 51, 51);"></div></div>
</li>
<li class="footer"><a href="#">See All Messages</a></li>
</ul>
</li>
<!-- Notifications: style can be found in dropdown.less -->
<li class="dropdown notifications-menu">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-warning"></i>
<span class="label label-warning">10</span>
</a>
<ul class="dropdown-menu">
<li class="header">You have 10 notifications</li>
<li>
<!-- inner menu: contains the actual data -->
<div class="slimScrollDiv" style="position: relative; overflow: hidden; width: auto; height: 200px;"><ul class="menu" style="overflow: hidden; width: 100%; height: 200px;">
<li>
<a href="#">
<i class="ion ion-ios7-people info"></i> 5 new members joined today
</a>
</li>
<li>
<a href="#">
<i class="fa fa-warning danger"></i> Very long description here that may not fit into the page and may cause design problems
</a>
</li>
<li>
<a href="#">
<i class="fa fa-users warning"></i> 5 new members joined
</a>
</li>
<li>
<a href="#">
<i class="ion ion-ios7-cart success"></i> 25 sales made
</a>
</li>
<li>
<a href="#">
<i class="ion ion-ios7-person danger"></i> You changed your username
</a>
</li>
</ul><div class="slimScrollBar" style="width: 3px; position: absolute; top: 0px; opacity: 0.4; display: block; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; z-index: 99; right: 1px; background: rgb(0, 0, 0);"></div><div class="slimScrollRail" style="width: 3px; height: 100%; position: absolute; top: 0px; display: none; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; opacity: 0.2; z-index: 90; right: 1px; background: rgb(51, 51, 51);"></div></div>
</li>
<li class="footer"><a href="#">View all</a></li>
</ul>
</li>
<!-- Tasks: style can be found in dropdown.less -->
<li class="dropdown tasks-menu">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-tasks"></i>
<span class="label label-danger">9</span>
</a>
<ul class="dropdown-menu">
<li class="header">You have 9 tasks</li>
<li>
<!-- inner menu: contains the actual data -->
<div class="slimScrollDiv" style="position: relative; overflow: hidden; width: auto; height: 200px;"><ul class="menu" style="overflow: hidden; width: 100%; height: 200px;">
<li><!-- Task item -->
<a href="#">
<h3>
Design some buttons
<small class="pull-right">20%</small>
</h3>
<div class="progress xs">
<div class="progress-bar progress-bar-aqua" style="width: 20%" role="progressbar" aria-valuenow="20" aria-valuemin="0" aria-valuemax="100">
<span class="sr-only">20% Complete</span>
</div>
</div>
</a>
</li><!-- end task item -->
<li><!-- Task item -->
<a href="#">
<h3>
Create a nice theme
<small class="pull-right">40%</small>
</h3>
<div class="progress xs">
<div class="progress-bar progress-bar-green" style="width: 40%" role="progressbar" aria-valuenow="20" aria-valuemin="0" aria-valuemax="100">
<span class="sr-only">40% Complete</span>
</div>
</div>
</a>
</li><!-- end task item -->
<li><!-- Task item -->
<a href="#">
<h3>
Some task I need to do
<small class="pull-right">60%</small>
</h3>
<div class="progress xs">
<div class="progress-bar progress-bar-red" style="width: 60%" role="progressbar" aria-valuenow="20" aria-valuemin="0" aria-valuemax="100">
<span class="sr-only">60% Complete</span>
</div>
</div>
</a>
</li><!-- end task item -->
<li><!-- Task item -->
<a href="#">
<h3>
Make beautiful transitions
<small class="pull-right">80%</small>
</h3>
<div class="progress xs">
<div class="progress-bar progress-bar-yellow" style="width: 80%" role="progressbar" aria-valuenow="20" aria-valuemin="0" aria-valuemax="100">
<span class="sr-only">80% Complete</span>
</div>
</div>
</a>
</li><!-- end task item -->
</ul><div class="slimScrollBar" style="width: 3px; position: absolute; top: 0px; opacity: 0.4; display: block; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; z-index: 99; right: 1px; background: rgb(0, 0, 0);"></div><div class="slimScrollRail" style="width: 3px; height: 100%; position: absolute; top: 0px; display: none; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; opacity: 0.2; z-index: 90; right: 1px; background: rgb(51, 51, 51);"></div></div>
</li>
<li class="footer">
<a href="#">View all tasks</a>
</li>
</ul>
</li>
<!-- User Account: style can be found in dropdown.less -->
<li class="dropdown user user-menu">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<i class="glyphicon glyphicon-user"></i>
<span>Jane Doe <i class="caret"></i></span>
</a>
<ul class="dropdown-menu">
<!-- User image -->
<li class="user-header bg-light-blue">
<img src="img/avatar3.png" class="img-circle" alt="User Image">
<p>
Jane Doe - Web Developer
<small>Member since Nov. 2012</small>
</p>
</li>
<!-- Menu Body -->
<li class="user-body">
<div class="col-xs-4 text-center">
<a href="#">Followers</a>
</div>
<div class="col-xs-4 text-center">
<a href="#">Sales</a>
</div>
<div class="col-xs-4 text-center">
<a href="#">Friends</a>
</div>
</li>
<!-- Menu Footer-->
<li class="user-footer">
<div class="pull-left">
<a href="#" class="btn btn-default btn-flat">Profile</a>
</div>
<div class="pull-right">
<a href="#" class="btn btn-default btn-flat">Sign out</a>
</div>
</li>
</ul>
</li>
</ul>
</div>
</nav>
{% endblock %}
</header>
{% endblock %}
{% block sonata_wrapper %}
<div class="wrapper row-offcanvas row-offcanvas-left">
{% block sonata_left_side %}
<aside class="left-side sidebar-offcanvas">
<section class="sidebar">
{{ sonata_block_render({'type': 'chamilolms.corebundle.block.main_menu', 'settings': {
'current_uri': app.request.requestUri,
'ttl': 60
}}) }}
{% block sonata_side_nav %}
{% block sonata_sidebar_search %}
{% if app.security.token and is_granted('ROLE_SONATA_ADMIN') %}
<form action="{{ url('sonata_admin_search') }}" method="GET" class="sidebar-form" role="search">
<div class="input-group custom-search-form">
<input type="text" name="q" value="{{ app.request.get('q') }}" class="form-control" placeholder="{{ 'search_placeholder'|trans({}, 'SonataAdminBundle') }}">
<span class="input-group-btn">
<button class="btn btn-flat" type="submit">
<i class="fa fa-search"></i>
</button>
</span>
</div>
</form>
{% endif %}
{% endblock sonata_sidebar_search %}
{% block side_bar_before_nav %} {% endblock %}
{% block side_bar_nav %}
{% if app.security.token and is_granted('ROLE_SONATA_ADMIN') %}
{% endif %}
{% endblock side_bar_nav %}
{% endblock sonata_side_nav %}
</section>
</aside>
{% endblock sonata_left_side %}
<aside class="right-side">
{% block sonata_page_content %}
<section class="content-header">
{% block sonata_page_content_header %}
{% block sonata_page_content_nav %}
{% if _tab_menu is not empty or _actions is not empty %}
<nav class="navbar navbar-default" role="navigation">
{% if _navbar_title is not empty %}
<div class="navbar-header">
<span class="navbar-brand">{{ _navbar_title|raw }}</span>
</div>
{% endif %}
<div class="container-fluid">
<div class="navbar-left">
{% if _tab_menu is not empty %}
{{ _tab_menu|raw }}
{% endif %}
</div>
{% if _actions is not empty %}
<ul class="nav navbar-nav navbar-right">
<li class="dropdown sonata-actions">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Actions <b class="caret"></b></a>
<ul class="dropdown-menu" role="menu">
{{ _actions|raw }}
</ul>
</li>
</ul>
{% endif %}
</div>
</nav>
{% endif %}
{% endblock sonata_page_content_nav %}
{% endblock sonata_page_content_header %}
</section>
<section class="content">
<div class="row">
<div class="col-md-3 col-sm-4">
{% block sidebar %}
{#{{ sonata_block_render({ 'type': 'sonata.block.service.menu' }, {#}
{#'menu_name': 'ChamiloLMSCoreBundle:MainMenuBuilder:profileMenu',#}
{#}) }}#}
{% include "@template_style/layout/sidebar.tpl" %}
{# course navigation links/shortcuts need to be activated by the admin #}
{% include "@template_style/layout/course_navigation.tpl" %}
{% endblock %}
</div>
<div class="col-md-9 col-sm-8">
{% block main_content %}
{% if plugin_content_top %}
<div id="plugin_content_top" class="col-lg-10 col-sm-11">
{{ plugin_content_top}}
</div>
{% endif %}
{% include "@template_style/layout/page_body.tpl" %}
{% block content %}
{% autoescape false %}
{% if content is not null %}
{{ content }}
{% endif %}
{% endautoescape %}
{% endblock %}
{# Plugin bottom #}
{% if plugin_content_bottom %}
<div id="plugin_content_bottom" class="col-md-12">
{{ plugin_content_bottom }}
</div>
{% endif %}
</section>
{# Footer #}
{% include "@template_style/layout/footer.tpl" %}
{% endblock %}
</div>
</div>
</section>
{% endblock sonata_page_content %}
</aside>
</div>
{% endblock sonata_wrapper %}

@ -0,0 +1,2 @@
{% extends '::base.html.twig' %}
{% block theme 'page' %}

@ -0,0 +1,313 @@
{% set _preview = block('preview') %}
{% set _form = block('form') %}
{% set _show = block('show') %}
{% set _list_table = block('list_table') %}
{% set _list_filters = block('list_filters') %}
{% set _tab_menu = block('tab_menu') %}
{% set _content = block('content') %}
{% set _title = block('title') %}
{% set _breadcrumb = block('breadcrumb') %}
{% set _actions = block('actions') %}
{% set _navbar_title = block('navbar_title') %}
<!DOCTYPE html>
<!--[if lt IE 7]> <html lang="{{ app.request.locale }}" class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html lang="{{ app.request.locale }}" class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html lang="{{ app.request.locale }}" class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--><html lang="{{ app.request.locale }}" class="no-js"> <!--<![endif]-->
<head>
{% block head %}
<noscript>{{ "NoJavascript"|trans }}</noscript>
<meta charset="UTF-8" />
<link href="http://www.chamilo.org/documentation.php" rel="help" />
<link href="http://www.chamilo.org/team.php" rel="author" />
<link href="http://www.chamilo.org" rel="copyright" />
<link rel="shortcut icon" href="{{ asset('favicon.ico') }}" />
<link rel="shortcut icon" href="{{ asset('apple-touch-icon.png') }}" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="Generator" content="{{ software_name }} {{ version }}" />
{# Use the latest engine in ie8/ie9 or use google chrome engine if available #}
{# Improve usability in portal devices #}
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}{% endblock %}</title>
{% block stylesheets %}
<link href="{{ asset('assetic/sonata_formatter_css.css') }}" rel="stylesheet" media="screen">
<link href="{{ asset('assetic/sonata_admin_css.css') }}" rel="stylesheet" media="screen">
<link href="{{ asset('assetic/sonata_jqueryui_css.css') }}" rel="stylesheet" media="screen">
<link href="{{ asset('ChamiloLMS/css/base.css') }}" rel="stylesheet" media="screen">
<link href="{{ asset('ChamiloLMS/css/themes/chamilo/default.css') }}" rel="stylesheet" media="screen">
{% endblock %}
{% block javascripts %}
<script src="{{ asset('assetic/sonata_admin_js.js') }}" type="text/javascript"></script>
<script src="{{ asset('assetic/sonata_formatter_js.js') }}" type="text/javascript"></script>
<script src="{{ asset('assetic/sonata_jqueryui_js.js') }}" type="text/javascript"></script>
{% endblock %}
{% block header_end %}{% endblock header_end %}
<script>
function setCheckbox(value, table_id) {
checkboxes = $("#"+table_id+" input:checkbox");
$.each(checkboxes, function(index, checkbox) {
checkbox.checked = value;
if (value) {
$(checkbox).parentsUntil("tr").parent().addClass("row_selected");
} else {
$(checkbox).parentsUntil("tr").parent().removeClass("row_selected");
}
});
return false;
}
function action_click(element, table_id) {
d = $("#"+table_id);
if (!confirm('{{ "ConfirmYourChoice"|trans }}')) {
return false;
} else {
var action =$(element).attr("data-action");
$('#'+table_id+' input[name="action"] ').attr("value", action);
d.submit();
return false;
}
}
/* Global chat variables */
{#
var ajax_url = '{{ _p.web_ajax }}chat.ajax.php';
var online_button = '{{ online_button |e('js') }}';
var offline_button = '{{ offline_button |e('js') }}';
#}
var connect_lang = '{{ "ChatConnected"|trans |e('js') }}';
var disconnect_lang = '{{ "ChatDisconnected"|trans |e('js') }}';
function get_url_params(q, attribute) {
var vars;
var hash;
if (q != undefined) {
q = q.split('&');
for(var i = 0; i < q.length; i++){
hash = q[i].split('=');
if (hash[0] == attribute) {
return hash[1];
}
}
}
}
function check_brand() {
if ($('.subnav').length) {
if ($(window).width() >= 969) {
$('.subnav .brand').hide();
} else {
$('.subnav .brand').show();
}
}
}
$(window).resize(function() {
//check_brand();
});
$(document).scroll(function() {
// Top bar scroll effect
if ($('body').width() > 959) {
if ($('.subnav').length) {
if (!$('.subnav').attr('data-top')) {
// If already fixed, then do nothing
if ($('.subnav').hasClass('subnav-fixed')) return;
// Remember top position
var offset = $('.subnav').offset();
$('.subnav').attr('data-top', offset.top);
}
if ($('.subnav').attr('data-top') - $('.subnav').outerHeight() <= $(this).scrollTop()) {
$('.subnav').addClass('subnav-fixed');
} else {
$('.subnav').removeClass('subnav-fixed');
}
//$('.subnav .brand').show();
}
} else {
//$('.subnav .brand').hide();
}
//Exercise warning fixed at the top
var fixed = $("#exercise_clock_warning");
if (fixed.length) {
if (!fixed.attr('data-top')) {
// If already fixed, then do nothing
if (fixed.hasClass('subnav-fixed')) return;
// Remember top position
var offset = fixed.offset();
fixed.attr('data-top', offset.top);
fixed.css('width', '100%');
}
if (fixed.attr('data-top') - fixed.outerHeight() <= $(this).scrollTop()) {
fixed.addClass('subnav-fixed');
fixed.css('width', '100%');
} else {
fixed.removeClass('subnav-fixed');
fixed.css('width', '200px');
}
}
// Admin -> Settings toolbar.
if ($('body').width() > 959) {/*
if ($('.new_actions').length) {
if (!$('.new_actions').attr('data-top')) {
// If already fixed, then do nothing
if ($('.new_actions').hasClass('new_actions-fixed')) return;
// Remember top position
var offset = $('.new_actions').offset();
var more_top = 0;
if ($('.subnav').hasClass('new_actions-fixed')) {
more_top = 50;
}
$('.new_actions').attr('data-top', offset.top + more_top);
}
if ($('.new_actions').attr('data-top') - $('.new_actions').outerHeight() <= $(this).scrollTop()) {
$('.new_actions').addClass('new_actions-fixed');
} else {
$('.new_actions').removeClass('new_actions-fixed');
}
}*/
}
// Bottom actions.
if ($('.bottom_actions').length) {
if (!$('.bottom_actions').attr('data-top')) {
// If already fixed, then do nothing
if ($('.bottom_actions').hasClass('bottom_actions_fixed')) return;
// Remember top position
var offset = $('.bottom_actions').offset();
$('.bottom_actions').attr('data-top', offset.top);
}
if ($('.bottom_actions').attr('data-top') > $('body').outerHeight()) {
if ( ($('.bottom_actions').attr('data-top') - $('body').outerHeight() - $('.bottom_actions').outerHeight()) >= $(this).scrollTop()) {
$('.bottom_actions').addClass('bottom_actions_fixed');
$('.bottom_actions').css("width", "100%");
} else {
$('.bottom_actions').css("width", "");
$('.bottom_actions').removeClass('bottom_actions_fixed');
}
} else {
if ( ($('.bottom_actions').attr('data-top') - $('.bottom_actions').outerHeight()) <= $(this).scrollTop()) {
$('.bottom_actions').addClass('bottom_actions_fixed');
$('.bottom_actions').css("width", "100%");
} else {
$('.bottom_actions').removeClass('bottom_actions_fixed');
$('.bottom_actions').css("width", "");
}
}
}
});
$(function() {
check_brand();
//Removes the yellow input in Chrome
if (navigator.userAgent.toLowerCase().indexOf("chrome") >= 0) {
$(window).load(function(){
$('input:-webkit-autofill').each(function(){
var text = $(this).val();
var name = $(this).attr('name');
$(this).after(this.outerHTML).remove();
//var has_string = $(name).find(":contains('[')");
$('input[name=' + name + ']').val(text);
});
});
}
// Fixes buttons to the new btn class.
if (!$('#button').hasClass('btn')) {
$("button").addClass('btn');
}
// Dropdown effect.
$('.dropdown-toggle').dropdown();
// Responsive effect.
//$(".collapse").collapse();
/*$(".accordion_jquery").accordion({
autoHeight: false,
active: false, // all items closed by default
collapsible: true,
header: ".accordion-heading"
});*/
// Global popup
$('.ajax').on('click', function() {
var url = this.href;
var dialog = $("#dialog");
if ($("#dialog").length == 0) {
dialog = $('<div id="dialog" style="display:none"></div>').appendTo('body');
}
width_value = 580;
height_value = 450;
resizable_value = true;
new_param = get_url_params(url, 'width');
if (new_param) {
width_value = new_param;
}
new_param = get_url_params(url, 'height')
if (new_param) {
height_value = new_param;
}
new_param = get_url_params(url, 'resizable');
if (new_param) {
resizable_value = new_param;
}
// load remote content
dialog.load(url,{}, function(responseText, textStatus, XMLHttpRequest) {
dialog.dialog({
modal : true,
width : width_value,
height : height_value,
resizable : resizable_value
});
});
//prevent the browser to follow the link
return false;
});
//old jquery.menu.js
$('#navigation a').stop().animate({
'marginLeft':'50px'
}, 1000);
$('#navigation > li').hover(
function () {
$('a',$(this)).stop().animate({
'marginLeft':'1px'
},200);
},
function () {
$('a',$(this)).stop().animate({
'marginLeft':'50px'
},200);
}
);
});
</script>
{% block extraHead %}
{% endblock %}
{% endblock %}
</head>
<body class="{% block theme %}default{% endblock %} sonata-bc skin-black fixed">
{% block layout %}{% endblock %}
</body>
</html>

@ -151,6 +151,7 @@ doctrine:
json: Sonata\Doctrine\Types\JsonType
#currency: Sonata\Component\Currency\CurrencyDoctrineType
orm:
auto_generate_proxy_classes: "%kernel.debug%"
default_entity_manager: default
# auto_mapping: true

@ -0,0 +1,32 @@
<?php
$config = new \Doctrine\ORM\Configuration();
$config->setMetadataCacheImpl(new \Doctrine\Common\Cache\ArrayCache);
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\AnnotationRegistry;
$sysPath = __DIR__."/";
AnnotationRegistry::registerFile($sysPath."vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php");
$reader = new AnnotationReader();
$driverImpl = new \Doctrine\ORM\Mapping\Driver\AnnotationDriver($reader, array($sysPath."tests/doctrine_console/mapping"));
$config->setMetadataDriverImpl($driverImpl);
$config->setProxyDir(__DIR__ . '/Proxies');
$config->setProxyNamespace('Proxies');
$defaultConnection = array(
'driver' => 'pdo_mysql',
'dbname' => 'chamilo',
'user' => 'root',
'password' => 'root',
'host' => 'localhost',
);
$em = \Doctrine\ORM\EntityManager::create($defaultConnection, $config);
use Doctrine\ORM\Tools\Console\ConsoleRunner;
return ConsoleRunner::createHelperSet($em);

@ -1,183 +0,0 @@
<?php
/* For licensing terms, see /license.txt */
$config = new \Doctrine\ORM\Configuration();
$config->setMetadataCacheImpl(new \Doctrine\Common\Cache\ArrayCache);
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\AnnotationRegistry;
$sysPath = __DIR__."/";
AnnotationRegistry::registerFile($sysPath."vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php");
$reader = new AnnotationReader();
$driverImpl = new \Doctrine\ORM\Mapping\Driver\AnnotationDriver($reader, array($sysPath."tests/doctrine_console/mapping"));
$config->setMetadataDriverImpl($driverImpl);
$config->setProxyDir(__DIR__ . '/Proxies');
$config->setProxyNamespace('Proxies');
$courseList = CourseManager::get_real_course_list();
$app['chamilo.log'] = $app['sys_log_path'].'chamilo-cli.log';
// Loading db connections
$connectionOptions = array();
if (!empty($courseList)) {
$dbPrefix = isset($_configuration['db_prefix']) && !empty($_configuration['db_prefix']) ? $_configuration['db_prefix'].Database::get_database_glue() : null;
foreach ($courseList as $course) {
$connectionOptions['_chamilo_course_'.$course['db_name']] = array(
'driver' => 'pdo_mysql',
'dbname' => $dbPrefix.$course['db_name'],
'user' => $_configuration['db_user'],
'password' => $_configuration['db_password'],
'host' => $_configuration['db_host'],
);
}
}
if (isset($_configuration['main_database'])) {
$connectionOptions['main_database'] = array(
'driver' => 'pdo_mysql',
'dbname' => $_configuration['main_database'],
'user' => $_configuration['db_user'],
'password' => $_configuration['db_password'],
'host' => $_configuration['db_host'],
);
}
if (isset($_configuration['statistics_database'])) {
$connectionOptions['statistics_database'] = array(
'driver' => 'pdo_mysql',
'dbname' => $_configuration['statistics_database'],
'user' => $_configuration['db_user'],
'password' => $_configuration['db_password'],
'host' => $_configuration['db_host'],
);
} else {
if (isset($_configuration['main_database'])) {
$connectionOptions['statistics_database'] = $connectionOptions['main_database'];
}
}
if (isset($_configuration['user_personal_database'])) {
$connectionOptions['user_personal_database'] = array(
'driver' => 'pdo_mysql',
'dbname' => $_configuration['user_personal_database'],
'user' => $_configuration['db_user'],
'password' => $_configuration['db_password'],
'host' => $_configuration['db_host'],
);
} else {
if (isset($_configuration['main_database'])) {
$connectionOptions['user_personal_database'] = $connectionOptions['main_database'];
}
}
$defaultConnection = array(
'driver' => 'pdo_mysql'
);
if (isset($_configuration['main_database'])) {
$defaultConnection = array(
'driver' => 'pdo_mysql',
'dbname' => $_configuration['main_database'],
'user' => $_configuration['db_user'],
'password' => $_configuration['db_password'],
'host' => $_configuration['db_host'],
);
}
$em = \Doctrine\ORM\EntityManager::create($defaultConnection, $config);
//Fixes some errors
$platform = $em->getConnection()->getDatabasePlatform();
$platform->registerDoctrineTypeMapping('enum', 'string');
$platform->registerDoctrineTypeMapping('set', 'string');
$helpers = array(
'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()),
'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em),
'configuration' => new \Chash\Helpers\ConfigurationHelper()
);
use Doctrine\DBAL\DriverManager;
$multipleEM = array();
foreach ($connectionOptions as $name => $connection) {
$em = \Doctrine\ORM\EntityManager::create($connection, $config);
//$helpers[$name] = new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em);
$helpers[$name] = new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection());
}
/*
To generate doctrine2 entities you must:
cd /var/www/chamilo11/tests/doctrine_console
Delete old mappings/entities
sudo rm -R mapping generated repository
Creating the mapping from the DB
sudo mkdir mapping generated repository
You can add a Namespace if you want to with: --namespace "Entity"
sudo php5 doctrine.php orm:convert-mapping --force --from-database --namespace "Entity" annotation mapping
1. Generate entities
sudo php5 doctrine.php orm:generate-entities --generate-annotations="true" generated
Validate schema
sudo php5 doctrine.php orm:validate-schema -v
Move generated files in a chamilo folder:
sudo rm -R main/inc/Entity/*
mkdir main/inc/Entity
cp -R tests/doctrine_console/generated/* main/inc/Entity
fixes \ORM bug see http://redgreenrefactor.blogsite.org/php/code-first-approaching-php-with-doctrine-2-2-1-and-composer/
cd main/inc/Entity
sed -i 's/@ORM\\/@/g' *.php
For tests
php5 tests/doctrine_console/doctrine.php orm:generate-entities --generate-annotations="true" main/inc/Entity
Then autoload classes with composer
sudo php5 composer.phar update or sudo composer.phar update
2. Migrations
a. Generate empty migration file
cd /var/www/chamilo11/tests/doctrine_console
php5 doctrine.php migrations:generate
b. Check status
php5 doctrine.php migrations:status
c. Check sql
php5 doctrine.php migrations:migrate --dry-run
d. execute migration
php5 doctrine.php migrations:migrate
e. Revert migrations
php5 doctrine.php migrations:migrate 0
http://docs.doctrine-project.org/projects/doctrine-migrations/en/latest/reference/managing_migrations.html
*/

@ -1,93 +0,0 @@
#!/usr/bin/env php
<?php
/* For licensing terms, see /license.txt */
set_time_limit(0);
if (PHP_SAPI != 'cli') {
die("Cannot be called by any other method than the command line.");
}
require_once __DIR__.'/vendor/autoload.php';
$app = require_once dirname(__FILE__).'/src/ChamiloLMS/app.php';
use Knp\Provider\ConsoleServiceProvider;
$app->register(
new ConsoleServiceProvider(),
array(
'console.name' => 'Chamilo CLI',
'console.version' => '1.0.0',
'console.project_directory' => __DIR__.'/..'
)
);
// Variable $helperSet is defined inside cli-config.php
//require __DIR__.'/console-config.php';
//$cli = new \Symfony\Component\Console\Application('Chamilo CLI');
// Adding commands.
/** @var Knp\Console\Application $cli */
$cli = $app['console'];
$cli->setCatchExceptions(true);
$helpers = array(
'configuration' => new Chash\Helpers\ConfigurationHelper()
);
$helperSet = $cli->getHelperSet();
foreach ($helpers as $name => $helper) {
$helperSet->set($helper, $name);
}
$cli->addCommands(
array(
// DBAL Commands.
new \Doctrine\DBAL\Tools\Console\Command\RunSqlCommand(),
new \Doctrine\DBAL\Tools\Console\Command\ImportCommand(),
// ORM Commands.
new \Doctrine\ORM\Tools\Console\Command\ClearCache\MetadataCommand(),
new \Doctrine\ORM\Tools\Console\Command\ClearCache\ResultCommand(),
new \Doctrine\ORM\Tools\Console\Command\ClearCache\QueryCommand(),
new \Doctrine\ORM\Tools\Console\Command\SchemaTool\CreateCommand(),
new \Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand(),
new \Doctrine\ORM\Tools\Console\Command\SchemaTool\DropCommand(),
new \Doctrine\ORM\Tools\Console\Command\EnsureProductionSettingsCommand(),
new \Doctrine\ORM\Tools\Console\Command\ConvertDoctrine1SchemaCommand(),
new \Doctrine\ORM\Tools\Console\Command\GenerateRepositoriesCommand(),
new \Doctrine\ORM\Tools\Console\Command\GenerateEntitiesCommand(),
new \Doctrine\ORM\Tools\Console\Command\GenerateProxiesCommand(),
new \Doctrine\ORM\Tools\Console\Command\ConvertMappingCommand(),
new \Doctrine\ORM\Tools\Console\Command\RunDqlCommand(),
new \Doctrine\ORM\Tools\Console\Command\ValidateSchemaCommand(),
// Migrations Commands.
new \Doctrine\DBAL\Migrations\Tools\Console\Command\DiffCommand(),
new \Doctrine\DBAL\Migrations\Tools\Console\Command\ExecuteCommand(),
new \Doctrine\DBAL\Migrations\Tools\Console\Command\GenerateCommand(),
new \Doctrine\DBAL\Migrations\Tools\Console\Command\MigrateCommand(),
new \Doctrine\DBAL\Migrations\Tools\Console\Command\StatusCommand(),
new \Doctrine\DBAL\Migrations\Tools\Console\Command\VersionCommand(),
// Chamilo commands.
new ChamiloLMS\Command\Template\AsseticDumpCommand(),
new ChamiloLMS\Command\Translation\ExportLanguagesCommand(),
// Chash commands.
new Chash\Command\Database\RunSQLCommand(),
//new Chash\Command\Database\DumpCommand(),
//new Chash\Command\Database\RestoreCommand(),
new Chash\Command\Database\SQLCountCommand(),
new Chash\Command\Database\FullBackupCommand(),
//new Chash\Command\Database\DropDatabaseCommand(),
new Chash\Command\Files\CleanTempFolderCommand(),
new Chash\Command\Translation\ExportLanguageCommand(),
new Chash\Command\Translation\ImportLanguageCommand()
)
);
$cli->run();

@ -1,7 +0,0 @@
<?php
/* For licensing terms, see /license.txt */
// Redirect calls to web/index
// Please make sure you read the installation manual in the documentation/
// folder if your installation doesn't work. Hint: you need to allow overrides
header('Location: web/index');
exit;

@ -15,12 +15,7 @@ $language_file = array('agenda', 'group');
// use anonymous mode when accessing this course tool
$use_anonymous = true;
require_once '../inc/global.inc.php';
// Functions for the agenda tool
require 'agenda.inc.php';
$current_course_tool = TOOL_CALENDAR_EVENT;
$course_info = api_get_course_info();
if (!empty($course_info)) {
@ -31,296 +26,288 @@ $action = isset($_GET['action']) ? $_GET['action'] : null;
$origin = isset($_GET['origin']) ? $_GET['origin'] : null;
$this_section = SECTION_COURSES;
$url = null;
if (empty($action)) {
$url = api_get_path(WEB_CODE_PATH).'calendar/agenda_js.php?type=course';
if (!empty($course_info)) {
$url = api_get_path(WEB_CODE_PATH).'calendar/agenda_js.php?type=course'.'&'.api_get_cidreq();
} else {
$url = api_get_path(WEB_CODE_PATH).'calendar/agenda_js.php?';
}
header("Location: $url");
exit;
}
/*
TREATING THE PARAMETERS
1. viewing month only or everything
2. sort ascending or descending
3. showing or hiding the send-to-specific-groups-or-users form
4. filter user or group
*/
// 3. showing or hiding the send-to-specific-groups-or-users form
$setting_allow_individual_calendar = true;
if (empty($_POST['To']) and empty($_SESSION['allow_individual_calendar'])) {
$_SESSION['allow_individual_calendar'] = "hide";
}
$allow_individual_calendar_status = $_SESSION['allow_individual_calendar'];
if (!empty($_POST['To']) and ($allow_individual_calendar_status == "hide")) {
$_SESSION['allow_individual_calendar'] = "show";
}
if (!empty($_GET['sort']) and ($allow_individual_calendar_status == "show")) {
$_SESSION['allow_individual_calendar'] = "hide";
}
// 4. filter user or group
if (!empty($_GET['user']) or !empty($_GET['group'])) {
$_SESSION['user'] = (int)$_GET['user'];
$_SESSION['group'] = (int)$_GET['group'];
}
if ((!empty($_GET['user']) and $_GET['user'] == "none") or (!empty($_GET['group']) and $_GET['group'] == "none")) {
Session::erase("user");
Session::erase("group");
}
/* Resource linker */
$_SESSION['source_type'] = 'Agenda';
require_once '../resourcelinker/resourcelinker.inc.php';
require_once api_get_path(LIBRARY_PATH).'fileUpload.lib.php';
$group_id = api_get_group_id();
$eventId = isset($_REQUEST['id']) ? $_REQUEST['id'] : null;
$type = $event_type = isset($_GET['type']) ? $_GET['type'] : null;
//It comes from the group tools. If it's define it overwrites $_SESSION['group']
$htmlHeadXtra[] = "<script>
$htmlHeadXtra[] = to_javascript();
$htmlHeadXtra[] = user_group_filter_javascript();
function plus_repeated_event() {
if (document.getElementById('options2').style.display == 'none') {
document.getElementById('options2').style.display = 'block';
} else {
document.getElementById('options2').style.display = 'none';
}
}
$(function() {
var checked = $('input[name=repeat]').attr('checked');
if (checked) {
$('#options2').show();
}
});
</script>
";
// setting the name of the tool
$nameTools = get_lang('Agenda'); // language variable in trad4all.inc.php
// showing the header if we are not in the learning path, if we are in
// the learning path, we do not include the banner so we have to explicitly
// include the stylesheet, which is normally done in the header
if (!empty($group_id)) {
$group_properties = GroupManager :: get_group_properties($group_id);
$interbreadcrumb[] = array("url" => "../group/group.php", "name" => get_lang('Groups'));
$interbreadcrumb[] = array(
"url" => "../group/group_space.php?gidReq=".$group_id,
"name" => get_lang('GroupSpace').' '.$group_properties['name']
);
Display::display_header($nameTools, 'Agenda');
} elseif (empty($origin) or $origin != 'learnpath') {
Display::display_header($nameTools, 'Agenda');
}
$nameTools = get_lang('Agenda');
/*
TRACKING
*/
event_access_tool(TOOL_CALENDAR_EVENT);
/* SETTING SOME VARIABLES
*/
// Variable definitions
// Defining the shorts for the days. We use camelcase because these are arrays of language variables
$DaysShort = api_get_week_days_short();
// Defining the days of the week to allow translation of the days. We use camelcase because these are arrays of language variables
$DaysLong = api_get_week_days_long();
// Defining the months of the year to allow translation of the months. We use camelcase because these are arrays of language variables
$MonthsLong = api_get_months_long();
// Database table definitions
$TABLEAGENDA = Database::get_course_table(TABLE_AGENDA);
$TABLE_ITEM_PROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
$tbl_user = Database::get_main_table(TABLE_MAIN_USER);
$tbl_courseUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
$tbl_group = Database::get_course_table(TABLE_GROUP);
$tbl_groupUser = Database::get_course_table(TABLE_GROUP_USER);
/* ACCESS RIGHTS */
// permission stuff - also used by loading from global in agenda.inc.php
$is_allowed_to_edit = api_is_allowed_to_edit(false, true) OR (api_get_course_setting(
'allow_user_edit_agenda'
) && !api_is_anonymous());
// Tool introduction
Display::display_introduction_section(TOOL_CALENDAR_EVENT);
/* MAIN SECTION */
//setting the default year and month
$select_year = '';
$select_month = '';
$select_day = '';
if (!empty($_GET['year'])) {
$select_year = (int)$_GET['year'];
}
if (!empty($_GET['month'])) {
$select_month = (int)$_GET['month'];
}
if (!empty($_GET['day'])) {
$select_day = (int)$_GET['day'];
}
$today = getdate();
if (empty($select_year)) {
$select_year = $today['year'];
}
if (empty($select_month)) {
$select_month = $today['mon'];
}
echo '<div class="actions">';
if (api_is_allowed_to_edit(false, true) OR
(api_get_course_setting('allow_user_edit_agenda') && !api_is_anonymous()) && api_is_allowed_to_session_edit(
false,
true
) OR
GroupManager::user_has_access(
api_get_user_id(),
$group_id,
GroupManager::GROUP_TOOL_CALENDAR
) && GroupManager::is_tutor_of_group(api_get_user_id(), $group_id)
) {
echo display_courseadmin_links();
}
echo '</div>';
$event_id = isset($_REQUEST['id']) ? $_REQUEST['id'] : null;
$type = $event_type = isset($_GET['type']) ? $_GET['type'] : null;
$is_allowed_to_edit = api_is_allowed_to_edit(false, true) OR (api_get_course_setting('allow_user_edit_agenda') && !api_is_anonymous());
$agenda = new Agenda();
$agenda->type = $type;
$actions = $agenda->displayActions('calendar');
if ($type == 'fromjs') {
$id_list = explode('_', $event_id);
$event_id = $id_list[1];
$id_list = explode('_', $eventId);
$eventId = $id_list[1];
$event_type = $id_list[0];
}
if (!api_is_allowed_to_edit(null, true) && $event_type == 'course') {
api_not_allowed();
api_not_allowed(true);
}
if ($event_type == 'course') {
$agendaUrl = api_get_path(WEB_CODE_PATH).'calendar/agenda_js.php?'.api_get_cidreq().'&type=course';
} else {
$agendaUrl = api_get_path(WEB_CODE_PATH).'calendar/agenda_js.php?&type='.$event_type;
}
$course_info = api_get_course_info();
$agenda->type = $event_type;
$message = null;
$content = null;
if (api_is_allowed_to_edit(false, true) or
(
api_get_course_setting('allow_user_edit_agenda') &&
!api_is_anonymous() &&
api_is_allowed_to_session_edit(false, true)
) or
GroupManager::user_has_access(api_get_user_id(), $group_id, GroupManager::GROUP_TOOL_CALENDAR) &&
if (api_is_allowed_to_edit(false, true) OR
(api_get_course_setting('allow_user_edit_agenda') &&
!api_is_anonymous() &&
api_is_allowed_to_session_edit(false, true)) OR
GroupManager::user_has_access(api_get_user_id(), $group_id, GroupManager::GROUP_TOOL_CALENDAR) &&
GroupManager::is_tutor_of_group(api_get_user_id(), $group_id)
) {
switch ($action) {
case 'add':
if (isset($_POST['submit_event']) && $_POST['submit_event']) {
$actionName = get_lang('Add');
$form = $agenda->getForm(array('action' => 'add'));
$startDate = Text::return_datetime_from_array($_POST['start_date']);
$endDate = Text::return_datetime_from_array($_POST['end_date']);
$repeatEndDay = Text::return_datetime_from_array($_POST['repeat_end_day']);
if ($form->validate()) {
$values = $form->getSubmitValues();
$fileComment = isset($_POST['file_comment']) ? $_POST['file_comment'] : null;
$fileAttachment = isset($_FILES['user_upload']) ? $_FILES['user_upload'] : null;
$agenda = new Agenda();
$agenda->setType('course');
$sendEmail = isset($values['add_announcement']) ? true : false;
$allDay = isset($values['all_day']) ? 'true' : 'false';
$repeatSettings = array();
$sendAttachment = isset($_FILES['user_upload']) ? true : false;
$attachment = $sendAttachment ? $_FILES['user_upload'] : null;
$attachmentComment = isset($values['file_comment']) ? $values['file_comment'] : null;
if (!empty($_POST['repeat'])) {
$repeatSettings = array(
'repeat_type' => $_POST['repeat_type'],
'repeat_end' => $repeatEndDay
);
/*
$res = agenda_add_repeat_item(
$course_info,
$id,
$_POST['repeat_type'],
$repeatEndDay,
$_POST['users'],
$safe_file_comment
);*/
}
$startDate = $values['date_range_start'];
$endDate = $values['date_range_end'];
$id = $agenda->add_event(
$eventId = $agenda->add_event(
$startDate,
$endDate,
$allDay,
$values['title'],
$values['content'],
$values['users_to_send'],
$sendEmail,
null,
null,
$_POST['title'],
$_POST['content'],
$_POST['users'],
false,
null,
array('comment' => $fileComment, 'file' => $fileAttachment),
$repeatSettings
$attachment,
$attachmentComment
);
Display::display_confirmation_message(get_lang('AddSuccess'));
if (!empty($values['repeat']) && !empty($eventId)) {
// End date is always set as 23:59:59
$endDate = substr($values['repeat_end_day'], 0, 10).' 23:59:59';
$agenda->addRepeatedItem(
$eventId,
$values['repeat_type'],
$endDate,
$values['users_to_send']
);
}
$message = Display::return_message(get_lang('AddSuccess'), 'confirmation');
if ($sendEmail) {
$message .= Display::return_message(get_lang('AdditionalMailWasSentToSelectedUsers'), 'confirmation');
}
Session::write('message', $message);
header("Location: $agendaUrl");
exit;
} else {
show_add_form();
$content = $form->return_form();
}
break;
case "announce":
//copying the agenda item into an announcement
if (!(api_is_course_coach() && !api_is_element_in_the_session(TOOL_AGENDA, $event_id))) {
// a coach can only delete an element belonging to his session
$ann_id = store_agenda_item_as_announcement($event_id);
$tool_group_link = (isset($_SESSION['toolgroup']) ? '&toolgroup='.$_SESSION['toolgroup'] : '');
Display::display_normal_message(
get_lang(
'CopiedAsAnnouncement'
).'&nbsp;<a href="../announcements/announcements.php?id='.$ann_id.$tool_group_link.'">'.get_lang(
'NewAnnouncement'
).'</a>',
false
case 'edit':
$actionName = get_lang('Edit');
$event = $agenda->get_event($eventId);
if (empty($event)) {
api_not_allowed(true);
}
$event['action'] = 'edit';
$event['id'] = $eventId;
$form = $agenda->getForm($event);
if ($form->validate()) {
$values = $form->getSubmitValues();
$allDay = isset($values['all_day']) ? 'true' : 'false';
$startDate = $values['date_range_start'];
$endDate = $values['date_range_end'];
$sendAttachment = isset($_FILES['user_upload']) ? true : false;
$attachment = $sendAttachment ? $_FILES['user_upload'] : null;
$attachmentComment = isset($values['file_comment']) ? $values['file_comment'] : null;
// This is a sub event. Delete the current and create another BT#7803
if (!empty($event['parent_event_id'])) {
$agenda->delete_event($eventId);
$eventId = $agenda->add_event(
$startDate,
$endDate,
$allDay,
$values['title'],
$values['content'],
$values['users_to_send'],
false,
null,
$attachment,
$attachmentComment
);
$message = Display::return_message(get_lang('Updated'), 'confirmation');
Session::write('message', $message);
header("Location: $agendaUrl");
exit;
}
// Editing normal event.
$agenda->edit_event(
$eventId,
$startDate,
$endDate,
$allDay,
$values['title'],
$values['content'],
$values['users_to_send'],
$attachment,
$attachmentComment
);
if (!empty($values['repeat']) && !empty($eventId)) {
// End date is always set as 23:59:59
$endDate = substr($values['repeat_end_day'], 0, 10).' 23:59:59';
$agenda->addRepeatedItem(
$eventId,
$values['repeat_type'],
$endDate,
$values['users_to_send']
);
}
$deleteAttachment = isset($values['delete_attachment']) ? true : false;
if ($deleteAttachment && isset($event['attachment']) && !empty($event['attachment'])) {
$agenda->deleteAttachmentFile(
$event['attachment']['id'],
$agenda->course
);
}
$message = Display::return_message(get_lang('Updated'), 'confirmation');
Session::write('message', $message);
header("Location: $agendaUrl");
exit;
} else {
$content = $form->return_form();
}
break;
case 'importical':
if (isset($_POST['ical_submit'])) {
$form = $agenda->getImportCalendarForm();
$content = $form->return_form();
if ($form->validate()) {
$ical_name = $_FILES['ical_import']['name'];
$ical_type = $_FILES['ical_import']['type'];
$ext = substr($ical_name, (strrpos($ical_name, ".") + 1));
//$ical_type === 'text/calendar'
if ($ext === 'ics' || $ext === 'ical' || $ext === 'icalendar' || $ext === 'ifb') {
$agenda_result = agenda_import_ical($course_info, $_FILES['ical_import']);
$result = $agenda->importEventFile($course_info, $_FILES['ical_import']);
$is_ical = true;
} else {
$is_ical = false;
}
if (!$is_ical) {
Display::display_error_message(get_lang('IsNotiCalFormatFile'));
display_ical_import_form();
$message = Display::return_message(get_lang('IsNotiCalFormatFile'), 'error');
$form = $agenda->getImportCalendarForm();
$content = $form->return_form();
break;
} else {
Display::display_confirmation_message(get_lang('AddSuccess'));
echo $agenda_result;
$message = Display::return_message(get_lang('AddSuccess'), 'error');
$content = $result;
}
} else {
display_ical_import_form();
}
break;
case 'edit':
// a coach can only delete an element belonging to his session
if ($_POST['submit_event']) {
store_edited_agenda_item($event_id, $_REQUEST['id_attach'], $_REQUEST['file_comment']);
$action = 'view';
} else {
show_add_form($event_id, $event_type);
Session::write('message', $message);
}
break;
case "delete":
if (!(api_is_course_coach() && !api_is_element_in_the_session(TOOL_AGENDA, $event_id))) {
if (!(api_is_course_coach() && !api_is_element_in_the_session(TOOL_AGENDA, $eventId) )) {
// a coach can only delete an element belonging to his session
delete_agenda_item($event_id);
$action = 'view';
}
break;
case "showhide":
if (!(api_is_course_coach() && !api_is_element_in_the_session(TOOL_AGENDA, $event_id))) {
// a coach can only delete an element belonging to his session
showhide_agenda_item($event_id);
$action = 'view';
}
if (!empty($_GET['agenda_id'])) {
display_one_agenda_item($_GET['agenda_id']);
}
break;
case "delete_attach": //delete attachment file
$id_attach = $_GET['id_attach'];
if (!empty($id_attach)) {
delete_attachment_file($id_attach);
$action = 'view';
$content = $agenda->delete_event($eventId);
}
break;
}
}
// The footer is displayed only if we are not in the learnpath
if ($origin != 'learnpath') {
Display::display_footer();
if (!empty($group_id)) {
$group_properties = GroupManager :: get_group_properties($group_id);
$interbreadcrumb[] = array(
"url" => api_get_path(WEB_CODE_PATH)."group/group.php",
"name" => get_lang('Groups')
);
$interbreadcrumb[] = array(
"url" => api_get_path(WEB_CODE_PATH)."group/group_space.php?gidReq=".$group_id,
"name" => get_lang('GroupSpace').' '.$group_properties['name']
);
}
if (!empty($actionName)) {
$interbreadcrumb[] = array(
"url" => $url,
"name" => get_lang('Agenda')
);
}
// Tool introduction
$introduction = Display::return_introduction_section(TOOL_CALENDAR_EVENT);
$message = Session::read('message');
Session::erase('message');
$tpl = new Template($actionName);
$tpl->assign('content', $content);
$tpl->assign('actions', $actions);
// Loading main Chamilo 1 col template
$tpl->display_one_col_template();

@ -8,9 +8,6 @@
*/
use \ChamiloSession as Session;
// name of the language file that needs to be included
$language_file = array('agenda', 'group', 'announcements');
// use anonymous mode when accessing this course tool
$use_anonymous = true;
@ -23,7 +20,6 @@ if ($type == 'personal') {
$cidReset = true; // fixes #5162
}
require_once '../inc/global.inc.php';
require_once 'agenda.inc.php';
$current_course_tool = TOOL_CALENDAR_EVENT;
@ -66,8 +62,8 @@ if (!empty($group_id)) {
}
$app['title'] = get_lang('Agenda');
$tpl = $app['template'];
$tpl->assign('use_google_calendar', 0);
$tpl = Session::getTwig();
$tpl->addGlobal('use_google_calendar', 0);
$can_add_events = 0;
@ -97,8 +93,8 @@ switch($type) {
}
$extra_field_data = UserManager::get_extra_user_data_by_field(api_get_user_id(), 'google_calendar_url');
if (!empty($extra_field_data) && isset($extra_field_data['google_calendar_url']) && !empty($extra_field_data['google_calendar_url'])) {
$tpl->assign('use_google_calendar', 1);
$tpl->assign('google_calendar_url', $extra_field_data['google_calendar_url']);
$tpl->addGlobal('use_google_calendar', 1);
$tpl->addGlobal('google_calendar_url', $extra_field_data['google_calendar_url']);
}
$this_section = SECTION_MYAGENDA;
if (!api_is_anonymous()) {
@ -115,52 +111,44 @@ $months = api_get_months_long();
$months_short = api_get_months_short();
//Setting calendar translations
$tpl->assign('month_names', json_encode($months));
$tpl->assign('month_names_short', json_encode($months_short));
$tpl->assign('day_names', json_encode($days));
$tpl->assign('day_names_short', json_encode($day_short));
$tpl->assign(
'button_text',
json_encode(
array(
$tpl->addGlobal('month_names', json_encode($months));
$tpl->addGlobal('month_names_short', json_encode($months_short));
$tpl->addGlobal('day_names', json_encode($days));
$tpl->addGlobal('day_names_short', json_encode($day_short));
$tpl->addGlobal('button_text',
json_encode(array(
'today' => get_lang('Today'),
'month' => get_lang('Month'),
'week' => get_lang('Week'),
'day' => get_lang('Day')
)
)
))
);
//see http://docs.jquery.com/UI/Datepicker/$.datepicker.formatDate
$tpl->assign('js_format_date', 'D d M yy');
$tpl->addGlobal('js_format_date', 'D d M yy');
$region_value = api_get_language_isocode();
if ($region_value == 'en') {
$region_value = 'en-GB';
}
$tpl->assign('region_value', $region_value);
$tpl->assign('export_ical_confidential_icon', Display::return_icon('export.png', get_lang('ExportiCalConfidential')));
$actions = null;
$filter = null;
if (api_is_allowed_to_edit(false,true) OR
(api_get_course_setting('allow_user_edit_agenda') && !api_is_anonymous()) &&
api_is_allowed_to_session_edit(false,true) OR
$is_group_tutor
) {
if ($type == 'course') {
if (isset($_GET['user_id'])) {
$filter = $_GET['user_id'];
}
$actions = display_courseadmin_links($filter);
}
$tpl->assign('actions', $actions);
}
$tpl->addGlobal('region_value', $region_value);
$export_icon = api_get_path(WEB_IMG_PATH).'img/export.png';
$export_icon_low = api_get_path(WEB_IMG_PATH).'img/export_low_fade.png';
$export_icon_high = api_get_path(WEB_IMG_PATH).'img/export_high_fade.png';
$tpl->addGlobal(
'export_ical_confidential_icon',
Display::return_icon($export_icon_high, get_lang('ExportiCalConfidential'))
);
//Calendar Type : course, admin, personal
$tpl->assign('type', $type);
$actions = $agenda->displayActions('calendar', $userId);
$tpl->addGlobal('actions', $actions);
// Calendar Type : course, admin, personal
$tpl->addGlobal('type', $type);
$type_event_class = $type.'_event';
$type_label = get_lang(ucfirst($type).'Calendar');
@ -169,89 +157,64 @@ if ($type == 'course' && !empty($group_id)) {
$type_label = get_lang('GroupCalendar');
}
$defaultView = api_get_setting('default_calendar_view');
if (empty($defaultView)) {
$defaultView = 'month';
}
/* month, basicWeek, agendaWeek, agendaDay */
$tpl->addGlobal('default_view', $defaultView);
if ($type == 'course' && !empty($session_id)) {
$type_event_class = 'session_event';
$type_label = get_lang('SessionCalendar');
}
$tpl->assign('type_label', $type_label);
$tpl->assign('type_event_class', $type_event_class);
$tpl->addGlobal('type_label', $type_label);
$tpl->addGlobal('type_event_class', $type_event_class);
//Current user can add event?
$tpl->assign('can_add_events', $can_add_events);
// Current user can add event?
$tpl->addGlobal('can_add_events', $can_add_events);
//Setting AJAX caller
if (isset($_GET['user_id'])) {
$user_id = $_GET['user_id'];
$agenda_ajax_url = api_get_path(WEB_AJAX_PATH).'agenda.ajax.php?user_id='.$user_id.'&type='.$type;
if (!empty($userId)) {
$agenda_ajax_url = api_get_path(WEB_AJAX_PATH).'agenda.ajax.php?user_id='.$userId.'&type='.$type;
} else {
$agenda_ajax_url = api_get_path(WEB_AJAX_PATH).'agenda.ajax.php?type='.$type;
}
$tpl->assign('web_agenda_ajax_url', $agenda_ajax_url);
$course_code = api_get_course_id();
$select = null;
if ((api_is_allowed_to_edit() || $is_group_tutor) && $course_code != '-1' && $type == 'course') {
$order = 'lastname';
if (api_is_western_name_order()) {
$order = 'firstname';
}
if (!empty($group_id)) {
$group_list = array($group_id => $group_properties);
$user_list = GroupManager::get_subscribed_users($group_id);
} else {
$user_list = CourseManager::get_user_list_from_course_code(api_get_course_id(), api_get_session_id(), null, $order);
$group_list = CourseManager::get_group_list_of_course(api_get_course_id(), api_get_session_id());
}
$agenda = new Agenda();
$tpl->addGlobal('web_agenda_ajax_url', $agenda_ajax_url);
$course_code = api_get_course_id();
//This will fill the select called #users_to_send_id
$select = $agenda->construct_not_selected_select_form($group_list, $user_list, array());
$tpl->assign('visible_to', $select);
}
$form = new FormValidator('form-simple', '', null);
$form->addElement('label', get_lang('Date'), '<span id="simple_start_date"></span><span id="simple_end_date"></span>');
$form->addElement('label', get_lang('Title'), '<div id="simple_title"></div>');
$form->addElement('label', get_lang('Description'), '<div id="simple_content"></div>');
$tpl->assign('form_simple', $form->return_form());
$form = new FormValidator('add_event_form', null, null);
if (!empty($select)) {
$form->addElement(
'label',
get_lang('To'),
$select,
array('id' => 'visible_to_input', 'style' => 'display:none')
);
}
$form = new FormValidator('form', 'get', null, null, array('id' => 'add_event_form'));
$form->addElement('html', '<div id="visible_to_input">');
$form->addElement(
'label',
get_lang('To'),
'<div id="visible_to_read_only_users"></div>',
array('id' => 'visible_to_read_only', 'style' => 'display:none')
);
$sendTo = $agenda->parseAgendaFilter($userId);
$addOnlyItemsInSendTo = true;
$form->addElement('label', get_lang('Agenda'), '<div id="color_calendar"></div>');
$form->addElement('label', get_lang('Date'), '<span id="start_date"></span><span id="end_date"></span>');
$form->addElement(
'label',
get_lang('Title'),
'<input type="text" name="title" id="title" size="40" /><span id="title_edit"></span>'
);
$form->addElement(
'label',
get_lang('Description'),
'<textarea name="content" id="content" class="span3" rows="5"></textarea>
<span id="content_edit"></span>'
);
if ($sendTo['everyone']) {
$addOnlyItemsInSendTo = false;
}
$agenda->showToForm($form, $sendTo, array(), $addOnlyItemsInSendTo);
$form->addElement('html', '</div>');
$form->addElement('html', '<div id="visible_to_read_only" style="display: none">');
$form->addElement('label', get_lang('To'), '<div id="visible_to_read_only_users"></div>');
$form->addElement('html', '</div>');
if ($type == 'course') {
$form->addElement('html', '<div id="add_as_announcement_div">');
$form->addElement('checkbox', 'add_as_annonuncement', array(null, null, get_lang('AddAsAnnouncement').' ('.get_lang('SendEmail').')'));
$form->addElement('label', get_lang('Agenda'), '<div id="color_calendar"></div>');
$form->addElement('label', get_lang('Date'), '<span id="start_date"></span><span id="end_date"></span>');
$form->addElement('text', 'title', get_lang('Title'), array('id' => 'title'));
$form->addElement('textarea', 'content', get_lang('Description'), array('id' => 'content'));
if ($agenda->type == 'course') {
$form->addElement('html', '<div id="add_as_announcement_div" style="display: none">');
$form->addElement('checkbox', 'add_as_annonuncement', null, get_lang('AddAsAnnouncement'));
$form->addElement('html', '</div>');
}
$tpl->assign('form_add', $form->return_form());
$tpl->addGlobal('form_add', $form->return_form());
$tpl->render('ChamiloLMSCoreBundle:Calendar:month.html.twig');
$tpl->display('default/agenda/month.tpl');

@ -1,80 +0,0 @@
<?php
/* For licensing terms, see /license.txt */
use \ChamiloSession as Session;
/**
* 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...).
*
* @package chamilo.course_home
*/
function return_block($title, $content)
{
$html = '<div class="page-header">
<h3>'.$title.'</h3>
</div>
'.$content.'</div>';
return $html;
}
$session_id = api_get_session_id();
$urlGenerator = Session::$urlGenerator;
$content = null;
// Start of tools for CourseAdmins (teachers/tutors)
$totalList = array();
if ($session_id == 0 && api_is_course_admin() && api_is_allowed_to_edit(null, true)) {
$list = CourseHome::get_tools_category(TOOL_AUTHORING);
$result = CourseHome::show_tools_category($urlGenerator, $list);
$content .= return_block(get_lang('Authoring'), $result['content']);
$totalList = $result['tool_list'];
$list = CourseHome::get_tools_category(TOOL_INTERACTION);
$list2 = CourseHome::get_tools_category(TOOL_COURSE_PLUGIN);
$list = array_merge($list, $list2);
$result = CourseHome::show_tools_category($urlGenerator, $list);
$totalList = array_merge($totalList, $result['tool_list']);
$content .= return_block(get_lang('Interaction'), $result['content']);
$list = CourseHome::get_tools_category(TOOL_ADMIN_PLATFORM);
$totalList = array_merge($totalList, $list);
$result = CourseHome::show_tools_category($urlGenerator, $list);
$totalList = array_merge($totalList, $result['tool_list']);
$content .= return_block(get_lang('Administration'), $result['content']);
} elseif (api_is_coach()) {
$content .= '<div class="row">';
$list = CourseHome::get_tools_category(TOOL_STUDENT_VIEW);
$content .= CourseHome::show_tools_category($urlGenerator, $result['content']);
$totalList = array_merge($totalList, $result['tool_list']);
$content .= '</div>';
} else {
$list = CourseHome::get_tools_category(TOOL_STUDENT_VIEW);
if (count($list) > 0) {
$content .= '<div class="row">';
$result = CourseHome::show_tools_category($urlGenerator, $list);
$content .= $result['content'];
$totalList = array_merge($totalList, $result['tool_list']);
$content .= '</div>';
}
}
return array(
'content' => $content,
'tool_list' => $totalList
);

File diff suppressed because it is too large Load Diff

@ -430,7 +430,12 @@ class CourseHome
$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";
$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";

@ -26,7 +26,6 @@
/**
* Base class for form elements
*/
//require_once 'HTML/QuickForm/element.php';
/**
* Class to dynamically create an HTML SELECT
@ -116,7 +115,7 @@ class HTML_QuickForm_select extends HTML_QuickForm_element {
function setSelected($values)
{
if (is_string($values) && $this->getMultiple()) {
$values = @split("[ ]?,[ ]?", $values);
$values = split("[ ]?,[ ]?", $values);
}
if (is_array($values)) {
$this->_values = array_values($values);
@ -326,7 +325,7 @@ class HTML_QuickForm_select extends HTML_QuickForm_element {
} // end func addOption
/**
/**
* Adds a new OPTION to the SELECT
*
* @param string $text Display text for the OPTION
@ -339,14 +338,11 @@ class HTML_QuickForm_select extends HTML_QuickForm_element {
*/
function addOptGroup($options, $label)
{
foreach ($options as &$option) {
$option[] = $this->addOption($option['text'], $option['value'], null, true);
foreach ($options as $option) {
$this->addOption($option['text'], $option['value'], $option, true);
}
$this->_optgroups[] = array('label' => $label, 'options' => $options);
} // end func addOption
// }}}
// {{{ loadArray()
}
/**
* Loads the options from an associative array
@ -428,7 +424,7 @@ class HTML_QuickForm_select extends HTML_QuickForm_element {
function loadQuery(&$conn, $sql, $textCol=null, $valueCol=null, $values=null)
{
if (is_string($conn)) {
//require_once('DB.php');
require_once('DB.php');
$dbConn = &DB::connect($conn, true);
if (DB::isError($dbConn)) {
return $dbConn;
@ -520,11 +516,8 @@ class HTML_QuickForm_select extends HTML_QuickForm_element {
$attrString = $this->_getAttrString($this->_attributes);
$this->setName($myName);
}
$strHtml .= $tabs . '<select' . $attrString . ">\n";
if (isset($this->_attributes['data-placeholder'])) {
$strHtml .= "<option></option>";
}
$strHtml .= $tabs . '<select' . $attrString . ">\n";
$strValues = is_array($this->_values)? array_map('strval', $this->_values): array();
foreach ($this->_options as $option) {
@ -532,25 +525,21 @@ class HTML_QuickForm_select extends HTML_QuickForm_element {
$option['attr']['selected'] = 'selected';
}
$strHtml .= $tabs . "\t<option" . $this->_getAttrString($option['attr']) . '>' .
$option['text'] . "</option>\n";
$option['text'] . "</option>\n";
}
foreach ($this->_optgroups as $optgroup) {
$strHtml .= $tabs . "\t<optgroup label=" . $optgroup['label'].">";
foreach($optgroup['options'] as $option) {
$strHtml .= $tabs . "\t<option" . $this->_getAttrString($option['attr']) . '>' .
$option['text'] . "</option>\n";
$strHtml .= $tabs . "<optgroup label=" . $optgroup['label'].">";
foreach ($optgroup['options'] as $option) {
$text = $option['text'];
unset($option['text']);
$strHtml .= $tabs . " <option" . $this->_getAttrString($option) . '>' .$text . "</option>";
}
$strHtml .= "</optgroup>\n";
$strHtml .= "</optgroup>";
}
return $strHtml . $tabs . '</select>';
}
} //end func toHtml
}
// }}}
// {{{ getFrozenHtml()
/**
* Returns the value of field without HTML tags
@ -584,10 +573,10 @@ class HTML_QuickForm_select extends HTML_QuickForm_element {
}
foreach ($value as $key => $item) {
$html .= '<input' . $this->_getAttrString(array(
'type' => 'hidden',
'name' => $name,
'value' => $this->_values[$key]
) + $idAttr) . ' />';
'type' => 'hidden',
'name' => $name,
'value' => $this->_values[$key]
) + $idAttr) . ' />';
}
}
return $html;
@ -596,10 +585,10 @@ class HTML_QuickForm_select extends HTML_QuickForm_element {
// }}}
// {{{ exportValue()
/**
* We check the options and return only the values that _could_ have been
* selected. We also return a scalar value if select is not "multiple"
*/
/**
* We check the options and return only the values that _could_ have been
* selected. We also return a scalar value if select is not "multiple"
*/
function exportValue(&$submitValues, $assoc = false)
{
$value = $this->_findValue($submitValues);

@ -0,0 +1,22 @@
<?php
namespace ChamiloLMS\CoreBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class DoctrineEntityListenerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$definition = $container->getDefinition('chamilolms.doctrine.entity_listener_resolver');
$services = $container->findTaggedServiceIds('doctrine.entity_listener');
foreach ($services as $service => $attributes) {
$definition->addMethodCall(
'addMapping',
array($container->getDefinition($service)->getClass(), $service)
);
}
}
}

@ -0,0 +1,40 @@
<?php
namespace ChamiloLMS\CoreBundle\Doctrine;
use Doctrine\ORM\Mapping\DefaultEntityListenerResolver;
use Symfony\Component\DependencyInjection\ContainerInterface;
class EntityListenerResolver extends DefaultEntityListenerResolver
{
private $container;
private $mapping;
/**
* @param ContainerInterface $container
*/
public function __construct(ContainerInterface $container)
{
$this->container = $container;
$this->mapping = array();
}
/**
* @param $className
* @param $service
*/
public function addMapping($className, $service)
{
$this->mapping[$className] = $service;
}
public function resolve($className)
{
if (isset($this->mapping[$className]) && $this->container->has($this->mapping[$className])) {
return $this->container->get($this->mapping[$className]);
}
return parent::resolve($className);
}
}

@ -0,0 +1,60 @@
<?php
/* For licensing terms, see /license.txt */
namespace ChamiloLMS\CoreBundle\EventListener;
use Avanzu\AdminThemeBundle\Event\SidebarMenuKnpEvent;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\Request;
class MenuListener
{
protected $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function onSetupMenu(SidebarMenuKnpEvent $event)
{
$request = $event->getRequest();
foreach ($this->getMenu($request) as $item) {
$event->addItem($item);
}
}
protected function getMenu(Request $request)
{
$menu = $this->container->get('chamilolms.menu.simple_menu');
/** @var \Knp\Menu\ItemInterface $menuItems */
$menuItems = $menu->mainMenu(
$this->container->get('knp_menu.factory'),
array()
);
return $this->activateByRoute($request->get('_route'), $menuItems);
}
protected function activateByRoute($route, $items)
{
/** @var \Knp\Menu\MenuItem $item */
foreach ($items as $item) {
if ($item->hasChildren()) {
$this->activateByRoute($route, $item->getChildren());
} else {
if ($item->isCurrent()) {
$item->setCurrent(true);
}
/*if ($item->getRoute() == $route) {
$item->setIsActive(true);
}*/
}
}
return $items;
}
}

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

@ -86,7 +86,7 @@ return array(
'Doctrine\\Common\\' => array($vendorDir . '/doctrine/common/lib'),
'Doctrine\\Bundle\\MigrationsBundle' => array($vendorDir . '/doctrine/doctrine-migrations-bundle'),
'Doctrine\\Bundle\\FixturesBundle' => array($vendorDir . '/doctrine/doctrine-fixtures-bundle'),
'Doctrine\\Bundle\\DoctrineBundle' => array($vendorDir . '/doctrine/doctrine-bundle'),
'Doctrine\\Bundle\\DoctrineCacheBundle' => array($vendorDir . '/doctrine/doctrine-cache-bundle'),
'Composer' => array($vendorDir . '/composer/composer/src'),
'Chash' => array($vendorDir . '/chamilo/chash/src'),
'CG\\' => array($vendorDir . '/jms/cg/src'),

@ -51,4 +51,5 @@ return array(
'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
'Google\\Authenticator\\Tests\\' => array($vendorDir . '/sonata-project/google-authenticator/tests'),
'Google\\Authenticator\\' => array($vendorDir . '/sonata-project/google-authenticator/lib'),
'Doctrine\\Bundle\\DoctrineBundle\\' => array($vendorDir . '/doctrine/doctrine-bundle'),
);

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInitafc49d8078f44ed99fdf94305db6ff51
class ComposerAutoloaderInita4aa94c829bfe1922707cba4e98c7e3f
{
private static $loader;
@ -19,9 +19,9 @@ class ComposerAutoloaderInitafc49d8078f44ed99fdf94305db6ff51
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInitafc49d8078f44ed99fdf94305db6ff51', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInita4aa94c829bfe1922707cba4e98c7e3f', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInitafc49d8078f44ed99fdf94305db6ff51', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInita4aa94c829bfe1922707cba4e98c7e3f', 'loadClassLoader'));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
@ -45,14 +45,14 @@ class ComposerAutoloaderInitafc49d8078f44ed99fdf94305db6ff51
$includeFiles = require __DIR__ . '/autoload_files.php';
foreach ($includeFiles as $file) {
composerRequireafc49d8078f44ed99fdf94305db6ff51($file);
composerRequirea4aa94c829bfe1922707cba4e98c7e3f($file);
}
return $loader;
}
}
function composerRequireafc49d8078f44ed99fdf94305db6ff51($file)
function composerRequirea4aa94c829bfe1922707cba4e98c7e3f($file)
{
require $file;
}

File diff suppressed because it is too large Load Diff

@ -27,6 +27,7 @@ $directories = array(getcwd(), getcwd() . DIRECTORY_SEPARATOR . 'config');
$configFile = null;
foreach ($directories as $directory) {
$configFile = $directory . DIRECTORY_SEPARATOR . 'cli-config.php';
if (file_exists($configFile)) {
break;
}

@ -14,7 +14,7 @@ Doctrine ORM don't panic. You can get help from different sources:
- There is a :doc:`FAQ <reference/faq>` with answers to frequent questions.
- The `Doctrine Mailing List <http://groups.google.com/group/doctrine-user>`_
- Internet Relay Chat (IRC) in #doctrine on Freenode
- Internet Relay Chat (IRC) in `#doctrine on Freenode <irc://irc.freenode.net/doctrine>`_
- Report a bug on `JIRA <http://www.doctrine-project.org/jira>`_.
- On `Twitter <https://twitter.com/search/%23doctrine2>`_ with ``#doctrine2``
- On `StackOverflow <http://stackoverflow.com/questions/tagged/doctrine2>`_
@ -120,4 +120,3 @@ Cookbook
:doc:`MySQL Enums <cookbook/mysql-enums>`
:doc:`Advanced Field Value Conversion <cookbook/advanced-field-value-conversion-using-custom-mapping-types>`
.. include:: toc.rst

@ -106,7 +106,7 @@ Redis
In order to use the Redis cache driver you must have it compiled
and enabled in your php.ini. You can read about what is Redis
`from here <http://redis.io/>`_. Also check
`A PHP extension for Redis <https://github.com/nicolasff/phpredis/>`_ for how you can use
`here <https://github.com/nicolasff/phpredis/>`_ for how you can use
and install Redis PHP extension.
Below is a simple example of how you could use the Redis cache

@ -100,7 +100,7 @@ Doctrine ships with a number of command line tools that are very helpful
during development. You can call this command from the Composer binary
directory:
.. code-block:: sh
.. code-block::
$ php vendor/bin/doctrine

@ -207,13 +207,10 @@ listeners:
- Lifecycle Callbacks are methods on the entity classes that are
called when the event is triggered. As of v2.4 they receive some kind
of ``EventArgs`` instance.
called when the event is triggered. They receives some kind of ``EventArgs``.
- Lifecycle Event Listeners and Subscribers are classes with specific callback
methods that receives some kind of ``EventArgs`` instance.
The EventArgs instance received by the listener gives access to the entity,
EntityManager and other relevant data.
methods that receives some kind of ``EventArgs`` instance which
give access to the entity, EntityManager or other relevant data.
.. note::
@ -227,11 +224,10 @@ EntityManager and other relevant data.
Lifecycle Callbacks
-------------------
Lifecycle Callbacks are defined on an entity class. They allow you to
trigger callbacks whenever an instance of that entity class experiences
a relevant lifecycle event. More than one callback can be defined for each
lifecycle event. Lifecycle Callbacks are best used for simple operations
specific to a particular entity class's lifecycle.
A lifecycle event is a regular event with the additional feature of
providing a mechanism to register direct callbacks inside the
corresponding entity classes that are executed when the lifecycle
event occurs.
.. code-block:: php
@ -281,9 +277,8 @@ specific to a particular entity class's lifecycle.
}
}
Note that the methods set as lifecycle callbacks need to be public and,
when using these annotations, you have to apply the
``@HasLifecycleCallbacks`` marker annotation on the entity class.
Note that when using annotations you have to apply the
@HasLifecycleCallbacks marker annotation on the entity class.
If you want to register lifecycle callbacks from YAML or XML you
can do it with the following.
@ -300,10 +295,6 @@ can do it with the following.
prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersistToo ]
postPersist: [ doStuffOnPostPersist ]
In YAML the ``key`` of the lifecycleCallbacks entry is the event that you
are triggering on and the value is the method (or methods) to call. The allowed
event types are the ones listed in the previous Lifecycle Events section.
XML would look something like this:
.. code-block:: xml
@ -326,14 +317,9 @@ XML would look something like this:
</doctrine-mapping>
In XML the ``type`` of the lifecycle-callback entry is the event that you
are triggering on and the ``method`` is the method to call. The allowed event
types are the ones listed in the previous Lifecycle Events section.
When using YAML or XML you need to remember to create public methods to match the
callback names you defined. E.g. in these examples ``doStuffOnPrePersist()``,
``doOtherStuffOnPrePersist()`` and ``doStuffOnPostPersist()`` methods need to be
defined on your ``User`` model.
You just need to make sure a public ``doStuffOnPrePersist()`` and
``doStuffOnPostPersist()`` method is defined on your ``User``
model.
.. code-block:: php
@ -389,10 +375,8 @@ Listening and subscribing to Lifecycle Events
Lifecycle event listeners are much more powerful than the simple
lifecycle callbacks that are defined on the entity classes. They
sit at a level above the entities and allow you to implement re-usable
behaviors across different entity classes.
Note that they require much more detailed knowledge about the inner
allow to implement re-usable behaviors between different entity
classes, yet require much more detailed knowledge about the inner
workings of the EntityManager and UnitOfWork. Please read the
*Implementing Event Listeners* section carefully if you are trying
to write your own listener.
@ -492,8 +476,8 @@ data and lost updates/persists/removes.
For the described events that are also lifecycle callback events
the restrictions apply as well, with the additional restriction
that (prior to version 2.4) you do not have access to the
EntityManager or UnitOfWork APIs inside these events.
that you do not have access to the EntityManager or UnitOfWork APIs
inside these events.
prePersist
~~~~~~~~~~
@ -517,9 +501,11 @@ The following restrictions apply to ``prePersist``:
- If you are using a PrePersist Identity Generator such as
sequences the ID value will *NOT* be available within any
PrePersist events.
- Doctrine will not recognize changes made to relations in a prePersist
event. This includes modifications to
collections such as additions, removals or replacement.
- Doctrine will not recognize changes made to relations in a pre
persist event called by "reachability" through a cascade persist
unless you use the internal ``UnitOfWork`` API. We do not recommend
such operations in the persistence by reachability context, so do
this at your own risk and possibly supported by unit-tests.
preRemove
~~~~~~~~~
@ -713,8 +699,7 @@ Restrictions for this event:
recognized by the flush operation anymore.
- Changes to fields of the passed entities are not recognized by
the flush operation anymore, use the computed change-set passed to
the event to modify primitive field values, e.g. use
``$eventArgs->setNewValue($field, $value);`` as in the Alice to Bob example above.
the event to modify primitive field values.
- Any calls to ``EntityManager#persist()`` or
``EntityManager#remove()``, even in combination with the UnitOfWork
API are strongly discouraged and don't work as expected outside the
@ -784,10 +769,9 @@ An ``Entity Listener`` could be any class, by default it should be a class with
- Different from :ref:`reference-events-implementing-listeners` an ``Entity Listener`` is invoked just to the specified entity
- An entity listener method receives two arguments, the entity instance and the lifecycle event.
- The callback method can be defined by naming convention or specifying a method mapping.
- When a listener mapping is not given the parser will use the naming convention to look for a matching method,
e.g. it will look for a public ``preUpdate()`` method if you are listening to the ``preUpdate`` event.
- When a listener mapping is given the parser will not look for any methods using the naming convention.
- A callback method could be defined by naming convention or specifying a method mapping.
- When the listener mapping is not given the parser will lookup for methods that match with the naming convention.
- When the listener mapping is given the parser won't lookup for any naming convention.
.. code-block:: php

@ -143,7 +143,7 @@ See the documentation chapter on :doc:`inheritance mapping <inheritance-mapping>
the details.
Why does Doctrine not create proxy objects for my inheritance hierarchy?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you set a many-to-one or one-to-one association target-entity to any parent class of
an inheritance hierarchy Doctrine does not know what PHP class the foreign is actually of.

@ -8,14 +8,12 @@ Tutorials
:maxdepth: 1
tutorials/getting-started
tutorials/getting-started-database
tutorials/getting-started-models
tutorials/working-with-indexed-associations
tutorials/extra-lazy-associations
tutorials/composite-primary-keys
tutorials/ordered-associations
tutorials/in-ten-quick-steps
tutorials/override-field-association-mappings-in-subclasses
tutorials/pagination.rst
Reference Guide
---------------
@ -24,9 +22,9 @@ Reference Guide
:maxdepth: 1
:numbered:
reference/introduction
reference/architecture
reference/installation
reference/configuration.rst
reference/configuration
reference/faq
reference/basic-mapping
reference/association-mapping
@ -53,9 +51,9 @@ Reference Guide
reference/metadata-drivers
reference/best-practices
reference/limitations-and-known-issues
tutorials/pagination.rst
reference/filters.rst
reference/namingstrategy.rst
reference/advanced-configuration.rst
Cookbook
@ -65,7 +63,6 @@ Cookbook
:maxdepth: 1
cookbook/aggregate-fields
cookbook/custom-mapping-types
cookbook/decorator-pattern
cookbook/dql-custom-walkers
cookbook/dql-user-defined-functions
@ -73,7 +70,6 @@ Cookbook
cookbook/implementing-the-notify-changetracking-policy
cookbook/implementing-wakeup-or-clone
cookbook/integrating-with-codeigniter
cookbook/resolve-target-entity-listener
cookbook/sql-table-prefixes
cookbook/strategy-cookbook-introduction
cookbook/validation-of-entities

@ -88,18 +88,4 @@ class HydrationException extends \Doctrine\ORM\ORMException
$discrColumnName, $entityName, $dqlAlias
));
}
/**
* @param string $discrValue
* @param array $discrMap
*
* @return HydrationException
*/
public static function invalidDiscriminatorValue($discrValue, $discrMap)
{
return new self(sprintf(
'The discriminator value "%s" is invalid. It must be one of "%s".',
$discrValue, implode('", "', $discrMap)
));
}
}

@ -266,13 +266,7 @@ class ObjectHydrator extends AbstractHydrator
throw HydrationException::emptyDiscriminatorValue($dqlAlias);
}
$discrMap = $this->ce[$className]->discriminatorMap;
if ( ! isset($discrMap[$data[$discrColumn]])) {
throw HydrationException::invalidDiscriminatorValue($data[$discrColumn], array_keys($discrMap));
}
$className = $discrMap[$data[$discrColumn]];
$className = $this->ce[$className]->discriminatorMap[$data[$discrColumn]];
unset($data[$discrColumn]);
}

@ -98,13 +98,7 @@ class SimpleObjectHydrator extends AbstractHydrator
throw HydrationException::emptyDiscriminatorValue(key($this->_rsm->aliasMap));
}
$discrMap = $this->class->discriminatorMap;
if ( ! isset($discrMap[$sqlResult[$discrColumnName]])) {
throw HydrationException::invalidDiscriminatorValue($sqlResult[$discrColumnName], array_keys($discrMap));
}
$entityName = $discrMap[$sqlResult[$discrColumnName]];
$entityName = $this->class->discriminatorMap[$sqlResult[$discrColumnName]];
unset($sqlResult[$discrColumnName]);
}

@ -866,11 +866,7 @@ class ClassMetadataInfo implements ClassMetadata
public function newInstance()
{
if ($this->_prototype === null) {
if (PHP_VERSION_ID === 50429 || PHP_VERSION_ID === 50513) {
$this->_prototype = $this->reflClass->newInstanceWithoutConstructor();
} else {
$this->_prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name));
}
$this->_prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name));
}
return clone $this->_prototype;

@ -57,7 +57,6 @@ class DefaultEntityListenerResolver implements EntityListenerResolver
if ( ! is_object($object)) {
throw new \InvalidArgumentException(sprintf('An object was expected, but got "%s".', gettype($object)));
}
$this->instances[get_class($object)] = $object;
}
@ -66,10 +65,11 @@ class DefaultEntityListenerResolver implements EntityListenerResolver
*/
public function resolve($className)
{
if (isset($this->instances[$className = trim($className, '\\')])) {
return $this->instances[$className];
}
return $this->instances[$className] = new $className();
}
}
}

@ -1497,7 +1497,6 @@ class SqlWalker implements TreeWalker
break;
}
$fieldType = 'string';
switch (true) {
case ($e instanceof AST\PathExpression):
$fieldName = $e->field;
@ -1518,6 +1517,10 @@ class SqlWalker implements TreeWalker
break;
}
break;
default:
$fieldType = 'string';
break;
}
$this->scalarResultAliasMap[$resultAlias] = $columnAlias;

@ -22,7 +22,7 @@ namespace Doctrine\ORM\Tools\Console;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Helper\HelperSet;
use Doctrine\ORM\Version;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityManager;
use Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper;
use Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper;
@ -35,10 +35,10 @@ class ConsoleRunner
/**
* Create a Symfony Console HelperSet
*
* @param EntityManagerInterface $entityManager
* @param EntityManager $entityManager
* @return HelperSet
*/
public static function createHelperSet(EntityManagerInterface $entityManager)
public static function createHelperSet(EntityManager $entityManager)
{
return new HelperSet(array(
'db' => new ConnectionHelper($entityManager->getConnection()),

@ -193,7 +193,7 @@ class XmlExporter extends AbstractExporter
}
if (isset($field['unique']) && $field['unique']) {
$fieldXml->addAttribute('unique', $field['unique'] ? 'true' : 'false');
$fieldXml->addAttribute('unique', $field['unique']);
}
if (isset($field['options'])) {

@ -100,9 +100,9 @@ class LimitSubqueryOutputWalker extends SqlWalker
$hiddens[$idx] = $expr->hiddenAliasResultVariable;
$expr->hiddenAliasResultVariable = false;
}
$innerSql = parent::walkSelectStatement($AST);
// Restore hiddens
foreach ($AST->selectClause->selectExpressions as $idx => $expr) {
$expr->hiddenAliasResultVariable = $hiddens[$idx];
@ -160,8 +160,11 @@ class LimitSubqueryOutputWalker extends SqlWalker
$sql = sprintf('SELECT DISTINCT %s FROM (%s) dctrn_result',
implode(', ', $sqlIdentifier), $innerSql);
// http://www.doctrine-project.org/jira/browse/DDC-1958
$sql = $this->preserveSqlOrdering($AST, $sqlIdentifier, $innerSql, $sql);
if ($this->platform instanceof PostgreSqlPlatform ||
$this->platform instanceof OraclePlatform) {
//http://www.doctrine-project.org/jira/browse/DDC-1958
$this->preserveSqlOrdering($AST, $sqlIdentifier, $innerSql, $sql);
}
// Apply the limit and offset.
$sql = $this->platform->modifyLimitQuery(
@ -178,7 +181,7 @@ class LimitSubqueryOutputWalker extends SqlWalker
return $sql;
}
/**
* Generates new SQL for Postgresql or Oracle if necessary.
*
@ -189,7 +192,7 @@ class LimitSubqueryOutputWalker extends SqlWalker
*
* @return void
*/
public function preserveSqlOrdering(SelectStatement $AST, array $sqlIdentifier, $innerSql, $sql)
public function preserveSqlOrdering(SelectStatement $AST, array $sqlIdentifier, $innerSql, &$sql)
{
// For every order by, find out the SQL alias by inspecting the ResultSetMapping.
$sqlOrderColumns = array();
@ -212,6 +215,11 @@ class LimitSubqueryOutputWalker extends SqlWalker
$sqlOrderColumns = array_diff($sqlOrderColumns, $sqlIdentifier);
}
// We don't need orderBy in inner query.
// However at least on 5.4.6 I'm getting a segmentation fault and thus we don't clear it for now.
/*$AST->orderByClause = null;
$innerSql = parent::walkSelectStatement($AST);*/
if (count($orderBy)) {
$sql = sprintf(
'SELECT DISTINCT %s FROM (%s) dctrn_result ORDER BY %s',
@ -220,7 +228,5 @@ class LimitSubqueryOutputWalker extends SqlWalker
implode(', ', $orderBy)
);
}
return $sql;
}
}

@ -541,15 +541,7 @@ class UnitOfWork implements PropertyChangedListener
foreach ($class->reflFields as $name => $refProp) {
$value = $refProp->getValue($entity);
if ($class->isCollectionValuedAssociation($name) && $value !== null) {
if ($value instanceof PersistentCollection) {
if ($value->getOwner() === $entity) {
continue;
}
$value = new ArrayCollection($value->getValues());
}
if ($class->isCollectionValuedAssociation($name) && $value !== null && ! ($value instanceof PersistentCollection)) {
// If $value is not a Collection then use an ArrayCollection.
if ( ! $value instanceof Collection) {
$value = new ArrayCollection($value);
@ -902,35 +894,30 @@ class UnitOfWork implements PropertyChangedListener
$actualData = array();
foreach ($class->reflFields as $name => $refProp) {
if (( ! $class->isIdentifier($name) || ! $class->isIdGeneratorIdentity())
&& ($name !== $class->versionField)
&& ! $class->isCollectionValuedAssociation($name)) {
if ( ! $class->isIdentifier($name) || ! $class->isIdGeneratorIdentity()) {
$actualData[$name] = $refProp->getValue($entity);
}
}
if ( ! isset($this->originalEntityData[$oid])) {
throw new \RuntimeException('Cannot call recomputeSingleEntityChangeSet before computeChangeSet on an entity.');
}
$originalData = $this->originalEntityData[$oid];
$changeSet = array();
foreach ($actualData as $propName => $actualValue) {
$orgValue = isset($originalData[$propName]) ? $originalData[$propName] : null;
if ($orgValue !== $actualValue) {
if (is_object($orgValue) && $orgValue !== $actualValue) {
$changeSet[$propName] = array($orgValue, $actualValue);
} else if ($orgValue != $actualValue || ($orgValue === null ^ $actualValue === null)) {
$changeSet[$propName] = array($orgValue, $actualValue);
}
}
if ($changeSet) {
$this->entityChangeSets[$oid] = (isset($this->entityChangeSets[$oid]))
? array_merge($this->entityChangeSets[$oid], $changeSet)
: $changeSet;
if (isset($this->entityChangeSets[$oid])) {
$this->entityChangeSets[$oid] = array_merge($this->entityChangeSets[$oid], $changeSet);
}
$this->originalEntityData[$oid] = $actualData;
$this->entityUpdates[$oid] = $entity;
}
}
@ -2492,15 +2479,15 @@ class UnitOfWork implements PropertyChangedListener
? $data[$class->associationMappings[$fieldName]['joinColumns'][0]['name']]
: $data[$fieldName];
}
$idHash = implode(' ', $id);
} else {
$id = isset($class->associationMappings[$class->identifier[0]])
$idHash = isset($class->associationMappings[$class->identifier[0]])
? $data[$class->associationMappings[$class->identifier[0]]['joinColumns'][0]['name']]
: $data[$class->identifier[0]];
$id = array($class->identifier[0] => $id);
$id = array($class->identifier[0] => $idHash);
}
$idHash = implode(' ', $id);
if (isset($this->identityMap[$class->rootEntityName][$idHash])) {
$entity = $this->identityMap[$class->rootEntityName][$idHash];

@ -36,7 +36,7 @@ class Version
/**
* Current Doctrine Version
*/
const VERSION = '2.4.3';
const VERSION = '2.4.2';
/**
* Compares a Doctrine version with the current one.

@ -1,6 +1,14 @@
CHANGELOG
=========
3.0
---
* fixed the Doctrine param converter that sent 500 when an entity was not found under some circumstancies
* ParamConverterInterface now uses ParamConverter as a type hint instead of ConfigurationInterface
* added support for @Security
* added support for HTTP validation cache in @Cache (ETag and LastModified)
2.2
---

@ -1,7 +1,5 @@
<?php
namespace Sensio\Bundle\FrameworkExtraBundle\Configuration;
/*
* This file is part of the Symfony package.
*
@ -11,8 +9,10 @@ namespace Sensio\Bundle\FrameworkExtraBundle\Configuration;
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\Configuration;
/**
* The Cache class handles the @Cache annotation parts.
* The Cache class handles the Cache annotation parts.
*
* @author Fabien Potencier <fabien@symfony.com>
* @Annotation
@ -30,7 +30,7 @@ class Cache extends ConfigurationAnnotation
* The number of seconds that the response is considered fresh by a private
* cache like a web browser.
*
* @var integer
* @var int
*/
protected $maxage;
@ -38,14 +38,14 @@ class Cache extends ConfigurationAnnotation
* The number of seconds that the response is considered fresh by a public
* cache like a reverse proxy cache.
*
* @var integer
* @var int
*/
protected $smaxage;
/**
* Whether or not the response is public or not.
* Whether the response is public or not.
*
* @var integer
* @var bool
*/
protected $public;
@ -56,6 +56,20 @@ class Cache extends ConfigurationAnnotation
*/
protected $vary = array();
/**
* An expression to compute the Last-Modified HTTP header.
*
* @var string
*/
protected $lastModified;
/**
* An expression to compute the ETag HTTP header.
*
* @var string
*/
protected $etag;
/**
* Returns the expiration date for the Expires header field.
*
@ -79,7 +93,7 @@ class Cache extends ConfigurationAnnotation
/**
* Sets the number of seconds for the max-age cache-control header field.
*
* @param integer $maxage A number of seconds
* @param int $maxage A number of seconds
*/
public function setMaxAge($maxage)
{
@ -90,7 +104,7 @@ class Cache extends ConfigurationAnnotation
* Returns the number of seconds the response is considered fresh by a
* private cache.
*
* @return integer
* @return int
*/
public function getMaxAge()
{
@ -100,7 +114,7 @@ class Cache extends ConfigurationAnnotation
/**
* Sets the number of seconds for the s-maxage cache-control header field.
*
* @param integer $smaxage A number of seconds
* @param int $smaxage A number of seconds
*/
public function setSMaxAge($smaxage)
{
@ -111,7 +125,7 @@ class Cache extends ConfigurationAnnotation
* Returns the number of seconds the response is considered fresh by a
* public cache.
*
* @return integer
* @return int
*/
public function getSMaxAge()
{
@ -121,21 +135,21 @@ class Cache extends ConfigurationAnnotation
/**
* Returns whether or not a response is public.
*
* @return Boolean
* @return bool
*/
public function isPublic()
{
return (Boolean) $this->public;
return (bool) $this->public;
}
/**
* Sets a response public.
*
* @param Boolean $public A boolean value
* @param bool $public A boolean value
*/
public function setPublic($public)
{
$this->public = (Boolean) $public;
$this->public = (bool) $public;
}
/**
@ -158,6 +172,46 @@ class Cache extends ConfigurationAnnotation
$this->vary = $vary;
}
/**
* Sets the "Last-Modified"-header expression.
*
* @param string $expression
*/
public function setLastModified($expression)
{
$this->lastModified = $expression;
}
/**
* Returns the "Last-Modified"-header expression.
*
* @return string
*/
public function getLastModified()
{
return $this->lastModified;
}
/**
* Sets the "ETag"-header expression.
*
* @param string $expression
*/
public function setETag($expression)
{
$this->etag = $expression;
}
/**
* Returns the "ETag"-header expression.
*
* @return string
*/
public function getETag()
{
return $this->etag;
}
/**
* Returns the annotation alias name.
*
@ -172,7 +226,7 @@ class Cache extends ConfigurationAnnotation
/**
* Only one cache directive is allowed
*
* @return Boolean
* @return bool
* @see ConfigurationInterface
*/
public function allowArray()

@ -1,5 +1,14 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\Configuration;
/**

@ -1,7 +1,5 @@
<?php
namespace Sensio\Bundle\FrameworkExtraBundle\Configuration;
/*
* This file is part of the Symfony package.
*
@ -11,6 +9,8 @@ namespace Sensio\Bundle\FrameworkExtraBundle\Configuration;
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\Configuration;
/**
* ConfigurationInterface.
*
@ -23,12 +23,12 @@ interface ConfigurationInterface
*
* @return string
*/
function getAliasName();
public function getAliasName();
/**
* Returns whether multiple annotations of this type are allowed
*
* @return Boolean
* @return bool
*/
function allowArray();
public function allowArray();
}

@ -1,7 +1,5 @@
<?php
namespace Sensio\Bundle\FrameworkExtraBundle\Configuration;
/*
* This file is part of the Symfony package.
*
@ -11,8 +9,10 @@ namespace Sensio\Bundle\FrameworkExtraBundle\Configuration;
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\Configuration;
/**
* The Method class handles the @Method annotation parts.
* The Method class handles the Method annotation parts.
*
* @author Fabien Potencier <fabien@symfony.com>
* @Annotation
@ -68,9 +68,9 @@ class Method extends ConfigurationAnnotation
}
/**
* Only one cache directive is allowed
* Only one method directive is allowed
*
* @return Boolean
* @return bool
* @see ConfigurationInterface
*/
public function allowArray()

@ -1,7 +1,5 @@
<?php
namespace Sensio\Bundle\FrameworkExtraBundle\Configuration;
/*
* This file is part of the Symfony package.
*
@ -11,8 +9,10 @@ namespace Sensio\Bundle\FrameworkExtraBundle\Configuration;
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\Configuration;
/**
* The ParamConverter class handles the @ParamConverter annotation parts.
* The ParamConverter class handles the ParamConverter annotation parts.
*
* @ParamConverter("post", class="BlogBundle:Post")
*
@ -45,7 +45,7 @@ class ParamConverter extends ConfigurationAnnotation
/**
* Whether or not the parameter is optional.
*
* @var Boolean
* @var bool
*/
protected $optional = false;
@ -129,17 +129,17 @@ class ParamConverter extends ConfigurationAnnotation
/**
* Sets whether or not the parameter is optional.
*
* @param Boolean $optional Wether the parameter is optional
* @param bool $optional Wether the parameter is optional
*/
public function setIsOptional($optional)
{
$this->optional = (Boolean) $optional;
$this->optional = (bool) $optional;
}
/**
* Returns whether or not the parameter is optional.
*
* @return Boolean
* @return bool
*/
public function isOptional()
{
@ -180,7 +180,7 @@ class ParamConverter extends ConfigurationAnnotation
/**
* Multiple ParamConverters are allowed
*
* @return Boolean
* @return bool
* @see ConfigurationInterface
*/
public function allowArray()

@ -1,18 +1,18 @@
<?php
namespace Sensio\Bundle\FrameworkExtraBundle\Configuration;
use Symfony\Component\Routing\Annotation\Route as BaseRoute;
/*
* This file is part of the Symfony framework.
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\Configuration;
use Symfony\Component\Routing\Annotation\Route as BaseRoute;
/**
* @author Kris Wallsmith <kris@symfony.com>
* @Annotation
@ -34,7 +34,7 @@ class Route extends BaseRoute
/**
* Multiple route annotations are allowed
*
* @return Boolean
* @return bool
* @see ConfigurationInterface
*/
public function allowArray()

@ -1,9 +1,5 @@
<?php
namespace Sensio\Bundle\FrameworkExtraBundle\Configuration;
use Symfony\Bundle\FrameworkBundle\Templating\TemplateReference;
/*
* This file is part of the Symfony package.
*
@ -13,8 +9,12 @@ use Symfony\Bundle\FrameworkBundle\Templating\TemplateReference;
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\Configuration;
use Symfony\Bundle\FrameworkBundle\Templating\TemplateReference;
/**
* The Template class handles the @Template annotation parts.
* The Template class handles the Template annotation parts.
*
* @author Fabien Potencier <fabien@symfony.com>
* @Annotation
@ -45,7 +45,7 @@ class Template extends ConfigurationAnnotation
/**
* Should the template be streamed?
*
* @var Boolean
* @var bool
*/
protected $streamable = false;
@ -60,7 +60,7 @@ class Template extends ConfigurationAnnotation
}
/**
* @param Boolean $streamable
* @param bool $streamable
*/
public function setIsStreamable($streamable)
{
@ -68,11 +68,11 @@ class Template extends ConfigurationAnnotation
}
/**
* @return Boolean
* @return bool
*/
public function isStreamable()
{
return (Boolean) $this->streamable;
return (bool) $this->streamable;
}
/**
@ -149,7 +149,7 @@ class Template extends ConfigurationAnnotation
/**
* Only one template directive is allowed
*
* @return Boolean
* @return bool
* @see ConfigurationInterface
*/
public function allowArray()

@ -1,5 +1,14 @@
<?php
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
@ -35,6 +44,7 @@ class Configuration implements ConfigurationInterface
->addDefaultsIfNotSet()
->children()
->booleanNode('converters')->defaultTrue()->end()
->booleanNode('auto_convert')->defaultTrue()->end()
->end()
->end()
->arrayNode('view')
@ -49,6 +59,13 @@ class Configuration implements ConfigurationInterface
->booleanNode('annotations')->defaultTrue()->end()
->end()
->end()
->arrayNode('security')
->addDefaultsIfNotSet()
->children()
->booleanNode('annotations')->defaultTrue()->end()
->scalarNode('expression_language')->defaultValue('sensio_framework_extra.security.expression_language.default')->end()
->end()
->end()
->end()
;

@ -1,12 +1,5 @@
<?php
namespace Sensio\Bundle\FrameworkExtraBundle\DependencyInjection;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
/*
* This file is part of the Symfony framework.
*
@ -16,6 +9,13 @@ use Symfony\Component\Config\FileLocator;
* with this source code in the file LICENSE.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\DependencyInjection;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
/**
* SensioFrameworkExtraExtension.
*
@ -67,7 +67,18 @@ class SensioFrameworkExtraExtension extends Extension
$annotationsToLoad[] = 'cache.xml';
$this->addClassesToCompile(array(
'Sensio\\Bundle\\FrameworkExtraBundle\\EventListener\\CacheListener',
'Sensio\\Bundle\\FrameworkExtraBundle\\EventListener\\HttpCacheListener',
));
}
if ($config['security']['annotations']) {
$annotationsToLoad[] = 'security.xml';
$container->setAlias('sensio_framework_extra.security.expression_language', $config['security']['expression_language']);
$container->getAlias('sensio_framework_extra.security.expression_language')->setPublic(false);
$this->addClassesToCompile(array(
'Sensio\\Bundle\\FrameworkExtraBundle\\EventListener\\SecurityListener',
));
}
@ -75,13 +86,17 @@ class SensioFrameworkExtraExtension extends Extension
// must be first
$loader->load('annotations.xml');
foreach ($annotationsToLoad as $config) {
$loader->load($config);
foreach ($annotationsToLoad as $configFile) {
$loader->load($configFile);
}
$this->addClassesToCompile(array(
'Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\ConfigurationAnnotation',
));
if ($config['request']['converters']) {
$container->getDefinition('sensio_framework_extra.converter.listener')->replaceArgument(1, $config['request']['auto_convert']);
}
}
}

@ -1,11 +1,5 @@
<?php
namespace Sensio\Bundle\FrameworkExtraBundle\EventListener;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/*
* This file is part of the Symfony framework.
*
@ -15,59 +9,21 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
* with this source code in the file LICENSE.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\EventListener;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* The CacheListener class has the responsibility to modify the
* Response object when a controller uses the "@Cache" annotation.
* CacheListener handles HTTP cache headers.
*
* @author Fabien Potencier <fabien@symfony.com>
* It can be configured via the Cache, LastModified, and Etag annotations.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated Deprecated since 3.0, to be removed in 4.0. Use the HttpCacheListener instead.
*/
class CacheListener implements EventSubscriberInterface
class CacheListener extends HttpCacheListener
{
/**
* Modifies the response to apply HTTP expiration header fields.
*
* @param FilterResponseEvent $event The notified event
*/
public function onKernelResponse(FilterResponseEvent $event)
{
if (!$configuration = $event->getRequest()->attributes->get('_cache')) {
return;
}
$response = $event->getResponse();
if (!$response->isSuccessful()) {
return;
}
if (null !== $configuration->getSMaxAge()) {
$response->setSharedMaxAge($configuration->getSMaxAge());
}
if (null !== $configuration->getMaxAge()) {
$response->setMaxAge($configuration->getMaxAge());
}
if (null !== $configuration->getExpires()) {
$date = \DateTime::createFromFormat('U', strtotime($configuration->getExpires()), new \DateTimeZone('UTC'));
$response->setExpires($date);
}
if (null !== $configuration->getVary()) {
$response->setVary($configuration->getVary());
}
if ($configuration->isPublic()) {
$response->setPublic();
}
$event->setResponse($response);
}
public static function getSubscribedEvents()
{
return array(
KernelEvents::RESPONSE => 'onKernelResponse',
);
}
}

@ -1,14 +1,5 @@
<?php
namespace Sensio\Bundle\FrameworkExtraBundle\EventListener;
use Doctrine\Common\Annotations\Reader;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface;
use Doctrine\Common\Util\ClassUtils;
/*
* This file is part of the Symfony framework.
*
@ -18,6 +9,15 @@ use Doctrine\Common\Util\ClassUtils;
* with this source code in the file LICENSE.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\EventListener;
use Doctrine\Common\Annotations\Reader;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface;
use Doctrine\Common\Util\ClassUtils;
/**
* The ControllerListener class parses annotation blocks located in
* controller classes.

@ -1,13 +1,5 @@
<?php
namespace Sensio\Bundle\FrameworkExtraBundle\EventListener;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterManager;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/*
* This file is part of the Symfony framework.
*
@ -17,8 +9,17 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
* with this source code in the file LICENSE.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\EventListener;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterManager;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* The ParamConverterListener handles the @ParamConverter annotation.
* The ParamConverterListener handles the ParamConverter annotation.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
@ -29,14 +30,18 @@ class ParamConverterListener implements EventSubscriberInterface
*/
protected $manager;
protected $autoConvert;
/**
* Constructor.
*
* @param ParamConverterManager $manager A ParamConverterManager instance
* @param ParamConverterManager $manager A ParamConverterManager instance
* @param bool $autoConvert Auto convert non-configured objects
*/
public function __construct(ParamConverterManager $manager)
public function __construct(ParamConverterManager $manager, $autoConvert = true)
{
$this->manager = $manager;
$this->autoConvert = $autoConvert;
}
/**
@ -63,6 +68,15 @@ class ParamConverterListener implements EventSubscriberInterface
}
// automatically apply conversion for non-configured objects
if ($this->autoConvert) {
$configurations = $this->autoConfigure($r, $request, $configurations);
}
$this->manager->apply($request, $configurations);
}
private function autoConfigure(\ReflectionFunctionAbstract $r, Request $request, $configurations)
{
foreach ($r->getParameters() as $param) {
if (!$param->getClass() || $param->getClass()->isInstance($request)) {
continue;
@ -83,9 +97,14 @@ class ParamConverterListener implements EventSubscriberInterface
$configurations[$name]->setIsOptional($param->isOptional());
}
$this->manager->apply($request, $configurations);
return $configurations;
}
/**
* Get subscribed events
*
* @return array Subscribed events
*/
public static function getSubscribedEvents()
{
return array(

@ -1,5 +1,14 @@
<?php
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\EventListener;
use Symfony\Component\DependencyInjection\ContainerInterface;
@ -10,19 +19,10 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* The TemplateListener class handles the @Template annotation.
* The TemplateListener class handles the Template annotation.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Fabien Potencier <fabien@symfony.com>
*/
class TemplateListener implements EventSubscriberInterface
{

@ -4,3 +4,9 @@ SensioFrameworkExtraBundle
This bundle provides a way to configure your controllers with annotations.
Read about it on its [official homepage](http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/index.html).
As of v3.0.0 of the bundle, the release cycle is de-synchronized from the
framework's. It means you can just require "sensio/framework-extra-bundle":
"~3.0" in your composer.json and Composer will automatically pick the latest
version of the bundle that works with your current version of Symfony. The
minimum version of Symfony2 for this workflow is 2.4.0.

@ -11,7 +11,7 @@
namespace Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use DateTime;
@ -24,11 +24,11 @@ use DateTime;
class DateTimeParamConverter implements ParamConverterInterface
{
/**
* @{inheritdoc}
*
* {@inheritdoc}
*
* @throws NotFoundHttpException When invalid date given
*/
public function apply(Request $request, ConfigurationInterface $configuration)
public function apply(Request $request, ParamConverter $configuration)
{
$param = $configuration->getName();
@ -39,6 +39,10 @@ class DateTimeParamConverter implements ParamConverterInterface
$options = $configuration->getOptions();
$value = $request->attributes->get($param);
if (!$value && $configuration->isOptional()) {
return false;
}
$date = isset($options['format'])
? DateTime::createFromFormat($options['format'], $value)
: new DateTime($value);
@ -53,9 +57,9 @@ class DateTimeParamConverter implements ParamConverterInterface
}
/**
* @{inheritdoc}
* {@inheritdoc}
*/
public function supports(ConfigurationInterface $configuration)
public function supports(ParamConverter $configuration)
{
if (null === $configuration->getClass()) {
return false;

@ -1,21 +1,21 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\Common\Persistence\ManagerRegistry;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
use Doctrine\ORM\NoResultException;
/**
* DoctrineParamConverter.
@ -35,12 +35,12 @@ class DoctrineParamConverter implements ParamConverterInterface
}
/**
* @{inheritdoc}
* {@inheritdoc}
*
* @throws \LogicException When unable to guess how to get a Doctrine instance from the request information
* @throws NotFoundHttpException When object not found
*/
public function apply(Request $request, ConfigurationInterface $configuration)
public function apply(Request $request, ParamConverter $configuration)
{
$name = $configuration->getName();
$class = $configuration->getClass();
@ -89,7 +89,11 @@ class DoctrineParamConverter implements ParamConverterInterface
$method = 'find';
}
return $this->getManager($options['entity_manager'], $class)->getRepository($class)->$method($id);
try {
return $this->getManager($options['entity_manager'], $class)->getRepository($class)->$method($id);
} catch (NoResultException $e) {
return null;
}
}
protected function getIdentifier(Request $request, $options, $name)
@ -157,18 +161,18 @@ class DoctrineParamConverter implements ParamConverterInterface
$method = 'findOneBy';
}
return $em->getRepository($class)->$method($criteria);
try {
return $em->getRepository($class)->$method($criteria);
} catch (NoResultException $e) {
return null;
}
}
/**
* @{inheritdoc}
* {@inheritdoc}
*/
public function supports(ConfigurationInterface $configuration)
public function supports(ParamConverter $configuration)
{
if (!$configuration instanceof ParamConverter) {
return false;
}
// if there is no manager, this means that only Doctrine DBAL is configured
if (null === $this->registry || !count($this->registry->getManagers())) {
return false;
@ -189,7 +193,7 @@ class DoctrineParamConverter implements ParamConverterInterface
return ! $em->getMetadataFactory()->isTransient($configuration->getClass());
}
protected function getOptions(ConfigurationInterface $configuration)
protected function getOptions(ParamConverter $configuration)
{
return array_replace(array(
'entity_manager' => null,

@ -1,19 +1,19 @@
<?php
namespace Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface;
use Symfony\Component\HttpFoundation\Request;
/*
* This file is part of the Symfony framework.
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\HttpFoundation\Request;
/**
* Converts request parameters to objects and stores them as request
* attributes, so they can be injected as controller method arguments.
@ -24,20 +24,20 @@ interface ParamConverterInterface
{
/**
* Stores the object in the request.
*
* @param Request $request The request
* @param ConfigurationInterface $configuration Contains the name, class and options of the object
*
* @return boolean True if the object has been successfully set, else false
*
* @param Request $request The request
* @param ParamConverter $configuration Contains the name, class and options of the object
*
* @return bool True if the object has been successfully set, else false
*/
function apply(Request $request, ConfigurationInterface $configuration);
public function apply(Request $request, ParamConverter $configuration);
/**
* Checks if the object is supported.
*
* @param ConfigurationInterface $configuration Should be an instance of ParamConverter
*
* @return boolean True if the object is supported, else false
*
* @param ParamConverter $configuration Should be an instance of ParamConverter
*
* @return bool True if the object is supported, else false
*/
function supports(ConfigurationInterface $configuration);
public function supports(ParamConverter $configuration);
}

@ -1,19 +1,19 @@
<?php
namespace Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter;
use Symfony\Component\HttpFoundation\Request;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface;
/*
* This file is part of the Symfony framework.
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter;
use Symfony\Component\HttpFoundation\Request;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface;
/**
* Managers converters.
*
@ -62,7 +62,7 @@ class ParamConverterManager
$className = $configuration->getClass();
// If the value is already an instance of the class we are trying to convert it into
// we should continue as no convertion is required
// we should continue as no conversion is required
if (is_object($value) && $value instanceof $className) {
return;
}
@ -107,7 +107,7 @@ class ParamConverterManager
* be invoked explicitly.
*
* @param ParamConverterInterface $converter A ParamConverterInterface instance
* @param integer $priority The priority (between -10 and 10).
* @param int $priority The priority (between -10 and 10).
* @param string $name Name of the converter.
*/
public function add(ParamConverterInterface $converter, $priority = 0, $name = null)

@ -5,7 +5,7 @@
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="sensio_framework_extra.cache.listener" class="Sensio\Bundle\FrameworkExtraBundle\EventListener\CacheListener">
<service id="sensio_framework_extra.cache.listener" class="Sensio\Bundle\FrameworkExtraBundle\EventListener\HttpCacheListener">
<tag name="kernel.event_subscriber" />
</service>
</services>

@ -15,6 +15,7 @@
<service id="sensio_framework_extra.converter.listener" class="%sensio_framework_extra.converter.listener.class%">
<tag name="kernel.event_subscriber" />
<argument type="service" id="sensio_framework_extra.converter.manager" />
<argument>true</argument>
</service>
<service id="sensio_framework_extra.converter.manager" class="%sensio_framework_extra.converter.manager.class%" />

@ -1,24 +1,28 @@
@Cache
======
Usage
-----
The ``@Cache`` annotation makes it easy to define HTTP caching headers for
expiration and validation.
HTTP Expiration Strategies
--------------------------
The ``@Cache`` annotation makes it easy to define HTTP caching::
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
/**
* @Cache(expires="tomorrow", public="true")
* @Cache(expires="tomorrow", public=true)
*/
public function indexAction()
{
}
You can also use the annotation on a class to define caching for all methods::
You can also use the annotation on a class to define caching for all actions
of a controller::
/**
* @Cache(expires="tomorrow", public="true")
* @Cache(expires="tomorrow", public=true)
*/
class BlogController extends Controller
{
@ -40,22 +44,63 @@ configuration, the latter overrides the former::
}
}
Attributes
----------
.. note::
Here is a list of accepted attributes and their HTTP header equivalent:
The ``expires`` attribute takes any valid date understood by the PHP
``strtotime()`` function.
HTTP Validation Strategies
--------------------------
The ``lastModified`` and ``ETag`` attributes manages the HTTP validation cache
headers. ``lastModified`` adds a ``Last-Modified`` header to Responses and
``ETag`` adds an ``ETag`` header.
Both automatically trigger the logic to return a 304 response when the
response is not modified (in this case, the controller is **not** called)::
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
/**
* @Cache(lastModified="post.getUpdatedAt()", ETag="'Post' ~ post.getId() ~ post.getUpdatedAt()")
*/
public function indexAction(Post $post)
{
// your code
// won't be called in case of a 304
}
It's roughly doing the same as the following code::
public function myAction(Request $request, Post $post)
{
$response = new Response();
$response->setLastModified($post->getUpdatedAt());
if ($response->isNotModified($request)) {
return $response;
}
============================== ===============
Annotation Response Method
============================== ===============
``@Cache(expires="tomorrow")`` ``$response->setExpires()``
``@Cache(smaxage="15")`` ``$response->setSharedMaxAge()``
``@Cache(maxage="15")`` ``$response->setMaxAge()``
``@Cache(vary=["Cookie"])`` ``$response->setVary()``
``@Cache(public="true")`` ``$response->setPublic()``
============================== ===============
// your code
}
.. note::
The ``expires`` attribute takes any valid date understood by the PHP
``strtotime()`` function.
The ETag HTTP header value is the result of the expression hashed with the
``sha256`` algorithm.
Attributes
----------
Here is a list of accepted attributes and their HTTP header equivalent:
===================================================== ================================
Annotation Response Method
===================================================== ================================
``@Cache(expires="tomorrow")`` ``$response->setExpires()``
``@Cache(smaxage="15")`` ``$response->setSharedMaxAge()``
``@Cache(maxage="15")`` ``$response->setMaxAge()``
``@Cache(vary={"Cookie"})`` ``$response->setVary()``
``@Cache(public=true)`` ``$response->setPublic()``
``@Cache(lastModified="post.getUpdatedAt()")`` ``$response->setLastModified()``
``@Cache(ETag="post.getId() ~ post.getUpdatedAt()")`` ``$response->setETag()``
===================================================== ================================

@ -19,7 +19,7 @@ they can be injected as controller method arguments::
{
}
Several things happens under the hood:
Several things happen under the hood:
* The converter tries to get a ``SensioBlogBundle:Post`` object from the
request attributes (request attributes comes from route placeholders -- here
@ -41,6 +41,27 @@ If you use type hinting as in the example above, you can even omit the
{
}
.. tip::
You can disable the auto-conversion of type-hinted method arguments feature
by setting the ``auto_convert`` flag to ``false``:
.. configuration-block::
.. code-block:: yaml
# app/config/config.yml
sensio_framework_extra:
request:
converters: true
auto_convert: false
.. code-block:: xml
<sensio-framework-extra:config>
<request converters="true" auto-convert="true" />
</sensio-framework-extra:config>
To detect which converter is run on a parameter the following process is run:
* If an explicit converter choice was made with
@ -54,7 +75,7 @@ To detect which converter is run on a parameter the following process is run:
Built-in Converters
-------------------
The bundle has two built-in converter, the Doctrine one and a DateTime
The bundle has two built-in converters, the Doctrine one and a DateTime
converter.
Doctrine Converter
@ -65,7 +86,7 @@ Converter Name: ``doctrine.orm``
The Doctrine Converter attempts to convert request attributes to Doctrine
entities fetched from the database. Two different approaches are possible:
- Fetch object by primary key
- Fetch object by primary key.
- Fetch object by one or several fields which contain unique values in the
database.
@ -102,6 +123,11 @@ option::
{
}
.. tip::
The ``id`` option specifies which placeholder from the route gets passed to the repository
method used. If no repository method is specified, ``find()`` is used by default.
This also allows you to have multiple converters in one action::
/**
@ -112,7 +138,7 @@ This also allows you to have multiple converters in one action::
{
}
In the example above, the post parameter is handled automatically, but the comment is
In the example above, the ``$post`` parameter is handled automatically, but ``$comment`` is
configured with the annotation since they can not both follow the default convention.
If you want to match an entity using multiple fields use the ``mapping`` hash
@ -133,7 +159,7 @@ route parameter from being part of the criteria::
/**
* @Route("/blog/{date}/{slug}")
* @ParamConverter("post", options={"exclude": ["date"]})
* @ParamConverter("post", options={"exclude": {"date"}})
*/
public function showAction(Post $post, \DateTime $date)
{
@ -180,37 +206,36 @@ is accepted. You can be stricter with input given through the options::
Creating a Converter
--------------------
All converters must implement the
:class:`Sensio\\Bundle\\FrameworkExtraBundle\\Request\\ParamConverter\\ParamConverterInterface`::
All converters must implement the ``ParamConverterInterface``::
namespace Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\HttpFoundation\Request;
interface ParamConverterInterface
{
function apply(Request $request, ConfigurationInterface $configuration);
function apply(Request $request, ParamConverter $configuration);
function supports(ConfigurationInterface $configuration);
function supports(ParamConverter $configuration);
}
The ``supports()`` method must return ``true`` when it is able to convert the
given configuration (a ``ParamConverter`` instance).
The ``ParamConverter`` instance has three information about the annotation:
The ``ParamConverter`` instance has three pieces of information about the annotation:
* ``name``: The attribute name;
* ``class``: The attribute class name (can be any string representing a class
name);
* ``options``: An array of options
* ``options``: An array of options.
The ``apply()`` method is called whenever a configuration is supported. Based
on the request attributes, it should set an attribute named
``$configuration->getName()``, which stores an object of class
``$configuration->getClass()``.
To register your converter service you must add a tag to your service
To register your converter service you must add a tag to your service:
.. configuration-block::
@ -235,6 +260,11 @@ the converter stack with a priority of `0`. To explicitly disable the
registration by priority you have to set `priority="false"` in your tag
definition.
.. tip::
If you would like to inject services or additional arguments to custom param converter, the priority shouldn't
be higher than 1. Otherwise, the service wouldn't be loaded.
.. tip::
Use the ``DoctrineParamConverter`` class as a template for your own converters.

@ -4,7 +4,7 @@
Usage
-----
The @Route annotation maps a route pattern with a controller::
The ``@Route`` annotation maps a route pattern with a controller::
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
@ -25,7 +25,7 @@ URL. This is equivalent to the following YAML configuration:
.. code-block:: yaml
blog_home:
pattern: /
path: /
defaults: { _controller: SensioBlogBundle:Post:index }
Like any route pattern, you can define placeholders, requirements, and default
@ -115,7 +115,8 @@ Route Prefix
------------
A ``@Route`` annotation on a controller class defines a prefix for all action
routes::
routes (note that you cannot have more than one ``@Route`` annotation on a
class)::
/**
* @Route("/blog")
@ -172,7 +173,7 @@ PostController()`` itself::
/**
* @Route(service="my_post_controller_service")
*/
class PostController extends Controller
class PostController
{
// ...
}

@ -41,29 +41,32 @@ The default configuration is as follow:
.. code-block:: yaml
sensio_framework_extra:
router: { annotations: true }
request: { converters: true }
view: { annotations: true }
cache: { annotations: true }
router: { annotations: true }
request: { converters: true, auto_convert: true }
view: { annotations: true }
cache: { annotations: true }
security: { annotations: true }
.. code-block:: xml
<!-- xmlns:sensio-framework-extra="http://symfony.com/schema/dic/symfony_extra" -->
<sensio-framework-extra:config>
<router annotations="true" />
<request converters="true" />
<request converters="true" auto_convert="true" />
<view annotations="true" />
<cache annotations="true" />
<security annotations="true" />
</sensio-framework-extra:config>
.. code-block:: php
// load the profiler
$container->loadFromExtension('sensio_framework_extra', array(
'router' => array('annotations' => true),
'request' => array('converters' => true),
'view' => array('annotations' => true),
'cache' => array('annotations' => true),
'router' => array('annotations' => true),
'request' => array('converters' => true, 'auto_convert' => true),
'view' => array('annotations' => true),
'cache' => array('annotations' => true),
'security' => array('annotations' => true),
));
You can disable some annotations and conventions by defining one or more
@ -98,6 +101,7 @@ The following annotations are defined by the bundle:
annotations/converters
annotations/view
annotations/cache
annotations/security
This example shows all the available annotations in action::
@ -106,6 +110,7 @@ This example shows all the available annotations in action::
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
/**
* @Route("/blog")
@ -128,8 +133,9 @@ This example shows all the available annotations in action::
* @Route("/{id}")
* @Method("GET")
* @ParamConverter("post", class="SensioBlogBundle:Post")
* @Template("SensioBlogBundle:Annot:post.html.twig", vars={"post"})
* @Cache(smaxage="15")
* @Template("SensioBlogBundle:Annot:show.html.twig", vars={"post"})
* @Cache(smaxage="15", lastmodified="post.getUpdatedAt()", etag="'Post' ~ post.getId() ~ post.getUpdatedAt()")
* @Security("has_role('ROLE_ADMIN') and is_granted('POST_SHOW', post)")
*/
public function showAction(Post $post)
{
@ -141,7 +147,8 @@ annotations::
/**
* @Route("/{id}")
* @Cache(smaxage="15")
* @Cache(smaxage="15", lastModified="post.getUpdatedAt()", ETag="'Post' ~ post.getId() ~ post.getUpdatedAt()")
* @Security("has_role('ROLE_ADMIN') and is_granted('POST_SHOW', post)")
*/
public function showAction(Post $post)
{

@ -1,5 +1,14 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\Routing;
use Symfony\Component\Routing\Loader\AnnotationClassLoader;
@ -7,15 +16,6 @@ use Symfony\Component\Routing\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route as FrameworkExtraBundleRoute;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* AnnotatedRouteControllerLoader is an implementation of AnnotationClassLoader
* that sets the '_controller' default based on the class and method names.
@ -57,6 +57,19 @@ class AnnotatedRouteControllerLoader extends AnnotationClassLoader
}
}
protected function getGlobals(\ReflectionClass $class)
{
$globals = parent::getGlobals($class);
foreach ($this->reader->getClassAnnotations($class) as $configuration) {
if ($configuration instanceof Method) {
$globals['methods'] = array_merge($globals['methods'], $configuration->getMethods());
}
}
return $globals;
}
/**
* Makes the default route name more sane by removing common keywords.
*

@ -1,5 +1,14 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\Templating;
use Symfony\Component\HttpKernel\KernelInterface;
@ -7,15 +16,6 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Templating\TemplateReference;
use Doctrine\Common\Util\ClassUtils;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* The TemplateGuesser class handles the guessing of template name based on controller
*

@ -1,5 +1,14 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\Tests\Configuration;
class ConfigurationAnnotationTest extends \PHPUnit_Framework_TestCase

@ -1,5 +1,14 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\Tests\EventListener;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
@ -20,6 +29,9 @@ class ControllerListenerTest extends \PHPUnit_Framework_TestCase
{
$this->listener = new ControllerListener(new AnnotationReader());
$this->request = $this->createRequest();
// trigger the autoloading of the @Cache annotation
class_exists('Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache');
}
public function tearDown()

@ -1,5 +1,14 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\Tests\EventListener;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
@ -12,22 +21,60 @@ class ParamConverterListenerTest extends \PHPUnit_Framework_TestCase
{
public function testRequestIsSkipped()
{
$kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$request = new Request();
$manager = $this->getMock('Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterManager');
$manager->expects($this->once())
->method('apply')
->with($this->equalTo($request), $this->equalTo(array()));
$listener = new ParamConverterListener($this->getParamConverterManager($request, array()));
$event = new FilterControllerEvent($kernel, array(new TestController(), 'noArgAction'), $request, null);
$listener->onKernelController($event);
}
public function testAutoConvert()
{
$kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$request = new Request(array(), array(), array('date' => '2014-03-14 09:00:00'));
$converter = new ParamConverter(array('name' => 'date', 'class' => 'DateTime'));
$listener = new ParamConverterListener($manager);
$event = new FilterControllerEvent($kernel, array(new TestController(), 'execute'), $request, null);
$listener = new ParamConverterListener($this->getParamConverterManager($request, array('date' => $converter)));
$event = new FilterControllerEvent($kernel, array(new TestController(), 'dateAction'), $request, null);
$listener->onKernelController($event);
}
public function testNoAutoConvert()
{
$kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$request = new Request(array(), array(), array('date' => '2014-03-14 09:00:00'));
$listener = new ParamConverterListener($this->getParamConverterManager($request, array()), false);
$event = new FilterControllerEvent($kernel, array(new TestController(), 'dateAction'), $request, null);
$listener->onKernelController($event);
}
protected function getParamConverterManager(Request $request, $configurations)
{
$manager = $this->getMock('Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterManager');
$manager
->expects($this->once())
->method('apply')
->with($this->equalTo($request), $this->equalTo($configurations))
;
return $manager;
}
}
class TestController
{
public function execute(Request $request) {}
public function noArgAction(Request $request)
{
}
public function dateAction(\DateTime $date)
{
}
}

@ -1,5 +1,14 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\Tests\Request\ParamConverter;
use Symfony\Component\HttpFoundation\Request;
@ -47,12 +56,26 @@ class DateTimeParamConverterTest extends \PHPUnit_Framework_TestCase
$this->converter->apply($request, $config);
}
public function testApplyOptionalWithEmptyAttribute()
{
$request = new Request(array(), array(), array('start' => null));
$config = $this->createConfiguration('DateTime', 'start');
$config->expects($this->once())
->method('isOptional')
->will($this->returnValue(true));
$this->assertFalse($this->converter->apply($request, $config));
$this->assertNull($request->attributes->get('start'));
}
public function createConfiguration($class = null, $name = null)
{
$config = $this->getMock(
'Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface', array(
'getClass', 'getAliasName', 'getOptions', 'getName', 'allowArray'
));
$config = $this
->getMockBuilder('Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter')
->setMethods(array('getClass', 'getAliasName', 'getOptions', 'getName', 'allowArray', 'isOptional'))
->disableOriginalConstructor()
->getMock();
if ($name !== null) {
$config->expects($this->any())
->method('getName')

@ -1,5 +1,14 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\Tests\Request\ParamConverter;
use Symfony\Component\HttpFoundation\Request;

@ -1,5 +1,14 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\Tests\Request\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterManager;
@ -8,25 +17,18 @@ use Symfony\Component\HttpFoundation\Request;
class ParamConverterManagerTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
$this->manager = new ParamConverterManager();
}
public function testPriorities()
{
$this->assertEquals(array(), $this->manager->all());
$manager = new ParamConverterManager();
$this->assertEquals(array(), $manager->all());
$high = $this->createParamConverterMock();
$low = $this->createParamConverterMock();
$this->manager->add($low);
$this->manager->add($high, 10);
$manager->add($low);
$manager->add($high, 10);
$this->assertEquals(array(
$high,
$low,
), $this->manager->all());
$this->assertEquals(array($high, $low), $manager->all());
}
public function testApply()
@ -60,9 +62,10 @@ class ParamConverterManagerTest extends \PHPUnit_Framework_TestCase
)),
);
$this->manager->add($supported);
$this->manager->add($invalid);
$this->manager->apply(new Request(), $configurations);
$manager = new ParamConverterManager();
$manager->add($supported);
$manager->add($invalid);
$manager->apply(new Request(), $configurations);
}
public function testApplyNamedConverter()
@ -79,8 +82,6 @@ class ParamConverterManagerTest extends \PHPUnit_Framework_TestCase
->method('apply')
;
$this->manager->add($converter, 0, "test");
$request = new Request();
$request->attributes->set('param', '1234');
@ -90,9 +91,15 @@ class ParamConverterManagerTest extends \PHPUnit_Framework_TestCase
'converter' => 'test',
));
$this->manager->apply($request, array($configuration));
$manager = new ParamConverterManager();
$manager->add($converter, 0, "test");
$manager->apply($request, array($configuration));
}
/**
* @expectedException \RuntimeException
* @expectedExceptionMessage Converter 'test' does not support conversion of parameter 'param'.
*/
public function testApplyNamedConverterNotSupportsParameter()
{
$converter = $this->createParamConverterMock();
@ -102,8 +109,6 @@ class ParamConverterManagerTest extends \PHPUnit_Framework_TestCase
->will($this->returnValue(false))
;
$this->manager->add($converter, 0, "test");
$request = new Request();
$request->attributes->set('param', '1234');
@ -113,10 +118,15 @@ class ParamConverterManagerTest extends \PHPUnit_Framework_TestCase
'converter' => 'test',
));
$this->setExpectedException("RuntimeException", "Converter 'test' does not support conversion of parameter 'param'.");
$this->manager->apply($request, array($configuration));
$manager = new ParamConverterManager();
$manager->add($converter, 0, "test");
$manager->apply($request, array($configuration));
}
/**
* @expectedException \RuntimeException
* @expectedExceptionMessage No converter named 'test' found for conversion of parameter 'param'.
*/
public function testApplyNamedConverterNoConverter()
{
$request = new Request();
@ -128,13 +138,12 @@ class ParamConverterManagerTest extends \PHPUnit_Framework_TestCase
'converter' => 'test',
));
$this->setExpectedException("RuntimeException", "No converter named 'test' found for conversion of parameter 'param'.");
$this->manager->apply($request, array($configuration));
$manager = new ParamConverterManager();
$manager->apply($request, array($configuration));
}
public function testApplyNotCalledOnAlreadyConvertedObjects()
{
$converter = $this->createParamConverterMock();
$converter
->expects($this->never())
@ -146,8 +155,6 @@ class ParamConverterManagerTest extends \PHPUnit_Framework_TestCase
->method('apply')
;
$this->manager->add($converter);
$request = new Request();
$request->attributes->set('converted', new \stdClass);
@ -156,7 +163,9 @@ class ParamConverterManagerTest extends \PHPUnit_Framework_TestCase
'class' => 'stdClass',
));
$this->manager->apply($request, array($configuration));
$manager = new ParamConverterManager();
$manager->add($converter);
$manager->apply($request, array($configuration));
}
protected function createParamConverterMock()

@ -1,8 +1,22 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\Tests\Routing;
use \Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\AnnotationRegistry;
use Doctrine\Common\Annotations\SimpleAnnotationReader;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Routing\AnnotatedRouteControllerLoader;
use Symfony\Component\Routing\Route as SymfonyRoute;
class AnnotatedRouteControllerLoaderTest extends \PHPUnit_Framework_TestCase
{
@ -106,4 +120,21 @@ class AnnotatedRouteControllerLoaderTest extends \PHPUnit_Framework_TestCase
null
);
}
public function testLoad()
{
$loader = new AnnotatedRouteControllerLoader(new AnnotationReader());
AnnotationRegistry::registerLoader('class_exists');
$rc = $loader->load('Sensio\Bundle\FrameworkExtraBundle\Tests\Routing\Fixtures\FoobarController');
$this->assertInstanceOf('Symfony\Component\Routing\RouteCollection', $rc);
$this->assertCount(2, $rc);
$this->assertInstanceOf('Symfony\Component\Routing\Route', $rc->get('index'));
$this->assertEquals(array('GET'), $rc->get('index')->getMethods());
$this->assertInstanceOf('Symfony\Component\Routing\Route', $rc->get('new'));
$this->assertEquals(array('POST'), $rc->get('new')->getMethods());
}
}

@ -1,5 +1,14 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\Tests\Templating;
use Sensio\Bundle\FrameworkExtraBundle\Templating\TemplateGuesser;

@ -11,16 +11,24 @@
}
],
"require": {
"symfony/framework-bundle": "~2.2",
"symfony/framework-bundle": "~2.5",
"doctrine/common": "~2.2"
},
"require-dev": {
"symfony/expression-language": "~2.4",
"symfony/security-bundle": "~2.4"
},
"suggest": {
"symfony/expression-language": "",
"symfony/security-bundle": ""
},
"autoload": {
"psr-0": { "Sensio\\Bundle\\FrameworkExtraBundle": "" }
},
"target-dir": "Sensio/Bundle/FrameworkExtraBundle",
"extra": {
"branch-alias": {
"dev-master": "2.3.x-dev"
"dev-master": "3.0.x-dev"
}
},
"minimum-stability": "dev"

@ -31,32 +31,10 @@ class GenerateControllerCommand extends GeneratorCommand
{
$this
->setDefinition(array(
new InputOption(
'controller',
'',
InputOption::VALUE_REQUIRED,
'The name of the controller to create'
),
new InputOption(
'route-format',
'',
InputOption::VALUE_REQUIRED,
'The format that is used for the routing (yml, xml, php, annotation)',
'annotation'
),
new InputOption(
'template-format',
'',
InputOption::VALUE_REQUIRED,
'The format that is used for templating (twig, php)',
'twig'
),
new InputOption(
'actions',
'',
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'The actions in the controller'
),
new InputOption('controller', '', InputOption::VALUE_REQUIRED, 'The name of the controller to create'),
new InputOption('route-format', '', InputOption::VALUE_REQUIRED, 'The format that is used for the routing (yml, xml, php, annotation)', 'annotation'),
new InputOption('template-format', '', InputOption::VALUE_REQUIRED, 'The format that is used for templating (twig, php)', 'twig'),
new InputOption('actions', '', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'The actions in the controller'),
))
->setDescription('Generates a controller')
->setHelp(<<<EOT
@ -171,7 +149,7 @@ EOT
$input->setOption('route-format', $routeFormat);
// templating format
$validateTemplateFormat = function($format) {
$validateTemplateFormat = function ($format) {
if (!in_array($format, array('twig', 'php'))) {
throw new \InvalidArgumentException(sprintf('The template format must be twig or php, "%s" given', $format));
}
@ -212,7 +190,7 @@ EOT
'',
));
$templateNameValidator = function($name) {
$templateNameValidator = function ($name) {
if ('default' == $name) {
return $name;
}

@ -11,7 +11,7 @@
namespace Sensio\Bundle\GeneratorBundle\Command;
use Doctrine\Bundle\DoctrineBundle\Mapping\MetadataFactory;
use Doctrine\Bundle\DoctrineBundle\Mapping\DisconnectedMetadataFactory;
abstract class GenerateDoctrineCommand extends GeneratorCommand
{
@ -33,7 +33,7 @@ abstract class GenerateDoctrineCommand extends GeneratorCommand
protected function getEntityMetadata($entity)
{
$factory = new MetadataFactory($this->getContainer()->get('doctrine'));
$factory = new DisconnectedMetadataFactory($this->getContainer()->get('doctrine'));
return $factory->getClassMetadata($entity)->getMetadata();
}

@ -66,9 +66,8 @@ EOT
$entityClass = $this->getContainer()->get('doctrine')->getAliasNamespace($bundle).'\\'.$entity;
$metadata = $this->getEntityMetadata($entityClass);
$bundle = $this->getApplication()->getKernel()->getBundle($bundle);
$generator = $this->getGenerator($bundle);
$generator = new DoctrineFormGenerator($this->getContainer()->get('filesystem'));
$generator->setSkeletonDirs($this->getSkeletonDirs($bundle));
$generator->generate($bundle, $entity, $metadata[0]);
$output->writeln(sprintf(

@ -102,7 +102,7 @@ class ControllerGenerator extends Generator
}
$content .= sprintf(
"\n%s:\n pattern: %s\n defaults: { _controller: %s }\n",
"\n%s:\n path: %s\n defaults: { _controller: %s }\n",
$name,
$action['route'],
$controller
@ -124,7 +124,7 @@ EOT;
$route = $sxe->addChild('route');
$route->addAttribute('id', $name);
$route->addAttribute('pattern', $action['route']);
$route->addAttribute('path', $action['route']);
$default = $route->addChild('default', $controller);
$default->addAttribute('key', '_controller');

@ -202,7 +202,7 @@ class DoctrineCrudGenerator extends Generator
'namespace' => $this->bundle->getNamespace(),
'entity_namespace' => $entityNamespace,
'actions' => $this->actions,
'form_type_name' => strtolower(str_replace('\\', '_', $this->bundle->getNamespace()).($parts ? '_' : '').implode('_', $parts).'_'.$entityClass.'Type'),
'form_type_name' => strtolower(str_replace('\\', '_', $this->bundle->getNamespace()).($parts ? '_' : '').implode('_', $parts).'_'.$entityClass),
));
}
@ -268,6 +268,7 @@ class DoctrineCrudGenerator extends Generator
'route_prefix' => $this->routePrefix,
'route_name_prefix' => $this->routeNamePrefix,
'entity' => $this->entity,
'fields' => $this->metadata->fieldMappings,
'bundle' => $this->bundle->getName(),
'actions' => $this->actions,
));
@ -280,7 +281,7 @@ class DoctrineCrudGenerator extends Generator
*/
protected function getRecordActions()
{
return array_filter($this->actions, function($item) {
return array_filter($this->actions, function ($item) {
return in_array($item, array('show', 'edit'));
});
}

@ -1,19 +0,0 @@
Copyright (c) 2011-2013 Fabien Potencier
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.

@ -59,10 +59,10 @@ Available Options
php app/console generate:bundle --format=annotation
* ``--structure``: (**no**) [values: yes|no] Whether or not to generate a
* ``--structure``: If present, generates a
complete default directory structure including empty public folders for
documentation, web assets and translations dictionaries:
.. code-block:: bash
php app/console generate:bundle --structure=yes
php app/console generate:bundle --structure

@ -27,7 +27,7 @@ Available Options
* ``--controller``: The controller name given as a shortcut notation containing
the bundle name in which the controller is located and the name of the
bundle. For instance: ``AcmeBlogBundle:Post`` (creates a ``PostController``
controller. For instance: ``AcmeBlogBundle:Post`` (creates a ``PostController``
inside the ``AcmeBlogBundle`` bundle):
.. code-block:: bash
@ -36,7 +36,7 @@ Available Options
* ``--actions``: The list of actions to generate in the controller class. This
has a format like ``%actionname%:%route%:%template`` (where ``:%template%``
is optional:
is optional):
.. code-block:: bash

@ -9,7 +9,7 @@ Doctrine 2 schema.
Installation
------------
`Download`_ the bundle and put it under the ``Sensio\\Bundle\\`` namespace.
`Download`_ the bundle and put it under the ``Sensio\Bundle`` namespace.
Then, like for any other bundle, include it in your Kernel class::
public function registerBundles()
@ -68,7 +68,7 @@ about the available templates, their path, and the variables they have access.
Instead of copy/pasting the original template to create your own, you can also
extend it and only override the relevant parts:
.. code-block: jinja
.. code-block:: jinja
{# in app/Resources/SensioGeneratorBundle/skeleton/crud/actions/create.php.twig #}
@ -88,7 +88,7 @@ easy inheritance and to avoid copy/pasting large chunks of code.
In some cases, templates in the skeleton include other ones, like
in the ``crud/views/edit.html.twig.twig`` template for instance:
.. code-block: jinja
.. code-block:: jinja
{% include 'crud/views/others/record_actions.html.twig.twig' %}
@ -96,7 +96,7 @@ If you have defined a custom template for this template, it is going to be
used instead of the default one. But you can explicitly include the original
skeleton template by prefixing its path with ``skeleton/`` like we did above:
.. code-block: jinja
.. code-block:: jinja
{% include 'skeleton/crud/views/others/record_actions.html.twig.twig' %}

@ -5,7 +5,7 @@
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
{% block body %}
<route id="{{ extension_alias }}_homepage" pattern="/hello/{name}">
<route id="{{ extension_alias }}_homepage" path="/hello/{name}">
<default key="_controller">{{ bundle }}:Default:index</default>
</route>
{% endblock body %}

@ -1,3 +1,3 @@
{{ extension_alias }}_homepage:
pattern: /hello/{name}
path: /hello/{name}
defaults: { _controller: {{ bundle }}:Default:index }

@ -31,6 +31,21 @@ class {{ controller }}Controller extends Controller
${{- action.placeholders|join(', $') -}}
{%- endif -%})
{
{% if 'annotation' != format.routing -%}
{% if 'default' == action.template -%}
return $this->render('{{ bundle }}:{{ controller }}:{{ action.name|slice(0, -6) }}.html.{{ format.templating }}', array(
// ...
));
{%- else -%}
return $this->render('{{ action.template }}', array(
// ...
));
{%- endif %}
{%- else -%}
return array(
// ...
);
{%- endif %}
}
{% endfor -%}

@ -51,12 +51,12 @@
{% block form %}
/**
* Creates a form to create a {{ entity }} entity.
*
* @param {{ entity_class }} $entity The entity
*
* @return \Symfony\Component\Form\Form The form
*/
* Creates a form to create a {{ entity }} entity.
*
* @param {{ entity_class }} $entity The entity
*
* @return \Symfony\Component\Form\Form The form
*/
private function createCreateForm({{ entity_class }} $entity)
{
$form = $this->createForm(new {{ entity_class }}Type(), $entity, array(

@ -43,7 +43,7 @@
'entity' => $entity,
{% if 'delete' in actions %}
'delete_form' => $deleteForm->createView(),
{%- endif %}
{% endif %}
));
{% endif %}
{% endblock method_return %}

@ -5,38 +5,38 @@
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
{% block body %}
<route id="{{ route_name_prefix }}" pattern="/">
<route id="{{ route_name_prefix }}" path="/">
<default key="_controller">{{ bundle }}:{{ entity }}:index</default>
</route>
<route id="{{ route_name_prefix }}_show" pattern="/{id}/show">
<route id="{{ route_name_prefix }}_show" path="/{id}/show">
<default key="_controller">{{ bundle }}:{{ entity }}:show</default>
</route>
{% if 'new' in actions %}
<route id="{{ route_name_prefix }}_new" pattern="/new">
<route id="{{ route_name_prefix }}_new" path="/new">
<default key="_controller">{{ bundle }}:{{ entity }}:new</default>
</route>
<route id="{{ route_name_prefix }}_create" pattern="/create">
<route id="{{ route_name_prefix }}_create" path="/create">
<default key="_controller">{{ bundle }}:{{ entity }}:create</default>
<requirement key="_method">post</requirement>
</route>
{% endif %}
{% if 'edit' in actions %}
<route id="{{ route_name_prefix }}_edit" pattern="/{id}/edit">
<route id="{{ route_name_prefix }}_edit" path="/{id}/edit">
<default key="_controller">{{ bundle }}:{{ entity }}:edit</default>
</route>
<route id="{{ route_name_prefix }}_update" pattern="/{id}/update">
<route id="{{ route_name_prefix }}_update" path="/{id}/update">
<default key="_controller">{{ bundle }}:{{ entity }}:update</default>
<requirement key="_method">post|put</requirement>
</route>
{% endif %}
{% if 'delete' in actions %}
<route id="{{ route_name_prefix }}_delete" pattern="/{id}/delete">
<route id="{{ route_name_prefix }}_delete" path="/{id}/delete">
<default key="_controller">{{ bundle }}:{{ entity }}:delete</default>
<requirement key="_method">post|delete</requirement>
</route>

@ -1,40 +1,40 @@
{% if 'index' in actions %}
{{ route_name_prefix }}:
pattern: /
path: /
defaults: { _controller: "{{ bundle }}:{{ entity }}:index" }
{% endif %}
{% if 'show' in actions %}
{{ route_name_prefix }}_show:
pattern: /{id}/show
path: /{id}/show
defaults: { _controller: "{{ bundle }}:{{ entity }}:show" }
{% endif %}
{% if 'new' in actions %}
{{ route_name_prefix }}_new:
pattern: /new
path: /new
defaults: { _controller: "{{ bundle }}:{{ entity }}:new" }
{{ route_name_prefix }}_create:
pattern: /create
path: /create
defaults: { _controller: "{{ bundle }}:{{ entity }}:create" }
requirements: { _method: post }
{% endif %}
{% if 'edit' in actions %}
{{ route_name_prefix }}_edit:
pattern: /{id}/edit
path: /{id}/edit
defaults: { _controller: "{{ bundle }}:{{ entity }}:edit" }
{{ route_name_prefix }}_update:
pattern: /{id}/update
path: /{id}/update
defaults: { _controller: "{{ bundle }}:{{ entity }}:update" }
requirements: { _method: post|put }
{% endif %}
{% if 'delete' in actions %}
{{ route_name_prefix }}_delete:
pattern: /{id}/delete
path: /{id}/delete
defaults: { _controller: "{{ bundle }}:{{ entity }}:delete" }
requirements: { _method: post|delete }
{% endif %}

@ -24,7 +24,7 @@
// Edit the entity
$crawler = $client->click($crawler->selectLink('Edit')->link());
$form = $crawler->selectButton('Edit')->form(array(
$form = $crawler->selectButton('Update')->form(array(
'{{ form_type_name|lower }}[field_name]' => 'Foo',
// ... other fields to fill
));

@ -77,6 +77,7 @@ class ControllerGeneratorTest extends GeneratorTest
'public function getListOfPagesAction($max_count)',
'@Template()',
'@Template("FooBarBundle:Page:pages_list.html.twig")',
'return array(',
);
foreach ($strings as $string) {
$this->assertContains($string, $content);
@ -107,11 +108,13 @@ class ControllerGeneratorTest extends GeneratorTest
$content = file_get_contents($this->tmpDir.'/Controller/PageController.php');
$this->assertNotContains('@Route()', $content, 'Routing is done via a yml file');
$this->assertContains("return \$this->render('FooBarBundle:Page:showPage.html.php', array(", $content, 'Controller renders template');
$content = file_get_contents($this->tmpDir.'/Resources/views/Page/showPage.html.php');
$this->assertContains($this->getBundle()->getName().':Page:showPage', $content);
$content = file_get_contents($this->tmpDir.'/Resources/config/routing.yml');
$this->assertContains("show_page:\n pattern: /{slug}\n defaults: { _controller: FooBarBundle:Page:showPage }", $content);
$this->assertContains("show_page:\n path: /{slug}\n defaults: { _controller: FooBarBundle:Page:showPage }", $content);
}
protected function getGenerator()

@ -0,0 +1,16 @@
<?php
use Symfony\Component\HttpFoundation\Request;
use Doctrine\Common\Annotations\AnnotationRegistry;
use Claroline\WebInstaller\Kernel;
$loader = require_once __DIR__ . '/../vendor/autoload.php';
$request = Request::createFromGlobals();
if (!file_exists($file = __DIR__ . '/../app/config/is_installed.php') || false === require_once $file) {
AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
$kernel = new Kernel(__DIR__ . '/../app');
$kernel->handle($request)->send();
} else {
header('Location: ' . $request->getBaseUrl() . '/../app.php');
}
Loading…
Cancel
Save