Merge branch '2.7'
* 2.7: (61 commits) fixxed order of usage [2.7] [Form] Replaced calls to array_search() by in_array() where is no need to get the index removed the last deprecation notice [Serializer] Silent deprecation notice removed deprecation notice [PropertyAccess] Show property path in all exception messages added deprecation notice for HttpCache::createEsi() added missing deprecation notice when using the form_enctype function [Process] Make test AbstractProcessTest::testStartAfterATimeout useful again removed non-sense example Fixes small typo. [Validator] Remove unnecessary include in tests [HttpFoundation] minor: clarify Request::getUrlencodedPrefix() regex fixed typo [Serializer] Use Serializer's LogicException when applicable [Serializer] Use autoloader for annotations in tests [Validator] fix DOS-style line endings Drop useless execution bit bumped Symfony version to 2.6.5 [Serializer] update changelog ... Conflicts: CHANGELOG-2.3.md CHANGELOG-2.5.md CHANGELOG-2.6.md src/Symfony/Bridge/Twig/Node/FormEnctypeNode.php src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php
This commit is contained in:
commit
5c0b5ea821
@ -13,19 +13,19 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Kris Wallsmith (kriswallsmith)
|
||||
- Christophe Coevoet (stof)
|
||||
- Nicolas Grekas (nicolas-grekas)
|
||||
- Pascal Borreli (pborreli)
|
||||
- Jakub Zalas (jakubzalas)
|
||||
- Pascal Borreli (pborreli)
|
||||
- Hugo Hamon (hhamon)
|
||||
- Karma Dordrak (drak)
|
||||
- Joseph Bielawski (stloyd)
|
||||
- Hugo Hamon (hhamon)
|
||||
- Ryan Weaver (weaverryan)
|
||||
- Lukas Kahwe Smith (lsmith)
|
||||
- Romain Neutron (romain)
|
||||
- Jeremy Mikola (jmikola)
|
||||
- Jean-François Simon (jfsimon)
|
||||
- Christian Flothmann (xabbuh)
|
||||
- Benjamin Eberlei (beberlei)
|
||||
- Igor Wiedler (igorw)
|
||||
- Christian Flothmann (xabbuh)
|
||||
- Martin Hasoň (hason)
|
||||
- Eriksen Costa (eriksencosta)
|
||||
- Jonathan Wage (jwage)
|
||||
@ -33,9 +33,9 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Alexandre Salomé (alexandresalome)
|
||||
- William Durand (couac)
|
||||
- ornicar
|
||||
- Wouter De Jong (wouterj)
|
||||
- stealth35 (stealth35)
|
||||
- Alexander Mols (asm89)
|
||||
- Wouter De Jong (wouterj)
|
||||
- Bulat Shakirzyanov (avalanche123)
|
||||
- Francis Besset (francisbesset)
|
||||
- Saša Stamenković (umpirsky)
|
||||
@ -44,15 +44,15 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Konstantin Kudryashov (everzet)
|
||||
- Bilal Amarni (bamarni)
|
||||
- Florin Patan (florinpatan)
|
||||
- Abdellatif Ait Boudad (aitboudad)
|
||||
- Eric Clemmons (ericclemmons)
|
||||
- Sarah Khalil (saro0h)
|
||||
- Andrej Hudec (pulzarraider)
|
||||
- Deni
|
||||
- Henrik Westphal (snc)
|
||||
- Dariusz Górecki (canni)
|
||||
- Arnout Boks (aboks)
|
||||
- Christian Raue
|
||||
- Sarah Khalil (saro0h)
|
||||
- Ait Boudad Abdellatif (aitboudad)
|
||||
- Michel Weimerskirch (mweimerskirch)
|
||||
- Lee McDermott
|
||||
- Brandon Turner
|
||||
@ -69,6 +69,7 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Kevin Bond (kbond)
|
||||
- Tim Nagel (merk)
|
||||
- Brice BERNARD (brikou)
|
||||
- Kévin Dunglas (dunglas)
|
||||
- marc.weistroff
|
||||
- lenar
|
||||
- Graham Campbell (graham)
|
||||
@ -81,7 +82,7 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Jérôme Tamarelle (gromnan)
|
||||
- Adrien Brault (adrienbrault)
|
||||
- Fabien Pennequin (fabienpennequin)
|
||||
- Kévin Dunglas (dunglas)
|
||||
- Peter Kokot (maastermedia)
|
||||
- Michal Piotrowski (eventhorizon)
|
||||
- Gordon Franke (gimler)
|
||||
- Robert Schönthal (digitalkaoz)
|
||||
@ -89,13 +90,13 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Sebastian Hörl (blogsh)
|
||||
- Daniel Gomes (danielcsgomes)
|
||||
- Hidenori Goto (hidenorigoto)
|
||||
- Peter Kokot (maastermedia)
|
||||
- David Buchmann (dbu)
|
||||
- Jérémy DERUSSÉ (jderusse)
|
||||
- Pablo Godel (pgodel)
|
||||
- Eric GELOEN (gelo)
|
||||
- Peter Rehm (rpet)
|
||||
- Jérémie Augustin (jaugustin)
|
||||
- Rafael Dohms (rdohms)
|
||||
- Jérémy DERUSSÉ (jderusse)
|
||||
- Stefano Sala (stefano.sala)
|
||||
- Tigran Azatyan (tigranazatyan)
|
||||
- Javier Eguiluz (javier.eguiluz)
|
||||
@ -113,7 +114,6 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Rouven Weßling (realityking)
|
||||
- Dmitrii Chekaliuk (lazyhammer)
|
||||
- Clément JOBEILI (dator)
|
||||
- Peter Rehm (rpet)
|
||||
- Dorian Villet (gnutix)
|
||||
- Richard Miller (mr_r_miller)
|
||||
- Arnaud Kleinpeter (nanocom)
|
||||
@ -130,25 +130,27 @@ Symfony is the result of the work of many people who made the code better
|
||||
- bronze1man
|
||||
- sun (sun)
|
||||
- Larry Garfield (crell)
|
||||
- Issei Murasawa (issei_m)
|
||||
- Martin Schuhfuß (usefulthink)
|
||||
- Thomas Rabaix (rande)
|
||||
- Matthieu Bontemps (mbontemps)
|
||||
- Pierre Minnieur (pminnieur)
|
||||
- fivestar
|
||||
- Dominique Bongiraud
|
||||
- Iltar van der Berg
|
||||
- Leszek Prabucki (l3l0)
|
||||
- François Zaninotto (fzaninotto)
|
||||
- Dustin Whittle (dustinwhittle)
|
||||
- jeff
|
||||
- Justin Hileman (bobthecow)
|
||||
- Sven Paulus (subsven)
|
||||
- Alexander Schwenn (xelaris)
|
||||
- Lars Strojny (lstrojny)
|
||||
- Rui Marinho (ruimarinho)
|
||||
- Julien Brochet (mewt)
|
||||
- Tugdual Saunier (tucksaun)
|
||||
- Sergey Linnik (linniksa)
|
||||
- Marcel Beerta (mazen)
|
||||
- Iltar van der Berg
|
||||
- Francois Zaninotto
|
||||
- Alexander Kotynia (olden)
|
||||
- Daniel Tschinder
|
||||
@ -158,6 +160,7 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Roman Marintšenko (inori)
|
||||
- Xavier Montaña Carreras (xmontana)
|
||||
- Michele Orselli (orso)
|
||||
- Chris Wilkinson (thewilkybarkid)
|
||||
- Xavier Perez
|
||||
- Arjen Brouwer (arjenjb)
|
||||
- Katsuhiro OGAWA
|
||||
@ -167,7 +170,6 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Joseph Rouff (rouffj)
|
||||
- Félix Labrecque (woodspire)
|
||||
- GordonsLondon
|
||||
- Issei Murasawa (issei_m)
|
||||
- Jan Sorgalla (jsor)
|
||||
- Ray
|
||||
- Chekote
|
||||
@ -181,10 +183,13 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Beau Simensen (simensen)
|
||||
- Robert Kiss (kepten)
|
||||
- Kim Hemsø Rasmussen (kimhemsoe)
|
||||
- Florian Lonqueu-Brochard (florianlb)
|
||||
- Tom Van Looy (tvlooy)
|
||||
- Wouter Van Hecke
|
||||
- Joshua Thijssen
|
||||
- Peter Kruithof (pkruithof)
|
||||
- Michael Holm (hollo)
|
||||
- Warnar Boekkooi (boekkooi)
|
||||
- Marc Weistroff (futurecat)
|
||||
- Chris Smith (cs278)
|
||||
- Florian Klein (docteurklein)
|
||||
@ -195,10 +200,10 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Bertrand Zuchuat (garfield-fr)
|
||||
- Gabor Toth (tgabi333)
|
||||
- realmfoo
|
||||
- Chris Wilkinson (thewilkybarkid)
|
||||
- Thomas Tourlourat (armetiz)
|
||||
- Andrey Esaulov (andremaha)
|
||||
- Grégoire Passault (gregwar)
|
||||
- Mikael Pajunen
|
||||
- Uwe Jäger (uwej711)
|
||||
- Aurelijus Valeiša (aurelijus)
|
||||
- Jan Decavele (jandc)
|
||||
@ -219,7 +224,6 @@ Symfony is the result of the work of many people who made the code better
|
||||
- alquerci
|
||||
- Francesco Levorato
|
||||
- Vitaliy Zakharov (zakharovvi)
|
||||
- Florian Lonqueu-Brochard (florianlb)
|
||||
- Gyula Sallai (salla)
|
||||
- Inal DJAFAR (inalgnu)
|
||||
- Christian Gärtner (dagardner)
|
||||
@ -227,7 +231,6 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Yaroslav Kiliba
|
||||
- Sébastien Lavoie (lavoiesl)
|
||||
- Terje Bråten
|
||||
- Joshua Thijssen
|
||||
- Kristen Gilden (kgilden)
|
||||
- Robbert Klarenbeek (robbertkl)
|
||||
- Blanchon Vincent (blanchonvincent)
|
||||
@ -239,6 +242,7 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Philipp Kräutli (pkraeutli)
|
||||
- Kirill chEbba Chebunin (chebba)
|
||||
- Greg Thornton (xdissent)
|
||||
- Baptiste Clavié (talus)
|
||||
- Grégoire Paris (greg0ire)
|
||||
- Costin Bereveanu (schniper)
|
||||
- Loïc Chardonnet (gnusat)
|
||||
@ -246,7 +250,6 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Vyacheslav Salakhutdinov (megazoll)
|
||||
- Alex Pott
|
||||
- Tamas Szijarto
|
||||
- Mikael Pajunen
|
||||
- Pavel Volokitin (pvolok)
|
||||
- Endre Fejes
|
||||
- Tobias Naumann (tna)
|
||||
@ -254,6 +257,7 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Shein Alexey
|
||||
- Joe Lencioni
|
||||
- Kai
|
||||
- Lee Rowlands
|
||||
- Maximilian Reichel (phramz)
|
||||
- Karoly Negyesi (chx)
|
||||
- Xavier HAUSHERR
|
||||
@ -275,6 +279,7 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Michel Salib (michelsalib)
|
||||
- geoffrey
|
||||
- Matthieu Auger (matthieuauger)
|
||||
- Lorenz Schori
|
||||
- Jeanmonod David (jeanmonod)
|
||||
- Jan Schumann
|
||||
- Niklas Fiekas
|
||||
@ -287,6 +292,7 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Konstantin Myakshin (koc)
|
||||
- vagrant
|
||||
- Asier Illarramendi (doup)
|
||||
- Alexander M. Turek (derrabus)
|
||||
- Chris Sedlmayr (catchamonkey)
|
||||
- Seb Koelen
|
||||
- Christoph Mewes (xrstf)
|
||||
@ -306,7 +312,6 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Jérôme Macias (jeromemacias)
|
||||
- Fabian Lange (codingfabian)
|
||||
- Yoshio HANAWA
|
||||
- Baptiste Clavié (talus)
|
||||
- Sebastian Bergmann
|
||||
- Pablo Díez (pablodip)
|
||||
- Kevin McBride
|
||||
@ -337,6 +342,7 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Nils Adermann (naderman)
|
||||
- Gábor Fási
|
||||
- Benjamin Leveque (benji07)
|
||||
- Javier Spagnoletti (phansys)
|
||||
- sasezaki
|
||||
- Dawid Pakuła (zulusx)
|
||||
- Florian Rey (nervo)
|
||||
@ -348,6 +354,7 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Ryan
|
||||
- Alexander Deruwe (aderuwe)
|
||||
- François Pluchino (francoispluchino)
|
||||
- Massimiliano Arione (garak)
|
||||
- Ivan Rey (ivanrey)
|
||||
- Marcin Chyłek (songoq)
|
||||
- Ned Schwartz
|
||||
@ -356,12 +363,10 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Zach Badgett (zachbadgett)
|
||||
- Aurélien Fredouelle
|
||||
- Pavel Campr (pcampr)
|
||||
- Alexander Schwenn (xelaris)
|
||||
- Disquedur
|
||||
- Geoffrey Tran (geoff)
|
||||
- Jan Behrens
|
||||
- Sebastian Krebs
|
||||
- Lorenz Schori
|
||||
- Christopher Davis (chrisguitarguy)
|
||||
- Thomas Lallement (raziel057)
|
||||
- alcaeus
|
||||
@ -386,8 +391,6 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Javier López (loalf)
|
||||
- Reinier Kip
|
||||
- Dustin Dobervich (dustin10)
|
||||
- Warnar Boekkooi
|
||||
- Alexander M. Turek (derrabus)
|
||||
- Sebastian Marek (proofek)
|
||||
- Erkhembayar Gantulga (erheme318)
|
||||
- David Fuhr
|
||||
@ -410,6 +413,7 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Antoine Corcy
|
||||
- Arturs Vonda
|
||||
- Sascha Grossenbacher
|
||||
- Szijarto Tamas
|
||||
- Ben Davies (bendavies)
|
||||
- Simon Schick (simonsimcity)
|
||||
- redstar504
|
||||
@ -472,7 +476,6 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Loick Piera (pyrech)
|
||||
- cgonzalez
|
||||
- Ben
|
||||
- Lee Rowlands
|
||||
- Jayson Xu (superjavason)
|
||||
- Jaik Dean (jaikdean)
|
||||
- Harm van Tilborg
|
||||
@ -490,7 +493,6 @@ Symfony is the result of the work of many people who made the code better
|
||||
- frost-nzcr4
|
||||
- Abhoryo
|
||||
- Fabian Vogler (fabian)
|
||||
- Javier Spagnoletti (phansys)
|
||||
- Korvin Szanto
|
||||
- Maksim Kotlyar (makasim)
|
||||
- Neil Ferreira
|
||||
@ -538,7 +540,6 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Maks
|
||||
- Gábor Tóth
|
||||
- Daniel Cestari
|
||||
- Massimiliano Arione (garak)
|
||||
- Brunet Laurent (lbrunet)
|
||||
- Magnus Nordlander (magnusnordlander)
|
||||
- Mikhail Yurasov (mym)
|
||||
@ -597,6 +598,7 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Per Sandström (per)
|
||||
- Goran Juric
|
||||
- Laurent Ghirardotti (laurentg)
|
||||
- Jan Rosier (rosier)
|
||||
- Lin Clark
|
||||
- Jeremy David (jeremy.david)
|
||||
- Troy McCabe
|
||||
@ -604,6 +606,7 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Boris Vujicic (boris.vujicic)
|
||||
- Max Beutel
|
||||
- Catalin Dan
|
||||
- nacho
|
||||
- Piotr Antosik (antek88)
|
||||
- Artem Lopata
|
||||
- Marcos Quesada (marcos_quesada)
|
||||
@ -658,7 +661,6 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Yannick
|
||||
- Luc Vieillescazes (iamluc)
|
||||
- Eduardo García Sanz (coma)
|
||||
- Szijarto Tamas
|
||||
- Roy Van Ginneken
|
||||
- David de Boer (ddeboer)
|
||||
- Gilles Doge (gido)
|
||||
@ -673,6 +675,7 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Derek Lambert
|
||||
- MightyBranch
|
||||
- Kacper Gunia (cakper)
|
||||
- Peter Thompson (petert82)
|
||||
- Felicitus
|
||||
- Krzysztof Przybyszewski
|
||||
- Paul Matthews
|
||||
@ -700,6 +703,7 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Aharon Perkel
|
||||
- Abdul.Mohsen B. A. A
|
||||
- Benoît Burnichon
|
||||
- pthompson
|
||||
- Malaney J. Hill
|
||||
- Christian Flach (cmfcmf)
|
||||
- Cédric Girard (enk_)
|
||||
@ -738,6 +742,7 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Jason Desrosiers
|
||||
- m.chwedziak
|
||||
- Lance McNearney
|
||||
- Frank Neff (fneff)
|
||||
- Giorgio Premi
|
||||
- caponica
|
||||
- Matt Daum (daum)
|
||||
@ -784,6 +789,7 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Klaus Silveira (klaussilveira)
|
||||
- Thomas Chmielowiec (chmielot)
|
||||
- Jānis Lukss
|
||||
- rkerner
|
||||
- Vladyslav Petrovych
|
||||
- Matthew J Mucklo
|
||||
- fdgdfg (psampaz)
|
||||
@ -832,6 +838,7 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Przemysław Piechota (kibao)
|
||||
- Leonid Terentyev (li0n)
|
||||
- Adam Prager (padam87)
|
||||
- victoria
|
||||
- Francisco Facioni (fran6co)
|
||||
- Iwan van Staveren (istaveren)
|
||||
- Povilas S. (povilas)
|
||||
@ -912,6 +919,7 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Daan van Renterghem
|
||||
- Bram Van der Sype (brammm)
|
||||
- Julien Moulin (lizjulien)
|
||||
- Nikita Nefedov (nikita2206)
|
||||
- Yannick Warnier (ywarnier)
|
||||
- Kevin Decherf
|
||||
- Jason Woods
|
||||
@ -958,6 +966,7 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Florian Pfitzer (marmelatze)
|
||||
- Martin Mayer (martin)
|
||||
- Grzegorz Łukaszewicz (newicz)
|
||||
- Richard van Laak (rvanlaak)
|
||||
- grifx
|
||||
- Robert Campbell
|
||||
- Matt Lehner
|
||||
@ -965,6 +974,7 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Ruben Kruiswijk
|
||||
- Michael J
|
||||
- Berny Cantos
|
||||
- Joseph Maarek
|
||||
- Alex Pods
|
||||
- timaschew
|
||||
- Ian Phillips
|
||||
@ -1020,6 +1030,7 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Pablo Monterde Perez (plebs)
|
||||
- Jimmy Leger (redpanda)
|
||||
- Cyrille Jouineau (tuxosaurus)
|
||||
- Vadim Kharitonov (virtuozzz)
|
||||
- Yorkie Chadwick (yorkie76)
|
||||
- Yanick Witschi
|
||||
- Ondrej Mirtes
|
||||
@ -1128,6 +1139,7 @@ Symfony is the result of the work of many people who made the code better
|
||||
- Andreas Forsblom (aforsblo)
|
||||
- Alaattin Kahramanlar (alaattin)
|
||||
- Alex Olmos (alexolmos)
|
||||
- Alain Hippolyte (aloneh)
|
||||
- Antonio Mansilla (amansilla)
|
||||
- Juan Ases García (ases)
|
||||
- Daniel Basten (axhm3a)
|
||||
|
@ -59,3 +59,49 @@ Form
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Serializer
|
||||
----------
|
||||
|
||||
* The `setCamelizedAttributes()` method of the
|
||||
`Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer` and
|
||||
`Symfony\Component\Serializer\Normalizer\PropertyNormalizer` classes is marked
|
||||
as deprecated in favor of the new NameConverter system.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
$normalizer->setCamelizedAttributes(array('foo_bar', 'bar_foo'));
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
|
||||
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
|
||||
|
||||
$nameConverter = new CamelCaseToSnakeCaseNameConverter(array('fooBar', 'barFoo'));
|
||||
$normalizer = new GetSetMethodNormalizer(null, $nameConverter);
|
||||
```
|
||||
|
||||
PropertyAccess
|
||||
--------------
|
||||
|
||||
* `UnexpectedTypeException` now expects three constructor arguments: The invalid property value,
|
||||
the `PropertyPathInterface` object and the current index of the property path.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
use Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException;
|
||||
|
||||
new UnexpectedTypeException($value, $expectedType);
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
use Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException;
|
||||
|
||||
new UnexpectedTypeException($value, $path, $pathIndex);
|
||||
```
|
||||
|
@ -244,35 +244,34 @@ class UniqueEntityValidatorTest extends AbstractConstraintValidatorTest
|
||||
->assertRaised();
|
||||
}
|
||||
|
||||
public function testValidateUniquenessAfterConsideringMultipleQueryResults()
|
||||
public function testValidateUniquenessWithValidCustomErrorPath()
|
||||
{
|
||||
$constraint = new UniqueEntity(array(
|
||||
'message' => 'myMessage',
|
||||
'fields' => array('name'),
|
||||
'fields' => array('name', 'name2'),
|
||||
'em' => self::EM_NAME,
|
||||
'errorPath' => "name2",
|
||||
));
|
||||
|
||||
$entity1 = new SingleIntIdEntity(1, 'Foo');
|
||||
$entity2 = new SingleIntIdEntity(2, 'Foo');
|
||||
$entity1 = new DoubleNameEntity(1, 'Foo', "Bar");
|
||||
$entity2 = new DoubleNameEntity(2, 'Foo', "Bar");
|
||||
|
||||
$this->validator->validate($entity1, $constraint);
|
||||
|
||||
$this->assertNoViolation();
|
||||
|
||||
$this->em->persist($entity1);
|
||||
$this->em->persist($entity2);
|
||||
$this->em->flush();
|
||||
|
||||
$this->validator->validate($entity1, $constraint);
|
||||
|
||||
$this->buildViolation('myMessage')
|
||||
->atPath('property.path.name')
|
||||
->setInvalidValue('Foo')
|
||||
->assertRaised();
|
||||
|
||||
$this->context->getViolations()->remove(0);
|
||||
$this->assertNoViolation();
|
||||
|
||||
$this->validator->validate($entity2, $constraint);
|
||||
|
||||
$this->buildViolation('myMessage')
|
||||
->atPath('property.path.name')
|
||||
->setInvalidValue('Foo')
|
||||
->atPath('property.path.name2')
|
||||
->setInvalidValue('Bar')
|
||||
->assertRaised();
|
||||
}
|
||||
|
||||
|
@ -133,16 +133,17 @@ class UniqueEntityValidator extends ConstraintValidator
|
||||
}
|
||||
|
||||
$errorPath = null !== $constraint->errorPath ? $constraint->errorPath : $fields[0];
|
||||
$invalidValue = isset($criteria[$errorPath]) ? $criteria[$errorPath] : $criteria[$fields[0]];
|
||||
|
||||
if ($this->context instanceof ExecutionContextInterface) {
|
||||
$this->context->buildViolation($constraint->message)
|
||||
->atPath($errorPath)
|
||||
->setInvalidValue($criteria[$fields[0]])
|
||||
->setInvalidValue($invalidValue)
|
||||
->addViolation();
|
||||
} else {
|
||||
$this->buildViolation($constraint->message)
|
||||
->atPath($errorPath)
|
||||
->setInvalidValue($criteria[$fields[0]])
|
||||
->setInvalidValue($invalidValue)
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ class ModelChoiceList extends ObjectChoiceList
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* This performance optimization reflects a common scenario:
|
||||
* * A simple select of a model entry.
|
||||
* * The choice option "expanded" is set to false.
|
||||
@ -239,7 +239,7 @@ class ModelChoiceList extends ObjectChoiceList
|
||||
}
|
||||
|
||||
if (!$this->loaded) {
|
||||
/**
|
||||
/*
|
||||
* This performance optimization assumes the validation of the respective values will be done by other means.
|
||||
*
|
||||
* It correlates with the performance optimization in {@link ModelChoiceList::getChoicesForValues()}
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace Symfony\Bridge\Twig\Command;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
@ -58,7 +59,7 @@ class LintCommand extends Command
|
||||
$this
|
||||
->setDescription('Lints a template and outputs encountered errors')
|
||||
->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt')
|
||||
->addArgument('filename')
|
||||
->addArgument('filename', InputArgument::IS_ARRAY)
|
||||
->setHelp(<<<EOF
|
||||
The <info>%command.name%</info> command lints a template and outputs to STDOUT
|
||||
the first encountered syntax error.
|
||||
@ -90,9 +91,9 @@ EOF
|
||||
return 1;
|
||||
}
|
||||
|
||||
$filename = $input->getArgument('filename');
|
||||
$filenames = $input->getArgument('filename');
|
||||
|
||||
if (!$filename) {
|
||||
if (0 === count($filenames)) {
|
||||
if (0 !== ftell(STDIN)) {
|
||||
throw new \RuntimeException("Please provide a filename or pipe template content to STDIN.");
|
||||
}
|
||||
@ -105,14 +106,23 @@ EOF
|
||||
return $this->display($input, $output, array($this->validate($twig, $template, uniqid('sf_'))));
|
||||
}
|
||||
|
||||
$filesInfo = array();
|
||||
foreach ($this->findFiles($filename) as $file) {
|
||||
$filesInfo[] = $this->validate($twig, file_get_contents($file), $file);
|
||||
}
|
||||
$filesInfo = $this->getFilesInfo($twig, $filenames);
|
||||
|
||||
return $this->display($input, $output, $filesInfo);
|
||||
}
|
||||
|
||||
private function getFilesInfo(\Twig_Environment $twig, array $filenames)
|
||||
{
|
||||
$filesInfo = array();
|
||||
foreach ($filenames as $filename) {
|
||||
foreach ($this->findFiles($filename) as $file) {
|
||||
$filesInfo[] = $this->validate($twig, file_get_contents($file), $file);
|
||||
}
|
||||
}
|
||||
|
||||
return $filesInfo;
|
||||
}
|
||||
|
||||
protected function findFiles($filename)
|
||||
{
|
||||
if (is_file($filename)) {
|
||||
|
@ -143,7 +143,7 @@ class FormExtension extends \Twig_Extension
|
||||
public function isSelectedChoice(ChoiceView $choice, $selectedValue)
|
||||
{
|
||||
if (is_array($selectedValue)) {
|
||||
return false !== array_search($choice->value, $selectedValue, true);
|
||||
return in_array($choice->value, $selectedValue, true);
|
||||
}
|
||||
|
||||
return $choice->value === $selectedValue;
|
||||
|
@ -28,7 +28,7 @@ class LintCommandTest extends \PHPUnit_Framework_TestCase
|
||||
$tester = $this->createCommandTester();
|
||||
$filename = $this->createFile('{{ foo }}');
|
||||
|
||||
$ret = $tester->execute(array('filename' => $filename), array('verbosity' => OutputInterface::VERBOSITY_VERBOSE));
|
||||
$ret = $tester->execute(array('filename' => array($filename)), array('verbosity' => OutputInterface::VERBOSITY_VERBOSE));
|
||||
|
||||
$this->assertEquals(0, $ret, 'Returns 0 in case of success');
|
||||
$this->assertRegExp('/^OK in /', $tester->getDisplay());
|
||||
@ -39,7 +39,7 @@ class LintCommandTest extends \PHPUnit_Framework_TestCase
|
||||
$tester = $this->createCommandTester();
|
||||
$filename = $this->createFile('{{ foo');
|
||||
|
||||
$ret = $tester->execute(array('filename' => $filename));
|
||||
$ret = $tester->execute(array('filename' => array($filename)));
|
||||
|
||||
$this->assertEquals(1, $ret, 'Returns 1 in case of error');
|
||||
$this->assertRegExp('/^KO in /', $tester->getDisplay());
|
||||
@ -54,7 +54,7 @@ class LintCommandTest extends \PHPUnit_Framework_TestCase
|
||||
$filename = $this->createFile('');
|
||||
unlink($filename);
|
||||
|
||||
$ret = $tester->execute(array('filename' => $filename));
|
||||
$ret = $tester->execute(array('filename' => array($filename)));
|
||||
}
|
||||
|
||||
public function testLintFileCompileTimeException()
|
||||
@ -62,7 +62,7 @@ class LintCommandTest extends \PHPUnit_Framework_TestCase
|
||||
$tester = $this->createCommandTester();
|
||||
$filename = $this->createFile("{{ 2|number_format(2, decimal_point='.', ',') }}");
|
||||
|
||||
$ret = $tester->execute(array('filename' => $filename));
|
||||
$ret = $tester->execute(array('filename' => array($filename)));
|
||||
|
||||
$this->assertEquals(1, $ret, 'Returns 1 in case of error');
|
||||
$this->assertRegExp('/^KO in /', $tester->getDisplay());
|
||||
|
@ -14,6 +14,7 @@
|
||||
<tag name="data_collector" id="dump" template="@Debug/Profiler/dump.html.twig" />
|
||||
<argument type="service" id="debug.stopwatch" on-invalid="ignore" />
|
||||
<argument>null</argument><!-- %templating.helper.code.file_link_format% -->
|
||||
<argument>%kernel.charset%</argument>
|
||||
</service>
|
||||
|
||||
<service id="debug.dump_listener" class="Symfony\Component\HttpKernel\EventListener\DumpListener">
|
||||
|
@ -33,7 +33,7 @@ class EventDispatcherDebugCommand extends ContainerAwareCommand
|
||||
$this
|
||||
->setName('debug:event-dispatcher')
|
||||
->setDefinition(array(
|
||||
new InputArgument('event', InputArgument::OPTIONAL, 'An event name (foo)'),
|
||||
new InputArgument('event', InputArgument::OPTIONAL, 'An event name'),
|
||||
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output description in other formats', 'txt'),
|
||||
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw description'),
|
||||
))
|
||||
|
@ -76,7 +76,7 @@ class ControllerResolver extends BaseControllerResolver
|
||||
throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
|
||||
}
|
||||
|
||||
$controller = new $class();
|
||||
$controller = $this->instantiateController($class);
|
||||
if ($controller instanceof ContainerAwareInterface) {
|
||||
$controller->setContainer($this->container);
|
||||
}
|
||||
|
@ -459,8 +459,13 @@ class Configuration implements ConfigurationInterface
|
||||
->arrayNode('translator')
|
||||
->info('translator configuration')
|
||||
->canBeEnabled()
|
||||
->fixXmlConfig('fallback')
|
||||
->children()
|
||||
->scalarNode('fallback')->defaultValue('en')->end()
|
||||
->arrayNode('fallbacks')
|
||||
->beforeNormalization()->ifString()->then(function ($v) { return array($v); })->end()
|
||||
->prototype('scalar')->end()
|
||||
->defaultValue(array('en'))
|
||||
->end()
|
||||
->booleanNode('logging')->defaultValue($this->debug)->end()
|
||||
->end()
|
||||
->end()
|
||||
|
@ -647,10 +647,7 @@ class FrameworkExtension extends Extension
|
||||
// Use the "real" translator instead of the identity default
|
||||
$container->setAlias('translator', 'translator.default');
|
||||
$translator = $container->findDefinition('translator.default');
|
||||
if (!is_array($config['fallback'])) {
|
||||
$config['fallback'] = array($config['fallback']);
|
||||
}
|
||||
$translator->addMethodCall('setFallbackLocales', array($config['fallback']));
|
||||
$translator->addMethodCall('setFallbackLocales', array($config['fallbacks']));
|
||||
|
||||
$container->setParameter('translator.logging', $config['logging']);
|
||||
|
||||
|
@ -157,6 +157,9 @@
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="translator">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="fallback" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="enabled" type="xsd:boolean" />
|
||||
<xsd:attribute name="fallback" type="xsd:string" />
|
||||
<xsd:attribute name="logging" type="xsd:boolean" />
|
||||
|
@ -122,7 +122,7 @@ class ConfigurationTest extends \PHPUnit_Framework_TestCase
|
||||
),
|
||||
'translator' => array(
|
||||
'enabled' => false,
|
||||
'fallback' => 'en',
|
||||
'fallbacks' => array('en'),
|
||||
'logging' => true,
|
||||
),
|
||||
'validation' => array(
|
||||
|
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
$container->loadFromExtension('framework', array(
|
||||
'translator' => array(
|
||||
'fallbacks' => array('en', 'fr'),
|
||||
),
|
||||
));
|
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" ?>
|
||||
|
||||
<container xmlns="http://symfony.com/schema/dic/services"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:framework="http://symfony.com/schema/dic/symfony"
|
||||
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
|
||||
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
|
||||
|
||||
<framework:config secret="s3cr3t">
|
||||
<framework:translator enabled="true">
|
||||
<framework:fallback>en</framework:fallback>
|
||||
<framework:fallback>fr</framework:fallback>
|
||||
</framework:translator>
|
||||
</framework:config>
|
||||
</container>
|
@ -0,0 +1,3 @@
|
||||
framework:
|
||||
translator:
|
||||
fallbacks: [en, fr]
|
@ -261,6 +261,14 @@ abstract class FrameworkExtensionTest extends TestCase
|
||||
$this->assertEquals(array('fr'), $calls[0][1][0]);
|
||||
}
|
||||
|
||||
public function testTranslatorMultipleFallbacks()
|
||||
{
|
||||
$container = $this->createContainerFromFile('translator_fallbacks');
|
||||
|
||||
$calls = $container->getDefinition('translator.default')->getMethodCalls();
|
||||
$this->assertEquals(array('en', 'fr'), $calls[0][1][0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
|
||||
*/
|
||||
@ -297,8 +305,10 @@ abstract class FrameworkExtensionTest extends TestCase
|
||||
$this->assertEquals(array(Validation::API_VERSION_2_5_BC), $calls[6][1]);
|
||||
}
|
||||
|
||||
public function testFullyConfiguredValidationService()
|
||||
public function testLegacyFullyConfiguredValidationService()
|
||||
{
|
||||
$this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED);
|
||||
|
||||
if (!extension_loaded('apc')) {
|
||||
$this->markTestSkipped('The apc extension is not available.');
|
||||
}
|
||||
|
@ -172,7 +172,7 @@
|
||||
<!-- Validator -->
|
||||
<service id="security.validator.user_password" class="%security.validator.user_password.class%">
|
||||
<tag name="validator.constraint_validator" alias="security.validator.user_password" />
|
||||
<argument type="service" id="security.context" />
|
||||
<argument type="service" id="security.token_storage" />
|
||||
<argument type="service" id="security.encoder_factory" />
|
||||
</service>
|
||||
</services>
|
||||
|
@ -151,6 +151,20 @@ class SetAclCommandTest extends WebTestCase
|
||||
$this->assertTrue($acl2->isGranted($permissionMap->getMasks($grantedPermission, null), array($roleSecurityIdentity)));
|
||||
}
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->deleteTmpDir('Acl');
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
parent::tearDown();
|
||||
|
||||
$this->deleteTmpDir('Acl');
|
||||
}
|
||||
|
||||
private function getApplication()
|
||||
{
|
||||
$kernel = $this->createKernel(array('test_case' => 'Acl'));
|
||||
|
@ -106,7 +106,7 @@ class TwigExtension extends Extension
|
||||
}
|
||||
unset($config['autoescape_service'], $config['autoescape_service_method']);
|
||||
|
||||
$container->setParameter('twig.options', $config);
|
||||
$container->getDefinition('twig')->replaceArgument(1, $config);
|
||||
|
||||
$this->addClassesToCompile(array(
|
||||
'Twig_Environment',
|
||||
|
@ -30,7 +30,7 @@
|
||||
<services>
|
||||
<service id="twig" class="%twig.class%">
|
||||
<argument type="service" id="twig.loader" />
|
||||
<argument>%twig.options%</argument>
|
||||
<argument /> <!-- Twig options -->
|
||||
<call method="addGlobal">
|
||||
<argument>app</argument>
|
||||
<argument type="service" id="twig.app_variable" />
|
||||
|
@ -35,10 +35,10 @@ class TwigExtensionTest extends TestCase
|
||||
$this->assertContains('form_div_layout.html.twig', $container->getParameter('twig.form.resources'), '->load() includes default template for form resources');
|
||||
|
||||
// Twig options
|
||||
$options = $container->getParameter('twig.options');
|
||||
$this->assertEquals(__DIR__.'/twig', $options['cache'], '->load() sets default value for cache option');
|
||||
$this->assertEquals('UTF-8', $options['charset'], '->load() sets default value for charset option');
|
||||
$this->assertFalse($options['debug'], '->load() sets default value for debug option');
|
||||
$options = $container->getDefinition('twig')->getArgument(1);
|
||||
$this->assertEquals('%kernel.cache_dir%/twig', $options['cache'], '->load() sets default value for cache option');
|
||||
$this->assertEquals('%kernel.charset%', $options['charset'], '->load() sets default value for charset option');
|
||||
$this->assertEquals('%kernel.debug%', $options['debug'], '->load() sets default value for debug option');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -76,7 +76,7 @@ class TwigExtensionTest extends TestCase
|
||||
}
|
||||
|
||||
// Twig options
|
||||
$options = $container->getParameter('twig.options');
|
||||
$options = $container->getDefinition('twig')->getArgument(1);
|
||||
$this->assertTrue($options['auto_reload'], '->load() sets the auto_reload option');
|
||||
$this->assertTrue($options['autoescape'], '->load() sets the autoescape option');
|
||||
$this->assertEquals('stdClass', $options['base_template_class'], '->load() sets the base_template_class option');
|
||||
@ -96,7 +96,7 @@ class TwigExtensionTest extends TestCase
|
||||
$this->loadFromFile($container, 'customTemplateEscapingGuesser', $format);
|
||||
$this->compileContainer($container);
|
||||
|
||||
$options = $container->getParameter('twig.options');
|
||||
$options = $container->getDefinition('twig')->getArgument(1);
|
||||
$this->assertEquals(array(new Reference('my_project.some_bundle.template_escaping_guesser'), 'guess'), $options['autoescape']);
|
||||
}
|
||||
|
||||
@ -110,7 +110,7 @@ class TwigExtensionTest extends TestCase
|
||||
$this->loadFromFile($container, 'empty', $format);
|
||||
$this->compileContainer($container);
|
||||
|
||||
$options = $container->getParameter('twig.options');
|
||||
$options = $container->getDefinition('twig')->getArgument(1);
|
||||
$this->assertEquals('filename', $options['autoescape']);
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,6 @@
|
||||
background-color: #f7f7f7;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 38px;
|
||||
margin: 0;
|
||||
padding: 0 40px 0 0;
|
||||
z-index: 6000000;
|
||||
@ -88,6 +87,7 @@
|
||||
color: #2f2f2f;
|
||||
display: block;
|
||||
min-height: 28px;
|
||||
border-bottom: 1px solid #e4e4e4;
|
||||
border-right: 1px solid #e4e4e4;
|
||||
padding: 0;
|
||||
float: left;
|
||||
@ -150,10 +150,6 @@
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
.sf-toolbarreset > div:last-of-type .sf-toolbar-info {
|
||||
right: -1px;
|
||||
}
|
||||
|
||||
.sf-toolbar-block .sf-toolbar-info:empty {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
@ -31,6 +31,30 @@
|
||||
}
|
||||
|
||||
Sfjs.renderAjaxRequests();
|
||||
|
||||
/* Handle toolbar-info position */
|
||||
var toolbarBlocks = document.getElementsByClassName('sf-toolbar-block');
|
||||
for (var i = 0; i < toolbarBlocks.length; i += 1) {
|
||||
toolbarBlocks[i].onmouseover = function () {
|
||||
var toolbarInfo = this.getElementsByClassName('sf-toolbar-info')[0];
|
||||
var pageWidth = document.body.clientWidth;
|
||||
var elementWidth = toolbarInfo.offsetWidth;
|
||||
var leftValue = (elementWidth + this.offsetLeft) - pageWidth;
|
||||
var rightValue = (elementWidth + (pageWidth - this.offsetLeft)) - pageWidth;
|
||||
|
||||
/* Reset right and left value, useful on window resize */
|
||||
toolbarInfo.style.right = '';
|
||||
toolbarInfo.style.left = '';
|
||||
|
||||
if (leftValue > 0 && rightValue > 0) {
|
||||
toolbarInfo.style.right = (rightValue * -1) + 'px';
|
||||
} else if (leftValue < 0) {
|
||||
toolbarInfo.style.left = 0;
|
||||
} else {
|
||||
toolbarInfo.style.right = '-1px';
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
function(xhr) {
|
||||
if (xhr.status !== 0) {
|
||||
|
@ -164,7 +164,7 @@ class TextDescriptor extends Descriptor
|
||||
}
|
||||
|
||||
$this->writeText("<comment>Usage:</comment>\n", $options);
|
||||
$this->writeText(" [options] command [arguments]\n\n", $options);
|
||||
$this->writeText(" command [options] [arguments]\n\n", $options);
|
||||
$this->writeText('<comment>Options:</comment>', $options);
|
||||
|
||||
$inputOptions = $application->getDefinition()->getOptions();
|
||||
|
@ -1,7 +1,7 @@
|
||||
<info>Console Tool</info>
|
||||
|
||||
<comment>Usage:</comment>
|
||||
[options] command [arguments]
|
||||
command [options] [arguments]
|
||||
|
||||
<comment>Options:</comment>
|
||||
<info>--help</info> (-h) Display this help message
|
||||
|
@ -1,7 +1,7 @@
|
||||
<info>My Symfony application</info> version <comment>v1.0</comment>
|
||||
|
||||
<comment>Usage:</comment>
|
||||
[options] command [arguments]
|
||||
command [options] [arguments]
|
||||
|
||||
<comment>Options:</comment>
|
||||
<info>--help</info> (-h) Display this help message
|
||||
|
@ -1,7 +1,7 @@
|
||||
<info>Console Tool</info>
|
||||
|
||||
<comment>Usage:</comment>
|
||||
[options] command [arguments]
|
||||
command [options] [arguments]
|
||||
|
||||
<comment>Options:</comment>
|
||||
<info>--help</info> (-h) Display this help message
|
||||
|
@ -1,7 +1,7 @@
|
||||
<info>Console Tool</info>
|
||||
|
||||
<comment>Usage:</comment>
|
||||
[options] command [arguments]
|
||||
command [options] [arguments]
|
||||
|
||||
<comment>Options:</comment>
|
||||
<info>--help</info> (-h) Display this help message
|
||||
|
@ -1,7 +1,7 @@
|
||||
Console Tool
|
||||
|
||||
Usage:
|
||||
[options] command [arguments]
|
||||
command [options] [arguments]
|
||||
|
||||
Options:
|
||||
--help (-h) Display this help message
|
||||
|
0
src/Symfony/Component/DomCrawler/Crawler.php
Executable file → Normal file
0
src/Symfony/Component/DomCrawler/Crawler.php
Executable file → Normal file
@ -216,7 +216,7 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
|
||||
$this->dispatcher->removeListener($eventName, $listener);
|
||||
$info = $this->getListenerInfo($listener, $eventName);
|
||||
$name = isset($info['class']) ? $info['class'] : $info['type'];
|
||||
$this->dispatcher->addListener($eventName, new WrappedListener($listener, $name, $this->stopwatch));
|
||||
$this->dispatcher->addListener($eventName, new WrappedListener($listener, $name, $this->stopwatch, $this));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,12 +25,14 @@ class WrappedListener
|
||||
private $called;
|
||||
private $stoppedPropagation;
|
||||
private $stopwatch;
|
||||
private $dispatcher;
|
||||
|
||||
public function __construct($listener, $name, Stopwatch $stopwatch)
|
||||
public function __construct($listener, $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null)
|
||||
{
|
||||
$this->listener = $listener;
|
||||
$this->name = $name;
|
||||
$this->stopwatch = $stopwatch;
|
||||
$this->dispatcher = $dispatcher;
|
||||
$this->called = false;
|
||||
$this->stoppedPropagation = false;
|
||||
}
|
||||
@ -56,7 +58,7 @@ class WrappedListener
|
||||
|
||||
$e = $this->stopwatch->start($this->name, 'event_listener');
|
||||
|
||||
call_user_func($this->listener, $event, $eventName, $dispatcher);
|
||||
call_user_func($this->listener, $event, $eventName, $this->dispatcher ?: $dispatcher);
|
||||
|
||||
if ($e->isStarted()) {
|
||||
$e->stop();
|
||||
|
@ -86,6 +86,20 @@ class TraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(array(), $tdispatcher->getNotCalledListeners());
|
||||
}
|
||||
|
||||
public function testGetCalledListenersNested()
|
||||
{
|
||||
$tdispatcher = null;
|
||||
$dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
|
||||
$dispatcher->addListener('foo', function (Event $event, $eventName, $dispatcher) use (&$tdispatcher) {
|
||||
$tdispatcher = $dispatcher;
|
||||
$dispatcher->dispatch('bar');
|
||||
});
|
||||
$dispatcher->addListener('bar', function (Event $event) {});
|
||||
$dispatcher->dispatch('foo');
|
||||
$this->assertSame($dispatcher, $tdispatcher);
|
||||
$this->assertCount(2, $dispatcher->getCalledListeners());
|
||||
}
|
||||
|
||||
public function testLogger()
|
||||
{
|
||||
$logger = $this->getMock('Psr\Log\LoggerInterface');
|
||||
|
@ -389,7 +389,7 @@ class ChoiceList implements ChoiceListInterface
|
||||
*/
|
||||
protected function isPreferred($choice, array $preferredChoices)
|
||||
{
|
||||
return false !== array_search($choice, $preferredChoices, true);
|
||||
return in_array($choice, $preferredChoices, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -110,7 +110,7 @@ class ChoiceType extends AbstractType
|
||||
// avoid making the type check inside the closure.
|
||||
if ($options['multiple']) {
|
||||
$view->vars['is_selected'] = function ($choice, array $values) {
|
||||
return false !== array_search($choice, $values, true);
|
||||
return in_array($choice, $values, true);
|
||||
};
|
||||
} else {
|
||||
$view->vars['is_selected'] = function ($choice, $value) {
|
||||
|
@ -1,19 +1,19 @@
|
||||
<?xml version="1.0"?>
|
||||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<file source-language="en" datatype="plaintext" original="file.ext">
|
||||
<body>
|
||||
<trans-unit id="28">
|
||||
<source>This form should not contain extra fields.</source>
|
||||
<target>Тази форма не трябва да съдържа допълнителни полета.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="29">
|
||||
<source>The uploaded file was too large. Please try to upload a smaller file.</source>
|
||||
<target>Каченият файл е твърде голям. Моля, опитайте да качите по-малък файл.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="30">
|
||||
<source>The CSRF token is invalid. Please try to resubmit the form.</source>
|
||||
<target>Невалиден CSRF токен. Моля, опитайте да изпратите формата отново.</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
<?xml version="1.0"?>
|
||||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<file source-language="en" datatype="plaintext" original="file.ext">
|
||||
<body>
|
||||
<trans-unit id="28">
|
||||
<source>This form should not contain extra fields.</source>
|
||||
<target>Тази форма не трябва да съдържа допълнителни полета.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="29">
|
||||
<source>The uploaded file was too large. Please try to upload a smaller file.</source>
|
||||
<target>Каченият файл е твърде голям. Моля, опитайте да качите по-малък файл.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="30">
|
||||
<source>The CSRF token is invalid. Please try to resubmit the form.</source>
|
||||
<target>Невалиден CSRF токен. Моля, опитайте да изпратите формата отново.</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
@ -1951,7 +1951,7 @@ class Request
|
||||
|
||||
$len = strlen($prefix);
|
||||
|
||||
if (preg_match("#^(%[[:xdigit:]]{2}|.){{$len}}#", $string, $match)) {
|
||||
if (preg_match(sprintf('#^(%%[[:xdigit:]]{2}|.){%d}#', $len), $string, $match)) {
|
||||
return $match[0];
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,6 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
|
||||
*
|
||||
* @see http://php.net/sessionhandler
|
||||
*/
|
||||
|
||||
class NativeSessionHandler extends \SessionHandler
|
||||
{
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Stopwatch\Stopwatch;
|
||||
use Symfony\Component\VarDumper\Cloner\Data;
|
||||
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||
use Symfony\Component\VarDumper\Dumper\CliDumper;
|
||||
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
|
||||
use Symfony\Component\VarDumper\Dumper\DataDumperInterface;
|
||||
@ -31,11 +32,13 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
private $clonesCount = 0;
|
||||
private $clonesIndex = 0;
|
||||
private $rootRefs;
|
||||
private $charset;
|
||||
|
||||
public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null)
|
||||
public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null, $charset = null)
|
||||
{
|
||||
$this->stopwatch = $stopwatch;
|
||||
$this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
|
||||
$this->charset = $charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8';
|
||||
|
||||
// All clones share these properties by reference:
|
||||
$this->rootRefs = array(
|
||||
@ -93,7 +96,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
$fileExcerpt = array();
|
||||
|
||||
for ($i = max($line - 3, 1), $max = min($line + 3, count($src)); $i <= $max; ++$i) {
|
||||
$fileExcerpt[] = '<li'.($i === $line ? ' class="selected"' : '').'><code>'.htmlspecialchars($src[$i - 1]).'</code></li>';
|
||||
$fileExcerpt[] = '<li'.($i === $line ? ' class="selected"' : '').'><code>'.$this->htmlEncode($src[$i - 1]).'</code></li>';
|
||||
}
|
||||
|
||||
$fileExcerpt = '<ol start="'.max($line - 3, 1).'">'.implode("\n", $fileExcerpt).'</ol>';
|
||||
@ -153,7 +156,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
$data = fopen('php://memory', 'r+b');
|
||||
|
||||
if ('html' === $format) {
|
||||
$dumper = new HtmlDumper($data);
|
||||
$dumper = new HtmlDumper($data, $this->charset);
|
||||
} else {
|
||||
throw new \InvalidArgumentException(sprintf('Invalid dump format: %s', $format));
|
||||
}
|
||||
@ -190,10 +193,9 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
}
|
||||
|
||||
if ('cli' !== PHP_SAPI && stripos($h[$i], 'html')) {
|
||||
echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
|
||||
$dumper = new HtmlDumper('php://output');
|
||||
$dumper = new HtmlDumper('php://output', $this->charset);
|
||||
} else {
|
||||
$dumper = new CliDumper('php://output');
|
||||
$dumper = new CliDumper('php://output', $this->charset);
|
||||
$dumper->setColors(false);
|
||||
}
|
||||
|
||||
@ -201,8 +203,8 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
$this->data[$i] = null;
|
||||
|
||||
if ($dumper instanceof HtmlDumper) {
|
||||
$dump['name'] = htmlspecialchars($dump['name'], ENT_QUOTES, 'UTF-8');
|
||||
$dump['file'] = htmlspecialchars($dump['file'], ENT_QUOTES, 'UTF-8');
|
||||
$dump['name'] = $this->htmlEncode($dump['name']);
|
||||
$dump['file'] = $this->htmlEncode($dump['file']);
|
||||
if ('' !== $dump['file']) {
|
||||
if ($this->fileLinkFormat) {
|
||||
$link = strtr($this->fileLinkFormat, array('%f' => $dump['file'], '%l' => $dump['line']));
|
||||
@ -222,4 +224,18 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
$this->dataCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private function htmlEncode($s)
|
||||
{
|
||||
$html = '';
|
||||
|
||||
$dumper = new HtmlDumper(function ($line) use (&$html) {$html .= $line;}, $this->charset);
|
||||
$dumper->setDumpHeader('');
|
||||
$dumper->setDumpBoundaries('', '');
|
||||
|
||||
$cloner = new VarCloner();
|
||||
$dumper->dump($cloner->cloneVar($s));
|
||||
|
||||
return substr(strip_tags($html), 1, -1);
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ namespace Symfony\Component\HttpKernel\Exception;
|
||||
|
||||
trigger_error('The '.__NAMESPACE__.'\FatalErrorException class is deprecated since version 2.3 and will be removed in 3.0. Use the Symfony\Component\Debug\Exception\FatalErrorException class instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
/*
|
||||
* Fatal Error Exception.
|
||||
*
|
||||
* @author Konstanton Myakshin <koc-dp@yandex.ru>
|
||||
|
@ -13,7 +13,7 @@ namespace Symfony\Component\HttpKernel\Exception;
|
||||
|
||||
trigger_error('The '.__NAMESPACE__.'\FlattenException class is deprecated since version 2.3 and will be removed in 3.0. Use the Symfony\Component\Debug\Exception\FlattenException class instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
/*
|
||||
* FlattenException wraps a PHP Exception to be able to serialize it.
|
||||
*
|
||||
* Basically, this class removes all objects from the trace.
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Tests;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\HttpKernel\Config\EnvParametersResource;
|
||||
use Symfony\Component\HttpKernel\Kernel;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
@ -113,7 +114,7 @@ class KernelTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testEnvParametersResourceIsAdded()
|
||||
{
|
||||
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
|
||||
$container = new ContainerBuilder();
|
||||
$kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(array('getContainerBuilder', 'prepareContainer', 'getCacheDir', 'getLogDir'))
|
||||
@ -130,14 +131,21 @@ class KernelTest extends \PHPUnit_Framework_TestCase
|
||||
$kernel->expects($this->any())
|
||||
->method('getLogDir')
|
||||
->will($this->returnValue(sys_get_temp_dir()));
|
||||
$container->expects($this->once())
|
||||
->method('addResource')
|
||||
->with(new EnvParametersResource('SYMFONY__'));
|
||||
|
||||
$reflection = new \ReflectionClass(get_class($kernel));
|
||||
$method = $reflection->getMethod('buildContainer');
|
||||
$method->setAccessible(true);
|
||||
$method->invoke($kernel);
|
||||
|
||||
$found = false;
|
||||
foreach ($container->getResources() as $resource) {
|
||||
if ($resource instanceof EnvParametersResource) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertTrue($found);
|
||||
}
|
||||
|
||||
public function testBootKernelSeveralTimesOnlyInitializesBundlesOnce()
|
||||
|
@ -504,7 +504,19 @@ class OptionsResolver2Dot6Test extends \PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testResolveFailsIfInvalidType()
|
||||
{
|
||||
$this->resolver->setDefault('foo', 42);
|
||||
$this->resolver->setDefined('foo');
|
||||
$this->resolver->setAllowedTypes('foo', 'string');
|
||||
|
||||
$this->resolver->resolve(array('foo' => 42));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
|
||||
* @expectedExceptionMessage The option "foo" with value null is expected to be of type "string", but is of type "NULL".
|
||||
*/
|
||||
public function testResolveFailsIfInvalidTypeIsNull()
|
||||
{
|
||||
$this->resolver->setDefault('foo', null);
|
||||
$this->resolver->setAllowedTypes('foo', 'string');
|
||||
|
||||
$this->resolver->resolve();
|
||||
@ -675,7 +687,19 @@ class OptionsResolver2Dot6Test extends \PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testResolveFailsIfInvalidValue()
|
||||
{
|
||||
$this->resolver->setDefault('foo', 42);
|
||||
$this->resolver->setDefined('foo');
|
||||
$this->resolver->setAllowedValues('foo', 'bar');
|
||||
|
||||
$this->resolver->resolve(array('foo' => 42));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
|
||||
* @expectedExceptionMessage The option "foo" with value null is invalid. Accepted values are: "bar".
|
||||
*/
|
||||
public function testResolveFailsIfInvalidValueIsNull()
|
||||
{
|
||||
$this->resolver->setDefault('foo', null);
|
||||
$this->resolver->setAllowedValues('foo', 'bar');
|
||||
|
||||
$this->resolver->resolve();
|
||||
|
@ -841,13 +841,13 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testStartAfterATimeout()
|
||||
{
|
||||
$process = $this->getProcess('php -r "$n = 1000; while ($n--) {echo \'\'; usleep(1000); }"');
|
||||
$process = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n = 1000; while ($n--) {echo \'\'; usleep(1000); }')));
|
||||
$process->setTimeout(0.1);
|
||||
|
||||
try {
|
||||
$process->run();
|
||||
$this->fail('An exception should have been raised.');
|
||||
} catch (\Exception $e) {
|
||||
$this->fail('A RuntimeException should have been raised.');
|
||||
} catch (RuntimeException $e) {
|
||||
}
|
||||
$process->start();
|
||||
usleep(1000);
|
||||
|
@ -1,6 +1,12 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
2.7.0
|
||||
------
|
||||
|
||||
* `UnexpectedTypeException` now expects three constructor arguments: The invalid property value,
|
||||
the `PropertyPathInterface` object and the current index of the property path.
|
||||
|
||||
2.5.0
|
||||
------
|
||||
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\PropertyAccess\Exception;
|
||||
|
||||
use Symfony\Component\PropertyAccess\PropertyPathInterface;
|
||||
|
||||
/**
|
||||
* Thrown when a value does not match an expected type.
|
||||
*
|
||||
@ -18,8 +20,31 @@ namespace Symfony\Component\PropertyAccess\Exception;
|
||||
*/
|
||||
class UnexpectedTypeException extends RuntimeException
|
||||
{
|
||||
public function __construct($value, $expectedType)
|
||||
/**
|
||||
* @param mixed $value The unexpected value found while traversing property path
|
||||
* @param PropertyPathInterface $path The property path
|
||||
* @param int $pathIndex The property path index when the unexpected value was found
|
||||
*/
|
||||
public function __construct($value, $path, $pathIndex = null)
|
||||
{
|
||||
parent::__construct(sprintf('Expected argument of type "%s", "%s" given', $expectedType, is_object($value) ? get_class($value) : gettype($value)));
|
||||
if (func_num_args() === 3 && $path instanceof PropertyPathInterface) {
|
||||
$message = sprintf(
|
||||
'PropertyAccessor requires a graph of objects or arrays to operate on, '.
|
||||
'but it found type "%s" while trying to traverse path "%s" at property "%s".',
|
||||
gettype($value),
|
||||
(string) $path,
|
||||
$path->getElement($pathIndex)
|
||||
);
|
||||
} else {
|
||||
trigger_error('The '.__CLASS__.' constructor now expects 3 arguments: the invalid property value, the '.__NAMESPACE__.'\PropertyPathInterface object and the current index of the property path.', E_USER_DEPRECATED);
|
||||
|
||||
$message = sprintf(
|
||||
'Expected argument of type "%s", "%s" given',
|
||||
$path,
|
||||
is_object($value) ? get_class($value) : gettype($value)
|
||||
);
|
||||
}
|
||||
|
||||
parent::__construct($message);
|
||||
}
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ class PropertyAccessor implements PropertyAccessorInterface
|
||||
|
||||
if ($overwrite) {
|
||||
if (!is_object($objectOrArray) && !is_array($objectOrArray)) {
|
||||
throw new UnexpectedTypeException($objectOrArray, 'object or array');
|
||||
throw new UnexpectedTypeException($objectOrArray, $propertyPath, $i);
|
||||
}
|
||||
|
||||
$property = $propertyPath->getElement($i);
|
||||
@ -221,7 +221,7 @@ class PropertyAccessor implements PropertyAccessorInterface
|
||||
|
||||
for ($i = 0; $i < $lastIndex; ++$i) {
|
||||
if (!is_object($objectOrArray) && !is_array($objectOrArray)) {
|
||||
throw new UnexpectedTypeException($objectOrArray, 'object or array');
|
||||
throw new UnexpectedTypeException($objectOrArray, $propertyPath, $i);
|
||||
}
|
||||
|
||||
$property = $propertyPath->getElement($i);
|
||||
|
@ -11,9 +11,9 @@
|
||||
|
||||
namespace Symfony\Component\PropertyAccess;
|
||||
|
||||
use Symfony\Component\PropertyAccess\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\PropertyAccess\Exception\InvalidPropertyPathException;
|
||||
use Symfony\Component\PropertyAccess\Exception\OutOfBoundsException;
|
||||
use Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link PropertyPathInterface}.
|
||||
@ -70,7 +70,7 @@ class PropertyPath implements \IteratorAggregate, PropertyPathInterface
|
||||
*
|
||||
* @param PropertyPath|string $propertyPath The property path as string or instance
|
||||
*
|
||||
* @throws UnexpectedTypeException If the given path is not a string
|
||||
* @throws InvalidArgumentException If the given path is not a string
|
||||
* @throws InvalidPropertyPathException If the syntax of the property path is not valid
|
||||
*/
|
||||
public function __construct($propertyPath)
|
||||
@ -87,7 +87,12 @@ class PropertyPath implements \IteratorAggregate, PropertyPathInterface
|
||||
return;
|
||||
}
|
||||
if (!is_string($propertyPath)) {
|
||||
throw new UnexpectedTypeException($propertyPath, 'string or Symfony\Component\PropertyAccess\PropertyPath');
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'The property path constructor needs a string or an instance of '.
|
||||
'"Symfony\Component\PropertyAccess\PropertyPath". '.
|
||||
'Got: "%s"',
|
||||
is_object($propertyPath) ? get_class($propertyPath) : gettype($propertyPath)
|
||||
));
|
||||
}
|
||||
|
||||
if ('' === $propertyPath) {
|
||||
|
@ -139,6 +139,7 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException
|
||||
* @expectedExceptionMessage PropertyAccessor requires a graph of objects or arrays to operate on, but it found type "string" while trying to traverse path "foobar" at property "foobar".
|
||||
*/
|
||||
public function testGetValueThrowsExceptionIfNotObjectOrArray()
|
||||
{
|
||||
@ -147,6 +148,7 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException
|
||||
* @expectedExceptionMessage PropertyAccessor requires a graph of objects or arrays to operate on, but it found type "NULL" while trying to traverse path "foobar" at property "foobar".
|
||||
*/
|
||||
public function testGetValueThrowsExceptionIfNull()
|
||||
{
|
||||
@ -155,12 +157,22 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException
|
||||
* @expectedExceptionMessage PropertyAccessor requires a graph of objects or arrays to operate on, but it found type "string" while trying to traverse path "foobar" at property "foobar".
|
||||
*/
|
||||
public function testGetValueThrowsExceptionIfEmpty()
|
||||
{
|
||||
$this->propertyAccessor->getValue('', 'foobar');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException
|
||||
* @expectedExceptionMessage PropertyAccessor requires a graph of objects or arrays to operate on, but it found type "NULL" while trying to traverse path "foobar.baz" at property "baz".
|
||||
*/
|
||||
public function testGetValueNestedExceptionMessage()
|
||||
{
|
||||
$this->propertyAccessor->getValue((object) array('foobar' => null), 'foobar.baz');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getValidPropertyPaths
|
||||
*/
|
||||
@ -249,6 +261,7 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException
|
||||
* @expectedExceptionMessage PropertyAccessor requires a graph of objects or arrays to operate on, but it found type "string" while trying to traverse path "foobar" at property "foobar".
|
||||
*/
|
||||
public function testSetValueThrowsExceptionIfNotObjectOrArray()
|
||||
{
|
||||
@ -259,6 +272,7 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException
|
||||
* @expectedExceptionMessage PropertyAccessor requires a graph of objects or arrays to operate on, but it found type "NULL" while trying to traverse path "foobar" at property "foobar".
|
||||
*/
|
||||
public function testSetValueThrowsExceptionIfNull()
|
||||
{
|
||||
@ -269,6 +283,7 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException
|
||||
* @expectedExceptionMessage PropertyAccessor requires a graph of objects or arrays to operate on, but it found type "string" while trying to traverse path "foobar" at property "foobar".
|
||||
*/
|
||||
public function testSetValueThrowsExceptionIfEmpty()
|
||||
{
|
||||
@ -277,6 +292,17 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
|
||||
$this->propertyAccessor->setValue($value, 'foobar', 'bam');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException
|
||||
* @expectedExceptionMessage PropertyAccessor requires a graph of objects or arrays to operate on, but it found type "NULL" while trying to traverse path "foobar.baz" at property "baz".
|
||||
*/
|
||||
public function testSetValueNestedExceptionMessage()
|
||||
{
|
||||
$value = (object) array('foobar' => null);
|
||||
|
||||
$this->propertyAccessor->setValue($value, 'foobar.baz', 'bam');
|
||||
}
|
||||
|
||||
public function testGetValueWhenArrayValueIsNull()
|
||||
{
|
||||
$this->propertyAccessor = new PropertyAccessor(false, true);
|
||||
|
@ -69,7 +69,7 @@ class PropertyPathTest extends \PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException
|
||||
* @expectedException \Symfony\Component\PropertyAccess\Exception\InvalidArgumentException
|
||||
*/
|
||||
public function testPathCannotBeNull()
|
||||
{
|
||||
@ -77,7 +77,7 @@ class PropertyPathTest extends \PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException
|
||||
* @expectedException \Symfony\Component\PropertyAccess\Exception\InvalidArgumentException
|
||||
*/
|
||||
public function testPathCannotBeFalse()
|
||||
{
|
||||
|
@ -225,7 +225,7 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt
|
||||
$routeHost = '';
|
||||
foreach ($hostTokens as $token) {
|
||||
if ('variable' === $token[0]) {
|
||||
if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#', $mergedParams[$token[3]])) {
|
||||
if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#i', $mergedParams[$token[3]])) {
|
||||
$message = sprintf('Parameter "%s" for route "%s" must match "%s" ("%s" given) to generate a corresponding URL.', $token[3], $name, $token[2], $mergedParams[$token[3]]);
|
||||
|
||||
if ($this->strictRequirements) {
|
||||
|
@ -46,7 +46,7 @@ class RouteCompiler implements RouteCompilerInterface
|
||||
$result = self::compilePattern($route, $host, true);
|
||||
|
||||
$hostVariables = $result['variables'];
|
||||
$variables = array_merge($variables, $hostVariables);
|
||||
$variables = $hostVariables;
|
||||
|
||||
$hostTokens = $result['tokens'];
|
||||
$hostRegex = $result['regex'];
|
||||
@ -163,7 +163,7 @@ class RouteCompiler implements RouteCompilerInterface
|
||||
|
||||
return array(
|
||||
'staticPrefix' => 'text' === $tokens[0][0] ? $tokens[0][1] : '',
|
||||
'regex' => self::REGEX_DELIMITER.'^'.$regexp.'$'.self::REGEX_DELIMITER.'s',
|
||||
'regex' => self::REGEX_DELIMITER.'^'.$regexp.'$'.self::REGEX_DELIMITER.'s'.($isHost ? 'i' : ''),
|
||||
'tokens' => array_reverse($tokens),
|
||||
'variables' => $variables,
|
||||
);
|
||||
|
@ -197,7 +197,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
|
||||
$host = $this->context->getHost();
|
||||
|
||||
if (preg_match('#^a\\.example\\.com$#s', $host, $hostMatches)) {
|
||||
if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) {
|
||||
// route1
|
||||
if ($pathinfo === '/route1') {
|
||||
return array('_route' => 'route1');
|
||||
@ -210,7 +210,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
|
||||
}
|
||||
|
||||
if (preg_match('#^b\\.example\\.com$#s', $host, $hostMatches)) {
|
||||
if (preg_match('#^b\\.example\\.com$#si', $host, $hostMatches)) {
|
||||
// route3
|
||||
if ($pathinfo === '/c2/route3') {
|
||||
return array('_route' => 'route3');
|
||||
@ -218,7 +218,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
|
||||
}
|
||||
|
||||
if (preg_match('#^a\\.example\\.com$#s', $host, $hostMatches)) {
|
||||
if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) {
|
||||
// route4
|
||||
if ($pathinfo === '/route4') {
|
||||
return array('_route' => 'route4');
|
||||
@ -226,7 +226,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
|
||||
}
|
||||
|
||||
if (preg_match('#^c\\.example\\.com$#s', $host, $hostMatches)) {
|
||||
if (preg_match('#^c\\.example\\.com$#si', $host, $hostMatches)) {
|
||||
// route5
|
||||
if ($pathinfo === '/route5') {
|
||||
return array('_route' => 'route5');
|
||||
@ -239,7 +239,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
return array('_route' => 'route6');
|
||||
}
|
||||
|
||||
if (preg_match('#^(?P<var1>[^\\.]++)\\.example\\.com$#s', $host, $hostMatches)) {
|
||||
if (preg_match('#^(?P<var1>[^\\.]++)\\.example\\.com$#si', $host, $hostMatches)) {
|
||||
if (0 === strpos($pathinfo, '/route1')) {
|
||||
// route11
|
||||
if ($pathinfo === '/route11') {
|
||||
@ -265,7 +265,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
|
||||
}
|
||||
|
||||
if (preg_match('#^c\\.example\\.com$#s', $host, $hostMatches)) {
|
||||
if (preg_match('#^c\\.example\\.com$#si', $host, $hostMatches)) {
|
||||
// route15
|
||||
if (0 === strpos($pathinfo, '/route15') && preg_match('#^/route15/(?P<name>[^/]++)$#s', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'route15')), array ());
|
||||
|
@ -209,7 +209,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
|
||||
$host = $this->context->getHost();
|
||||
|
||||
if (preg_match('#^a\\.example\\.com$#s', $host, $hostMatches)) {
|
||||
if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) {
|
||||
// route1
|
||||
if ($pathinfo === '/route1') {
|
||||
return array('_route' => 'route1');
|
||||
@ -222,7 +222,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
|
||||
}
|
||||
|
||||
if (preg_match('#^b\\.example\\.com$#s', $host, $hostMatches)) {
|
||||
if (preg_match('#^b\\.example\\.com$#si', $host, $hostMatches)) {
|
||||
// route3
|
||||
if ($pathinfo === '/c2/route3') {
|
||||
return array('_route' => 'route3');
|
||||
@ -230,7 +230,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
|
||||
}
|
||||
|
||||
if (preg_match('#^a\\.example\\.com$#s', $host, $hostMatches)) {
|
||||
if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) {
|
||||
// route4
|
||||
if ($pathinfo === '/route4') {
|
||||
return array('_route' => 'route4');
|
||||
@ -238,7 +238,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
|
||||
}
|
||||
|
||||
if (preg_match('#^c\\.example\\.com$#s', $host, $hostMatches)) {
|
||||
if (preg_match('#^c\\.example\\.com$#si', $host, $hostMatches)) {
|
||||
// route5
|
||||
if ($pathinfo === '/route5') {
|
||||
return array('_route' => 'route5');
|
||||
@ -251,7 +251,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
return array('_route' => 'route6');
|
||||
}
|
||||
|
||||
if (preg_match('#^(?P<var1>[^\\.]++)\\.example\\.com$#s', $host, $hostMatches)) {
|
||||
if (preg_match('#^(?P<var1>[^\\.]++)\\.example\\.com$#si', $host, $hostMatches)) {
|
||||
if (0 === strpos($pathinfo, '/route1')) {
|
||||
// route11
|
||||
if ($pathinfo === '/route11') {
|
||||
@ -277,7 +277,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
|
||||
}
|
||||
|
||||
if (preg_match('#^c\\.example\\.com$#s', $host, $hostMatches)) {
|
||||
if (preg_match('#^c\\.example\\.com$#si', $host, $hostMatches)) {
|
||||
// route15
|
||||
if (0 === strpos($pathinfo, '/route15') && preg_match('#^/route15/(?P<name>[^/]++)$#s', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'route15')), array ());
|
||||
|
@ -449,6 +449,33 @@ class UrlGeneratorTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertNull($generator->generate('test', array('foo' => 'baz'), false));
|
||||
}
|
||||
|
||||
public function testHostIsCaseInsensitive()
|
||||
{
|
||||
$routes = $this->getRoutes('test', new Route('/', array(), array('locale' => 'en|de|fr'), array(), '{locale}.FooBar.com'));
|
||||
$generator = $this->getGenerator($routes);
|
||||
$this->assertSame('//EN.FooBar.com/app.php/', $generator->generate('test', array('locale' => 'EN'), UrlGeneratorInterface::NETWORK_PATH));
|
||||
}
|
||||
|
||||
public function testLegacyGenerateNetworkPath()
|
||||
{
|
||||
$this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED);
|
||||
|
||||
$routes = $this->getRoutes('test', new Route('/{name}', array(), array('_scheme' => 'http'), array(), '{locale}.example.com'));
|
||||
|
||||
$this->assertSame('//fr.example.com/app.php/Fabien', $this->getGenerator($routes)->generate('test',
|
||||
array('name' => 'Fabien', 'locale' => 'fr'), UrlGeneratorInterface::NETWORK_PATH), 'network path with different host'
|
||||
);
|
||||
$this->assertSame('//fr.example.com/app.php/Fabien?query=string', $this->getGenerator($routes, array('host' => 'fr.example.com'))->generate('test',
|
||||
array('name' => 'Fabien', 'locale' => 'fr', 'query' => 'string'), UrlGeneratorInterface::NETWORK_PATH), 'network path although host same as context'
|
||||
);
|
||||
$this->assertSame('http://fr.example.com/app.php/Fabien', $this->getGenerator($routes, array('scheme' => 'https'))->generate('test',
|
||||
array('name' => 'Fabien', 'locale' => 'fr'), UrlGeneratorInterface::NETWORK_PATH), 'absolute URL because scheme requirement does not match context'
|
||||
);
|
||||
$this->assertSame('http://fr.example.com/app.php/Fabien', $this->getGenerator($routes)->generate('test',
|
||||
array('name' => 'Fabien', 'locale' => 'fr'), UrlGeneratorInterface::ABSOLUTE_URL), 'absolute URL with same scheme because it is requested'
|
||||
);
|
||||
}
|
||||
|
||||
public function testGenerateNetworkPath()
|
||||
{
|
||||
$routes = $this->getRoutes('test', new Route('/{name}', array(), array(), array(), '{locale}.example.com', array('http')));
|
||||
|
@ -395,4 +395,25 @@ class UrlMatcherTest extends \PHPUnit_Framework_TestCase
|
||||
$matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'example.com'));
|
||||
$matcher->match('/foo/bar');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
|
||||
*/
|
||||
public function testPathIsCaseSensitive()
|
||||
{
|
||||
$coll = new RouteCollection();
|
||||
$coll->add('foo', new Route('/locale', array(), array('locale' => 'EN|FR|DE')));
|
||||
|
||||
$matcher = new UrlMatcher($coll, new RequestContext());
|
||||
$matcher->match('/en');
|
||||
}
|
||||
|
||||
public function testHostIsCaseInsensitive()
|
||||
{
|
||||
$coll = new RouteCollection();
|
||||
$coll->add('foo', new Route('/', array(), array('locale' => 'EN|FR|DE'), array(), '{locale}.example.com'));
|
||||
|
||||
$matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com'));
|
||||
$this->assertEquals(array('_route' => 'foo', 'locale' => 'en'), $matcher->match('/'));
|
||||
}
|
||||
}
|
||||
|
@ -208,7 +208,7 @@ class RouteCompilerTest extends \PHPUnit_Framework_TestCase
|
||||
'/hello', '#^/hello$#s', array(), array(), array(
|
||||
array('text', '/hello'),
|
||||
),
|
||||
'#^www\.example\.com$#s', array(), array(
|
||||
'#^www\.example\.com$#si', array(), array(
|
||||
array('text', 'www.example.com'),
|
||||
),
|
||||
),
|
||||
@ -219,7 +219,7 @@ class RouteCompilerTest extends \PHPUnit_Framework_TestCase
|
||||
array('variable', '/', '[^/]++', 'name'),
|
||||
array('text', '/hello'),
|
||||
),
|
||||
'#^www\.example\.(?P<tld>[^\.]++)$#s', array('tld'), array(
|
||||
'#^www\.example\.(?P<tld>[^\.]++)$#si', array('tld'), array(
|
||||
array('variable', '.', '[^\.]++', 'tld'),
|
||||
array('text', 'www.example'),
|
||||
),
|
||||
@ -230,7 +230,7 @@ class RouteCompilerTest extends \PHPUnit_Framework_TestCase
|
||||
'/hello', '#^/hello$#s', array('locale', 'tld'), array(), array(
|
||||
array('text', '/hello'),
|
||||
),
|
||||
'#^(?P<locale>[^\.]++)\.example\.(?P<tld>[^\.]++)$#s', array('locale', 'tld'), array(
|
||||
'#^(?P<locale>[^\.]++)\.example\.(?P<tld>[^\.]++)$#si', array('locale', 'tld'), array(
|
||||
array('variable', '.', '[^\.]++', 'tld'),
|
||||
array('text', '.example'),
|
||||
array('variable', '', '[^\.]++', 'locale'),
|
||||
@ -242,7 +242,7 @@ class RouteCompilerTest extends \PHPUnit_Framework_TestCase
|
||||
'/hello', '#^/hello$#s', array('locale', 'tld'), array(), array(
|
||||
array('text', '/hello'),
|
||||
),
|
||||
'#^(?P<locale>[^\.]++)\.example\.(?P<tld>[^\.]++)$#s', array('locale', 'tld'), array(
|
||||
'#^(?P<locale>[^\.]++)\.example\.(?P<tld>[^\.]++)$#si', array('locale', 'tld'), array(
|
||||
array('variable', '.', '[^\.]++', 'tld'),
|
||||
array('text', '.example'),
|
||||
array('variable', '', '[^\.]++', 'locale'),
|
||||
|
@ -226,7 +226,7 @@ class RouteTest extends \PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testSerializedRepresentationKeepsWorking()
|
||||
{
|
||||
$serialized = 'C:31:"Symfony\Component\Routing\Route":933:{a:8:{s:4:"path";s:13:"/prefix/{foo}";s:4:"host";s:20:"{locale}.example.net";s:8:"defaults";a:1:{s:3:"foo";s:7:"default";}s:12:"requirements";a:1:{s:3:"foo";s:3:"\d+";}s:7:"options";a:1:{s:14:"compiler_class";s:39:"Symfony\Component\Routing\RouteCompiler";}s:7:"schemes";a:0:{}s:7:"methods";a:0:{}s:8:"compiled";C:39:"Symfony\Component\Routing\CompiledRoute":568:{a:8:{s:4:"vars";a:2:{i:0;s:6:"locale";i:1;s:3:"foo";}s:11:"path_prefix";s:7:"/prefix";s:10:"path_regex";s:30:"#^/prefix(?:/(?P<foo>\d+))?$#s";s:11:"path_tokens";a:2:{i:0;a:4:{i:0;s:8:"variable";i:1;s:1:"/";i:2;s:3:"\d+";i:3;s:3:"foo";}i:1;a:2:{i:0;s:4:"text";i:1;s:7:"/prefix";}}s:9:"path_vars";a:1:{i:0;s:3:"foo";}s:10:"host_regex";s:38:"#^(?P<locale>[^\.]++)\.example\.net$#s";s:11:"host_tokens";a:2:{i:0;a:2:{i:0;s:4:"text";i:1;s:12:".example.net";}i:1;a:4:{i:0;s:8:"variable";i:1;s:0:"";i:2;s:7:"[^\.]++";i:3;s:6:"locale";}}s:9:"host_vars";a:1:{i:0;s:6:"locale";}}}}}';
|
||||
$serialized = 'C:31:"Symfony\Component\Routing\Route":934:{a:8:{s:4:"path";s:13:"/prefix/{foo}";s:4:"host";s:20:"{locale}.example.net";s:8:"defaults";a:1:{s:3:"foo";s:7:"default";}s:12:"requirements";a:1:{s:3:"foo";s:3:"\d+";}s:7:"options";a:1:{s:14:"compiler_class";s:39:"Symfony\Component\Routing\RouteCompiler";}s:7:"schemes";a:0:{}s:7:"methods";a:0:{}s:8:"compiled";C:39:"Symfony\Component\Routing\CompiledRoute":569:{a:8:{s:4:"vars";a:2:{i:0;s:6:"locale";i:1;s:3:"foo";}s:11:"path_prefix";s:7:"/prefix";s:10:"path_regex";s:30:"#^/prefix(?:/(?P<foo>\d+))?$#s";s:11:"path_tokens";a:2:{i:0;a:4:{i:0;s:8:"variable";i:1;s:1:"/";i:2;s:3:"\d+";i:3;s:3:"foo";}i:1;a:2:{i:0;s:4:"text";i:1;s:7:"/prefix";}}s:9:"path_vars";a:1:{i:0;s:3:"foo";}s:10:"host_regex";s:39:"#^(?P<locale>[^\.]++)\.example\.net$#si";s:11:"host_tokens";a:2:{i:0;a:2:{i:0;s:4:"text";i:1;s:12:".example.net";}i:1;a:4:{i:0;s:8:"variable";i:1;s:0:"";i:2;s:7:"[^\.]++";i:3;s:6:"locale";}}s:9:"host_vars";a:1:{i:0;s:6:"locale";}}}}}';
|
||||
$unserialized = unserialize($serialized);
|
||||
|
||||
$route = new Route('/prefix/{foo}', array('foo' => 'default'), array('foo' => '\d+'));
|
||||
|
@ -60,7 +60,7 @@ class SecurityContext implements SecurityContextInterface
|
||||
}
|
||||
|
||||
if ($oldSignature) {
|
||||
// renamed for clearity
|
||||
// renamed for clarity
|
||||
$authenticationManager = $tokenStorage;
|
||||
$accessDecisionManager = $authorizationChecker;
|
||||
$tokenStorage = new TokenStorage();
|
||||
|
@ -1,11 +1,26 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
2.7.0
|
||||
-----
|
||||
|
||||
* added support for serialization and deserialization groups including
|
||||
annotations, XML and YAML mapping.
|
||||
* added `AbstractNormalizer` to factorise code and ease normalizers development
|
||||
* added circular references handling for `PropertyNormalizer`
|
||||
* added support for a context key called `object_to_populate` in `AbstractNormalizer`
|
||||
to reuse existing objects in the deserialization process
|
||||
* added `NameConverterInterface` and `CamelCaseToSnakeCaseNameConverter`
|
||||
* [DEPRECATION] `GetSetMethodNormalizer::setCamelizedAttributes()` and
|
||||
`PropertyNormalizer::setCamelizedAttributes()` are replaced by
|
||||
`CamelCaseToSnakeCaseNameConverter`
|
||||
|
||||
2.6.0
|
||||
-----
|
||||
|
||||
* added a new serializer: `PropertyNormalizer`. Like `GetSetMethodNormalizer`,
|
||||
this normalizer will map an object's properties to an array.
|
||||
* added circular references handling for `GetSetMethodNormalizer`
|
||||
|
||||
2.5.0
|
||||
-----
|
||||
|
@ -374,11 +374,9 @@ class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, Dec
|
||||
} elseif ($key === '#') {
|
||||
$append = $this->selectNodeType($parentNode, $data);
|
||||
} elseif (is_array($data) && false === is_numeric($key)) {
|
||||
/**
|
||||
* Is this array fully numeric keys?
|
||||
*/
|
||||
// Is this array fully numeric keys?
|
||||
if (ctype_digit(implode('', array_keys($data)))) {
|
||||
/**
|
||||
/*
|
||||
* Create nodes to append to $parentNode based on the $key of this array
|
||||
* Produces <xml><item>0</item><item>1</item></xml>
|
||||
* From array("item" => array(0,1));.
|
||||
|
@ -86,12 +86,12 @@ class ClassMetadataFactory
|
||||
|
||||
$reflClass = $metadata->getReflectionClass();
|
||||
|
||||
// Include constraints from the parent class
|
||||
// Include groups from the parent class
|
||||
if ($parent = $reflClass->getParentClass()) {
|
||||
$metadata->mergeAttributesGroups($this->getMetadataFor($parent->name));
|
||||
}
|
||||
|
||||
// Include constraints from all implemented interfaces
|
||||
// Include groups from all implemented interfaces
|
||||
foreach ($reflClass->getInterfaces() as $interface) {
|
||||
$metadata->mergeAttributesGroups($this->getMetadataFor($interface->name));
|
||||
}
|
||||
|
@ -0,0 +1,82 @@
|
||||
<?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 Symfony\Component\Serializer\NameConverter;
|
||||
|
||||
/**
|
||||
* CamelCase to Underscore name converter.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class CamelCaseToSnakeCaseNameConverter implements NameConverterInterface
|
||||
{
|
||||
/**
|
||||
* @var array|null
|
||||
*/
|
||||
private $attributes;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $lowerCamelCase;
|
||||
|
||||
/**
|
||||
* @param null|array $attributes The list of attributes to rename or null for all attributes.
|
||||
* @param bool $lowerCamelCase Use lowerCamelCase style.
|
||||
*/
|
||||
public function __construct(array $attributes = null, $lowerCamelCase = true)
|
||||
{
|
||||
$this->attributes = $attributes;
|
||||
$this->lowerCamelCase = $lowerCamelCase;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function normalize($propertyName)
|
||||
{
|
||||
if (null === $this->attributes || in_array($propertyName, $this->attributes)) {
|
||||
$snakeCasedName = '';
|
||||
|
||||
$len = strlen($propertyName);
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
if (ctype_upper($propertyName[$i])) {
|
||||
$snakeCasedName .= '_'.strtolower($propertyName[$i]);
|
||||
} else {
|
||||
$snakeCasedName .= strtolower($propertyName[$i]);
|
||||
}
|
||||
}
|
||||
|
||||
return $snakeCasedName;
|
||||
}
|
||||
|
||||
return $propertyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function denormalize($propertyName)
|
||||
{
|
||||
$camelCasedName = preg_replace_callback('/(^|_|\.)+(.)/', function ($match) {
|
||||
return ('.' === $match[1] ? '_' : '').strtoupper($match[2]);
|
||||
}, $propertyName);
|
||||
|
||||
if ($this->lowerCamelCase) {
|
||||
$camelCasedName = lcfirst($camelCasedName);
|
||||
}
|
||||
|
||||
if (null === $this->attributes || in_array($camelCasedName, $this->attributes)) {
|
||||
return $this->lowerCamelCase ? lcfirst($camelCasedName) : $camelCasedName;
|
||||
}
|
||||
|
||||
return $propertyName;
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
<?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 Symfony\Component\Serializer\NameConverter;
|
||||
|
||||
/**
|
||||
* Defines the interface for property name converters.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
interface NameConverterInterface
|
||||
{
|
||||
/**
|
||||
* Converts a property name to its normalized value.
|
||||
*
|
||||
* @param string $propertyName
|
||||
* @return string
|
||||
*/
|
||||
public function normalize($propertyName);
|
||||
|
||||
/**
|
||||
* Converts a property name to its denormalized value.
|
||||
*
|
||||
* @param string $propertyName
|
||||
* @return string
|
||||
*/
|
||||
public function denormalize($propertyName);
|
||||
}
|
@ -13,8 +13,11 @@ namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\CircularReferenceException;
|
||||
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Serializer\Exception\LogicException;
|
||||
use Symfony\Component\Serializer\Exception\RuntimeException;
|
||||
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
|
||||
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
|
||||
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
|
||||
|
||||
/**
|
||||
* Normalizer implementation.
|
||||
@ -26,6 +29,7 @@ abstract class AbstractNormalizer extends SerializerAwareNormalizer implements N
|
||||
protected $circularReferenceLimit = 1;
|
||||
protected $circularReferenceHandler;
|
||||
protected $classMetadataFactory;
|
||||
protected $nameConverter;
|
||||
protected $callbacks = array();
|
||||
protected $ignoredAttributes = array();
|
||||
protected $camelizedAttributes = array();
|
||||
@ -33,11 +37,13 @@ abstract class AbstractNormalizer extends SerializerAwareNormalizer implements N
|
||||
/**
|
||||
* Sets the {@link ClassMetadataFactory} to use.
|
||||
*
|
||||
* @param ClassMetadataFactory $classMetadataFactory
|
||||
* @param ClassMetadataFactory|null $classMetadataFactory
|
||||
* @param NameConverterInterface|null $nameConverter
|
||||
*/
|
||||
public function __construct(ClassMetadataFactory $classMetadataFactory = null)
|
||||
public function __construct(ClassMetadataFactory $classMetadataFactory = null, NameConverterInterface $nameConverter = null)
|
||||
{
|
||||
$this->classMetadataFactory = $classMetadataFactory;
|
||||
$this->nameConverter = $nameConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -115,13 +121,30 @@ abstract class AbstractNormalizer extends SerializerAwareNormalizer implements N
|
||||
/**
|
||||
* Set attributes to be camelized on denormalize.
|
||||
*
|
||||
* @deprecated Deprecated since version 2.7, to be removed in 3.0. Use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter instead.
|
||||
*
|
||||
* @param array $camelizedAttributes
|
||||
*
|
||||
* @return self
|
||||
*
|
||||
* @throws LogicException
|
||||
*/
|
||||
public function setCamelizedAttributes(array $camelizedAttributes)
|
||||
{
|
||||
$this->camelizedAttributes = $camelizedAttributes;
|
||||
trigger_error(sprintf('%s is deprecated since version 2.7 and will be removed in 3.0. Use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
if ($this->nameConverter && !$this->nameConverter instanceof CamelCaseToSnakeCaseNameConverter) {
|
||||
throw new LogicException(sprintf('%s cannot be called if a custom Name Converter is defined.', __METHOD__));
|
||||
}
|
||||
|
||||
$attributes = array();
|
||||
foreach ($camelizedAttributes as $camelizedAttribute) {
|
||||
$attributes[] = lcfirst(preg_replace_callback('/(^|_|\.)+(.)/', function ($match) {
|
||||
return ('.' === $match[1] ? '_' : '').strtoupper($match[2]);
|
||||
}, $camelizedAttribute));
|
||||
}
|
||||
|
||||
$this->nameConverter = new CamelCaseToSnakeCaseNameConverter($attributes);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -179,18 +202,17 @@ abstract class AbstractNormalizer extends SerializerAwareNormalizer implements N
|
||||
/**
|
||||
* Format an attribute name, for example to convert a snake_case name to camelCase.
|
||||
*
|
||||
* @deprecated Deprecated since version 2.7, to be removed in 3.0. Use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter instead.
|
||||
*
|
||||
* @param string $attributeName
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function formatAttribute($attributeName)
|
||||
{
|
||||
if (in_array($attributeName, $this->camelizedAttributes)) {
|
||||
return preg_replace_callback('/(^|_|\.)+(.)/', function ($match) {
|
||||
return ('.' === $match[1] ? '_' : '').strtoupper($match[2]);
|
||||
}, $attributeName);
|
||||
}
|
||||
trigger_error(sprintf('%s is deprecated since version 2.7 and will be removed in 3.0. Use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
return $attributeName;
|
||||
return $this->nameConverter ? $this->nameConverter->normalize($attributeName) : $attributeName;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -273,14 +295,15 @@ abstract class AbstractNormalizer extends SerializerAwareNormalizer implements N
|
||||
|
||||
$params = array();
|
||||
foreach ($constructorParameters as $constructorParameter) {
|
||||
$paramName = lcfirst($this->formatAttribute($constructorParameter->name));
|
||||
$paramName = $constructorParameter->name;
|
||||
$key = $this->nameConverter ? $this->nameConverter->normalize($paramName) : $paramName;
|
||||
|
||||
$allowed = $allowedAttributes === false || in_array($paramName, $allowedAttributes);
|
||||
$ignored = in_array($paramName, $this->ignoredAttributes);
|
||||
if ($allowed && !$ignored && isset($data[$paramName])) {
|
||||
$params[] = $data[$paramName];
|
||||
if ($allowed && !$ignored && isset($data[$key])) {
|
||||
$params[] = $data[$key];
|
||||
// don't run set for a parameter passed to the constructor
|
||||
unset($data[$paramName]);
|
||||
unset($data[$key]);
|
||||
} elseif ($constructorParameter->isOptional()) {
|
||||
$params[] = $constructorParameter->getDefaultValue();
|
||||
} else {
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace Symfony\Component\Serializer\Normalizer;
|
||||
|
||||
use Symfony\Component\Serializer\Exception\CircularReferenceException;
|
||||
use Symfony\Component\Serializer\Exception\LogicException;
|
||||
use Symfony\Component\Serializer\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
@ -40,6 +41,7 @@ class GetSetMethodNormalizer extends AbstractNormalizer
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws LogicException
|
||||
* @throws CircularReferenceException
|
||||
*/
|
||||
public function normalize($object, $format = null, array $context = array())
|
||||
@ -71,12 +73,16 @@ class GetSetMethodNormalizer extends AbstractNormalizer
|
||||
}
|
||||
if (null !== $attributeValue && !is_scalar($attributeValue)) {
|
||||
if (!$this->serializer instanceof NormalizerInterface) {
|
||||
throw new \LogicException(sprintf('Cannot normalize attribute "%s" because injected serializer is not a normalizer', $attributeName));
|
||||
throw new LogicException(sprintf('Cannot normalize attribute "%s" because injected serializer is not a normalizer', $attributeName));
|
||||
}
|
||||
|
||||
$attributeValue = $this->serializer->normalize($attributeValue, $format, $context);
|
||||
}
|
||||
|
||||
if ($this->nameConverter) {
|
||||
$attributeName = $this->nameConverter->normalize($attributeName);
|
||||
}
|
||||
|
||||
$attributes[$attributeName] = $attributeValue;
|
||||
}
|
||||
}
|
||||
@ -102,7 +108,11 @@ class GetSetMethodNormalizer extends AbstractNormalizer
|
||||
$ignored = in_array($attribute, $this->ignoredAttributes);
|
||||
|
||||
if ($allowed && !$ignored) {
|
||||
$setter = 'set'.$this->formatAttribute($attribute);
|
||||
if ($this->nameConverter) {
|
||||
$attribute = $this->nameConverter->denormalize($attribute);
|
||||
}
|
||||
|
||||
$setter = 'set'.ucfirst($attribute);
|
||||
|
||||
if (method_exists($object, $setter)) {
|
||||
$object->$setter($value);
|
||||
|
@ -71,7 +71,12 @@ class PropertyNormalizer extends AbstractNormalizer
|
||||
$attributeValue = $this->serializer->normalize($attributeValue, $format, $context);
|
||||
}
|
||||
|
||||
$attributes[$property->name] = $attributeValue;
|
||||
$propertyName = $property->name;
|
||||
if ($this->nameConverter) {
|
||||
$propertyName = $this->nameConverter->normalize($propertyName);
|
||||
}
|
||||
|
||||
$attributes[$propertyName] = $attributeValue;
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
@ -91,7 +96,9 @@ class PropertyNormalizer extends AbstractNormalizer
|
||||
$object = $this->instantiateObject($data, $class, $context, $reflectionClass, $allowedAttributes);
|
||||
|
||||
foreach ($data as $propertyName => $value) {
|
||||
$propertyName = lcfirst($this->formatAttribute($propertyName));
|
||||
if ($this->nameConverter) {
|
||||
$propertyName = $this->nameConverter->denormalize($propertyName);
|
||||
}
|
||||
|
||||
$allowed = $allowedAttributes === false || in_array($propertyName, $allowedAttributes);
|
||||
$ignored = in_array($propertyName, $this->ignoredAttributes);
|
||||
|
@ -0,0 +1,47 @@
|
||||
<?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 Symfony\Component\Serializer\Tests\NameConverter;
|
||||
|
||||
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
|
||||
|
||||
/**
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class CamelCaseToSnakeCaseNameConverterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider attributeProvider
|
||||
*/
|
||||
public function testNormalize($underscored, $lowerCamelCased)
|
||||
{
|
||||
$nameConverter = new CamelCaseToSnakeCaseNameConverter();
|
||||
$this->assertEquals($nameConverter->normalize($lowerCamelCased), $underscored);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider attributeProvider
|
||||
*/
|
||||
public function testDenormalize($underscored, $lowerCamelCased)
|
||||
{
|
||||
$nameConverter = new CamelCaseToSnakeCaseNameConverter();
|
||||
$this->assertEquals($nameConverter->denormalize($underscored), $lowerCamelCased);
|
||||
}
|
||||
|
||||
public function attributeProvider()
|
||||
{
|
||||
return array(
|
||||
array('coop_tilleuls', 'coopTilleuls'),
|
||||
array('_kevin_dunglas', '_kevinDunglas'),
|
||||
array('this_is_a_test', 'thisIsATest'),
|
||||
);
|
||||
}
|
||||
}
|
@ -22,8 +22,6 @@ use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
|
||||
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
|
||||
use Symfony\Component\Serializer\Tests\Fixtures\GroupDummy;
|
||||
|
||||
require_once __DIR__.'/../../Annotation/Groups.php';
|
||||
|
||||
class GetSetMethodNormalizerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
@ -95,13 +93,16 @@ class GetSetMethodNormalizerTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('bar', $obj->getBar());
|
||||
}
|
||||
|
||||
public function testDenormalizeOnCamelCaseFormat()
|
||||
public function testLegacyDenormalizeOnCamelCaseFormat()
|
||||
{
|
||||
$this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED);
|
||||
|
||||
$this->normalizer->setCamelizedAttributes(array('camel_case'));
|
||||
$obj = $this->normalizer->denormalize(
|
||||
array('camel_case' => 'camelCase'),
|
||||
__NAMESPACE__.'\GetSetDummy'
|
||||
);
|
||||
|
||||
$this->assertEquals('camelCase', $obj->getCamelCase());
|
||||
}
|
||||
|
||||
@ -110,27 +111,50 @@ class GetSetMethodNormalizerTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(new GetSetDummy(), $this->normalizer->denormalize(null, __NAMESPACE__.'\GetSetDummy'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider attributeProvider
|
||||
*/
|
||||
public function testFormatAttribute($attribute, $camelizedAttributes, $result)
|
||||
public function testLegacyCamelizedAttributesNormalize()
|
||||
{
|
||||
$r = new \ReflectionObject($this->normalizer);
|
||||
$m = $r->getMethod('formatAttribute');
|
||||
$m->setAccessible(true);
|
||||
$this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED);
|
||||
|
||||
$this->normalizer->setCamelizedAttributes($camelizedAttributes);
|
||||
$this->assertEquals($m->invoke($this->normalizer, $attribute, $camelizedAttributes), $result);
|
||||
$obj = new GetCamelizedDummy('dunglas.fr');
|
||||
$obj->setFooBar('les-tilleuls.coop');
|
||||
$obj->setBar_foo('lostinthesupermarket.fr');
|
||||
|
||||
$this->normalizer->setCamelizedAttributes(array('kevin_dunglas'));
|
||||
$this->assertEquals($this->normalizer->normalize($obj), array(
|
||||
'kevin_dunglas' => 'dunglas.fr',
|
||||
'fooBar' => 'les-tilleuls.coop',
|
||||
'bar_foo' => 'lostinthesupermarket.fr',
|
||||
));
|
||||
|
||||
$this->normalizer->setCamelizedAttributes(array('foo_bar'));
|
||||
$this->assertEquals($this->normalizer->normalize($obj), array(
|
||||
'kevinDunglas' => 'dunglas.fr',
|
||||
'foo_bar' => 'les-tilleuls.coop',
|
||||
'bar_foo' => 'lostinthesupermarket.fr',
|
||||
));
|
||||
}
|
||||
|
||||
public function attributeProvider()
|
||||
public function testLegacyCamelizedAttributesDenormalize()
|
||||
{
|
||||
return array(
|
||||
array('attribute_test', array('attribute_test'),'AttributeTest'),
|
||||
array('attribute_test', array('any'),'attribute_test'),
|
||||
array('attribute', array('attribute'),'Attribute'),
|
||||
array('attribute', array(), 'attribute'),
|
||||
);
|
||||
$this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED);
|
||||
|
||||
$obj = new GetCamelizedDummy('dunglas.fr');
|
||||
$obj->setFooBar('les-tilleuls.coop');
|
||||
$obj->setBar_foo('lostinthesupermarket.fr');
|
||||
|
||||
$this->normalizer->setCamelizedAttributes(array('kevin_dunglas'));
|
||||
$this->assertEquals($this->normalizer->denormalize(array(
|
||||
'kevin_dunglas' => 'dunglas.fr',
|
||||
'fooBar' => 'les-tilleuls.coop',
|
||||
'bar_foo' => 'lostinthesupermarket.fr',
|
||||
), __NAMESPACE__.'\GetCamelizedDummy'), $obj);
|
||||
|
||||
$this->normalizer->setCamelizedAttributes(array('foo_bar'));
|
||||
$this->assertEquals($this->normalizer->denormalize(array(
|
||||
'kevinDunglas' => 'dunglas.fr',
|
||||
'foo_bar' => 'les-tilleuls.coop',
|
||||
'bar_foo' => 'lostinthesupermarket.fr',
|
||||
), __NAMESPACE__.'\GetCamelizedDummy'), $obj);
|
||||
}
|
||||
|
||||
public function testConstructorDenormalize()
|
||||
@ -328,7 +352,7 @@ class GetSetMethodNormalizerTest extends \PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
* @expectedException \Symfony\Component\Serializer\Exception\LogicException
|
||||
* @expectedExceptionMessage Cannot normalize attribute "object" because injected serializer is not a normalizer
|
||||
*/
|
||||
public function testUnableToNormalizeObjectAttribute()
|
||||
@ -544,3 +568,40 @@ class GetConstructorOptionalArgsDummy
|
||||
throw new \RuntimeException("Dummy::otherMethod() should not be called");
|
||||
}
|
||||
}
|
||||
|
||||
class GetCamelizedDummy
|
||||
{
|
||||
private $kevinDunglas;
|
||||
private $fooBar;
|
||||
private $bar_foo;
|
||||
|
||||
public function __construct($kevinDunglas = null)
|
||||
{
|
||||
$this->kevinDunglas = $kevinDunglas;
|
||||
}
|
||||
|
||||
public function getKevinDunglas()
|
||||
{
|
||||
return $this->kevinDunglas;
|
||||
}
|
||||
|
||||
public function setFooBar($fooBar)
|
||||
{
|
||||
$this->fooBar = $fooBar;
|
||||
}
|
||||
|
||||
public function getFooBar()
|
||||
{
|
||||
return $this->fooBar;
|
||||
}
|
||||
|
||||
public function setBar_foo($bar_foo)
|
||||
{
|
||||
$this->bar_foo = $bar_foo;
|
||||
}
|
||||
|
||||
public function getBar_foo()
|
||||
{
|
||||
return $this->bar_foo;
|
||||
}
|
||||
}
|
||||
|
@ -21,8 +21,6 @@ use Symfony\Component\Serializer\Tests\Fixtures\GroupDummy;
|
||||
use Symfony\Component\Serializer\Tests\Fixtures\PropertyCircularReferenceDummy;
|
||||
use Symfony\Component\Serializer\Tests\Fixtures\PropertySiblingHolder;
|
||||
|
||||
require_once __DIR__.'/../../Annotation/Groups.php';
|
||||
|
||||
class PropertyNormalizerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
@ -64,8 +62,10 @@ class PropertyNormalizerTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('bar', $obj->getBar());
|
||||
}
|
||||
|
||||
public function testDenormalizeOnCamelCaseFormat()
|
||||
public function testLegacyDenormalizeOnCamelCaseFormat()
|
||||
{
|
||||
$this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED);
|
||||
|
||||
$this->normalizer->setCamelizedAttributes(array('camel_case'));
|
||||
$obj = $this->normalizer->denormalize(
|
||||
array('camel_case' => 'value'),
|
||||
@ -74,27 +74,50 @@ class PropertyNormalizerTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('value', $obj->getCamelCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider attributeProvider
|
||||
*/
|
||||
public function testFormatAttribute($attribute, $camelizedAttributes, $result)
|
||||
public function testLegacyCamelizedAttributesNormalize()
|
||||
{
|
||||
$r = new \ReflectionObject($this->normalizer);
|
||||
$m = $r->getMethod('formatAttribute');
|
||||
$m->setAccessible(true);
|
||||
$this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED);
|
||||
|
||||
$this->normalizer->setCamelizedAttributes($camelizedAttributes);
|
||||
$this->assertEquals($m->invoke($this->normalizer, $attribute, $camelizedAttributes), $result);
|
||||
$obj = new PropertyCamelizedDummy('dunglas.fr');
|
||||
$obj->fooBar = 'les-tilleuls.coop';
|
||||
$obj->bar_foo = 'lostinthesupermarket.fr';
|
||||
|
||||
$this->normalizer->setCamelizedAttributes(array('kevin_dunglas'));
|
||||
$this->assertEquals($this->normalizer->normalize($obj), array(
|
||||
'kevin_dunglas' => 'dunglas.fr',
|
||||
'fooBar' => 'les-tilleuls.coop',
|
||||
'bar_foo' => 'lostinthesupermarket.fr',
|
||||
));
|
||||
|
||||
$this->normalizer->setCamelizedAttributes(array('foo_bar'));
|
||||
$this->assertEquals($this->normalizer->normalize($obj), array(
|
||||
'kevinDunglas' => 'dunglas.fr',
|
||||
'foo_bar' => 'les-tilleuls.coop',
|
||||
'bar_foo' => 'lostinthesupermarket.fr',
|
||||
));
|
||||
}
|
||||
|
||||
public function attributeProvider()
|
||||
public function testLegacyCamelizedAttributesDenormalize()
|
||||
{
|
||||
return array(
|
||||
array('attribute_test', array('attribute_test'),'AttributeTest'),
|
||||
array('attribute_test', array('any'),'attribute_test'),
|
||||
array('attribute', array('attribute'),'Attribute'),
|
||||
array('attribute', array(), 'attribute'),
|
||||
);
|
||||
$this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED);
|
||||
|
||||
$obj = new PropertyCamelizedDummy('dunglas.fr');
|
||||
$obj->fooBar = 'les-tilleuls.coop';
|
||||
$obj->bar_foo = 'lostinthesupermarket.fr';
|
||||
|
||||
$this->normalizer->setCamelizedAttributes(array('kevin_dunglas'));
|
||||
$this->assertEquals($this->normalizer->denormalize(array(
|
||||
'kevin_dunglas' => 'dunglas.fr',
|
||||
'fooBar' => 'les-tilleuls.coop',
|
||||
'bar_foo' => 'lostinthesupermarket.fr',
|
||||
), __NAMESPACE__.'\PropertyCamelizedDummy'), $obj);
|
||||
|
||||
$this->normalizer->setCamelizedAttributes(array('foo_bar'));
|
||||
$this->assertEquals($this->normalizer->denormalize(array(
|
||||
'kevinDunglas' => 'dunglas.fr',
|
||||
'foo_bar' => 'les-tilleuls.coop',
|
||||
'bar_foo' => 'lostinthesupermarket.fr',
|
||||
), __NAMESPACE__.'\PropertyCamelizedDummy'), $obj);
|
||||
}
|
||||
|
||||
public function testConstructorDenormalize()
|
||||
@ -360,3 +383,15 @@ class PropertyConstructorDummy
|
||||
return $this->bar;
|
||||
}
|
||||
}
|
||||
|
||||
class PropertyCamelizedDummy
|
||||
{
|
||||
private $kevinDunglas;
|
||||
public $fooBar;
|
||||
public $bar_foo;
|
||||
|
||||
public function __construct($kevinDunglas = null)
|
||||
{
|
||||
$this->kevinDunglas = $kevinDunglas;
|
||||
}
|
||||
}
|
||||
|
14
src/Symfony/Component/Serializer/Tests/bootstrap.php
Normal file
14
src/Symfony/Component/Serializer/Tests/bootstrap.php
Normal file
@ -0,0 +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.
|
||||
*/
|
||||
|
||||
$loader = require __DIR__.'/../vendor/autoload.php';
|
||||
|
||||
Doctrine\Common\Annotations\AnnotationRegistry::registerLoader(function ($class) { return class_exists($class); });
|
@ -4,7 +4,7 @@
|
||||
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
|
||||
backupGlobals="false"
|
||||
colors="true"
|
||||
bootstrap="vendor/autoload.php"
|
||||
bootstrap="Tests/bootstrap.php"
|
||||
>
|
||||
<php>
|
||||
<!-- Disable E_USER_DEPRECATED until 3.0 -->
|
||||
|
@ -28,72 +28,52 @@ use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
||||
class CardSchemeValidator extends ConstraintValidator
|
||||
{
|
||||
protected $schemes = array(
|
||||
/**
|
||||
* American Express card numbers start with 34 or 37 and have 15 digits.
|
||||
*/
|
||||
// American Express card numbers start with 34 or 37 and have 15 digits.
|
||||
'AMEX' => array(
|
||||
'/^3[47][0-9]{13}$/',
|
||||
),
|
||||
/**
|
||||
* China UnionPay cards start with 62 and have between 16 and 19 digits.
|
||||
* Please note that these cards do not follow Luhn Algorithm as a checksum.
|
||||
*/
|
||||
// China UnionPay cards start with 62 and have between 16 and 19 digits.
|
||||
// Please note that these cards do not follow Luhn Algorithm as a checksum.
|
||||
'CHINA_UNIONPAY' => array(
|
||||
'/^62[0-9]{14,17}$/',
|
||||
),
|
||||
/**
|
||||
* Diners Club card numbers begin with 300 through 305, 36 or 38. All have 14 digits.
|
||||
* There are Diners Club cards that begin with 5 and have 16 digits.
|
||||
* These are a joint venture between Diners Club and MasterCard, and should be processed like a MasterCard.
|
||||
*/
|
||||
// Diners Club card numbers begin with 300 through 305, 36 or 38. All have 14 digits.
|
||||
// There are Diners Club cards that begin with 5 and have 16 digits.
|
||||
// These are a joint venture between Diners Club and MasterCard, and should be processed like a MasterCard.
|
||||
'DINERS' => array(
|
||||
'/^3(?:0[0-5]|[68][0-9])[0-9]{11}$/',
|
||||
),
|
||||
/**
|
||||
* Discover card numbers begin with 6011, 622126 through 622925, 644 through 649 or 65.
|
||||
* All have 16 digits.
|
||||
*/
|
||||
// Discover card numbers begin with 6011, 622126 through 622925, 644 through 649 or 65.
|
||||
// All have 16 digits.
|
||||
'DISCOVER' => array(
|
||||
'/^6011[0-9]{12}$/',
|
||||
'/^64[4-9][0-9]{13}$/',
|
||||
'/^65[0-9]{14}$/',
|
||||
'/^622(12[6-9]|1[3-9][0-9]|[2-8][0-9][0-9]|91[0-9]|92[0-5])[0-9]{10}$/',
|
||||
),
|
||||
/**
|
||||
* InstaPayment cards begin with 637 through 639 and have 16 digits.
|
||||
*/
|
||||
// InstaPayment cards begin with 637 through 639 and have 16 digits.
|
||||
'INSTAPAYMENT' => array(
|
||||
'/^63[7-9][0-9]{13}$/',
|
||||
),
|
||||
/**
|
||||
* JCB cards beginning with 2131 or 1800 have 15 digits.
|
||||
* JCB cards beginning with 35 have 16 digits.
|
||||
*/
|
||||
// JCB cards beginning with 2131 or 1800 have 15 digits.
|
||||
// JCB cards beginning with 35 have 16 digits.
|
||||
'JCB' => array(
|
||||
'/^(?:2131|1800|35[0-9]{3})[0-9]{11}$/',
|
||||
),
|
||||
/**
|
||||
* Laser cards begin with either 6304, 6706, 6709 or 6771 and have between 16 and 19 digits.
|
||||
*/
|
||||
// Laser cards begin with either 6304, 6706, 6709 or 6771 and have between 16 and 19 digits.
|
||||
'LASER' => array(
|
||||
'/^(6304|670[69]|6771)[0-9]{12,15}$/',
|
||||
),
|
||||
/**
|
||||
* Maestro cards begin with either 5018, 5020, 5038, 5893, 6304, 6759, 6761, 6762, 6763 or 0604
|
||||
* They have between 12 and 19 digits.
|
||||
*/
|
||||
// Maestro cards begin with either 5018, 5020, 5038, 5893, 6304, 6759, 6761, 6762, 6763 or 0604
|
||||
// They have between 12 and 19 digits.
|
||||
'MAESTRO' => array(
|
||||
'/^(5018|5020|5038|6304|6759|6761|676[23]|0604)[0-9]{8,15}$/',
|
||||
),
|
||||
/**
|
||||
* All MasterCard numbers start with the numbers 51 through 55. All have 16 digits.
|
||||
*/
|
||||
// All MasterCard numbers start with the numbers 51 through 55. All have 16 digits.
|
||||
'MASTERCARD' => array(
|
||||
'/^5[1-5][0-9]{14}$/',
|
||||
),
|
||||
/**
|
||||
* All Visa card numbers start with a 4. New cards have 16 digits. Old cards have 13.
|
||||
*/
|
||||
// All Visa card numbers start with a 4. New cards have 16 digits. Old cards have 13.
|
||||
'VISA' => array(
|
||||
'/^4([0-9]{12}|[0-9]{15})$/',
|
||||
),
|
||||
|
@ -35,6 +35,7 @@ class Length extends Constraint
|
||||
public $maxMessage = 'This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.';
|
||||
public $minMessage = 'This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.';
|
||||
public $exactMessage = 'This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.';
|
||||
public $charsetMessage = 'This value does not match the expected {{ charset }} charset.';
|
||||
public $max;
|
||||
public $min;
|
||||
public $charset = 'UTF-8';
|
||||
|
@ -39,13 +39,39 @@ class LengthValidator extends ConstraintValidator
|
||||
}
|
||||
|
||||
$stringValue = (string) $value;
|
||||
$invalidCharset = false;
|
||||
|
||||
if (function_exists('grapheme_strlen') && 'UTF-8' === $constraint->charset) {
|
||||
$length = grapheme_strlen($stringValue);
|
||||
if ('UTF8' === $charset = strtoupper($constraint->charset)) {
|
||||
$charset = 'UTF-8';
|
||||
}
|
||||
|
||||
if (function_exists('iconv_strlen')) {
|
||||
$length = @iconv_strlen($stringValue, $constraint->charset);
|
||||
$invalidCharset = false === $length;
|
||||
} elseif (function_exists('mb_strlen')) {
|
||||
$length = mb_strlen($stringValue, $constraint->charset);
|
||||
} else {
|
||||
if (mb_check_encoding($stringValue, $constraint->charset)) {
|
||||
$length = mb_strlen($stringValue, $constraint->charset);
|
||||
} else {
|
||||
$invalidCharset = true;
|
||||
}
|
||||
} elseif ('UTF-8' !== $charset) {
|
||||
$length = strlen($stringValue);
|
||||
} elseif (!preg_match('//u', $stringValue)) {
|
||||
$invalidCharset = true;
|
||||
} elseif (function_exists('utf8_decode')) {
|
||||
$length = strlen(utf8_decode($stringValue));
|
||||
} else {
|
||||
preg_replace('/./u', '', $stringValue, -1, $length);
|
||||
}
|
||||
|
||||
if ($invalidCharset) {
|
||||
$this->buildViolation($constraint->charsetMessage)
|
||||
->setParameter('{{ value }}', $this->formatValue($stringValue))
|
||||
->setParameter('{{ charset }}', $constraint->charset)
|
||||
->setInvalidValue($value)
|
||||
->addViolation();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (null !== $constraint->max && $length > $constraint->max) {
|
||||
|
@ -23,7 +23,7 @@ abstract class ElementMetadata extends GenericMetadata
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
if (__CLASS__ === get_class($this) || !in_array(get_parent_class($this), array('Symfony\Component\Validator\Mapping\MemberMetadata', 'Symfony\Component\Validator\Mapping\ClassMetadata'))) {
|
||||
if (!$this instanceof MemberMetadata && !$this instanceof ClassMetadata) {
|
||||
trigger_error('The '.__CLASS__.' class is deprecated since version 2.5 and will be removed in 3.0. Use the Symfony\Component\Validator\Mapping\GenericMetadata class instead.', E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
|
@ -1,283 +1,283 @@
|
||||
<?xml version="1.0"?>
|
||||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<file source-language="en" datatype="plaintext" original="file.ext">
|
||||
<body>
|
||||
<trans-unit id="1">
|
||||
<source>This value should be false.</source>
|
||||
<target>Стойността трябва да бъде лъжа (false).</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2">
|
||||
<source>This value should be true.</source>
|
||||
<target>Стойността трябва да бъде истина (true).</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="3">
|
||||
<source>This value should be of type {{ type }}.</source>
|
||||
<target>Стойността трябва да бъде от тип {{ type }}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="4">
|
||||
<source>This value should be blank.</source>
|
||||
<target>Стойността трябва да бъде празна.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="5">
|
||||
<source>The value you selected is not a valid choice.</source>
|
||||
<target>Избраната стойност е невалидна.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6">
|
||||
<source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
|
||||
<target>Трябва да изберете поне {{ limit }} опция.|Трябва да изберете поне {{ limit }} опции.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="7">
|
||||
<source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
|
||||
<target>Трябва да изберете най-много {{ limit }} опция.|Трябва да изберете най-много {{ limit }} опции.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="8">
|
||||
<source>One or more of the given values is invalid.</source>
|
||||
<target>Една или повече от зададените стойности е невалидна.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="9">
|
||||
<source>This field was not expected.</source>
|
||||
<target>Това поле не се е очаквало.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="10">
|
||||
<source>This field is missing.</source>
|
||||
<target>Това поле липсва.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="11">
|
||||
<source>This value is not a valid date.</source>
|
||||
<target>Стойността не е валидна дата (date).</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="12">
|
||||
<source>This value is not a valid datetime.</source>
|
||||
<target>Стойността не е валидна дата (datetime).</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="13">
|
||||
<source>This value is not a valid email address.</source>
|
||||
<target>Стойността не е валиден email адрес.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="14">
|
||||
<source>The file could not be found.</source>
|
||||
<target>Файлът не беше открит.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="15">
|
||||
<source>The file is not readable.</source>
|
||||
<target>Файлът не може да бъде прочетен.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="16">
|
||||
<source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
|
||||
<target>Файлът е твърде голям ({{ size }} {{ suffix }}). Максималният размер е {{ limit }} {{ suffix }}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="17">
|
||||
<source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
|
||||
<target>Майм типа на файла е невалиден ({{ type }}). Разрешени майм типове са {{ types }}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="18">
|
||||
<source>This value should be {{ limit }} or less.</source>
|
||||
<target>Стойността трябва да бъде {{ limit }} или по-малко.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="19">
|
||||
<source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
|
||||
<target>Стойността е твърде дълга. Трябва да съдържа най-много {{ limit }} символ.|Стойността е твърде дълга. Трябва да съдържа най-много {{ limit }} символа.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="20">
|
||||
<source>This value should be {{ limit }} or more.</source>
|
||||
<target>Стойността трябва да бъде {{ limit }} или повече.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="21">
|
||||
<source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
|
||||
<target>Стойността е твърде кратка. Трябва да съдържа поне {{ limit }} символ.|Стойността е твърде кратка. Трябва да съдържа поне {{ limit }} символа.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="22">
|
||||
<source>This value should not be blank.</source>
|
||||
<target>Стойността не трябва да бъде празна.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="23">
|
||||
<source>This value should not be null.</source>
|
||||
<target>Стойността не трябва да бъде null.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="24">
|
||||
<source>This value should be null.</source>
|
||||
<target>Стойността трябва да бъде null.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="25">
|
||||
<source>This value is not valid.</source>
|
||||
<target>Стойността не е валидна.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="26">
|
||||
<source>This value is not a valid time.</source>
|
||||
<target>Стойността не е валидно време (time).</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="27">
|
||||
<source>This value is not a valid URL.</source>
|
||||
<target>Стойността не е валиден URL.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="31">
|
||||
<source>The two values should be equal.</source>
|
||||
<target>Двете стойности трябва да бъдат равни.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="32">
|
||||
<source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
|
||||
<target>Файлът е твърде голям. Разрешеният максимален размер е {{ limit }} {{ suffix }}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="33">
|
||||
<source>The file is too large.</source>
|
||||
<target>Файлът е твърде голям.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="34">
|
||||
<source>The file could not be uploaded.</source>
|
||||
<target>Файлът не може да бъде качен.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="35">
|
||||
<source>This value should be a valid number.</source>
|
||||
<target>Стойността трябва да бъде валиден номер.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="36">
|
||||
<source>This file is not a valid image.</source>
|
||||
<target>Файлът не е валидно изображение.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="37">
|
||||
<source>This is not a valid IP address.</source>
|
||||
<target>Това не е валиден IP адрес.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="38">
|
||||
<source>This value is not a valid language.</source>
|
||||
<target>Стойността не е валиден език.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="39">
|
||||
<source>This value is not a valid locale.</source>
|
||||
<target>Стойността не е валидна локализация.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="40">
|
||||
<source>This value is not a valid country.</source>
|
||||
<target>Стойността не е валидна държава.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="41">
|
||||
<source>This value is already used.</source>
|
||||
<target>Стойността вече е в употреба.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="42">
|
||||
<source>The size of the image could not be detected.</source>
|
||||
<target>Размера на изображението не може да бъде определен.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="43">
|
||||
<source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
|
||||
<target>Изображението е твърде широко ({{ width }}px). Широчината трябва да бъде максимум {{ max_width }}px.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="44">
|
||||
<source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
|
||||
<target>Изображението е с твърде малка широчина ({{ width }}px). Широчината трябва да бъде минимум {{ min_width }}px.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="45">
|
||||
<source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
|
||||
<target>Изображението е с твърде голяма височина ({{ height }}px). Височината трябва да бъде максимум {{ max_height }}px.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="46">
|
||||
<source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
|
||||
<target>Изображението е с твърде малка височина ({{ height }}px). Височина трябва да бъде минимум {{ min_height }}px.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="47">
|
||||
<source>This value should be the user's current password.</source>
|
||||
<target>Стойността трябва да бъде текущата потребителска парола.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="48">
|
||||
<source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
|
||||
<target>Стойността трябва да бъде точно {{ limit }} символ.|Стойността трябва да бъде точно {{ limit }} символа.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="49">
|
||||
<source>The file was only partially uploaded.</source>
|
||||
<target>Файлът е качен частично.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="50">
|
||||
<source>No file was uploaded.</source>
|
||||
<target>Файлът не беше качен.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="51">
|
||||
<source>No temporary folder was configured in php.ini.</source>
|
||||
<target>Не е посочена директория за временни файлове в php.ini.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="52">
|
||||
<source>Cannot write temporary file to disk.</source>
|
||||
<target>Не може да запише временен файл на диска.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="53">
|
||||
<source>A PHP extension caused the upload to fail.</source>
|
||||
<target>PHP разширение предизвика прекъсване на качването.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="54">
|
||||
<source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
|
||||
<target>Колекцията трябва да съдържа поне {{ limit }} елемент.|Колекцията трябва да съдържа поне {{ limit }} елемента.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="55">
|
||||
<source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
|
||||
<target>Колекцията трябва да съдържа най-много {{ limit }} елемент.|Колекцията трябва да съдържа най-много {{ limit }} елемента.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="56">
|
||||
<source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
|
||||
<target>Колекцията трябва да съдържа точно {{ limit }} елемент.|Колекцията трябва да съдържа точно {{ limit }} елемента.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="57">
|
||||
<source>Invalid card number.</source>
|
||||
<target>Невалиден номер на картата.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="58">
|
||||
<source>Unsupported card type or invalid card number.</source>
|
||||
<target>Неподдържан тип карта или невалиден номер на картата.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="59">
|
||||
<source>This is not a valid International Bank Account Number (IBAN).</source>
|
||||
<target>Невалиден Международен номер на банкова сметка (IBAN).</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="60">
|
||||
<source>This value is not a valid ISBN-10.</source>
|
||||
<target>Невалиден ISBN-10.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="61">
|
||||
<source>This value is not a valid ISBN-13.</source>
|
||||
<target>Невалиден ISBN-13.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="62">
|
||||
<source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
|
||||
<target>Невалидна стойност както за ISBN-10, така и за ISBN-13 .</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="63">
|
||||
<source>This value is not a valid ISSN.</source>
|
||||
<target>Невалиден Международен стандартен сериен номер (ISSN).</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="64">
|
||||
<source>This value is not a valid currency.</source>
|
||||
<target>Невалидна валута.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="65">
|
||||
<source>This value should be equal to {{ compared_value }}.</source>
|
||||
<target>Стойността трябва да бъде равна на {{ compared_value }}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="66">
|
||||
<source>This value should be greater than {{ compared_value }}.</source>
|
||||
<target>Стойността трябва да бъде по-голяма от {{ compared_value }}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="67">
|
||||
<source>This value should be greater than or equal to {{ compared_value }}.</source>
|
||||
<target>Стойността трябва да бъде по-голяма или равна на {{ compared_value }}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="68">
|
||||
<source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
|
||||
<target>Стойността трябва да бъде идентична с {{ compared_value_type }} {{ compared_value }}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="69">
|
||||
<source>This value should be less than {{ compared_value }}.</source>
|
||||
<target>Стойността трябва да бъде по-малка {{ compared_value }}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="70">
|
||||
<source>This value should be less than or equal to {{ compared_value }}.</source>
|
||||
<target>Стойността трябва да бъде по-малка или равна на {{ compared_value }}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="71">
|
||||
<source>This value should not be equal to {{ compared_value }}.</source>
|
||||
<target>Стойността не трябва да бъде равна на {{ compared_value }}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="72">
|
||||
<source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
|
||||
<target>Стойността не трябва да бъде идентична с {{ compared_value_type }} {{ compared_value }}.</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
<?xml version="1.0"?>
|
||||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<file source-language="en" datatype="plaintext" original="file.ext">
|
||||
<body>
|
||||
<trans-unit id="1">
|
||||
<source>This value should be false.</source>
|
||||
<target>Стойността трябва да бъде лъжа (false).</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="2">
|
||||
<source>This value should be true.</source>
|
||||
<target>Стойността трябва да бъде истина (true).</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="3">
|
||||
<source>This value should be of type {{ type }}.</source>
|
||||
<target>Стойността трябва да бъде от тип {{ type }}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="4">
|
||||
<source>This value should be blank.</source>
|
||||
<target>Стойността трябва да бъде празна.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="5">
|
||||
<source>The value you selected is not a valid choice.</source>
|
||||
<target>Избраната стойност е невалидна.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="6">
|
||||
<source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
|
||||
<target>Трябва да изберете поне {{ limit }} опция.|Трябва да изберете поне {{ limit }} опции.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="7">
|
||||
<source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
|
||||
<target>Трябва да изберете най-много {{ limit }} опция.|Трябва да изберете най-много {{ limit }} опции.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="8">
|
||||
<source>One or more of the given values is invalid.</source>
|
||||
<target>Една или повече от зададените стойности е невалидна.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="9">
|
||||
<source>This field was not expected.</source>
|
||||
<target>Това поле не се е очаквало.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="10">
|
||||
<source>This field is missing.</source>
|
||||
<target>Това поле липсва.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="11">
|
||||
<source>This value is not a valid date.</source>
|
||||
<target>Стойността не е валидна дата (date).</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="12">
|
||||
<source>This value is not a valid datetime.</source>
|
||||
<target>Стойността не е валидна дата (datetime).</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="13">
|
||||
<source>This value is not a valid email address.</source>
|
||||
<target>Стойността не е валиден email адрес.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="14">
|
||||
<source>The file could not be found.</source>
|
||||
<target>Файлът не беше открит.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="15">
|
||||
<source>The file is not readable.</source>
|
||||
<target>Файлът не може да бъде прочетен.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="16">
|
||||
<source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
|
||||
<target>Файлът е твърде голям ({{ size }} {{ suffix }}). Максималният размер е {{ limit }} {{ suffix }}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="17">
|
||||
<source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
|
||||
<target>Майм типа на файла е невалиден ({{ type }}). Разрешени майм типове са {{ types }}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="18">
|
||||
<source>This value should be {{ limit }} or less.</source>
|
||||
<target>Стойността трябва да бъде {{ limit }} или по-малко.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="19">
|
||||
<source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
|
||||
<target>Стойността е твърде дълга. Трябва да съдържа най-много {{ limit }} символ.|Стойността е твърде дълга. Трябва да съдържа най-много {{ limit }} символа.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="20">
|
||||
<source>This value should be {{ limit }} or more.</source>
|
||||
<target>Стойността трябва да бъде {{ limit }} или повече.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="21">
|
||||
<source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
|
||||
<target>Стойността е твърде кратка. Трябва да съдържа поне {{ limit }} символ.|Стойността е твърде кратка. Трябва да съдържа поне {{ limit }} символа.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="22">
|
||||
<source>This value should not be blank.</source>
|
||||
<target>Стойността не трябва да бъде празна.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="23">
|
||||
<source>This value should not be null.</source>
|
||||
<target>Стойността не трябва да бъде null.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="24">
|
||||
<source>This value should be null.</source>
|
||||
<target>Стойността трябва да бъде null.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="25">
|
||||
<source>This value is not valid.</source>
|
||||
<target>Стойността не е валидна.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="26">
|
||||
<source>This value is not a valid time.</source>
|
||||
<target>Стойността не е валидно време (time).</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="27">
|
||||
<source>This value is not a valid URL.</source>
|
||||
<target>Стойността не е валиден URL.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="31">
|
||||
<source>The two values should be equal.</source>
|
||||
<target>Двете стойности трябва да бъдат равни.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="32">
|
||||
<source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
|
||||
<target>Файлът е твърде голям. Разрешеният максимален размер е {{ limit }} {{ suffix }}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="33">
|
||||
<source>The file is too large.</source>
|
||||
<target>Файлът е твърде голям.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="34">
|
||||
<source>The file could not be uploaded.</source>
|
||||
<target>Файлът не може да бъде качен.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="35">
|
||||
<source>This value should be a valid number.</source>
|
||||
<target>Стойността трябва да бъде валиден номер.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="36">
|
||||
<source>This file is not a valid image.</source>
|
||||
<target>Файлът не е валидно изображение.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="37">
|
||||
<source>This is not a valid IP address.</source>
|
||||
<target>Това не е валиден IP адрес.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="38">
|
||||
<source>This value is not a valid language.</source>
|
||||
<target>Стойността не е валиден език.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="39">
|
||||
<source>This value is not a valid locale.</source>
|
||||
<target>Стойността не е валидна локализация.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="40">
|
||||
<source>This value is not a valid country.</source>
|
||||
<target>Стойността не е валидна държава.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="41">
|
||||
<source>This value is already used.</source>
|
||||
<target>Стойността вече е в употреба.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="42">
|
||||
<source>The size of the image could not be detected.</source>
|
||||
<target>Размера на изображението не може да бъде определен.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="43">
|
||||
<source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
|
||||
<target>Изображението е твърде широко ({{ width }}px). Широчината трябва да бъде максимум {{ max_width }}px.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="44">
|
||||
<source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
|
||||
<target>Изображението е с твърде малка широчина ({{ width }}px). Широчината трябва да бъде минимум {{ min_width }}px.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="45">
|
||||
<source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
|
||||
<target>Изображението е с твърде голяма височина ({{ height }}px). Височината трябва да бъде максимум {{ max_height }}px.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="46">
|
||||
<source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
|
||||
<target>Изображението е с твърде малка височина ({{ height }}px). Височина трябва да бъде минимум {{ min_height }}px.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="47">
|
||||
<source>This value should be the user's current password.</source>
|
||||
<target>Стойността трябва да бъде текущата потребителска парола.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="48">
|
||||
<source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
|
||||
<target>Стойността трябва да бъде точно {{ limit }} символ.|Стойността трябва да бъде точно {{ limit }} символа.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="49">
|
||||
<source>The file was only partially uploaded.</source>
|
||||
<target>Файлът е качен частично.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="50">
|
||||
<source>No file was uploaded.</source>
|
||||
<target>Файлът не беше качен.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="51">
|
||||
<source>No temporary folder was configured in php.ini.</source>
|
||||
<target>Не е посочена директория за временни файлове в php.ini.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="52">
|
||||
<source>Cannot write temporary file to disk.</source>
|
||||
<target>Не може да запише временен файл на диска.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="53">
|
||||
<source>A PHP extension caused the upload to fail.</source>
|
||||
<target>PHP разширение предизвика прекъсване на качването.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="54">
|
||||
<source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
|
||||
<target>Колекцията трябва да съдържа поне {{ limit }} елемент.|Колекцията трябва да съдържа поне {{ limit }} елемента.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="55">
|
||||
<source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
|
||||
<target>Колекцията трябва да съдържа най-много {{ limit }} елемент.|Колекцията трябва да съдържа най-много {{ limit }} елемента.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="56">
|
||||
<source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
|
||||
<target>Колекцията трябва да съдържа точно {{ limit }} елемент.|Колекцията трябва да съдържа точно {{ limit }} елемента.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="57">
|
||||
<source>Invalid card number.</source>
|
||||
<target>Невалиден номер на картата.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="58">
|
||||
<source>Unsupported card type or invalid card number.</source>
|
||||
<target>Неподдържан тип карта или невалиден номер на картата.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="59">
|
||||
<source>This is not a valid International Bank Account Number (IBAN).</source>
|
||||
<target>Невалиден Международен номер на банкова сметка (IBAN).</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="60">
|
||||
<source>This value is not a valid ISBN-10.</source>
|
||||
<target>Невалиден ISBN-10.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="61">
|
||||
<source>This value is not a valid ISBN-13.</source>
|
||||
<target>Невалиден ISBN-13.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="62">
|
||||
<source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
|
||||
<target>Невалидна стойност както за ISBN-10, така и за ISBN-13 .</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="63">
|
||||
<source>This value is not a valid ISSN.</source>
|
||||
<target>Невалиден Международен стандартен сериен номер (ISSN).</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="64">
|
||||
<source>This value is not a valid currency.</source>
|
||||
<target>Невалидна валута.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="65">
|
||||
<source>This value should be equal to {{ compared_value }}.</source>
|
||||
<target>Стойността трябва да бъде равна на {{ compared_value }}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="66">
|
||||
<source>This value should be greater than {{ compared_value }}.</source>
|
||||
<target>Стойността трябва да бъде по-голяма от {{ compared_value }}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="67">
|
||||
<source>This value should be greater than or equal to {{ compared_value }}.</source>
|
||||
<target>Стойността трябва да бъде по-голяма или равна на {{ compared_value }}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="68">
|
||||
<source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
|
||||
<target>Стойността трябва да бъде идентична с {{ compared_value_type }} {{ compared_value }}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="69">
|
||||
<source>This value should be less than {{ compared_value }}.</source>
|
||||
<target>Стойността трябва да бъде по-малка {{ compared_value }}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="70">
|
||||
<source>This value should be less than or equal to {{ compared_value }}.</source>
|
||||
<target>Стойността трябва да бъде по-малка или равна на {{ compared_value }}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="71">
|
||||
<source>This value should not be equal to {{ compared_value }}.</source>
|
||||
<target>Стойността не трябва да бъде равна на {{ compared_value }}.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="72">
|
||||
<source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
|
||||
<target>Стойността не трябва да бъде идентична с {{ compared_value_type }} {{ compared_value }}.</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
@ -306,6 +306,10 @@
|
||||
<source>The host could not be resolved.</source>
|
||||
<target>Der Hostname konnte nicht aufgelöst werden.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="80">
|
||||
<source>This value does not match the expected {{ charset }} charset.</source>
|
||||
<target>Dieser Wert entspricht nicht dem erwarteten Zeichensatz {{ charset }}.</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
@ -306,6 +306,10 @@
|
||||
<source>The host could not be resolved.</source>
|
||||
<target>The host could not be resolved.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="80">
|
||||
<source>This value does not match the expected {{ charset }} charset.</source>
|
||||
<target>This value does not match the expected {{ charset }} charset.</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
@ -306,6 +306,10 @@
|
||||
<source>The host could not be resolved.</source>
|
||||
<target>No se puede resolver el host.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="80">
|
||||
<source>This value does not match the expected {{ charset }} charset.</source>
|
||||
<target>La codificación de caracteres para este valor debería ser {{ charset }}.</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
@ -306,6 +306,10 @@
|
||||
<source>The host could not be resolved.</source>
|
||||
<target>Le nom de domaine n'a pas pu être résolu.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="80">
|
||||
<source>This value does not match the expected {{ charset }} charset.</source>
|
||||
<target>Cette valeur ne correspond pas au jeu de caractères {{ charset }} attendu.</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
@ -302,6 +302,10 @@
|
||||
<source>An empty file is not allowed.</source>
|
||||
<target>Lege bestanden zijn niet toegestaan.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="80">
|
||||
<source>This value does not match the expected {{ charset }} charset.</source>
|
||||
<target>Deze waarde is niet in de verwachte tekencodering {{ charset }}.</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
@ -306,6 +306,10 @@
|
||||
<source>The host could not be resolved.</source>
|
||||
<target>Nazwa hosta nie została rozpoznana.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="80">
|
||||
<source>This value does not match the expected {{ charset }} charset.</source>
|
||||
<target>Ta wartość nie pasuje do oczekiwanego zestawu znaków {{ charset }}.</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
@ -306,6 +306,10 @@
|
||||
<source>The host could not be resolved.</source>
|
||||
<target>Имя хоста не может быть разрешено.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="80">
|
||||
<source>This value does not match the expected {{ charset }} charset.</source>
|
||||
<target>Значение не совпадает с ожидаемой {{ charset }} кодировкой.</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
@ -306,6 +306,10 @@
|
||||
<source>The host could not be resolved.</source>
|
||||
<target>Gostitelja ni bilo mogoče prepoznati.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="80">
|
||||
<source>This value does not match the expected {{ charset }} charset.</source>
|
||||
<target>Ta vrednost se ne ujema s pričakovanim naborom znakov {{ charset }}.</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
@ -54,12 +54,12 @@ class LengthValidatorTest extends AbstractConstraintValidatorTest
|
||||
return array(
|
||||
array(12),
|
||||
array('12'),
|
||||
array('üü', true),
|
||||
array('éé', true),
|
||||
array('üü'),
|
||||
array('éé'),
|
||||
array(123),
|
||||
array('123'),
|
||||
array('üüü', true),
|
||||
array('ééé', true),
|
||||
array('üüü'),
|
||||
array('ééé'),
|
||||
);
|
||||
}
|
||||
|
||||
@ -68,8 +68,8 @@ class LengthValidatorTest extends AbstractConstraintValidatorTest
|
||||
return array(
|
||||
array(1234),
|
||||
array('1234'),
|
||||
array('üüüü', true),
|
||||
array('éééé', true),
|
||||
array('üüüü'),
|
||||
array('éééé'),
|
||||
);
|
||||
}
|
||||
|
||||
@ -78,24 +78,34 @@ class LengthValidatorTest extends AbstractConstraintValidatorTest
|
||||
return array(
|
||||
array(12345),
|
||||
array('12345'),
|
||||
array('üüüüü', true),
|
||||
array('ééééé', true),
|
||||
array('üüüüü'),
|
||||
array('ééééé'),
|
||||
array(123456),
|
||||
array('123456'),
|
||||
array('üüüüüü', true),
|
||||
array('éééééé', true),
|
||||
array('üüüüüü'),
|
||||
array('éééééé'),
|
||||
);
|
||||
}
|
||||
|
||||
public function getOneCharset()
|
||||
{
|
||||
if (!function_exists('iconv') && !function_exists('mb_convert_encoding')) {
|
||||
$this->markTestSkipped('Mbstring or iconv is required for this test.');
|
||||
}
|
||||
|
||||
return array(
|
||||
array("é", "utf8", true),
|
||||
array("\xE9", "CP1252", true),
|
||||
array("\xE9", "XXX", false),
|
||||
array("\xE9", "utf8", false),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getFiveOrMoreCharacters
|
||||
*/
|
||||
public function testValidValuesMin($value, $mbOnly = false)
|
||||
public function testValidValuesMin($value)
|
||||
{
|
||||
if ($mbOnly && !function_exists('mb_strlen')) {
|
||||
$this->markTestSkipped('mb_strlen does not exist');
|
||||
}
|
||||
|
||||
$constraint = new Length(array('min' => 5));
|
||||
$this->validator->validate($value, $constraint);
|
||||
|
||||
@ -105,12 +115,8 @@ class LengthValidatorTest extends AbstractConstraintValidatorTest
|
||||
/**
|
||||
* @dataProvider getThreeOrLessCharacters
|
||||
*/
|
||||
public function testValidValuesMax($value, $mbOnly = false)
|
||||
public function testValidValuesMax($value)
|
||||
{
|
||||
if ($mbOnly && !function_exists('mb_strlen')) {
|
||||
$this->markTestSkipped('mb_strlen does not exist');
|
||||
}
|
||||
|
||||
$constraint = new Length(array('max' => 3));
|
||||
$this->validator->validate($value, $constraint);
|
||||
|
||||
@ -120,12 +126,8 @@ class LengthValidatorTest extends AbstractConstraintValidatorTest
|
||||
/**
|
||||
* @dataProvider getFourCharacters
|
||||
*/
|
||||
public function testValidValuesExact($value, $mbOnly = false)
|
||||
public function testValidValuesExact($value)
|
||||
{
|
||||
if ($mbOnly && !function_exists('mb_strlen')) {
|
||||
$this->markTestSkipped('mb_strlen does not exist');
|
||||
}
|
||||
|
||||
$constraint = new Length(4);
|
||||
$this->validator->validate($value, $constraint);
|
||||
|
||||
@ -135,12 +137,8 @@ class LengthValidatorTest extends AbstractConstraintValidatorTest
|
||||
/**
|
||||
* @dataProvider getThreeOrLessCharacters
|
||||
*/
|
||||
public function testInvalidValuesMin($value, $mbOnly = false)
|
||||
public function testInvalidValuesMin($value)
|
||||
{
|
||||
if ($mbOnly && !function_exists('mb_strlen')) {
|
||||
$this->markTestSkipped('mb_strlen does not exist');
|
||||
}
|
||||
|
||||
$constraint = new Length(array(
|
||||
'min' => 4,
|
||||
'minMessage' => 'myMessage',
|
||||
@ -160,12 +158,8 @@ class LengthValidatorTest extends AbstractConstraintValidatorTest
|
||||
/**
|
||||
* @dataProvider getFiveOrMoreCharacters
|
||||
*/
|
||||
public function testInvalidValuesMax($value, $mbOnly = false)
|
||||
public function testInvalidValuesMax($value)
|
||||
{
|
||||
if ($mbOnly && !function_exists('mb_strlen')) {
|
||||
$this->markTestSkipped('mb_strlen does not exist');
|
||||
}
|
||||
|
||||
$constraint = new Length(array(
|
||||
'max' => 4,
|
||||
'maxMessage' => 'myMessage',
|
||||
@ -185,12 +179,8 @@ class LengthValidatorTest extends AbstractConstraintValidatorTest
|
||||
/**
|
||||
* @dataProvider getThreeOrLessCharacters
|
||||
*/
|
||||
public function testInvalidValuesExactLessThanFour($value, $mbOnly = false)
|
||||
public function testInvalidValuesExactLessThanFour($value)
|
||||
{
|
||||
if ($mbOnly && !function_exists('mb_strlen')) {
|
||||
$this->markTestSkipped('mb_strlen does not exist');
|
||||
}
|
||||
|
||||
$constraint = new Length(array(
|
||||
'min' => 4,
|
||||
'max' => 4,
|
||||
@ -211,12 +201,8 @@ class LengthValidatorTest extends AbstractConstraintValidatorTest
|
||||
/**
|
||||
* @dataProvider getFiveOrMoreCharacters
|
||||
*/
|
||||
public function testInvalidValuesExactMoreThanFour($value, $mbOnly = false)
|
||||
public function testInvalidValuesExactMoreThanFour($value)
|
||||
{
|
||||
if ($mbOnly && !function_exists('mb_strlen')) {
|
||||
$this->markTestSkipped('mb_strlen does not exist');
|
||||
}
|
||||
|
||||
$constraint = new Length(array(
|
||||
'min' => 4,
|
||||
'max' => 4,
|
||||
@ -234,6 +220,31 @@ class LengthValidatorTest extends AbstractConstraintValidatorTest
|
||||
->assertRaised();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getOneCharset
|
||||
*/
|
||||
public function testOneCharset($value, $charset, $isValid)
|
||||
{
|
||||
$constraint = new Length(array(
|
||||
'min' => 1,
|
||||
'max' => 1,
|
||||
'charset' => $charset,
|
||||
'charsetMessage' => 'myMessage',
|
||||
));
|
||||
|
||||
$this->validator->validate($value, $constraint);
|
||||
|
||||
if ($isValid) {
|
||||
$this->assertNoViolation();
|
||||
} else {
|
||||
$this->buildViolation('myMessage')
|
||||
->setParameter('{{ value }}', '"'.$value.'"')
|
||||
->setParameter('{{ charset }}', $charset)
|
||||
->setInvalidValue($value)
|
||||
->assertRaised();
|
||||
}
|
||||
}
|
||||
|
||||
public function testConstraintGetDefaultOption()
|
||||
{
|
||||
$constraint = new Length(5);
|
||||
|
@ -98,8 +98,6 @@ class StaticMethodLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
$this->markTestSkipped('Could not disable error reporting');
|
||||
}
|
||||
|
||||
include __DIR__.'/AbstractStaticMethodLoader.php';
|
||||
|
||||
$metadata = new ClassMetadata(__NAMESPACE__.'\AbstractStaticMethodLoader');
|
||||
|
||||
$loader = new StaticMethodLoader('loadMetadata');
|
||||
|
@ -176,7 +176,7 @@ class Data
|
||||
$cursor->hashCut = $hashCut;
|
||||
foreach ($children as $key => $child) {
|
||||
$cursor->hashKeyIsBinary = isset($key[0]) && !preg_match('//u', $key);
|
||||
$cursor->hashKey = $cursor->hashKeyIsBinary ? self::utf8Encode($key) : $key;
|
||||
$cursor->hashKey = $key;
|
||||
$this->dumpItem($dumper, $cursor, $refs, $child);
|
||||
if (++$cursor->hashIndex === $this->maxItemsPerDepth || $cursor->stop) {
|
||||
$parentCursor->stop = true;
|
||||
@ -191,33 +191,4 @@ class Data
|
||||
|
||||
return $hashCut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Portable variant of utf8_encode()
|
||||
*
|
||||
* @param string $s
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public static function utf8Encode($s)
|
||||
{
|
||||
if (function_exists('mb_convert_encoding')) {
|
||||
return mb_convert_encoding($s, 'UTF-8', 'CP1252');
|
||||
}
|
||||
|
||||
$s .= $s;
|
||||
$len = strlen($s);
|
||||
|
||||
for ($i = $len >> 1, $j = 0; $i < $len; ++$i, ++$j) {
|
||||
switch (true) {
|
||||
case $s[$i] < "\x80": $s[$j] = $s[$i]; break;
|
||||
case $s[$i] < "\xC0": $s[$j] = "\xC2"; $s[++$j] = $s[$i]; break;
|
||||
default: $s[$j] = "\xC3"; $s[++$j] = chr(ord($s[$i]) - 64); break;
|
||||
}
|
||||
}
|
||||
|
||||
return substr($s, 0, $j);
|
||||
}
|
||||
}
|
||||
|
@ -97,11 +97,10 @@ class VarCloner extends AbstractCloner
|
||||
$stub->class = Stub::STRING_BINARY;
|
||||
if (0 <= $maxString && 0 < $cut = strlen($v) - $maxString) {
|
||||
$stub->cut = $cut;
|
||||
$cut = substr_replace($v, '', -$cut);
|
||||
$stub->value = substr($v, 0, -$cut);
|
||||
} else {
|
||||
$cut = $v;
|
||||
$stub->value = $v;
|
||||
}
|
||||
$stub->value = Data::utf8Encode($cut);
|
||||
} elseif (0 <= $maxString && isset($v[1 + ($maxString >> 2)]) && 0 < $cut = iconv_strlen($v, 'UTF-8') - $maxString) {
|
||||
$stub = new Stub();
|
||||
$stub->type = Stub::TYPE_STRING;
|
||||
|
@ -29,11 +29,16 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface
|
||||
protected $decimalPoint; // This is locale dependent
|
||||
protected $indentPad = ' ';
|
||||
|
||||
private $charset;
|
||||
private $charsetConverter;
|
||||
|
||||
/**
|
||||
* @param callable|resource|string|null $output A line dumper callable, an opened stream or an output path, defaults to static::$defaultOutput.
|
||||
* @param callable|resource|string|null $output A line dumper callable, an opened stream or an output path, defaults to static::$defaultOutput.
|
||||
* @param string $charset The default character encoding to use for non-UTF8 strings.
|
||||
*/
|
||||
public function __construct($output = null)
|
||||
public function __construct($output = null, $charset = null)
|
||||
{
|
||||
$this->setCharset($charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8');
|
||||
$this->decimalPoint = (string) 0.5;
|
||||
$this->decimalPoint = $this->decimalPoint[1];
|
||||
$this->setOutput($output ?: static::$defaultOutput);
|
||||
@ -67,6 +72,43 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface
|
||||
return $prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default character encoding to use for non-UTF8 strings.
|
||||
*
|
||||
* @param string $charset The default character encoding to use for non-UTF8 strings.
|
||||
*
|
||||
* @return string The previous charset.
|
||||
*/
|
||||
public function setCharset($charset)
|
||||
{
|
||||
$prev = $this->charset;
|
||||
$this->charsetConverter = 'fallback';
|
||||
|
||||
$charset = strtoupper($charset);
|
||||
$charset = null === $charset || 'UTF-8' === $charset || 'UTF8' === $charset ? 'CP1252' : $charset;
|
||||
|
||||
$supported = true;
|
||||
set_error_handler(function () use (&$supported) {$supported = false;});
|
||||
|
||||
if (function_exists('mb_encoding_aliases') && mb_encoding_aliases($charset)) {
|
||||
$this->charset = $charset;
|
||||
$this->charsetConverter = 'mbstring';
|
||||
} elseif (function_exists('iconv')) {
|
||||
$supported = true;
|
||||
iconv($charset, 'UTF-8', '');
|
||||
if ($supported) {
|
||||
$this->charset = $charset;
|
||||
$this->charsetConverter = 'iconv';
|
||||
}
|
||||
}
|
||||
if ('fallback' === $this->charsetConverter) {
|
||||
$this->charset = 'ISO-8859-1';
|
||||
}
|
||||
restore_error_handler();
|
||||
|
||||
return $prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the indentation pad string.
|
||||
*
|
||||
@ -131,4 +173,50 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface
|
||||
fwrite($this->outputStream, str_repeat($indentPad, $depth).$line."\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a non-UTF-8 string to UTF-8.
|
||||
*
|
||||
* @param string $s The non-UTF-8 string to convert.
|
||||
*
|
||||
* @return string The string converted to UTF-8.
|
||||
*/
|
||||
protected function utf8Encode($s)
|
||||
{
|
||||
if ('mbstring' === $this->charsetConverter) {
|
||||
return mb_convert_encoding($s, 'UTF-8', mb_check_encoding($s, $this->charset) ? $this->charset : '8bit');
|
||||
}
|
||||
if ('iconv' === $this->charsetConverter) {
|
||||
$valid = true;
|
||||
set_error_handler(function () use (&$valid) {$valid = false;});
|
||||
$c = iconv($this->charset, 'UTF-8', $s);
|
||||
restore_error_handler();
|
||||
if ($valid) {
|
||||
return $c;
|
||||
}
|
||||
}
|
||||
|
||||
$s .= $s;
|
||||
$len = strlen($s);
|
||||
|
||||
for ($i = $len >> 1, $j = 0; $i < $len; ++$i, ++$j) {
|
||||
switch (true) {
|
||||
case $s[$i] < "\x80":
|
||||
$s[$j] = $s[$i];
|
||||
break;
|
||||
|
||||
case $s[$i] < "\xC0":
|
||||
$s[$j] = "\xC2";
|
||||
$s[++$j] = $s[$i];
|
||||
break;
|
||||
|
||||
default:
|
||||
$s[$j] = "\xC3";
|
||||
$s[++$j] = chr(ord($s[$i]) - 64);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return substr($s, 0, $j);
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,6 @@
|
||||
|
||||
namespace Symfony\Component\VarDumper\Dumper;
|
||||
|
||||
use Symfony\Component\VarDumper\Cloner\Data;
|
||||
use Symfony\Component\VarDumper\Cloner\Cursor;
|
||||
|
||||
/**
|
||||
@ -48,9 +47,9 @@ class CliDumper extends AbstractDumper
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct($output = null)
|
||||
public function __construct($output = null, $charset = null)
|
||||
{
|
||||
parent::__construct($output);
|
||||
parent::__construct($output, $charset);
|
||||
|
||||
if ('\\' === DIRECTORY_SEPARATOR && false !== @getenv('ANSICON')) {
|
||||
// Use only the base 16 xterm colors when using ANSICON
|
||||
@ -140,8 +139,8 @@ class CliDumper extends AbstractDumper
|
||||
break;
|
||||
|
||||
default:
|
||||
$attr['value'] = isset($value[0]) && !preg_match('//u', $value) ? Data::utf8Encode($value) : $value;
|
||||
$value = isset($type[0]) && !preg_match('//u', $type) ? Data::utf8Encode($type) : $type;
|
||||
$attr['value'] = isset($value[0]) && !preg_match('//u', $value) ? $this->utf8Encode($value) : $value;
|
||||
$value = isset($type[0]) && !preg_match('//u', $type) ? $this->utf8Encode($type) : $type;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -157,6 +156,9 @@ class CliDumper extends AbstractDumper
|
||||
{
|
||||
$this->dumpKey($cursor);
|
||||
|
||||
if ($bin) {
|
||||
$str = $this->utf8Encode($str);
|
||||
}
|
||||
if ('' === $str) {
|
||||
$this->line .= '""';
|
||||
$this->dumpLine($cursor->depth);
|
||||
@ -220,6 +222,9 @@ class CliDumper extends AbstractDumper
|
||||
{
|
||||
$this->dumpKey($cursor);
|
||||
|
||||
if (!preg_match('//u', $class)) {
|
||||
$class = $this->utf8Encode($class);
|
||||
}
|
||||
if (Cursor::HASH_OBJECT === $type) {
|
||||
$prefix = 'stdClass' !== $class ? $this->style('note', $class).' {' : '{';
|
||||
} elseif (Cursor::HASH_RESOURCE === $type) {
|
||||
@ -279,6 +284,9 @@ class CliDumper extends AbstractDumper
|
||||
protected function dumpKey(Cursor $cursor)
|
||||
{
|
||||
if (null !== $key = $cursor->hashKey) {
|
||||
if ($cursor->hashKeyIsBinary) {
|
||||
$key = $this->utf8Encode($key);
|
||||
}
|
||||
$attr = array('binary' => $cursor->hashKeyIsBinary);
|
||||
$bin = $cursor->hashKeyIsBinary ? 'b' : '';
|
||||
$style = 'key';
|
||||
|
@ -31,7 +31,7 @@ class HtmlDumper extends CliDumper
|
||||
protected $headerIsDumped = false;
|
||||
protected $lastDepth = -1;
|
||||
protected $styles = array(
|
||||
'default' => 'background-color:#18171B; color:#FF8400; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap',
|
||||
'default' => 'background-color:#18171B; color:#FF8400; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:100000',
|
||||
'num' => 'font-weight:bold; color:#1299DA',
|
||||
'const' => 'font-weight:bold',
|
||||
'str' => 'font-weight:bold; color:#56DB3A',
|
||||
|
@ -24,7 +24,6 @@ class HtmlDumperTest extends \PHPUnit_Framework_TestCase
|
||||
require __DIR__.'/Fixtures/dumb-var.php';
|
||||
|
||||
$dumper = new HtmlDumper('php://output');
|
||||
$dumper->setColors(false);
|
||||
$dumper->setDumpHeader('<foo></foo>');
|
||||
$dumper->setDumpBoundaries('<bar>', '</bar>');
|
||||
$cloner = new VarCloner();
|
||||
@ -108,6 +107,36 @@ class HtmlDumperTest extends \PHPUnit_Framework_TestCase
|
||||
</samp>]
|
||||
</bar>
|
||||
|
||||
EOTXT
|
||||
,
|
||||
|
||||
$out
|
||||
);
|
||||
}
|
||||
|
||||
public function testCharset()
|
||||
{
|
||||
if (!extension_loaded('mbstring')) {
|
||||
$this->markTestSkipped('This test requires mbstring.');
|
||||
}
|
||||
$var = mb_convert_encoding('Словарь', 'CP1251', 'UTF-8');
|
||||
|
||||
$dumper = new HtmlDumper('php://output', 'CP1251');
|
||||
$dumper->setDumpHeader('<foo></foo>');
|
||||
$dumper->setDumpBoundaries('<bar>', '</bar>');
|
||||
$cloner = new VarCloner();
|
||||
|
||||
$data = $cloner->cloneVar($var);
|
||||
$out = fopen('php://memory', 'r+b');
|
||||
$dumper->dump($data, $out);
|
||||
rewind($out);
|
||||
$out = stream_get_contents($out);
|
||||
|
||||
$this->assertStringMatchesFormat(
|
||||
<<<EOTXT
|
||||
<foo></foo><bar>b"<span class=sf-dump-str title="7 binary or non-UTF-8 characters">Словарь</span>"
|
||||
</bar>
|
||||
|
||||
EOTXT
|
||||
,
|
||||
|
||||
|
Reference in New Issue
Block a user