diff --git a/bower.json b/bower.json index 160b1c6703..43fc245ac8 100644 --- a/bower.json +++ b/bower.json @@ -23,7 +23,8 @@ "geonames-server-jquery-plugin": "~0.2", "swfobject": "latest", "tinymce": "~4.0", - "jquery-galleria": "1.2.9" + "jquery-galleria": "1.2.9", + "jquery.cookie": "~1.4" }, "devDependencies": { "mocha": "latest", diff --git a/lib/Alchemy/Phrasea/Controller/Root/Login.php b/lib/Alchemy/Phrasea/Controller/Root/Login.php index a01d53195f..6816145e4b 100644 --- a/lib/Alchemy/Phrasea/Controller/Root/Login.php +++ b/lib/Alchemy/Phrasea/Controller/Root/Login.php @@ -308,7 +308,7 @@ class Login implements ControllerProviderInterface require_once $app['root.path'] . '/lib/classes/deprecated/inscript.api.php'; - if ($app['phraseanet.registry']->get('GV_autoSelectDb')) { + if ($app['phraseanet.registry']->get('GV_autoselectDB')) { $selected = null; } else { $selected = isset($data['collections']) ? $data['collections'] : null; @@ -385,8 +385,8 @@ class Login implements ControllerProviderInterface $appbox_register = new \appbox_register($app['phraseanet.appbox']); - foreach ($selected as $base_id) { - if (false === $inscOK[$base_id] || $user->ACL()->has_access_to_base($base_id)) { + foreach ($inscOK as $base_id => $autorisation) { + if (false === $autorisation || $user->ACL()->has_access_to_base($base_id)) { continue; } @@ -1055,10 +1055,9 @@ class Login implements ControllerProviderInterface $token = $app['auth.password-encoder']->encodePassword($string, $nonce); - $session->setToken($token) - ->setNonce($nonce); - $cookie = new Cookie('persistent', $token); - $response->headers->setCookie($cookie); + $session->setToken($token)->setNonce($nonce); + + $response->headers->setCookie(new Cookie('persistent', $token)); $app['EM']->persist($session); $app['EM']->flush(); diff --git a/lib/Alchemy/Phrasea/Core/Event/Subscriber/PhraseaLocaleSubscriber.php b/lib/Alchemy/Phrasea/Core/Event/Subscriber/PhraseaLocaleSubscriber.php index 18f128aa89..d2d9bdfddd 100644 --- a/lib/Alchemy/Phrasea/Core/Event/Subscriber/PhraseaLocaleSubscriber.php +++ b/lib/Alchemy/Phrasea/Core/Event/Subscriber/PhraseaLocaleSubscriber.php @@ -14,7 +14,9 @@ namespace Alchemy\Phrasea\Core\Event\Subscriber; use Silex\Application; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpKernel\Event\FilterResponseEvent; class PhraseaLocaleSubscriber implements EventSubscriberInterface { @@ -34,16 +36,19 @@ class PhraseaLocaleSubscriber implements EventSubscriberInterface // symfony locale is set on 16 priority, let's override it array('addLocale', 17), array('addLocale', 15), - array('removePhraseanetLocale', 14), ), + KernelEvents::RESPONSE => array( + array('addLocaleCookie', 8), + ), + KernelEvents::TERMINATE => array( + array('unsetLocale', -255), + ) ); } - public function removePhraseanetLocale(GetResponseEvent $event) + public function unsetLocale() { - if (isset($this->locale)) { - unset($this->locale); - } + $this->locale = null; } public function addLocale(GetResponseEvent $event) @@ -66,7 +71,7 @@ class PhraseaLocaleSubscriber implements EventSubscriberInterface ) ); - $this->app['locale'] = $this->locale = $this->app->share(function(Application $app) use ($event) { + $this->app['locale'] = $this->app->share(function(Application $app) use ($event) { if (isset($app['phraseanet.registry'])) { $event->getRequest()->setDefaultLocale( $app['phraseanet.registry']->get('GV_default_lng', 'en_GB') @@ -102,6 +107,16 @@ class PhraseaLocaleSubscriber implements EventSubscriberInterface return $event->getRequest()->getLocale(); }); - \phrasea::use_i18n($this->app['locale']); + $this->locale = $this->app['locale']; + \phrasea::use_i18n($this->locale); + } + + public function addLocaleCookie(FilterResponseEvent $event) + { + $cookies = $event->getRequest()->cookies; + + if (isset($this->locale) && (false === $cookies->has('locale') || $cookies->get('locale') !== $this->locale)) { + $event->getResponse()->headers->setCookie(new Cookie('locale', $this->locale, 0, '/', null, false, false)); + } } } diff --git a/lib/Alchemy/Phrasea/Form/Login/PhraseaRegisterForm.php b/lib/Alchemy/Phrasea/Form/Login/PhraseaRegisterForm.php index 01e2888c0a..1a6cd3cf97 100644 --- a/lib/Alchemy/Phrasea/Form/Login/PhraseaRegisterForm.php +++ b/lib/Alchemy/Phrasea/Form/Login/PhraseaRegisterForm.php @@ -105,7 +105,7 @@ class PhraseaRegisterForm extends AbstractType } } - if (!$this->app['phraseanet.registry']->get('GV_autoSelectDb')) { + if (!$this->app['phraseanet.registry']->get('GV_autoselectDB')) { $builder->add('collections', 'choice', array( 'choices' => $choices, 'multiple' => true, diff --git a/lib/conf.d/minifyGroupsConfig.php b/lib/conf.d/minifyGroupsConfig.php index 58e27f418e..96917c9f49 100644 --- a/lib/conf.d/minifyGroupsConfig.php +++ b/lib/conf.d/minifyGroupsConfig.php @@ -23,7 +23,7 @@ $groups = array( 'client' => array( '//assets/swfobject/swfobject.js' , '//assets/jquery.ui/i18n/jquery-ui-i18n.js' - , '//include/jslibs/jquery.cookie.js' + , '//assets/jquery.cookie/jquery.cookie.js' , '//include/jquery.common.js' , '//assets/json2/json2.js' , '//include/jslibs/audio-player/audio-player-noswfobject.js' @@ -37,7 +37,7 @@ $groups = array( 'admin' => array( '//assets/modernizr/modernizr.js' , '//assets/underscore-amd/underscore.js' - , '//include/jslibs/jquery.cookie.js' + , '//assets/jquery.cookie/jquery.cookie.js' , '//include/jslibs/jquery-treeview/jquery.treeview.js' , '//assets/jquery.ui/i18n/jquery-ui-i18n.js' , '//include/jquery.kb-event.js' @@ -52,7 +52,7 @@ $groups = array( ), 'report' => array( '//assets/jquery.ui/i18n/jquery-ui-i18n.js' - , '//include/jslibs/jquery.cookie.js' + , '//assets/jquery.cookie/jquery.cookie.js' , '//include/jquery.common.js' , '//include/jquery.tooltip.js' , '//include/jslibs/jquery.contextmenu_scroll.js' @@ -72,7 +72,7 @@ $groups = array( , '//include/jslibs/jquery.mousewheel.js' , '//include/jslibs/jquery.lazyload/jquery.lazyload.1.8.1.js' , '//assets/jquery.ui/i18n/jquery-ui-i18n.js' - , '//include/jslibs/jquery.cookie.js' + , '//assets/jquery.cookie/jquery.cookie.js' , '//include/jquery.common.js' , '//assets/humane-js/humane.js' , '//assets/blueimp-load-image/load-image.js' @@ -105,7 +105,7 @@ $groups = array( , '//include/jslibs/jquery-treeview/jquery.treeview.js' , '//include/jslibs/jquery-treeview/jquery.treeview.async.js'), 'thesaurus' => array( - '//include/jslibs/jquery.cookie.js' + '//assets/jquery.cookie/jquery.cookie.js' , '//include/jslibs/jquery.contextmenu_scroll.js' , '//include/jquery.common.js' , '//skins/thesaurus/win.js' @@ -118,7 +118,7 @@ $groups = array( , '//include/jquery.tooltip.js' , '//assets/swfobject/swfobject.js' , '//assets/jquery.ui/i18n/jquery-ui-i18n.js' - , '//include/jslibs/jquery.cookie.js' + , '//assets/jquery.cookie/jquery.cookie.js' , '//include/jslibs/jquery.contextmenu_scroll.js' , '//include/jquery.common.js' , '//skins/prod/jquery.Dialog.js' @@ -130,7 +130,7 @@ $groups = array( , '//include/jquery.tooltip.js' , '//assets/swfobject/swfobject.js' , '//assets/jquery.ui/i18n/jquery-ui-i18n.js' - , '//include/jslibs/jquery.cookie.js' + , '//assets/jquery.cookie/jquery.cookie.js' , '//include/jslibs/jquery.contextmenu_scroll.js' , '//include/jquery.common.js' , '//skins/prod/jquery.Dialog.js' diff --git a/templates/web/admin/fields/templates.html.twig b/templates/web/admin/fields/templates.html.twig index 6d68e4ca56..8bad226ce3 100644 --- a/templates/web/admin/fields/templates.html.twig +++ b/templates/web/admin/fields/templates.html.twig @@ -91,7 +91,7 @@ diff --git a/templates/web/login/cgus.html.twig b/templates/web/login/cgus.html.twig index 39dde0ef5b..609c08aebb 100644 --- a/templates/web/login/cgus.html.twig +++ b/templates/web/login/cgus.html.twig @@ -14,9 +14,6 @@ {{ cgus|raw }} {% endblock %} - - {% trans "Return to login page" %} - {% endblock %} diff --git a/templates/web/login/register-classic.html.twig b/templates/web/login/register-classic.html.twig index 6917d45311..0e9f00b00a 100644 --- a/templates/web/login/register-classic.html.twig +++ b/templates/web/login/register-classic.html.twig @@ -62,7 +62,7 @@
{% set label %} - + {% trans "I have read the terms of use" %} {% endset %} @@ -71,11 +71,14 @@
-
-
- {{ auth_macro.selectInput(form.collections) }} + {# form.collections is not defined if current instance is configured with auto collection selection #} + {% if form.collections is defined %} +
+
+ {{ auth_macro.selectInput(form.collections) }} +
-
+ {% endif %} {{ form_rest(form) }} diff --git a/tests/Alchemy/Tests/Phrasea/ApplicationTest.php b/tests/Alchemy/Tests/Phrasea/ApplicationTest.php index ac110887e0..28929a0f71 100644 --- a/tests/Alchemy/Tests/Phrasea/ApplicationTest.php +++ b/tests/Alchemy/Tests/Phrasea/ApplicationTest.php @@ -72,7 +72,7 @@ class ApplicationTest extends \PhraseanetPHPUnitAbstract $cookies = $response->headers->getCookies(ResponseHeaderBag::COOKIES_ARRAY); - $this->assertEquals(2, count($cookies['']['/'])); + $this->assertEquals(3, count($cookies['']['/'])); } /** @@ -111,10 +111,8 @@ class ApplicationTest extends \PhraseanetPHPUnitAbstract */ public function testCookieLocale() { - $app = $this->getAppThatReturnLocale(); - foreach (array('fr_FR', 'en_GB', 'de_DE') as $locale) { - $client = $this->getClientWithCookie($app, $locale); + $client = $this->getClientWithCookie( $this->getAppThatReturnLocale(), $locale); $client->request('GET', '/'); $this->assertEquals($locale, $client->getResponse()->getContent()); diff --git a/tests/Alchemy/Tests/Phrasea/Controller/Root/LoginTest.php b/tests/Alchemy/Tests/Phrasea/Controller/Root/LoginTest.php index c4a7400c95..fb3d488f74 100644 --- a/tests/Alchemy/Tests/Phrasea/Controller/Root/LoginTest.php +++ b/tests/Alchemy/Tests/Phrasea/Controller/Root/LoginTest.php @@ -515,6 +515,11 @@ class LoginTest extends \PhraseanetWebTestCaseAuthenticatedAbstract $parameters[$key] = self::$email; } } + + if (self::$DI['app']['phraseanet.registry']->get('GV_autoselectDB')) { + unset($parameters['collections']); + } + $crawler = self::$DI['client']->request('POST', '/login/register-classic/', $parameters); $this->assertFalse(self::$DI['client']->getResponse()->isRedirect()); @@ -527,7 +532,7 @@ class LoginTest extends \PhraseanetWebTestCaseAuthenticatedAbstract $crawler = self::$DI['client']->request('POST', '/login/register-classic/'); $this->assertFalse(self::$DI['client']->getResponse()->isRedirect()); - $this->assertFormOrFlashError($crawler, 8); + $this->assertFormOrFlashError($crawler, self::$DI['app']['phraseanet.registry']->get('GV_autoselectDB') ? 7 : 8); } public function provideInvalidRegistrationData() @@ -613,15 +618,6 @@ class LoginTest extends \PhraseanetWebTestCaseAuthenticatedAbstract ), "email" => $this->generateEmail(), "collections" => null - ), array(), 1), - array(array(//no demands - "password" => array( - 'password' => 'password', - 'confirm' => 'password' - ), - "email" => $this->generateEmail(), - "accept-tou" => '1', - "collections" => array() ), array(), 1) ); } @@ -955,6 +951,10 @@ class LoginTest extends \PhraseanetWebTestCaseAuthenticatedAbstract } } + if ( self::$DI['app']['phraseanet.registry']->get('GV_autoselectDB')) { + unset($parameters['collections']); + } + self::$DI['client']->request('POST', '/login/register-classic/', $parameters); if (false === $userId = \User_Adapter::get_usr_id_from_email(self::$DI['app'], $parameters['email'])) { @@ -1006,6 +1006,10 @@ class LoginTest extends \PhraseanetWebTestCaseAuthenticatedAbstract } } + if ( self::$DI['app']['phraseanet.registry']->get('GV_autoselectDB')) { + unset($parameters['collections']); + } + self::$DI['client']->request('POST', '/login/register-classic/', $parameters); if (false === $userId = \User_Adapter::get_usr_id_from_email(self::$DI['app'], $parameters['email'])) { diff --git a/tests/Alchemy/Tests/Phrasea/Controller/Root/RootTest.php b/tests/Alchemy/Tests/Phrasea/Controller/Root/RootTest.php index b544b03db5..441cfdc056 100644 --- a/tests/Alchemy/Tests/Phrasea/Controller/Root/RootTest.php +++ b/tests/Alchemy/Tests/Phrasea/Controller/Root/RootTest.php @@ -12,8 +12,13 @@ class RootTest extends \PhraseanetWebTestCaseAuthenticatedAbstract { public function testRouteSetLocale() { - $crawler = self::$DI['client']->request('GET', '/language/fr_CA/'); - $response = self::$DI['client']->getResponse(); + $cookieJar = new CookieJar(); + $cookieJar->set(new BrowserCookie('locale', 'de_DE')); + + $client = new Client(self::$DI['app'], array(), null, $cookieJar); + $crawler = $client->request('GET', '/language/fr_CA/'); + + $response = $client->getResponse(); $this->assertEquals(302, $response->getStatusCode()); $found = false; diff --git a/tests/Alchemy/Tests/Phrasea/Core/Event/Subscriber/PhraseaLocaleSubscriberTest.php b/tests/Alchemy/Tests/Phrasea/Core/Event/Subscriber/PhraseaLocaleSubscriberTest.php index 7377ac6bda..65f587c661 100644 --- a/tests/Alchemy/Tests/Phrasea/Core/Event/Subscriber/PhraseaLocaleSubscriberTest.php +++ b/tests/Alchemy/Tests/Phrasea/Core/Event/Subscriber/PhraseaLocaleSubscriberTest.php @@ -57,6 +57,23 @@ class PhraseaLocaleSubscriberTest extends \PhraseanetPHPUnitAbstract $this->assertEquals('fr_FR', $client->getResponse()->getContent()); } + public function testCookieIsSet() + { + $client = new Client(self::$DI['app']); + $client->request('GET', '/', array(), array(), array('HTTP_ACCEPT_LANGUAGE' => 'fr-FR,fr;q=0.9')); + + $settedCookie = null; + foreach($client->getResponse()->headers->getCookies() as $cookie) { + if($cookie->getName() === 'locale') { + $settedCookie = $cookie; + break; + } + } + + $this->assertNotNull($settedCookie); + $this->assertEquals('fr_FR', $settedCookie->getValue()); + } + /** * @covers Alchemy\Phrasea\Application */ diff --git a/tests/Alchemy/Tests/Phrasea/Form/Login/PhraseaRegisterFormTest.php b/tests/Alchemy/Tests/Phrasea/Form/Login/PhraseaRegisterFormTest.php index 331d75da26..e7e6775d88 100644 --- a/tests/Alchemy/Tests/Phrasea/Form/Login/PhraseaRegisterFormTest.php +++ b/tests/Alchemy/Tests/Phrasea/Form/Login/PhraseaRegisterFormTest.php @@ -51,7 +51,7 @@ class PhraseaRegisterFormTest extends FormTestCase $form = new PhraseaRegisterForm(self::$DI['app'], $available, $params, new Camelizer()); - $this->assertCount(8, self::$DI['app']->form($form)->createView()->vars['form']->children); + $this->assertCount(self::$DI['app']['phraseanet.registry']->get('GV_autoselectDB') ? 7 : 8, self::$DI['app']->form($form)->createView()->vars['form']->children); } public function testFormDoesNotRegisterNonValidFields() @@ -75,6 +75,6 @@ class PhraseaRegisterFormTest extends FormTestCase $form = new PhraseaRegisterForm(self::$DI['app'], $available, $params, new Camelizer()); - $this->assertCount(7, self::$DI['app']->form($form)->createView()->vars['form']->children); + $this->assertCount(self::$DI['app']['phraseanet.registry']->get('GV_autoselectDB') ? 6 : 7, self::$DI['app']->form($form)->createView()->vars['form']->children); } } diff --git a/tests/classes/PhraseanetWebTestCaseAuthenticatedAbstract.php b/tests/classes/PhraseanetWebTestCaseAuthenticatedAbstract.php index bbb9b4f70b..2d0f08a936 100644 --- a/tests/classes/PhraseanetWebTestCaseAuthenticatedAbstract.php +++ b/tests/classes/PhraseanetWebTestCaseAuthenticatedAbstract.php @@ -166,7 +166,7 @@ abstract class PhraseanetWebTestCaseAuthenticatedAbstract extends PhraseanetPHPU protected function assertFormOrFlashError(Crawler $crawler, $quantity) { - $total = $crawler->filter('form div:not(div[ng-show]) > div.popover.field-error')->count(); + $total = $crawler->filter('.field-error')->count(); $total += $crawler->filter('.alert')->count(); $this->assertEquals($quantity, $total); @@ -174,7 +174,7 @@ abstract class PhraseanetWebTestCaseAuthenticatedAbstract extends PhraseanetPHPU protected function assertFormError(Crawler $crawler, $quantity) { - $this->assertEquals($quantity, $crawler->filter('form div:not(div[ng-show]) > div.popover.field-error')->count()); + $this->assertEquals($quantity, $crawler->filter('.field-error')->count()); } protected function assertFlashMessage(Crawler $crawler, $flashType, $quantity, $message = null, $offset = 0) diff --git a/www/include/jquery.common.js b/www/include/jquery.common.js index 6a80123e64..1a03f7fef9 100644 --- a/www/include/jquery.common.js +++ b/www/include/jquery.common.js @@ -5,9 +5,10 @@ $(document).ready(function(){ function(){$(this).addClass('hover');}, function(){$(this).removeClass('hover');} ); + var locale = $.cookie('locale'); - var jq_date = p4.lng = locale !== null ? locale.split('_').reverse().pop() : 'en'; + var jq_date = p4.lng = typeof locale !== "undefined" ? locale.split('_').reverse().pop() : 'en'; if(jq_date == 'en') { diff --git a/www/include/jslibs/jquery.cookie.js b/www/include/jslibs/jquery.cookie.js deleted file mode 100644 index 7b3e701251..0000000000 --- a/www/include/jslibs/jquery.cookie.js +++ /dev/null @@ -1,89 +0,0 @@ -/*jslint browser: true */ /*global jQuery: true */ - -/** - * jQuery Cookie plugin - * - * Copyright (c) 2010 Klaus Hartl (stilbuero.de) - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html - * - */ - -// TODO JsDoc - -/** - * Create a cookie with the given key and value and other optional parameters. - * - * @example $.cookie('the_cookie', 'the_value'); - * @desc Set the value of a cookie. - * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true }); - * @desc Create a cookie with all available options. - * @example $.cookie('the_cookie', 'the_value'); - * @desc Create a session cookie. - * @example $.cookie('the_cookie', null); - * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain - * used when the cookie was set. - * - * @param String key The key of the cookie. - * @param String value The value of the cookie. - * @param Object options An object literal containing key/value pairs to provide optional cookie attributes. - * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object. - * If a negative value is specified (e.g. a date in the past), the cookie will be deleted. - * If set to null or omitted, the cookie will be a session cookie and will not be retained - * when the the browser exits. - * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie). - * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie). - * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will - * require a secure protocol (like HTTPS). - * @type undefined - * - * @name $.cookie - * @cat Plugins/Cookie - * @author Klaus Hartl/klaus.hartl@stilbuero.de - */ - -/** - * Get the value of a cookie with the given key. - * - * @example $.cookie('the_cookie'); - * @desc Get the value of a cookie. - * - * @param String key The key of the cookie. - * @return The value of the cookie. - * @type String - * - * @name $.cookie - * @cat Plugins/Cookie - * @author Klaus Hartl/klaus.hartl@stilbuero.de - */ -jQuery.cookie = function (key, value, options) { - - // key and value given, set cookie... - if (arguments.length > 1 && (value === null || typeof value !== "object")) { - options = jQuery.extend({}, options); - - if (value === null) { - options.expires = -1; - } - - if (typeof options.expires === 'number') { - var days = options.expires, t = options.expires = new Date(); - t.setDate(t.getDate() + days); - } - - return (document.cookie = [ - encodeURIComponent(key), '=', - options.raw ? String(value) : encodeURIComponent(String(value)), - options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE - options.path ? '; path=' + options.path : '', - options.domain ? '; domain=' + options.domain : '', - options.secure ? '; secure' : '' - ].join('')); - } - - // key and possibly options given, get cookie... - options = value || {}; - var result, decode = options.raw ? function (s) { return s; } : decodeURIComponent; - return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null; -}; diff --git a/www/scripts/apps/admin/fields/app.js b/www/scripts/apps/admin/fields/app.js index 0f03583149..baf77a0925 100644 --- a/www/scripts/apps/admin/fields/app.js +++ b/www/scripts/apps/admin/fields/app.js @@ -31,6 +31,9 @@ define([ $leftBlock : $(".left-block", this.$bottom), $rightBlock : $(".right-block", this.$bottom), fieldsToDelete : [], + lng : function() { + return typeof p4 === "undefined" ? "en" : (p4.lng || "en"); + }, resizeListBlock: function () { var listBlock = $(".list-block", AdminFieldApp.$leftBlock); listBlock.height(AdminFieldApp.$window.height() - listBlock.offset().top - 10); diff --git a/www/scripts/apps/admin/fields/views/edit.js b/www/scripts/apps/admin/fields/views/edit.js index 8fc9ed9d4e..2864f6e4e3 100644 --- a/www/scripts/apps/admin/fields/views/edit.js +++ b/www/scripts/apps/admin/fields/views/edit.js @@ -35,6 +35,7 @@ define([ render: function() { var self = this; var template = _.template($("#edit_template").html(), { + lng: AdminFieldApp.lng(), field: this.model.toJSON(), vocabularyTypes: AdminFieldApp.vocabularyCollection.toJSON(), modelErrors: AdminFieldApp.errorManager.getModelError(this.model),