commit
87df0b7ee2
@ -4,6 +4,11 @@ php:
|
||||
- 5.3.3
|
||||
- 5.3
|
||||
- 5.4
|
||||
- 5.5
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- php: 5.5
|
||||
|
||||
before_script:
|
||||
- COMPOSER_ROOT_VERSION=dev-master composer --prefer-source --dev install
|
||||
|
@ -7,6 +7,22 @@ in 2.0 minor versions.
|
||||
To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash
|
||||
To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v2.0.0...v2.0.1
|
||||
|
||||
* 2.0.21 (2012-12-21)
|
||||
|
||||
* b8e5689: [FrameworkBundle] fixed ESI calls
|
||||
|
||||
* 2.0.20 (2012-12-20)
|
||||
|
||||
* 532cc9a: [FrameworkBundle] added support for URIs as an argument to HttpKernel::render()
|
||||
* 1f8c501: [FrameworkBundle] restricted the type of controllers that can be executed by InternalController
|
||||
* 8b2c17f: fix double-decoding in the routing system
|
||||
* 773d818: [FrameworkBundle] Added a check on file mime type for CodeHelper::fileExcerpt()
|
||||
* a0e2391: [FrameworkBundle] used the new method for trusted proxies
|
||||
* 8bb3208: [Config] Loader::import must return imported data
|
||||
* 447ff91: [HttpFoundation] changed UploadedFile::move() to use move_uploaded_file() when possible
|
||||
* 0489799: [HttpFoundation] added a check for the host header value
|
||||
* ae3d531: [TwigBundle] Moved the registration of the app global to the environment
|
||||
|
||||
* 2.0.19 (2012-11-29)
|
||||
|
||||
* e5536f0: replaced magic strings by proper constants
|
||||
|
@ -7,6 +7,46 @@ in 2.1 minor versions.
|
||||
To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash
|
||||
To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v2.1.0...v2.1.1
|
||||
|
||||
* 2.1.6 (2012-12-21)
|
||||
|
||||
* b8e5689: [FrameworkBundle] fixed ESI calls
|
||||
* ce536cd: [FrameworkBundle] fixed ESI calls
|
||||
|
||||
* 2.1.5 (2012-12-20)
|
||||
|
||||
* 532cc9a: [FrameworkBundle] added support for URIs as an argument to HttpKernel::render()
|
||||
* 1f8c501: [FrameworkBundle] restricted the type of controllers that can be executed by InternalController
|
||||
* 2cd43da: [Process] Allow non-blocking start with PhpProcess
|
||||
* 8b2c17f: fix double-decoding in the routing system
|
||||
* 098b593: [Session] Added exception to save method
|
||||
* ad29df5: [Form] Fixed DateTimeToStringTransformer parsing on PHP < 5.3.8
|
||||
* 773d818: [FrameworkBundle] Added a check on file mime type for CodeHelper::fileExcerpt()
|
||||
* f24e3d7: [HttpKernel] Revise MongoDbProfilerStorage::write() return value
|
||||
* 78c5273: [Session] Document Mongo|MongoClient argument type instead of "object"
|
||||
* de19a81: [HttpKernel] Support MongoClient and Mongo connection classes
|
||||
* b28af77: [Session] Support MongoClient and Mongo connection classes
|
||||
* 20e93bf: [Session] Utilize MongoDB::selectCollection()
|
||||
* b20c5ca: [Form] Fixed reverse transformation of values in DateTimeToStringTransformer
|
||||
* d2231d8: [Console] Add support for parsing terminal width/height on localized windows, fixes #5742
|
||||
* 03b880f: [Form] Fixed treatment of countables and traversables in Form::isEmpty()
|
||||
* 21a59ca: [Form] Fixed FileType not to throw an exception when bound empty
|
||||
* eac14b5: Check if key # is defined in $value
|
||||
* a0e2391: [FrameworkBundle] used the new method for trusted proxies
|
||||
* d6a402a: [Security] fixed path info encoding (closes #6040, closes #5695)
|
||||
* 47dfb9c: [HttpFoundation] added some tests for the previous merge and removed dead code (closes #6037)
|
||||
* 1ab4923: Improved Cache-Control header when no-cache is sent
|
||||
* 4e909bd: Fix to allow null values in labels array
|
||||
* 9e46819: Fixed: HeaderBag::parseCacheControl() not parsing quoted zero correctly
|
||||
* 8bb3208: [Config] Loader::import must return imported data
|
||||
* ca5d9ac: [DoctrineBridge] Fixed caching in DoctrineType when "choices" or "preferred_choices" is passed
|
||||
* 6e7e08f: [Form] Fixed the default value of "format" in DateType to DateType::DEFAULT_FORMAT if "widget" is not "single_text"
|
||||
* 447ff91: [HttpFoundation] changed UploadedFile::move() to use move_uploaded_file() when possible (closes #5878, closes #6185)
|
||||
* 0489799: [HttpFoundation] added a check for the host header value
|
||||
* b604eb7: [DoctrineBridge] Improved performance of the EntityType when used with the "query_builder" option
|
||||
* 99321cb: [DoctrineBridge] Fixed: Exception is thrown if the entity class is not known to Doctrine
|
||||
* 2ed30e7: Fixed DefaultValue for session.auto_start in NodeDefinition
|
||||
* ae3d531: [TwigBundle] Moved the registration of the app global to the environment
|
||||
|
||||
* 2.1.4 (2012-11-29)
|
||||
|
||||
* e5536f0: replaced magic strings by proper constants
|
||||
|
@ -3,7 +3,9 @@ Contributing
|
||||
|
||||
Symfony2 is an open source, community-driven project. If you'd like to contribute,
|
||||
please read the [Contributing Code][1] part of the documentation. If you're submitting
|
||||
a pull request, please follow the guidelines in the [Submitting a Patch][2] section.
|
||||
a pull request, please follow the guidelines in the [Submitting a Patch][2] section
|
||||
and use the [Pull Request Template][3].
|
||||
|
||||
[1]: http://symfony.com/doc/current/contributing/code/index.html
|
||||
[2]: http://symfony.com/doc/current/contributing/code/patches.html#check-list
|
||||
[3]: http://symfony.com/doc/current/contributing/code/patches.html#make-a-pull-request
|
||||
|
168
CONTRIBUTORS.md
168
CONTRIBUTORS.md
@ -11,116 +11,125 @@ Symfony2 is the result of the work of many people who made the code better
|
||||
- Johannes S (johannes)
|
||||
- Kris Wallsmith (kriswallsmith)
|
||||
- Christophe Coevoet (stof)
|
||||
- Tobias Schultze (tobion)
|
||||
- Pascal Borreli (pborreli)
|
||||
- Karma Dordrak (drak)
|
||||
- Ryan Weaver
|
||||
- Pascal Borreli (pborreli)
|
||||
- Lukas Kahwe Smith (lsmith)
|
||||
- Tobias Schultze (tobion)
|
||||
- Jeremy Mikola (jmikola)
|
||||
- Benjamin Eberlei (beberlei)
|
||||
- Igor Wiedler (igorw)
|
||||
- Joseph Bielawski (stloyd)
|
||||
- Eriksen Costa (eriksencosta)
|
||||
- Hugo Hamon (hhamon)
|
||||
- Jonathan Wage (jwage)
|
||||
- Martin Hasoň (hason)
|
||||
- Jonathan Wage (jwage)
|
||||
- William Durand (couac)
|
||||
- Alexandre Salomé (alexandresalome)
|
||||
- ornicar
|
||||
- stealth35 (stealth35)
|
||||
- Jean-François Simon (jfsimon)
|
||||
- Bulat Shakirzyanov (avalanche123)
|
||||
- Francis Besset (francisbesset)
|
||||
- Miha Vrhovnik
|
||||
- Henrik Bjørnskov (henrikbjorn)
|
||||
- Konstantin Kudryashov (everzet)
|
||||
- Jean-François Simon (jfsimon)
|
||||
- Jakub Zalas (jakubzalas)
|
||||
- Arnaud Le Blanc (arnaud-lb)
|
||||
- Eric Clemmons (ericclemmons)
|
||||
- Henrik Westphal (snc)
|
||||
- Deni
|
||||
- Dariusz Górecki (canni)
|
||||
- Alexander Mols (asm89)
|
||||
- Arnout Boks (aboks)
|
||||
- Hidenori Goto (hidenorigoto)
|
||||
- Jordan Alliot (jalliot)
|
||||
- Deni
|
||||
- Romain Neutron (romain)
|
||||
- Dariusz Górecki (canni)
|
||||
- Marc Weistroff (futurecat)
|
||||
- Brandon Turner
|
||||
- Jordan Alliot (jalliot)
|
||||
- Arnout Boks (aboks)
|
||||
- Саша Стаменковић (umpirsky)
|
||||
- Hidenori Goto (hidenorigoto)
|
||||
- Brandon Turner
|
||||
- Andrej Hudec (pulzarraider)
|
||||
- Brikou Carré (brikou)
|
||||
- John Wards (johnwards)
|
||||
- Daniel Holmes (dholmes)
|
||||
- Antoine Hérault (herzult)
|
||||
- Daniel Holmes (dholmes)
|
||||
- Bilal Amarni (bamarni)
|
||||
- Christian Raue
|
||||
- Tim Nagel (merk)
|
||||
- Michal Piotrowski (eventhorizon)
|
||||
- Włodzimierz Gajda (gajdaw)
|
||||
- Florin Patan (florinpatan)
|
||||
- lenar
|
||||
- Fabien Pennequin (fabienpennequin)
|
||||
- Tim Nagel (merk)
|
||||
- excelwebzone
|
||||
- Bilal Amarni (bamarni)
|
||||
- Romain Neutron (romain)
|
||||
- Bart van den Burg (burgov)
|
||||
- excelwebzone
|
||||
- Kevin Bond (kbond)
|
||||
- Włodzimierz Gajda (gajdaw)
|
||||
- Toni Uebernickel (havvg)
|
||||
- Douglas Greenshields (shieldo)
|
||||
- Richard Miller (mr_r_miller)
|
||||
- Grégoire Pineau (lyrixx)
|
||||
- Toni Uebernickel (havvg)
|
||||
- Jacob Dreesen (jdreesen)
|
||||
- Douglas Greenshields (shieldo)
|
||||
- Richard Shank (iampersistent)
|
||||
- Sebastian Hörl (blogsh)
|
||||
- Florin Patan (florinpatan)
|
||||
- Michal Piotrowski (eventhorizon)
|
||||
- Grégoire Pineau (lyrixx)
|
||||
- Mario A. Alvarez Garcia (nomack84)
|
||||
- Juti Noppornpitak
|
||||
- Robert Schönthal (digitalkaoz)
|
||||
- Michał Pipa (michal.pipa)
|
||||
- woodspire
|
||||
- Daniel Gomes (danielcsgomes)
|
||||
- Michel Weimerskirch (mweimerskirch)
|
||||
- Tigran Azatyan (tigranazatyan)
|
||||
- Pierre Minnieur (pminnieur)
|
||||
- Arnaud Kleinpeter (nanocom)
|
||||
- Jonathan Ingram (jonathaningram)
|
||||
- Javier Eguiluz (javier.eguiluz)
|
||||
- Matthieu Ouellette-Vachon (maoueh)
|
||||
- Larry Garfield (crell)
|
||||
- Amal Raghav (kertz)
|
||||
- Artur Kotyrba
|
||||
- Pablo Godel (pgodel)
|
||||
- Helmer Aaviksoo
|
||||
- Clément JOBEILI (dator)
|
||||
- Julien Brochet (mewt)
|
||||
- Arnaud Kleinpeter (nanocom)
|
||||
- Jonathan Ingram (jonathaningram)
|
||||
- David Buchmann (dbu)
|
||||
- Sebastiaan Stok (sstok)
|
||||
- Benjamin Dulau (dbenjamin)
|
||||
- Felix Labrecque
|
||||
- Andreas Hucks (meandmymonkey)
|
||||
- Noel Guilbert (noel)
|
||||
- Jérémie Augustin (jaugustin)
|
||||
- Martin Schuhfuß (usefulthink)
|
||||
- Thomas Rabaix (rande)
|
||||
- Dennis Benkert (denderello)
|
||||
- Marcel Beerta (mazen)
|
||||
- Rafael Dohms (rdohms)
|
||||
- Matthieu Bontemps (mbontemps)
|
||||
- fivestar
|
||||
- Dominique Bongiraud
|
||||
- Pablo Godel (pgodel)
|
||||
- Arnaud Le Blanc (arnaud-lb)
|
||||
- Leszek Prabucki (l3l0)
|
||||
- Danny Berger (dpb587)
|
||||
- Dustin Whittle (dustinwhittle)
|
||||
- Fran Moreno (franmomu)
|
||||
- jeff
|
||||
- Justin Hileman (bobthecow)
|
||||
- Sven Paulus (subsven)
|
||||
- Xavier Perez
|
||||
- Rui Marinho (ruimarinho)
|
||||
- Ray
|
||||
- Joseph Rouff (rouffj)
|
||||
- Marcel Beerta (mazen)
|
||||
- Albert Casademont (acasademont)
|
||||
- Gordon Franke (gimler)
|
||||
- Francois Zaninotto
|
||||
- François Zaninotto (fzaninotto)
|
||||
- Danny Berger (dpb587)
|
||||
- Xavier Montaña Carreras (xmontana)
|
||||
- Gábor Egyed (1ed)
|
||||
- Katsuhiro OGAWA
|
||||
- Clemens Tolboom
|
||||
- Alif Rachmawadi
|
||||
- Larry Garfield (crell)
|
||||
- boombatower
|
||||
- Florian Klein (docteurklein)
|
||||
- jules boussekeyt (gordonslondon)
|
||||
- Jan Sorgalla (jsor)
|
||||
- Ray
|
||||
- Lee McDermott
|
||||
- Guilherme Blanco (guilhermeblanco)
|
||||
- jdhoek
|
||||
@ -128,40 +137,44 @@ Symfony2 is the result of the work of many people who made the code better
|
||||
- Wodor Wodorski
|
||||
- Matthew Lewinski (lewinski)
|
||||
- Kim Hemsø Rasmussen
|
||||
- Dirk Pahl (dirkaholic)
|
||||
- Wouter Van Hecke
|
||||
- Gyula Sallai (salla)
|
||||
- Michael Holm (hollo)
|
||||
- Peter Kokot (maastermedia)
|
||||
- arjen
|
||||
- Florian Klein (docteurklein)
|
||||
- Adrien Brault (adrienbrault)
|
||||
- David Buchmann (dbu)
|
||||
- Manuel Kiessling (manuelkiessling)
|
||||
- Sergey Linnik
|
||||
- Bertrand Zuchuat (garfield-fr)
|
||||
- Beau Simensen (simensen)
|
||||
- Grégoire Paris (greg0ire)
|
||||
- Tamas Szijarto
|
||||
- Grégoire Passault (gregwar)
|
||||
- Aurelijus Valeiša (aurelijus)
|
||||
- Gustavo Piltcher
|
||||
- Albert Casademont (acasademont)
|
||||
- Stepan Tanasiychuk (stfalcon)
|
||||
- Albert Jessurum (ajessu)
|
||||
- Tiago Ribeiro (fixe)
|
||||
- Adrian Rudnik (kreischweide)
|
||||
- Francesc Rosàs (frosas)
|
||||
- Julien Galenski (ruian)
|
||||
- Bongiraud Dominique
|
||||
- Michel Salib (michelsalib)
|
||||
- Jeanmonod David (jeanmonod)
|
||||
- Thomas Lallement (raziel057)
|
||||
- Niklas Fiekas
|
||||
- Brouznouf
|
||||
- Andréia Bohner (andreia)
|
||||
- Sebastiaan Stok (sstok)
|
||||
- Sebastian Bergmann
|
||||
- Fran Moreno (franmomu)
|
||||
- Greg Thornton (xdissent)
|
||||
- sun (sun)
|
||||
- Yaroslav Kiliba
|
||||
- Lars Strojny
|
||||
- Beau Simensen (simensen)
|
||||
- Terje Bråten
|
||||
- Costin Bereveanu (schniper)
|
||||
- Markus Lanthaler (lanthaler)
|
||||
- realmfoo
|
||||
- Tamas Szijarto
|
||||
- Mario A. Alvarez Garcia (nomack84)
|
||||
- Tobias Naumann
|
||||
- Shein Alexey
|
||||
- Joe Lencioni
|
||||
@ -173,21 +186,18 @@ Symfony2 is the result of the work of many people who made the code better
|
||||
- Oscar Cubo Medina (ocubom)
|
||||
- Christophe L. (christophelau)
|
||||
- Michael Ridgway
|
||||
- Stepan Tanasiychuk (stfalcon)
|
||||
- Pavel Campr (pcampr)
|
||||
- Brian King
|
||||
- Jeanmonod David (jeanmonod)
|
||||
- Jan Schumann
|
||||
- Niklas Fiekas
|
||||
- Olivier Dolbeau (odolbeau)
|
||||
- Michele Orselli (orso)
|
||||
- Asier Illarramendi (doup)
|
||||
- Christoph Mewes (xrstf)
|
||||
- Dirk Pahl (dirkaholic)
|
||||
- Jonas Flodén (flojon)
|
||||
- Shigenibu Nishikawa
|
||||
- Marcin Sikoń (marphi)
|
||||
- Miquel Rodríguez Telep (mrtorrent)
|
||||
- boombatower
|
||||
- Filippo Tessarotto
|
||||
- Laurent Bachelier (laurentb)
|
||||
- Fabian Lange (codingfabian)
|
||||
- Yoshio HANAWA
|
||||
@ -196,9 +206,11 @@ Symfony2 is the result of the work of many people who made the code better
|
||||
- Michael Piecko (michael.piecko)
|
||||
- Manuel de Ruiter (manuel)
|
||||
- ondrowan
|
||||
- Roman Marintsenko (inori)
|
||||
- mcben
|
||||
- Yaroslav Kiliba
|
||||
- Jérôme Vieilledent (lolautruche)
|
||||
- Peter Kruithof (pkruithof)
|
||||
- Eric GELOEN (gelo)
|
||||
- Erik Trapman (eriktrapman)
|
||||
- De Cock Xavier (xdecock)
|
||||
- Manuel Reinhard (sprain)
|
||||
@ -221,19 +233,33 @@ Symfony2 is the result of the work of many people who made the code better
|
||||
- Zach Badgett (zachbadgett)
|
||||
- Aurélien Fredouelle
|
||||
- Francesco Levorato
|
||||
- Thomas Tourlourat (armetiz)
|
||||
- Geoffrey Tran (geoff)
|
||||
- Florian Rey (nervo)
|
||||
- Christian Schaefer (caefer)
|
||||
- Julien Galenski (ruian)
|
||||
- Elliot Anderson (elliot)
|
||||
- Patrick Kaufmann
|
||||
- Ben Ramsey (ramsey)
|
||||
- Christian Jul Jensen
|
||||
- Chris Jones (leek)
|
||||
- Markus Bachmann (baachi)
|
||||
- Colin Frei
|
||||
- aubx
|
||||
- Max Rath (drak3)
|
||||
- DerManoMann
|
||||
- Nahuel Cuesta (ncuesta)
|
||||
- Chris Boden (cboden)
|
||||
- Roumen Damianoff (roumen)
|
||||
- Jeremy David (jeremy.david)
|
||||
- Konstantin Myakshin (koc)
|
||||
- Dustin Dobervich (dustin10)
|
||||
- Sebastian Marek (proofek)
|
||||
- Erkhembayar Gantulga (erheme318)
|
||||
- Ken Marfilla (marfillaster)
|
||||
- Rostyslav Kinash
|
||||
- jfcixmedia
|
||||
- Vincent Simonin
|
||||
- Chris Heng
|
||||
- yktd26
|
||||
- Tom Van Looy (tvlooy)
|
||||
- umpirski
|
||||
@ -241,57 +267,70 @@ Symfony2 is the result of the work of many people who made the code better
|
||||
- John Kary (johnkary)
|
||||
- Hossein Bukhamsin
|
||||
- Fabrice Bernhard (fabriceb)
|
||||
- Mark Sonnabaum
|
||||
- develop
|
||||
- Filippo Tessarotto
|
||||
- hossein zolfi (ocean)
|
||||
- Atsuhiro KUBO (iteman)
|
||||
- Samy Dindane (dinduks)
|
||||
- yclian
|
||||
- Jérémy Romey (jeremyfreeagent)
|
||||
- Matt Daum (daum)
|
||||
- Hiromi Hishida (77web)
|
||||
- Yuen-Chi Lian
|
||||
- Joshua Nye
|
||||
- Sebastian Krebs
|
||||
- avorobiev
|
||||
- Mark Challoner
|
||||
- Andrew Tchircoff (andrewtch)
|
||||
- BilgeXA
|
||||
- michaelwilliams
|
||||
- Casper Valdemar Poulsen
|
||||
- Josiah (josiah)
|
||||
- John Bohn (jbohn)
|
||||
- Nicolas Schwartz (nicoschwartz)
|
||||
- Degory Valentine
|
||||
- Krzysiek Łabuś
|
||||
- Xavier Lacot (xavier)
|
||||
- Markus Lanthaler (lanthaler)
|
||||
- Olivier Maisonneuve
|
||||
- Daniel F. Kudwien (sun)
|
||||
- cgonzalez
|
||||
- matt foster
|
||||
- Evan S Kaufman (evanskaufman)
|
||||
- Ismael Ambrosi (iambrosi)
|
||||
- Jayson Xu (superjavason)
|
||||
- Jan Prieser
|
||||
- James Michael DuPont
|
||||
- Tom Klingenberg
|
||||
- Gunther Konig
|
||||
- Christopher Hall (mythmakr)
|
||||
- Paul Kamer (pkamer)
|
||||
- Pierre Vanliefland (pvanliefland)
|
||||
- Philipp Kräutli (pkraeutli)
|
||||
- frost-nzcr4
|
||||
- Loïc Chardonnet (gnusat)
|
||||
- Michaël Perrin (michael.perrin)
|
||||
- Abhoryo
|
||||
- Fabian Vogler (fabian)
|
||||
- Leevi Graham
|
||||
- Maksim Kotlyar (makasim)
|
||||
- Neil Ferreira
|
||||
- Tony Malzhacker
|
||||
- Cyril Quintin (cyqui)
|
||||
- Gerard van Helden (drm)
|
||||
- Johnny Peck (johnnypeck)
|
||||
- Denis Gorbachev (starfall)
|
||||
- Kirill chEbba Chebunin
|
||||
- Benjamin Leveque (benji07)
|
||||
- Gustavo Falco (gfalco)
|
||||
- Matt Robinson (inanimatt)
|
||||
- julien pauli (jpauli)
|
||||
- mwsaz
|
||||
- Benoît Bourgeois
|
||||
- Filipe Guerra
|
||||
- corphi
|
||||
- grizlik
|
||||
- Derek ROTH
|
||||
- Shin Ohno (ganchiku)
|
||||
- Jan Kramer (jankramer)
|
||||
- Drew Butler (nodrew)
|
||||
- Don Pinkster
|
||||
- Emil Einarsson
|
||||
@ -302,28 +341,27 @@ Symfony2 is the result of the work of many people who made the code better
|
||||
- Arno Geurts
|
||||
- Adán Lobato (adanlobato)
|
||||
- Mikhail Yurasov
|
||||
- jamogon
|
||||
- Sam Williams
|
||||
- Miha Vrhovnik
|
||||
- Moritz Borgmann
|
||||
- Daniel Cestari
|
||||
- Thomas Tourlourat (armetiz)
|
||||
- Eugene Leonovich
|
||||
- Karoly Negyesi (chx)
|
||||
- Javier López (loalf)
|
||||
- Magnus Nordlander (magnusnordlander)
|
||||
- Adam Monsen (meonkeys)
|
||||
- Florian Rey (nervo)
|
||||
- LOUARDI Abdeltif (ouardisoft)
|
||||
- Robert Gruendler (pulse00)
|
||||
- ragtek (ragtek)
|
||||
- Benoît Merlet (trompette)
|
||||
- Maks
|
||||
- Jan Behrens
|
||||
- Raul Fraile (raulfraile)
|
||||
- sensio
|
||||
- Patrick Kaufmann
|
||||
- Théophile Helleboid - chtitux
|
||||
- Ben Ramsey (ramsey)
|
||||
- Christian Jul Jensen
|
||||
- Chris Jones (leek)
|
||||
- xaav
|
||||
- Juti Noppornpitak
|
||||
- Roumen Damianoff
|
||||
- Sander Coolen
|
||||
- Josip Kruslin
|
||||
- Anton Babenko (antonbabenko)
|
||||
@ -339,12 +377,9 @@ Symfony2 is the result of the work of many people who made the code better
|
||||
- julien.galenski
|
||||
- Sébastien Lavoie
|
||||
- Per Sandström (per)
|
||||
- Ken Marfilla (marfillaster)
|
||||
- Robert Kiss (kepten)
|
||||
- jfcixmedia
|
||||
- Vitaliy Tverdokhlib (vitaliytv)
|
||||
- Martijn Evers
|
||||
- Chris Heng
|
||||
- Nerijus Arlauskas
|
||||
- DerManoMann
|
||||
- Jochen Bayer (jocl)
|
||||
@ -352,6 +387,7 @@ Symfony2 is the result of the work of many people who made the code better
|
||||
- Evan Villemez
|
||||
- Davide Borsatto (davide.borsatto)
|
||||
- kaiwa
|
||||
- Albert Ganiev (helios-ag)
|
||||
- Neil Katin
|
||||
- Gustavo Adrian
|
||||
- Roger Webb
|
||||
@ -365,8 +401,8 @@ Symfony2 is the result of the work of many people who made the code better
|
||||
- modi
|
||||
- Sergey Yuferev
|
||||
- Richard van den Brand (ricbra)
|
||||
- Mark Sonnabaum
|
||||
- Aharon Perkel
|
||||
- Malaney J. Hill
|
||||
- Andy Cox (ringo)
|
||||
- Balázs Benyó (duplabe)
|
||||
- Sebastian Utz
|
||||
@ -374,8 +410,6 @@ Symfony2 is the result of the work of many people who made the code better
|
||||
- Cédric Lahouste (rapotor)
|
||||
- Janusz Jablonski
|
||||
- George Giannoulopoulos
|
||||
- Thomas Lallement (raziel057)
|
||||
- Matt Daum (daum)
|
||||
- Alberto Pirovano (geezmo)
|
||||
- Xavier Briand (xavierbriand)
|
||||
- Evan Kaufman
|
||||
@ -386,7 +420,6 @@ Symfony2 is the result of the work of many people who made the code better
|
||||
- Stéphane PY (steph_py)
|
||||
- Martin Eckhardt
|
||||
- Michael Dowling (mtdowling)
|
||||
- BilgeXA
|
||||
- mlively
|
||||
- Thomas Chmielowiec (chmielot)
|
||||
- Sebastian Ionescu
|
||||
@ -406,30 +439,28 @@ Symfony2 is the result of the work of many people who made the code better
|
||||
- Paweł Wacławczyk (pwc)
|
||||
- Thomas Bibb
|
||||
- Josef Cech
|
||||
- Andrey Esaulov (andremaha)
|
||||
- hicham ELGUAROUANI (hiiimoo)
|
||||
- Roman Marintsenko (inori)
|
||||
- Ivan Kurnosov
|
||||
- stloyd
|
||||
- Martin Parsiegla (spea)
|
||||
- Chris Tickner (tickner)
|
||||
- Luis Muñoz
|
||||
- Thomas Chmielowiec
|
||||
- Gunther Konig
|
||||
- Oleg Zinchenko
|
||||
- Benjamin Grandfond (benjamin)
|
||||
- Christoph Nissle (derstoffel)
|
||||
- Stefano Sala (stefano.sala)
|
||||
- Xavier HAUSHERR
|
||||
- Benjamin Zikarsky
|
||||
- Romain Dorgueil
|
||||
- Grayson Koonce (breerly)
|
||||
- Andy Stanberry
|
||||
- alefranz
|
||||
- Loïc Chardonnet (gnusat)
|
||||
- Alessio Baglio (ioalessio)
|
||||
- Jérôme Macias (jeromemacias)
|
||||
- Cédric Dugat (ph3nol)
|
||||
- Philip Dahlstrøm (phidah)
|
||||
- Pierre Vanliefland (pvanliefland)
|
||||
- Artem Lopata (bumz)
|
||||
- Alexey Popkov
|
||||
- Artyom Protaskin
|
||||
@ -440,10 +471,12 @@ Symfony2 is the result of the work of many people who made the code better
|
||||
- hirocaster
|
||||
- Andrey Chernykh
|
||||
- Alexander Miehe (engerim)
|
||||
- Jörn Lang (j.lang)
|
||||
- Jan Marek (janmarek)
|
||||
- Dan Patrick (mdpatrick)
|
||||
- Pierre-Yves LEBECQ (pylebecq)
|
||||
- Rares Vlaseanu (raresvla)
|
||||
- Tugdual Saunier (tucksaun)
|
||||
- Alexander Zogheb
|
||||
- Florian Pfitzer
|
||||
- Linnik Sergey
|
||||
@ -463,7 +496,6 @@ Symfony2 is the result of the work of many people who made the code better
|
||||
- Grummfy
|
||||
- Eduardo Gulias
|
||||
- Rowan Manning
|
||||
- Eric GELOEN
|
||||
- David Windell
|
||||
- Gabriel Birke
|
||||
- Alan Chen
|
||||
@ -517,7 +549,6 @@ Symfony2 is the result of the work of many people who made the code better
|
||||
- Samuel Laulhau
|
||||
- Oleg Stepura
|
||||
- James Michael DuPont
|
||||
- Miha Vrhovnik
|
||||
- Ondrej Slinták
|
||||
- vlechemin
|
||||
- Skorney
|
||||
@ -533,6 +564,7 @@ Symfony2 is the result of the work of many people who made the code better
|
||||
- David Soria Parra
|
||||
- Sergiy Sokolenko
|
||||
- Penny Leach
|
||||
- Philipp Rieber
|
||||
- DanSync
|
||||
- Peter Zwosta
|
||||
- parhs
|
||||
@ -552,7 +584,6 @@ Symfony2 is the result of the work of many people who made the code better
|
||||
- Daniel Londero (dlondero)
|
||||
- Adel ELHAIBA (eadel)
|
||||
- Fabien Dosse (fabd)
|
||||
- Jonas Flodén (flojon)
|
||||
- Yohan Giarelli (frequence-web)
|
||||
- Massimiliano Arione (garak)
|
||||
- Vladislav Krupenkin (ideea)
|
||||
@ -568,6 +599,7 @@ Symfony2 is the result of the work of many people who made the code better
|
||||
- Daniel Perez Pinazo (pitiflautico)
|
||||
- Ruud Kamphuis (ruudk)
|
||||
- Sebastian Busch (sebu)
|
||||
- Simon Terrien (sterrien)
|
||||
- Markus Tacker (tacker)
|
||||
- Tyler Stroud (tystr)
|
||||
- Eugene Babushkin (warl)
|
||||
|
2
LICENSE
2
LICENSE
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2004-2012 Fabien Potencier
|
||||
Copyright (c) 2004-2013 Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -46,17 +46,19 @@ Contributing
|
||||
|
||||
Symfony2 is an open source, community-driven project. If you'd like to contribute,
|
||||
please read the [Contributing Code][4] part of the documentation. If you're submitting
|
||||
a pull request, please follow the guidelines in the [Submitting a Patch][5] section.
|
||||
a pull request, please follow the guidelines in the [Submitting a Patch][5] section
|
||||
and use [Pull Request Template][6].
|
||||
|
||||
Running Symfony2 Tests
|
||||
----------------------
|
||||
|
||||
Information on how to run the Symfony2 test suite can be found in the
|
||||
[Running Symfony2 Tests][6] section.
|
||||
[Running Symfony2 Tests][7] section.
|
||||
|
||||
[1]: http://symfony.com/download
|
||||
[2]: http://symfony.com/get_started
|
||||
[3]: http://symfony.com/doc/current/
|
||||
[4]: http://symfony.com/doc/current/contributing/code/index.html
|
||||
[5]: http://symfony.com/doc/current/contributing/code/patches.html#check-list
|
||||
[6]: http://symfony.com/doc/master/contributing/code/tests.html
|
||||
[6]: http://symfony.com/doc/current/contributing/code/patches.html#make-a-pull-request
|
||||
[7]: http://symfony.com/doc/master/contributing/code/tests.html
|
||||
|
240
UPGRADE-2.2.md
240
UPGRADE-2.2.md
@ -1,6 +1,24 @@
|
||||
UPGRADE FROM 2.1 to 2.2
|
||||
=======================
|
||||
|
||||
### TwigBridge
|
||||
|
||||
* The `render` tag signature and arguments changed.
|
||||
|
||||
Before:
|
||||
|
||||
```
|
||||
{% render 'BlogBundle:Post:list' with { 'limit': 2 }, { 'alt': 'BlogBundle:Post:error' } %}
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```
|
||||
{% render url('post_list', { 'limit': 2 }), { 'alt': 'BlogBundle:Post:error' } %}
|
||||
```
|
||||
|
||||
where `post_list` is the route name for the `BlogBundle:Post:list` controller.
|
||||
|
||||
### HttpFoundation
|
||||
|
||||
* The MongoDbSessionHandler default field names and timestamp type have changed.
|
||||
@ -39,6 +57,168 @@
|
||||
|
||||
* The PasswordType is now not trimmed by default.
|
||||
|
||||
* The class FormException is now an interface. The old class is still available
|
||||
under the name Symfony\Component\Form\Exception\Exception, but will probably
|
||||
be removed before 2.2. If you created FormException instances manually,
|
||||
you are now advised to create any of the other exceptions in the
|
||||
Symfony\Component\Form\Exception namespace or to create custom exception
|
||||
classes for your purpose.
|
||||
|
||||
* Translating validation errors is now optional. You can still do so
|
||||
manually if you like, or you can simplify your templates to simply output
|
||||
the already translated message.
|
||||
|
||||
Before:
|
||||
|
||||
```
|
||||
{{
|
||||
error.messagePluralization is null
|
||||
? error.messageTemplate|trans(error.messageParameters, 'validators')
|
||||
: error.messageTemplate|transchoice(error.messagePluralization, error.messageParameters, 'validators')
|
||||
}}
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```
|
||||
{{ error.message }}
|
||||
```
|
||||
|
||||
* FormType, ModelType and PropertyPathMapper now have constructors. If you
|
||||
extended these classes, you should call the parent constructor now.
|
||||
Note that you are not recommended to extend FormType nor ModelType. You should
|
||||
extend AbstractType instead and use the Form component's own inheritance
|
||||
mechanism (`AbstractType::getParent()`).
|
||||
|
||||
Before:
|
||||
|
||||
```
|
||||
use Symfony\Component\Form\Extensions\Core\DataMapper\PropertyPathMapper;
|
||||
|
||||
class CustomMapper extends PropertyPathMapper
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```
|
||||
use Symfony\Component\Form\Extensions\Core\DataMapper\PropertyPathMapper;
|
||||
|
||||
class CustomMapper extends PropertyPathMapper
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### Deprecations
|
||||
|
||||
* The methods `getParent()`, `setParent()` and `hasParent()` in
|
||||
`FormBuilderInterface` were deprecated and will be removed in Symfony 2.3.
|
||||
You should not rely on these methods in your form type because the parent
|
||||
of a form can change after building it.
|
||||
|
||||
* The class PropertyPath and related classes were deprecated and moved to a
|
||||
dedicated component PropertyAccess. If you used any of these classes or
|
||||
interfaces, you should adapt the namespaces now. During the move,
|
||||
InvalidPropertyException was renamed to NoSuchPropertyException.
|
||||
|
||||
Before:
|
||||
|
||||
```
|
||||
use Symfony\Component\Form\Util\PropertyPath;
|
||||
use Symfony\Component\Form\Util\PropertyPathBuilder;
|
||||
use Symfony\Component\Form\Util\PropertyPathInterface;
|
||||
use Symfony\Component\Form\Util\PropertyPathIterator;
|
||||
use Symfony\Component\Form\Util\PropertyPathIteratorInterface;
|
||||
use Symfony\Component\Form\Exception\InvalidPropertyException;
|
||||
use Symfony\Component\Form\Exception\InvalidPropertyPathException;
|
||||
use Symfony\Component\Form\Exception\PropertyAccessDeniedException;
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```
|
||||
use Symfony\Component\PropertyAccess\PropertyPath;
|
||||
use Symfony\Component\PropertyAccess\PropertyPathBuilder;
|
||||
use Symfony\Component\PropertyAccess\PropertyPathInterface;
|
||||
use Symfony\Component\PropertyAccess\PropertyPathIterator;
|
||||
use Symfony\Component\PropertyAccess\PropertyPathIteratorInterface;
|
||||
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
|
||||
use Symfony\Component\PropertyAccess\Exception\InvalidPropertyPathException;
|
||||
use Symfony\Component\PropertyAccess\Exception\PropertyAccessDeniedException;
|
||||
```
|
||||
|
||||
Also, `FormUtil::singularify()` was split away into a class StringUtil
|
||||
in the new component.
|
||||
|
||||
Before:
|
||||
|
||||
```
|
||||
use Symfony\Component\Form\Util\FormUtil;
|
||||
|
||||
$singular = FormUtil::singularify($plural);
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```
|
||||
use Symfony\Component\PropertyAccess\StringUtil;
|
||||
|
||||
$singular = StringUtil::singularify($plural);
|
||||
```
|
||||
|
||||
The methods `getValue()` and `setValue()` were moved to a new class
|
||||
PropertyAccessor.
|
||||
|
||||
Before:
|
||||
|
||||
```
|
||||
use Symfony\Component\Form\Util\PropertyPath;
|
||||
|
||||
$propertyPath = new PropertyPath('some.path');
|
||||
|
||||
$value = $propertyPath->getValue($object);
|
||||
$propertyPath->setValue($object, 'new value');
|
||||
```
|
||||
|
||||
After (alternative 1):
|
||||
|
||||
```
|
||||
use Symfony\Component\PropertyAccess\PropertyAccess;
|
||||
|
||||
$accessor = PropertyAccess::getPropertyAccessor();
|
||||
|
||||
$value = $propertyAccessor->getValue($object, 'some.path');
|
||||
$accessor->setValue($object, 'some.path', 'new value');
|
||||
```
|
||||
|
||||
After (alternative 2):
|
||||
|
||||
```
|
||||
use Symfony\Component\PropertyAccess\PropertyAccess;
|
||||
use Symfony\Component\PropertyAccess\PropertyPath;
|
||||
|
||||
$accessor = PropertyAccess::getPropertyAccessor();
|
||||
$propertyPath = new PropertyPath('some.path');
|
||||
|
||||
$value = $propertyAccessor->getValue($object, $propertyPath);
|
||||
$accessor->setValue($object, $propertyPath, 'new value');
|
||||
```
|
||||
|
||||
### Routing
|
||||
|
||||
* RouteCollection does not behave like a tree structure anymore but as a flat
|
||||
@ -154,6 +334,27 @@
|
||||
}
|
||||
```
|
||||
|
||||
* The sources of the pluralized messages in translation files have changed
|
||||
from the singular to the pluralized version. If you created custom
|
||||
translation files for validator errors, you should adapt them.
|
||||
|
||||
Before:
|
||||
|
||||
<trans-unit id="6">
|
||||
<source>You must select at least {{ limit }} choices.</source>
|
||||
<target>Sie müssen mindestens {{ limit }} Möglichkeit wählen.|Sie müssen mindestens {{ limit }} Möglichkeiten wählen.</target>
|
||||
</trans-unit>
|
||||
|
||||
After:
|
||||
|
||||
<trans-unit id="6">
|
||||
<source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
|
||||
<target>Sie müssen mindestens {{ limit }} Möglichkeit wählen.|Sie müssen mindestens {{ limit }} Möglichkeiten wählen.</target>
|
||||
</trans-unit>
|
||||
|
||||
Check the file src/Symfony/Component/Validator/Resources/translations/validators.en.xlf
|
||||
for the new message sources.
|
||||
|
||||
#### Deprecations
|
||||
|
||||
* The interface `ClassMetadataFactoryInterface` was deprecated and will be
|
||||
@ -319,3 +520,42 @@
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### FrameworkBundle
|
||||
|
||||
* The `render` method of the `actions` templating helper signature and arguments changed:
|
||||
|
||||
Before:
|
||||
|
||||
```
|
||||
<?php echo $view['actions']->render('BlogBundle:Post:list', array('limit' => 2), array('alt' => 'BlogBundle:Post:error')) ?>
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```
|
||||
<?php echo $view['actions']->render($view['router']->generate('post_list', array('limit' => 2)), array('alt' => 'BlogBundle:Post:error')) ?>
|
||||
```
|
||||
|
||||
where `post_list` is the route name for the `BlogBundle:Post:list` controller.
|
||||
|
||||
#### Configuration
|
||||
|
||||
* The 2.2 version introduces a new parameter `trusted_proxies` that replaces
|
||||
`trust_proxy_headers` in the framework configuration.
|
||||
|
||||
Before:
|
||||
|
||||
```
|
||||
# app/config/config.yml
|
||||
framework:
|
||||
trust_proxy_headers: false
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```
|
||||
# app/config/config.yml
|
||||
framework:
|
||||
trusted_proxies: ['127.0.0.1', '10.0.0.1'] # a list of proxy IPs you trust
|
||||
```
|
||||
|
@ -18,7 +18,8 @@
|
||||
"require": {
|
||||
"php": ">=5.3.3",
|
||||
"doctrine/common": ">2.2,<2.4-dev",
|
||||
"twig/twig": ">=1.9.1,<2.0-dev"
|
||||
"twig/twig": ">=1.11.0,<2.0-dev",
|
||||
"psr/log": "~1.0"
|
||||
},
|
||||
"replace": {
|
||||
"symfony/browser-kit": "self.version",
|
||||
@ -59,7 +60,7 @@
|
||||
"doctrine/data-fixtures": "1.0.*",
|
||||
"doctrine/dbal": ">=2.2,<2.4-dev",
|
||||
"doctrine/orm": ">=2.2.3,<2.4-dev",
|
||||
"monolog/monolog": "1.*",
|
||||
"monolog/monolog": "~1.3",
|
||||
"propel/propel1": "dev-master"
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -1,10 +1,11 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
2.1.5
|
||||
2.2.0
|
||||
-----
|
||||
|
||||
* fixed caching of choice lists when EntityType is used with the "query_builder" option
|
||||
* added an optional PropertyAccessorInterface parameter to DoctrineType,
|
||||
EntityType and EntityChoiceList
|
||||
|
||||
2.1.0
|
||||
-----
|
||||
|
@ -93,6 +93,8 @@ class ContainerAwareEventManager extends EventManager
|
||||
*
|
||||
* @param string|array $events The event(s) to listen on.
|
||||
* @param object|string $listener The listener object.
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function addEventListener($events, $listener)
|
||||
{
|
||||
|
@ -42,6 +42,8 @@ abstract class AbstractDoctrineExtension extends Extension
|
||||
/**
|
||||
* @param array $objectManager A configured object manager.
|
||||
* @param ContainerBuilder $container A ContainerBuilder instance
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function loadMappingInformation(array $objectManager, ContainerBuilder $container)
|
||||
{
|
||||
@ -119,6 +121,8 @@ abstract class AbstractDoctrineExtension extends Extension
|
||||
*
|
||||
* @param array $mappingConfig
|
||||
* @param string $mappingName
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function setMappingDriverConfig(array $mappingConfig, $mappingName)
|
||||
{
|
||||
@ -228,6 +232,8 @@ abstract class AbstractDoctrineExtension extends Extension
|
||||
*
|
||||
* @param array $mappingConfig
|
||||
* @param string $objectManagerName
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function assertValidMappingConfiguration(array $mappingConfig, $objectManagerName)
|
||||
{
|
||||
@ -309,7 +315,7 @@ abstract class AbstractDoctrineExtension extends Extension
|
||||
$memcacheClass = !empty($cacheDriver['class']) ? $cacheDriver['class'] : '%'.$this->getObjectManagerElementName('cache.memcache.class').'%';
|
||||
$memcacheInstanceClass = !empty($cacheDriver['instance_class']) ? $cacheDriver['instance_class'] : '%'.$this->getObjectManagerElementName('cache.memcache_instance.class').'%';
|
||||
$memcacheHost = !empty($cacheDriver['host']) ? $cacheDriver['host'] : '%'.$this->getObjectManagerElementName('cache.memcache_host').'%';
|
||||
$memcachePort = !empty($cacheDriver['port']) ? $cacheDriver['port'] : '%'.$this->getObjectManagerElementName('cache.memcache_port').'%';
|
||||
$memcachePort = !empty($cacheDriver['port']) || (isset($cacheDriver['port']) && $cacheDriver['port'] === 0) ? $cacheDriver['port'] : '%'.$this->getObjectManagerElementName('cache.memcache_port').'%';
|
||||
$cacheDef = new Definition($memcacheClass);
|
||||
$memcacheInstance = new Definition($memcacheInstanceClass);
|
||||
$memcacheInstance->addMethodCall('connect', array(
|
||||
|
@ -47,7 +47,7 @@ class DoctrineValidationPass implements CompilerPassInterface
|
||||
*
|
||||
* @param ContainerBuilder $container
|
||||
* @param string $mapping
|
||||
* @param type $extension
|
||||
* @param string $extension
|
||||
*/
|
||||
private function updateValidatorMappingFiles(ContainerBuilder $container, $mapping, $extension)
|
||||
{
|
||||
|
@ -11,10 +11,11 @@
|
||||
|
||||
namespace Symfony\Bridge\Doctrine\Form\ChoiceList;
|
||||
|
||||
use Symfony\Component\Form\Exception\FormException;
|
||||
use Symfony\Component\Form\Exception\Exception;
|
||||
use Symfony\Component\Form\Exception\StringCastException;
|
||||
use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList;
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||
|
||||
/**
|
||||
* A choice list presenting a list of Doctrine entities as choices
|
||||
@ -95,8 +96,9 @@ class EntityChoiceList extends ObjectChoiceList
|
||||
* @param string $groupPath A property path pointing to the property used
|
||||
* to group the choices. Only allowed if
|
||||
* the choices are given as flat array.
|
||||
* @param PropertyAccessorInterface $propertyAccessor The reflection graph for reading property paths.
|
||||
*/
|
||||
public function __construct(ObjectManager $manager, $class, $labelPath = null, EntityLoaderInterface $entityLoader = null, $entities = null, array $preferredEntities = array(), $groupPath = null)
|
||||
public function __construct(ObjectManager $manager, $class, $labelPath = null, EntityLoaderInterface $entityLoader = null, $entities = null, array $preferredEntities = array(), $groupPath = null, PropertyAccessorInterface $propertyAccessor = null)
|
||||
{
|
||||
$this->em = $manager;
|
||||
$this->entityLoader = $entityLoader;
|
||||
@ -122,7 +124,7 @@ class EntityChoiceList extends ObjectChoiceList
|
||||
$entities = array();
|
||||
}
|
||||
|
||||
parent::__construct($entities, $labelPath, $preferredEntities, $groupPath);
|
||||
parent::__construct($entities, $labelPath, $preferredEntities, $groupPath, null, $propertyAccessor);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -329,7 +331,7 @@ class EntityChoiceList extends ObjectChoiceList
|
||||
protected function createIndex($entity)
|
||||
{
|
||||
if ($this->idAsIndex) {
|
||||
return current($this->getIdentifierValues($entity));
|
||||
return $this->fixIndex(current($this->getIdentifierValues($entity)));
|
||||
}
|
||||
|
||||
return parent::createIndex($entity);
|
||||
@ -355,6 +357,23 @@ class EntityChoiceList extends ObjectChoiceList
|
||||
return parent::createValue($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function fixIndex($index)
|
||||
{
|
||||
$index = parent::fixIndex($index);
|
||||
|
||||
// If the ID is a single-field integer identifier, it is used as
|
||||
// index. Replace any leading minus by underscore to make it a valid
|
||||
// form name.
|
||||
if ($this->idAsIndex && $index < 0) {
|
||||
$index = strtr($index, '-', '_');
|
||||
}
|
||||
|
||||
return $index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the list with entities.
|
||||
*/
|
||||
@ -387,12 +406,12 @@ class EntityChoiceList extends ObjectChoiceList
|
||||
*
|
||||
* @return array The identifier values
|
||||
*
|
||||
* @throws FormException If the entity does not exist in Doctrine's identity map
|
||||
* @throws Exception If the entity does not exist in Doctrine's identity map
|
||||
*/
|
||||
private function getIdentifierValues($entity)
|
||||
{
|
||||
if (!$this->em->contains($entity)) {
|
||||
throw new FormException(
|
||||
throw new Exception(
|
||||
'Entities passed to the choice field must be managed. Maybe ' .
|
||||
'persist them in the entity manager?'
|
||||
);
|
||||
|
@ -26,7 +26,7 @@ class ORMQueryBuilderLoader implements EntityLoaderInterface
|
||||
*
|
||||
* This property should only be accessed through queryBuilder.
|
||||
*
|
||||
* @var Doctrine\ORM\QueryBuilder
|
||||
* @var QueryBuilder
|
||||
*/
|
||||
private $queryBuilder;
|
||||
|
||||
@ -36,6 +36,8 @@ class ORMQueryBuilderLoader implements EntityLoaderInterface
|
||||
* @param QueryBuilder|\Closure $queryBuilder
|
||||
* @param EntityManager $manager
|
||||
* @param string $class
|
||||
*
|
||||
* @throws UnexpectedTypeException
|
||||
*/
|
||||
public function __construct($queryBuilder, $manager = null, $class = null)
|
||||
{
|
||||
|
@ -27,6 +27,8 @@ class CollectionToArrayTransformer implements DataTransformerInterface
|
||||
* @param Collection $collection A collection of entities
|
||||
*
|
||||
* @return mixed An array of entities
|
||||
*
|
||||
* @throws UnexpectedTypeException
|
||||
*/
|
||||
public function transform($collection)
|
||||
{
|
||||
|
@ -13,6 +13,7 @@ namespace Symfony\Bridge\Doctrine\Form;
|
||||
|
||||
use Doctrine\Common\Persistence\ManagerRegistry;
|
||||
use Symfony\Component\Form\AbstractExtension;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccess;
|
||||
|
||||
class DoctrineOrmExtension extends AbstractExtension
|
||||
{
|
||||
@ -26,7 +27,7 @@ class DoctrineOrmExtension extends AbstractExtension
|
||||
protected function loadTypes()
|
||||
{
|
||||
return array(
|
||||
new Type\EntityType($this->registry),
|
||||
new Type\EntityType($this->registry, PropertyAccess::getPropertyAccessor()),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -143,6 +143,7 @@ class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface
|
||||
*/
|
||||
public function guessMinLength($class, $property)
|
||||
{
|
||||
trigger_error('guessMinLength() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -12,7 +12,7 @@
|
||||
namespace Symfony\Bridge\Doctrine\Form\Type;
|
||||
|
||||
use Doctrine\Common\Persistence\ManagerRegistry;
|
||||
use Symfony\Component\Form\Exception\FormException;
|
||||
use Symfony\Component\Form\Exception\Exception;
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList;
|
||||
@ -22,6 +22,8 @@ use Symfony\Bridge\Doctrine\Form\DataTransformer\CollectionToArrayTransformer;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\OptionsResolver\Options;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccess;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||
|
||||
abstract class DoctrineType extends AbstractType
|
||||
{
|
||||
@ -35,9 +37,15 @@ abstract class DoctrineType extends AbstractType
|
||||
*/
|
||||
private $choiceListCache = array();
|
||||
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
/**
|
||||
* @var PropertyAccessorInterface
|
||||
*/
|
||||
private $propertyAccessor;
|
||||
|
||||
public function __construct(ManagerRegistry $registry, PropertyAccessorInterface $propertyAccessor = null)
|
||||
{
|
||||
$this->registry = $registry;
|
||||
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::getPropertyAccessor();
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
@ -54,6 +62,7 @@ abstract class DoctrineType extends AbstractType
|
||||
{
|
||||
$choiceListCache =& $this->choiceListCache;
|
||||
$registry = $this->registry;
|
||||
$propertyAccessor = $this->propertyAccessor;
|
||||
$type = $this;
|
||||
|
||||
$loader = function (Options $options) use ($type) {
|
||||
@ -64,7 +73,7 @@ abstract class DoctrineType extends AbstractType
|
||||
return null;
|
||||
};
|
||||
|
||||
$choiceList = function (Options $options) use (&$choiceListCache, &$time) {
|
||||
$choiceList = function (Options $options) use (&$choiceListCache, $propertyAccessor) {
|
||||
// Support for closures
|
||||
$propertyHash = is_object($options['property'])
|
||||
? spl_object_hash($options['property'])
|
||||
@ -118,7 +127,8 @@ abstract class DoctrineType extends AbstractType
|
||||
$options['loader'],
|
||||
$options['choices'],
|
||||
$options['preferred_choices'],
|
||||
$options['group_by']
|
||||
$options['group_by'],
|
||||
$propertyAccessor
|
||||
);
|
||||
}
|
||||
|
||||
@ -134,7 +144,7 @@ abstract class DoctrineType extends AbstractType
|
||||
$em = $registry->getManagerForClass($options['class']);
|
||||
|
||||
if (null === $em) {
|
||||
throw new FormException(sprintf(
|
||||
throw new Exception(sprintf(
|
||||
'Class "%s" seems not to be a managed Doctrine entity. ' .
|
||||
'Did you forget to map it?',
|
||||
$options['class']
|
||||
|
@ -11,53 +11,26 @@
|
||||
|
||||
namespace Symfony\Bridge\Doctrine\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\Exception\UnexpectedTypeException;
|
||||
use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader;
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader;
|
||||
|
||||
class EntityType extends DoctrineType
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $loaderCache = array();
|
||||
|
||||
/**
|
||||
* Return the default loader object.
|
||||
*
|
||||
* @param ObjectManager $manager
|
||||
* @param QueryBuilder|\Closure $queryBuilder
|
||||
* @param mixed $queryBuilder
|
||||
* @param string $class
|
||||
*
|
||||
* @return ORMQueryBuilderLoader
|
||||
*
|
||||
* @throws UnexpectedTypeException If the passed $queryBuilder is no \Closure
|
||||
* and no QueryBuilder or if the closure
|
||||
* does not return a QueryBuilder.
|
||||
*/
|
||||
public function getLoader(ObjectManager $manager, $queryBuilder, $class)
|
||||
{
|
||||
if ($queryBuilder instanceof \Closure) {
|
||||
$queryBuilder = $queryBuilder($manager->getRepository($class));
|
||||
|
||||
if (!$queryBuilder instanceof QueryBuilder) {
|
||||
throw new UnexpectedTypeException($queryBuilder, 'Doctrine\ORM\QueryBuilder');
|
||||
}
|
||||
} elseif (!$queryBuilder instanceof QueryBuilder) {
|
||||
throw new UnexpectedTypeException($queryBuilder, 'Doctrine\ORM\QueryBuilder or \Closure');
|
||||
}
|
||||
|
||||
// It is important to return the same loader for identical queries,
|
||||
// otherwise the caching mechanism in DoctrineType does not work
|
||||
// (which expects identical loaders for the cache to work)
|
||||
$hash = md5($queryBuilder->getQuery()->getDQL());
|
||||
|
||||
if (!isset($this->loaderCache[$hash])) {
|
||||
$this->loaderCache[$hash] = new ORMQueryBuilderLoader($queryBuilder);
|
||||
}
|
||||
|
||||
return $this->loaderCache[$hash];
|
||||
return new ORMQueryBuilderLoader(
|
||||
$queryBuilder,
|
||||
$manager,
|
||||
$class
|
||||
);
|
||||
}
|
||||
|
||||
public function getName()
|
||||
|
@ -157,6 +157,8 @@ class DbalSessionHandler implements \SessionHandlerInterface
|
||||
*
|
||||
* @param string $id
|
||||
* @param string $data
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
private function createNewSession($id, $data = '')
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2004-2012 Fabien Potencier
|
||||
Copyright (c) 2004-2013 Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
namespace Symfony\Bridge\Doctrine\Logger;
|
||||
|
||||
use Symfony\Component\HttpKernel\Log\LoggerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Stopwatch\Stopwatch;
|
||||
use Doctrine\DBAL\Logging\SQLLogger;
|
||||
|
||||
|
@ -70,10 +70,10 @@ class EntityChoiceListTest extends DoctrineOrmTestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\Form\Exception\FormException
|
||||
* @expectedException \Symfony\Component\Form\Exception\FormException
|
||||
* @expectedMessage Entity "Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIdentEntity" passed to the choice field must have a "__toString()" method defined (or you can also override the "property" option).
|
||||
*/
|
||||
public function testEntitesMustHaveAToStringMethod()
|
||||
public function testEntitiesMustHaveAToStringMethod()
|
||||
{
|
||||
$entity1 = new NoToStringSingleIdentEntity(1, 'Foo');
|
||||
$entity2 = new NoToStringSingleIdentEntity(2, 'Bar');
|
||||
@ -97,7 +97,7 @@ class EntityChoiceListTest extends DoctrineOrmTestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\Form\Exception\FormException
|
||||
* @expectedException \Symfony\Component\Form\Exception\FormException
|
||||
*/
|
||||
public function testChoicesMustBeManaged()
|
||||
{
|
||||
@ -312,4 +312,47 @@ class EntityChoiceListTest extends DoctrineOrmTestCase
|
||||
|
||||
$this->assertSame(array(0 => $entity1, 1 => $entity2), $choiceList->getChoices());
|
||||
}
|
||||
|
||||
public function testMinusReplacedByUnderscoreInNegativeIntIds()
|
||||
{
|
||||
$entity1 = new SingleIdentEntity(-1, 'Foo');
|
||||
$entity2 = new SingleIdentEntity(1, 'Bar');
|
||||
|
||||
// Persist for managed state
|
||||
$this->em->persist($entity1);
|
||||
$this->em->persist($entity2);
|
||||
$this->em->flush();
|
||||
|
||||
$choiceList = new EntityChoiceList(
|
||||
$this->em,
|
||||
self::SINGLE_IDENT_CLASS,
|
||||
'name'
|
||||
);
|
||||
|
||||
$this->assertSame(array('_1' => $entity1, 1 => $entity2), $choiceList->getChoices());
|
||||
$this->assertSame(array('_1', 1), $choiceList->getIndicesForChoices(array($entity1, $entity2)));
|
||||
$this->assertSame(array('_1', 1), $choiceList->getIndicesForValues(array('-1', '1')));
|
||||
}
|
||||
|
||||
public function testMinusReplacedByUnderscoreIfNotLoaded()
|
||||
{
|
||||
$entity1 = new SingleIdentEntity(-1, 'Foo');
|
||||
$entity2 = new SingleIdentEntity(1, 'Bar');
|
||||
|
||||
// Persist for managed state
|
||||
$this->em->persist($entity1);
|
||||
$this->em->persist($entity2);
|
||||
$this->em->flush();
|
||||
|
||||
$choiceList = new EntityChoiceList(
|
||||
$this->em,
|
||||
self::SINGLE_IDENT_CLASS,
|
||||
'name'
|
||||
);
|
||||
|
||||
// no getChoices()!
|
||||
|
||||
$this->assertSame(array('_1', 1), $choiceList->getIndicesForChoices(array($entity1, $entity2)));
|
||||
$this->assertSame(array('_1', 1), $choiceList->getIndicesForValues(array('-1', '1')));
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,6 @@
|
||||
namespace Symfony\Bridge\Doctrine\Tests\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\Tests\FormPerformanceTestCase;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIdentEntity;
|
||||
use Doctrine\ORM\Tools\SchemaTool;
|
||||
use Symfony\Bridge\Doctrine\Tests\DoctrineOrmTestCase;
|
||||
@ -37,9 +36,6 @@ class EntityTypePerformanceTest extends FormPerformanceTestCase
|
||||
$manager->expects($this->any())
|
||||
->method('getManager')
|
||||
->will($this->returnValue($this->em));
|
||||
$manager->expects($this->any())
|
||||
->method('getManagerForClass')
|
||||
->will($this->returnValue($this->em));
|
||||
|
||||
return array(
|
||||
new CoreExtension(),
|
||||
@ -114,26 +110,6 @@ class EntityTypePerformanceTest extends FormPerformanceTestCase
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @group benchmark
|
||||
*/
|
||||
public function testCollapsedEntityFieldWithQueryBuilder()
|
||||
{
|
||||
$this->setMaxRunningTime(1);
|
||||
|
||||
for ($i = 0; $i < 40; ++$i) {
|
||||
$form = $this->factory->create('entity', null, array(
|
||||
'class' => self::ENTITY_CLASS,
|
||||
'query_builder' => function (EntityRepository $repo) {
|
||||
return $repo->createQueryBuilder('e')->addOrderBy('e.id', 'DESC');
|
||||
}
|
||||
));
|
||||
|
||||
// force loading of the choice list
|
||||
$form->createView();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @group benchmark
|
||||
*/
|
||||
|
@ -90,6 +90,7 @@ class EntityTypeTest extends TypeTestCase
|
||||
parent::tearDown();
|
||||
|
||||
$this->em = null;
|
||||
$this->emRegistry = null;
|
||||
}
|
||||
|
||||
protected function getExtensions()
|
||||
@ -111,7 +112,7 @@ class EntityTypeTest extends TypeTestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\OptionsResolver\Exception\MissingOptionsException
|
||||
* @expectedException \Symfony\Component\OptionsResolver\Exception\MissingOptionsException
|
||||
*/
|
||||
public function testClassOptionIsRequired()
|
||||
{
|
||||
@ -171,7 +172,7 @@ class EntityTypeTest extends TypeTestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException
|
||||
* @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
|
||||
*/
|
||||
public function testConfigureQueryBuilderWithNonQueryBuilderAndNonClosure()
|
||||
{
|
||||
@ -183,7 +184,7 @@ class EntityTypeTest extends TypeTestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException
|
||||
* @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
|
||||
*/
|
||||
public function testConfigureQueryBuilderWithClosureReturningNonQueryBuilder()
|
||||
{
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace Symfony\Bridge\Doctrine\Tests\Validator\Constraints;
|
||||
|
||||
use Symfony\Bridge\Doctrine\Tests\DoctrineOrmTestCase;
|
||||
use Symfony\Component\Validator\DefaultTranslator;
|
||||
use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory;
|
||||
use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIdentEntity;
|
||||
use Symfony\Bridge\Doctrine\Tests\Fixtures\DoubleIdentEntity;
|
||||
@ -132,7 +133,7 @@ class UniqueValidatorTest extends DoctrineOrmTestCase
|
||||
$metadataFactory->addMetadata($metadata);
|
||||
$validatorFactory = $this->createValidatorFactory($uniqueValidator);
|
||||
|
||||
return new Validator($metadataFactory, $validatorFactory);
|
||||
return new Validator($metadataFactory, $validatorFactory, new DefaultTranslator());
|
||||
}
|
||||
|
||||
private function createSchema($em)
|
||||
|
@ -40,6 +40,9 @@ class UniqueEntityValidator extends ConstraintValidator
|
||||
/**
|
||||
* @param object $entity
|
||||
* @param Constraint $constraint
|
||||
*
|
||||
* @throws UnexpectedTypeException
|
||||
* @throws ConstraintDefinitionException
|
||||
*/
|
||||
public function validate($entity, Constraint $constraint)
|
||||
{
|
||||
@ -63,7 +66,7 @@ class UniqueEntityValidator extends ConstraintValidator
|
||||
$em = $this->registry->getManagerForClass(get_class($entity));
|
||||
}
|
||||
|
||||
$className = $this->context->getCurrentClass();
|
||||
$className = $this->context->getClassName();
|
||||
$class = $em->getClassMetadata($className);
|
||||
/* @var $class \Doctrine\Common\Persistence\Mapping\ClassMetadata */
|
||||
|
||||
@ -120,6 +123,6 @@ class UniqueEntityValidator extends ConstraintValidator
|
||||
|
||||
$errorPath = null !== $constraint->errorPath ? $constraint->errorPath : $fields[0];
|
||||
|
||||
$this->context->addViolationAtSubPath($errorPath, $constraint->message, array(), $criteria[$fields[0]]);
|
||||
$this->context->addViolationAt($errorPath, $constraint->message, array(), $criteria[$fields[0]]);
|
||||
}
|
||||
}
|
||||
|
@ -47,10 +47,7 @@ class DebugHandler extends TestHandler implements DebugLoggerInterface
|
||||
public function countErrors()
|
||||
{
|
||||
$cnt = 0;
|
||||
$levels = array(Logger::ERROR, Logger::CRITICAL, Logger::ALERT);
|
||||
if (defined('Monolog\Logger::EMERGENCY')) {
|
||||
$levels[] = Logger::EMERGENCY;
|
||||
}
|
||||
$levels = array(Logger::ERROR, Logger::CRITICAL, Logger::ALERT, Logger::EMERGENCY);
|
||||
foreach ($levels as $level) {
|
||||
if (isset($this->recordsByLevel[$level])) {
|
||||
$cnt += count($this->recordsByLevel[$level]);
|
||||
|
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2004-2012 Fabien Potencier
|
||||
Copyright (c) 2004-2013 Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -22,6 +22,38 @@ use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
|
||||
*/
|
||||
class Logger extends BaseLogger implements LoggerInterface, DebugLoggerInterface
|
||||
{
|
||||
/**
|
||||
* @deprecated since 2.2, to be removed in 3.0. Use emergency() which is PSR-3 compatible.
|
||||
*/
|
||||
public function emerg($message, array $context = array())
|
||||
{
|
||||
return parent::addRecord(BaseLogger::EMERGENCY, $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since 2.2, to be removed in 3.0. Use critical() which is PSR-3 compatible.
|
||||
*/
|
||||
public function crit($message, array $context = array())
|
||||
{
|
||||
return parent::addRecord(BaseLogger::CRITICAL, $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since 2.2, to be removed in 3.0. Use error() which is PSR-3 compatible.
|
||||
*/
|
||||
public function err($message, array $context = array())
|
||||
{
|
||||
return parent::addRecord(BaseLogger::ERROR, $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since 2.2, to be removed in 3.0. Use warning() which is PSR-3 compatible.
|
||||
*/
|
||||
public function warn($message, array $context = array())
|
||||
{
|
||||
return parent::addRecord(BaseLogger::WARNING, $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Symfony\Component\HttpKernel\Log\DebugLoggerInterface
|
||||
*/
|
||||
|
@ -18,7 +18,7 @@
|
||||
"require": {
|
||||
"php": ">=5.3.3",
|
||||
"symfony/http-kernel": "2.2.*",
|
||||
"monolog/monolog": "1.*"
|
||||
"monolog/monolog": "~1.3"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": { "Symfony\\Bridge\\Monolog\\": "" }
|
||||
|
@ -5,6 +5,9 @@ CHANGELOG
|
||||
-----
|
||||
|
||||
* added a collection type for the I18n behavior
|
||||
* added an optional PropertyAccessorInterface parameter to ModelType and
|
||||
ModelChoiceList
|
||||
* [BC BREAK] ModelType now has a constructor
|
||||
|
||||
2.1.0
|
||||
-----
|
||||
|
@ -11,16 +11,20 @@
|
||||
|
||||
namespace Symfony\Bridge\Propel1\Form\ChoiceList;
|
||||
|
||||
use \ModelCriteria;
|
||||
use \BaseObject;
|
||||
use \Persistent;
|
||||
|
||||
use Symfony\Component\Form\Exception\FormException;
|
||||
use Symfony\Component\Form\Exception\StringCastException;
|
||||
use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||
|
||||
/**
|
||||
* Widely inspirated by the EntityChoiceList.
|
||||
* Widely inspired by the EntityChoiceList.
|
||||
*
|
||||
* @author William Durand <william.durand1@gmail.com>
|
||||
* @author Toni Uebernickel <tuebernickel@gmail.com>
|
||||
*/
|
||||
class ModelChoiceList extends ObjectChoiceList
|
||||
{
|
||||
@ -31,19 +35,28 @@ class ModelChoiceList extends ObjectChoiceList
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $identifier = array();
|
||||
protected $identifier = array();
|
||||
|
||||
/**
|
||||
* Query
|
||||
* The query to retrieve the choices of this list.
|
||||
*
|
||||
* @var ModelCriteria
|
||||
*/
|
||||
private $query = null;
|
||||
protected $query;
|
||||
|
||||
/**
|
||||
* The query to retrieve the preferred choices for this list.
|
||||
*
|
||||
* @var ModelCriteria
|
||||
*/
|
||||
protected $preferredQuery;
|
||||
|
||||
/**
|
||||
* Whether the model objects have already been loaded.
|
||||
*
|
||||
* @var Boolean
|
||||
*/
|
||||
private $loaded = false;
|
||||
protected $loaded = false;
|
||||
|
||||
/**
|
||||
* Whether to use the identifier for index generation
|
||||
@ -53,13 +66,21 @@ class ModelChoiceList extends ObjectChoiceList
|
||||
private $identifierAsIndex = false;
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $labelPath
|
||||
* @param array $choices
|
||||
* @param \ModelCriteria $queryObject
|
||||
* @param string $groupPath
|
||||
* Constructor.
|
||||
*
|
||||
* @see Symfony\Bridge\Propel1\Form\Type\ModelType How to use the preferred choices.
|
||||
*
|
||||
* @param string $class The FQCN of the model class to be loaded.
|
||||
* @param string $labelPath A property path pointing to the property used for the choice labels.
|
||||
* @param array $choices An optional array to use, rather than fetching the models.
|
||||
* @param ModelCriteria $queryObject The query to use retrieving model data from database.
|
||||
* @param string $groupPath A property path pointing to the property used to group the choices.
|
||||
* @param array|ModelCriteria $preferred The preferred items of this choice.
|
||||
* Either an array if $choices is given,
|
||||
* or a ModelCriteria to be merged with the $queryObject.
|
||||
* @param PropertyAccessorInterface $propertyAccessor The reflection graph for reading property paths.
|
||||
*/
|
||||
public function __construct($class, $labelPath = null, $choices = null, $queryObject = null, $groupPath = null)
|
||||
public function __construct($class, $labelPath = null, $choices = null, $queryObject = null, $groupPath = null, $preferred = array(), PropertyAccessorInterface $propertyAccessor = null)
|
||||
{
|
||||
$this->class = $class;
|
||||
|
||||
@ -70,17 +91,22 @@ class ModelChoiceList extends ObjectChoiceList
|
||||
$this->query = $queryObject ?: $query;
|
||||
$this->loaded = is_array($choices) || $choices instanceof \Traversable;
|
||||
|
||||
if ($preferred instanceof ModelCriteria) {
|
||||
$this->preferredQuery = $preferred->mergeWith($this->query);
|
||||
}
|
||||
|
||||
if (!$this->loaded) {
|
||||
// Make sure the constraints of the parent constructor are
|
||||
// fulfilled
|
||||
$choices = array();
|
||||
$preferred = array();
|
||||
}
|
||||
|
||||
if (1 === count($this->identifier) && $this->isInteger(current($this->identifier))) {
|
||||
$this->identifierAsIndex = true;
|
||||
}
|
||||
|
||||
parent::__construct($choices, $labelPath, array(), $groupPath);
|
||||
parent::__construct($choices, $labelPath, $preferred, $groupPath, null, $propertyAccessor);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -328,10 +354,14 @@ class ModelChoiceList extends ObjectChoiceList
|
||||
{
|
||||
$models = (array) $this->query->find();
|
||||
|
||||
$preferred = array();
|
||||
if ($this->preferredQuery instanceof ModelCriteria) {
|
||||
$preferred = (array) $this->preferredQuery->find();
|
||||
}
|
||||
|
||||
try {
|
||||
// The second parameter $labels is ignored by ObjectChoiceList
|
||||
// The third parameter $preferredChoices is currently not supported
|
||||
parent::initialize($models, array(), array());
|
||||
parent::initialize($models, array(), $preferred);
|
||||
} catch (StringCastException $e) {
|
||||
throw new StringCastException(str_replace('argument $labelPath', 'option "property"', $e->getMessage()), null, $e);
|
||||
}
|
||||
@ -348,6 +378,8 @@ class ModelChoiceList extends ObjectChoiceList
|
||||
*
|
||||
* @param object $model The model for which to get the identifier
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws FormException If the model does not exist
|
||||
*/
|
||||
private function getIdentifierValues($model)
|
||||
@ -357,7 +389,7 @@ class ModelChoiceList extends ObjectChoiceList
|
||||
}
|
||||
|
||||
// readonly="true" models do not implement Persistent.
|
||||
if ($model instanceof BaseObject and method_exists($model, 'getPrimaryKey')) {
|
||||
if ($model instanceof BaseObject && method_exists($model, 'getPrimaryKey')) {
|
||||
return array($model->getPrimaryKey());
|
||||
}
|
||||
|
||||
@ -367,9 +399,9 @@ class ModelChoiceList extends ObjectChoiceList
|
||||
/**
|
||||
* Whether this column in an integer
|
||||
*
|
||||
* @param ColumnMap $column
|
||||
* @param \ColumnMap $column
|
||||
*
|
||||
* @return boolean
|
||||
* @return Boolean
|
||||
*/
|
||||
private function isInteger(\ColumnMap $column)
|
||||
{
|
||||
|
@ -11,7 +11,6 @@
|
||||
namespace Symfony\Bridge\Propel1\Form\EventListener;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
|
||||
@ -24,13 +23,11 @@ class TranslationFormListener implements EventSubscriberInterface
|
||||
{
|
||||
private $columns;
|
||||
private $dataClass;
|
||||
private $formFactory;
|
||||
|
||||
public function __construct(FormFactoryInterface $formFactory, $columns, $dataClass)
|
||||
public function __construct($columns, $dataClass)
|
||||
{
|
||||
$this->columns = $columns;
|
||||
$this->dataClass = $dataClass;
|
||||
$this->formFactory = $formFactory;
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
@ -78,7 +75,7 @@ class TranslationFormListener implements EventSubscriberInterface
|
||||
|
||||
$options = array_merge($options, $customOptions);
|
||||
|
||||
$form->add($this->formFactory->createNamed($column, $type, null, $options));
|
||||
$form->add($column, $type, $options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace Symfony\Bridge\Propel1\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractExtension;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccess;
|
||||
|
||||
/**
|
||||
* Represents the Propel form extension, which loads the Propel functionality.
|
||||
@ -23,7 +24,7 @@ class PropelExtension extends AbstractExtension
|
||||
protected function loadTypes()
|
||||
{
|
||||
return array(
|
||||
new Type\ModelType(),
|
||||
new Type\ModelType(PropertyAccess::getPropertyAccessor()),
|
||||
new Type\TranslationCollectionType(),
|
||||
new Type\TranslationType()
|
||||
);
|
||||
|
@ -126,6 +126,7 @@ class PropelTypeGuesser implements FormTypeGuesserInterface
|
||||
*/
|
||||
public function guessMinLength($class, $property)
|
||||
{
|
||||
trigger_error('guessMinLength() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -17,14 +17,49 @@ use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\Options;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccess;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||
|
||||
/**
|
||||
* ModelType class.
|
||||
*
|
||||
* @author William Durand <william.durand1@gmail.com>
|
||||
* @author Toni Uebernickel <tuebernickel@gmail.com>
|
||||
*
|
||||
* Example using the preferred_choices option.
|
||||
*
|
||||
* <code>
|
||||
* public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
* {
|
||||
* $builder
|
||||
* ->add('product', 'model', array(
|
||||
* 'class' => 'Model\Product',
|
||||
* 'query' => ProductQuery::create()
|
||||
* ->filterIsActive(true)
|
||||
* ->useI18nQuery($options['locale'])
|
||||
* ->orderByName()
|
||||
* ->endUse()
|
||||
* ,
|
||||
* 'preferred_choices' => ProductQuery::create()
|
||||
* ->filterByIsTopProduct(true)
|
||||
* ,
|
||||
* ))
|
||||
* ;
|
||||
* }
|
||||
* </code>
|
||||
*/
|
||||
class ModelType extends AbstractType
|
||||
{
|
||||
/**
|
||||
* @var PropertyAccessorInterface
|
||||
*/
|
||||
private $propertyAccessor;
|
||||
|
||||
public function __construct(PropertyAccessorInterface $propertyAccessor = null)
|
||||
{
|
||||
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::getPropertyAccessor();
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
if ($options['multiple']) {
|
||||
@ -34,13 +69,17 @@ class ModelType extends AbstractType
|
||||
|
||||
public function setDefaultOptions(OptionsResolverInterface $resolver)
|
||||
{
|
||||
$choiceList = function (Options $options) {
|
||||
$propertyAccessor = $this->propertyAccessor;
|
||||
|
||||
$choiceList = function (Options $options) use ($propertyAccessor) {
|
||||
return new ModelChoiceList(
|
||||
$options['class'],
|
||||
$options['property'],
|
||||
$options['choices'],
|
||||
$options['query'],
|
||||
$options['group_by']
|
||||
$options['group_by'],
|
||||
$options['preferred_choices'],
|
||||
$propertyAccessor
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -28,8 +28,9 @@ class TranslationType extends AbstractType
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$listener = new TranslationFormListener($builder->getFormFactory(), $options['columns'], $options['data_class']);
|
||||
$builder->addEventSubscriber($listener);
|
||||
$builder->addEventSubscriber(
|
||||
new TranslationFormListener($options['columns'], $options['data_class'])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2004-2012 Fabien Potencier
|
||||
Copyright (c) 2004-2013 Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -12,7 +12,7 @@
|
||||
namespace Symfony\Bridge\Propel1\Logger;
|
||||
|
||||
use Symfony\Component\Stopwatch\Stopwatch;
|
||||
use Symfony\Component\HttpKernel\Log\LoggerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* PropelLogger.
|
||||
@ -73,7 +73,7 @@ class PropelLogger
|
||||
public function crit($message)
|
||||
{
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->crit($message);
|
||||
$this->logger->critical($message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,7 +85,7 @@ class PropelLogger
|
||||
public function err($message)
|
||||
{
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->err($message);
|
||||
$this->logger->error($message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,7 +97,7 @@ class PropelLogger
|
||||
public function warning($message)
|
||||
{
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->warn($message);
|
||||
$this->logger->warning($message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,10 @@ class ModelChoiceListTest extends Propel1TestCase
|
||||
if (!class_exists('Symfony\Component\Form\Form')) {
|
||||
$this->markTestSkipped('The "Form" component is not available');
|
||||
}
|
||||
|
||||
if (!class_exists('Symfony\Component\PropertyAccess\PropertyAccessor')) {
|
||||
$this->markTestSkipped('The "PropertyAccessor" component is not available');
|
||||
}
|
||||
}
|
||||
|
||||
public function testEmptyChoicesReturnsEmpty()
|
||||
@ -70,6 +74,29 @@ class ModelChoiceListTest extends Propel1TestCase
|
||||
$this->assertSame(array(1 => $item1, 2 => $item2), $choiceList->getChoices());
|
||||
}
|
||||
|
||||
public function testFlattenedPreferredChoices()
|
||||
{
|
||||
$item1 = new Item(1, 'Foo');
|
||||
$item2 = new Item(2, 'Bar');
|
||||
|
||||
$choiceList = new ModelChoiceList(
|
||||
self::ITEM_CLASS,
|
||||
'value',
|
||||
array(
|
||||
$item1,
|
||||
$item2,
|
||||
),
|
||||
null,
|
||||
null,
|
||||
array(
|
||||
$item1
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertSame(array(1 => $item1, 2 => $item2), $choiceList->getChoices());
|
||||
$this->assertEquals(array(1 => new ChoiceView($item1, '1', 'Foo')), $choiceList->getPreferredViews());
|
||||
}
|
||||
|
||||
public function testNestedChoices()
|
||||
{
|
||||
$item1 = new Item(1, 'Foo');
|
||||
|
@ -96,7 +96,7 @@ class TranslationCollectionTypeTest extends TypeTestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException
|
||||
* @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
|
||||
*/
|
||||
public function testNoArrayGiven()
|
||||
{
|
||||
@ -118,7 +118,7 @@ class TranslationCollectionTypeTest extends TypeTestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\OptionsResolver\Exception\MissingOptionsException
|
||||
* @expectedException \Symfony\Component\OptionsResolver\Exception\MissingOptionsException
|
||||
*/
|
||||
public function testNoDataClassAdded()
|
||||
{
|
||||
@ -131,7 +131,7 @@ class TranslationCollectionTypeTest extends TypeTestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\OptionsResolver\Exception\MissingOptionsException
|
||||
* @expectedException \Symfony\Component\OptionsResolver\Exception\MissingOptionsException
|
||||
*/
|
||||
public function testNoLanguagesAdded()
|
||||
{
|
||||
@ -144,7 +144,7 @@ class TranslationCollectionTypeTest extends TypeTestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\OptionsResolver\Exception\MissingOptionsException
|
||||
* @expectedException \Symfony\Component\OptionsResolver\Exception\MissingOptionsException
|
||||
*/
|
||||
public function testNoColumnsAdded()
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2004-2012 Fabien Potencier
|
||||
Copyright (c) 2004-2013 Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -17,7 +17,7 @@
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.3",
|
||||
"swiftmailer/swiftmailer": ">=4.2.0,<4.3-dev"
|
||||
"swiftmailer/swiftmailer": ">=4.2.0,<4.4-dev"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/http-kernel": "2.2.*"
|
||||
|
@ -4,7 +4,11 @@ CHANGELOG
|
||||
2.2.0
|
||||
-----
|
||||
|
||||
* [BC BREAK] restricted the `render` tag to only accept URIs as reference (the signature changed)
|
||||
* added a render function to render a request
|
||||
* The `app` global variable is now injected even when using the twig service directly.
|
||||
* Added an optional parameter to the `path` and `url` function which allows to generate
|
||||
relative paths (e.g. "../parent-file") and scheme-relative URLs (e.g. "//example.com/dir/file").
|
||||
|
||||
2.1.0
|
||||
-----
|
||||
|
97
src/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php
Normal file
97
src/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php
Normal file
@ -0,0 +1,97 @@
|
||||
<?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\Bridge\Twig\Extension;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Provides integration with the HttpKernel component.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class HttpKernelExtension extends \Twig_Extension implements EventSubscriberInterface
|
||||
{
|
||||
private $kernel;
|
||||
private $request;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param HttpKernelInterface $kernel A HttpKernelInterface install
|
||||
*/
|
||||
public function __construct(HttpKernelInterface $kernel)
|
||||
{
|
||||
$this->kernel = $kernel;
|
||||
}
|
||||
|
||||
public function getFunctions()
|
||||
{
|
||||
return array(
|
||||
'render' => new \Twig_Function_Method($this, 'render', array('needs_environment' => true, 'is_safe' => array('html'))),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a URI.
|
||||
*
|
||||
* @param \Twig_Environment $twig A \Twig_Environment instance
|
||||
* @param string $uri The URI to render
|
||||
*
|
||||
* @return string The Response content
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function render(\Twig_Environment $twig, $uri)
|
||||
{
|
||||
if (null !== $this->request) {
|
||||
$cookies = $this->request->cookies->all();
|
||||
$server = $this->request->server->all();
|
||||
} else {
|
||||
$cookies = array();
|
||||
$server = array();
|
||||
}
|
||||
|
||||
$subRequest = Request::create($uri, 'get', array(), $cookies, array(), $server);
|
||||
if (null !== $this->request && $this->request->getSession()) {
|
||||
$subRequest->setSession($this->request->getSession());
|
||||
}
|
||||
|
||||
$response = $this->kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false);
|
||||
|
||||
if (!$response->isSuccessful()) {
|
||||
throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $subRequest->getUri(), $response->getStatusCode()));
|
||||
}
|
||||
|
||||
return $response->getContent();
|
||||
}
|
||||
|
||||
public function onKernelRequest(GetResponseEvent $event)
|
||||
{
|
||||
$this->request = $event->getRequest();
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
KernelEvents::REQUEST => array('onKernelRequest'),
|
||||
);
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'http_kernel';
|
||||
}
|
||||
}
|
@ -40,14 +40,14 @@ class RoutingExtension extends \Twig_Extension
|
||||
);
|
||||
}
|
||||
|
||||
public function getPath($name, $parameters = array())
|
||||
public function getPath($name, $parameters = array(), $relative = false)
|
||||
{
|
||||
return $this->generator->generate($name, $parameters, false);
|
||||
return $this->generator->generate($name, $parameters, $relative ? UrlGeneratorInterface::RELATIVE_PATH : UrlGeneratorInterface::ABSOLUTE_PATH);
|
||||
}
|
||||
|
||||
public function getUrl($name, $parameters = array())
|
||||
public function getUrl($name, $parameters = array(), $schemeRelative = false)
|
||||
{
|
||||
return $this->generator->generate($name, $parameters, true);
|
||||
return $this->generator->generate($name, $parameters, $schemeRelative ? UrlGeneratorInterface::NETWORK_PATH : UrlGeneratorInterface::ABSOLUTE_URL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2004-2012 Fabien Potencier
|
||||
Copyright (c) 2004-2013 Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -69,7 +69,7 @@
|
||||
{% spaceless %}
|
||||
<select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple"{% endif %}>
|
||||
{% if empty_value is not none %}
|
||||
<option value="">{{ empty_value|trans({}, translation_domain) }}</option>
|
||||
<option value="" disabled="disabled"{% if value is empty %} selected="selected"{% endif %}>{{ empty_value|trans({}, translation_domain) }}</option>
|
||||
{% endif %}
|
||||
{% if preferred_choices|length > 0 %}
|
||||
{% set options = preferred_choices %}
|
||||
@ -148,7 +148,7 @@
|
||||
{{ block('form_widget_simple') }}
|
||||
{% else %}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{{ form_widget(form.hour, { 'attr': { 'size': '1' } }) }}:{{ form_widget(form.minute, { 'attr': { 'size': '1' } }) }}{% if with_seconds %}:{{ form_widget(form.second, { 'attr': { 'size': '1' } }) }}{% endif %}
|
||||
{{ form_widget(form.hour, { 'attr': { 'size': '1' } }) }}{% if with_minutes %}:{{ form_widget(form.minute, { 'attr': { 'size': '1' } }) }}{% endif %}{% if with_seconds %}:{{ form_widget(form.second, { 'attr': { 'size': '1' } }) }}{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endspaceless %}
|
||||
@ -275,11 +275,7 @@
|
||||
{% if errors|length > 0 %}
|
||||
<ul>
|
||||
{% for error in errors %}
|
||||
<li>{{
|
||||
error.messagePluralization is null
|
||||
? error.messageTemplate|trans(error.messageParameters, 'validators')
|
||||
: error.messageTemplate|transchoice(error.messagePluralization, error.messageParameters, 'validators')
|
||||
}}</li>
|
||||
<li>{{ error.message }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
@ -0,0 +1,73 @@
|
||||
<?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\Bridge\Twig\Tests\Extension;
|
||||
|
||||
use Symfony\Bridge\Twig\Extension\HttpKernelExtension;
|
||||
use Symfony\Bridge\Twig\Tests\TestCase;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
class HttpKernelExtensionTest extends TestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
if (!class_exists('Symfony\Component\HttpKernel\HttpKernel')) {
|
||||
$this->markTestSkipped('The "HttpKernel" component is not available');
|
||||
}
|
||||
|
||||
if (!class_exists('Twig_Environment')) {
|
||||
$this->markTestSkipped('Twig is not available.');
|
||||
}
|
||||
}
|
||||
|
||||
public function testRenderWithoutMasterRequest()
|
||||
{
|
||||
$kernel = $this->getKernel($this->returnValue(new Response('foo')));
|
||||
|
||||
$this->assertEquals('foo', $this->renderTemplate($kernel));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Twig_Error_Runtime
|
||||
*/
|
||||
public function testRenderWithError()
|
||||
{
|
||||
$kernel = $this->getKernel($this->throwException(new \Exception('foo')));
|
||||
|
||||
$loader = new \Twig_Loader_Array(array('index' => '{{ render("foo") }}'));
|
||||
$twig = new \Twig_Environment($loader, array('debug' => true, 'cache' => false));
|
||||
$twig->addExtension(new HttpKernelExtension($kernel));
|
||||
|
||||
$this->renderTemplate($kernel);
|
||||
}
|
||||
|
||||
protected function getKernel($return)
|
||||
{
|
||||
$kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
|
||||
$kernel
|
||||
->expects($this->once())
|
||||
->method('handle')
|
||||
->will($return)
|
||||
;
|
||||
|
||||
return $kernel;
|
||||
}
|
||||
|
||||
protected function renderTemplate(HttpKernelInterface $kernel, $template = '{{ render("foo") }}')
|
||||
{
|
||||
$loader = new \Twig_Loader_Array(array('index' => $template));
|
||||
$twig = new \Twig_Environment($loader, array('debug' => true, 'cache' => false));
|
||||
$twig->addExtension(new HttpKernelExtension($kernel));
|
||||
|
||||
return $twig->render('index');
|
||||
}
|
||||
}
|
@ -26,6 +26,8 @@ class TransChoiceTokenParser extends TransTokenParser
|
||||
* @param \Twig_Token $token A Twig_Token instance
|
||||
*
|
||||
* @return \Twig_NodeInterface A Twig_NodeInterface instance
|
||||
*
|
||||
* @throws \Twig_Error_Syntax
|
||||
*/
|
||||
public function parse(\Twig_Token $token)
|
||||
{
|
||||
|
@ -26,6 +26,8 @@ class TransTokenParser extends \Twig_TokenParser
|
||||
* @param \Twig_Token $token A Twig_Token instance
|
||||
*
|
||||
* @return \Twig_NodeInterface A Twig_NodeInterface instance
|
||||
*
|
||||
* @throws \Twig_Error_Syntax
|
||||
*/
|
||||
public function parse(\Twig_Token $token)
|
||||
{
|
||||
|
@ -21,6 +21,7 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/form": "2.2.*",
|
||||
"symfony/http-kernel": "2.2.*",
|
||||
"symfony/routing": "2.2.*",
|
||||
"symfony/templating": "2.2.*",
|
||||
"symfony/translation": "2.2.*",
|
||||
@ -29,6 +30,7 @@
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/form": "2.2.*",
|
||||
"symfony/http-kernel": "2.2.*",
|
||||
"symfony/routing": "2.2.*",
|
||||
"symfony/templating": "2.2.*",
|
||||
"symfony/translation": "2.2.*",
|
||||
|
@ -4,12 +4,18 @@ CHANGELOG
|
||||
2.2.0
|
||||
-----
|
||||
|
||||
* [BC BREAK] restricted the `Symfony\Bundle\FrameworkBundle\HttpKernel::render()` method to only accept URIs as reference
|
||||
* `Symfony\Bundle\FrameworkBundle\HttpKernel::render()` method signature changed and the first argument
|
||||
must now be a URI (the `generateInternalUri()` method was removed)
|
||||
* The internal routes have been removed (`Resources/config/routing/internal.xml`)
|
||||
* The `render` method of the `actions` templating helper signature and arguments changed:
|
||||
* replaced Symfony\Bundle\FrameworkBundle\Controller\TraceableControllerResolver by Symfony\Component\HttpKernel\Controller\TraceableControllerResolver
|
||||
* replaced Symfony\Component\HttpKernel\Debug\ContainerAwareTraceableEventDispatcher by Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher
|
||||
* added Client::enableProfiler()
|
||||
* A new parameter has been added to the DIC: `router.request_context.base_url`
|
||||
You can customize it for your functional tests or for generating urls with
|
||||
the right base url when your are in the cli context.
|
||||
* Added support for default templates per render tag
|
||||
|
||||
2.1.0
|
||||
-----
|
||||
|
@ -280,6 +280,8 @@ EOF
|
||||
* Loads the ContainerBuilder from the cache.
|
||||
*
|
||||
* @return ContainerBuilder
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
protected function getContainerBuilder()
|
||||
{
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Controller;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
@ -19,8 +20,8 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\Form\FormTypeInterface;
|
||||
use Symfony\Component\Form\Form;
|
||||
use Symfony\Component\Form\FormBuilder;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Doctrine\Bundle\DoctrineBundle\Registry;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Controller is a simple implementation of a Controller.
|
||||
@ -36,13 +37,15 @@ class Controller extends ContainerAware
|
||||
*
|
||||
* @param string $route The name of the route
|
||||
* @param mixed $parameters An array of parameters
|
||||
* @param Boolean $absolute Whether to generate an absolute URL
|
||||
* @param Boolean|string $referenceType The type of reference (one of the constants in UrlGeneratorInterface)
|
||||
*
|
||||
* @return string The generated URL
|
||||
*
|
||||
* @see UrlGeneratorInterface
|
||||
*/
|
||||
public function generateUrl($route, $parameters = array(), $absolute = false)
|
||||
public function generateUrl($route, $parameters = array(), $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH)
|
||||
{
|
||||
return $this->container->get('router')->generate($route, $parameters, $absolute);
|
||||
return $this->container->get('router')->generate($route, $parameters, $referenceType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -38,6 +38,11 @@ class ControllerNameParser
|
||||
* Converts a short notation a:b:c to a class::method.
|
||||
*
|
||||
* @param string $controller A short notation controller (a:b:c)
|
||||
*
|
||||
* @return string A string with class::method
|
||||
*
|
||||
* @throws \InvalidArgumentException when the specified bundle is not enabled
|
||||
* or the controller cannot be found
|
||||
*/
|
||||
public function parse($controller)
|
||||
{
|
||||
@ -47,40 +52,23 @@ class ControllerNameParser
|
||||
|
||||
list($bundle, $controller, $action) = $parts;
|
||||
$controller = str_replace('/', '\\', $controller);
|
||||
$class = null;
|
||||
$logs = array();
|
||||
$bundles = array();
|
||||
|
||||
// this throws an exception if there is no such bundle
|
||||
foreach ($this->kernel->getBundle($bundle, false) as $b) {
|
||||
$try = $b->getNamespace().'\\Controller\\'.$controller.'Controller';
|
||||
if (!class_exists($try)) {
|
||||
$logs[] = sprintf('Unable to find controller "%s:%s" - class "%s" does not exist.', $bundle, $controller, $try);
|
||||
} else {
|
||||
$class = $try;
|
||||
|
||||
break;
|
||||
}
|
||||
if (class_exists($try)) {
|
||||
return $try.'::'.$action.'Action';
|
||||
}
|
||||
|
||||
if (null === $class) {
|
||||
$this->handleControllerNotFoundException($bundle, $controller, $logs);
|
||||
$bundles[] = $b->getName();
|
||||
$msg = sprintf('Unable to find controller "%s:%s" - class "%s" does not exist.', $bundle, $controller, $try);
|
||||
}
|
||||
|
||||
return $class.'::'.$action.'Action';
|
||||
if (count($bundles) > 1) {
|
||||
$msg = sprintf('Unable to find controller "%s:%s" in bundles %s.', $bundle, $controller, implode(', ', $bundles));
|
||||
}
|
||||
|
||||
private function handleControllerNotFoundException($bundle, $controller, array $logs)
|
||||
{
|
||||
// just one log, return it as the exception
|
||||
if (1 == count($logs)) {
|
||||
throw new \InvalidArgumentException($logs[0]);
|
||||
}
|
||||
|
||||
// many logs, use a message that mentions each searched bundle
|
||||
$names = array();
|
||||
foreach ($this->kernel->getBundle($bundle, false) as $b) {
|
||||
$names[] = $b->getName();
|
||||
}
|
||||
$msg = sprintf('Unable to find controller "%s:%s" in bundles %s.', $bundle, $controller, implode(', ', $names));
|
||||
|
||||
throw new \InvalidArgumentException($msg);
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Controller;
|
||||
|
||||
use Symfony\Component\HttpKernel\Log\LoggerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpKernel\Controller\ControllerResolver as BaseControllerResolver;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
|
||||
|
@ -1,46 +0,0 @@
|
||||
<?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\Bundle\FrameworkBundle\Controller;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerAware;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* InternalController.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class InternalController extends ContainerAware
|
||||
{
|
||||
/**
|
||||
* Forwards to the given controller with the given path.
|
||||
*
|
||||
* @param string $path The path
|
||||
* @param string $controller The controller name
|
||||
*
|
||||
* @return Response A Response instance
|
||||
*/
|
||||
public function indexAction($path, $controller)
|
||||
{
|
||||
$request = $this->container->get('request');
|
||||
$attributes = $request->attributes;
|
||||
|
||||
$attributes->remove('path');
|
||||
$attributes->remove('controller');
|
||||
if ('none' !== $path) {
|
||||
parse_str($path, $tmp);
|
||||
$attributes->add($tmp);
|
||||
}
|
||||
|
||||
return $this->container->get('http_kernel')->forward($controller, $attributes->all(), $request->query->all());
|
||||
}
|
||||
}
|
@ -12,8 +12,9 @@
|
||||
namespace Symfony\Bundle\FrameworkBundle\Controller;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerAware;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
|
||||
/**
|
||||
* Redirects a request to another URL.
|
||||
@ -45,7 +46,7 @@ class RedirectController extends ContainerAware
|
||||
$attributes = $this->container->get('request')->attributes->get('_route_params');
|
||||
unset($attributes['route'], $attributes['permanent']);
|
||||
|
||||
return new RedirectResponse($this->container->get('router')->generate($route, $attributes, true), $permanent ? 301 : 302);
|
||||
return new RedirectResponse($this->container->get('router')->generate($route, $attributes, UrlGeneratorInterface::ABSOLUTE_URL), $permanent ? 301 : 302);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -28,6 +28,6 @@ class AddValidatorInitializersPass implements CompilerPassInterface
|
||||
$initializers[] = new Reference($id);
|
||||
}
|
||||
|
||||
$container->getDefinition('validator')->replaceArgument(2, $initializers);
|
||||
$container->getDefinition('validator')->replaceArgument(4, $initializers);
|
||||
}
|
||||
}
|
||||
|
@ -51,8 +51,20 @@ class Configuration implements ConfigurationInterface
|
||||
})
|
||||
->end()
|
||||
->end()
|
||||
->scalarNode('trust_proxy_headers')->defaultFalse()->end()
|
||||
->scalarNode('secret')->end()
|
||||
->scalarNode('trust_proxy_headers')->defaultFalse()->end() // @deprecated, to be removed in 2.3
|
||||
->arrayNode('trusted_proxies')
|
||||
->beforeNormalization()
|
||||
->ifTrue(function($v) { return !is_array($v) && !is_null($v); })
|
||||
->then(function($v) { return is_bool($v) ? array() : preg_split('/\s*,\s*/', $v); })
|
||||
->end()
|
||||
->prototype('scalar')
|
||||
->validate()
|
||||
->ifTrue(function($v) { return !empty($v) && !filter_var($v, FILTER_VALIDATE_IP); })
|
||||
->thenInvalid('Invalid proxy IP "%s"')
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->scalarNode('ide')->defaultNull()->end()
|
||||
->booleanNode('test')->end()
|
||||
->scalarNode('default_locale')->defaultValue('en')->end()
|
||||
@ -358,6 +370,7 @@ class Configuration implements ConfigurationInterface
|
||||
->children()
|
||||
->scalarNode('cache')->end()
|
||||
->booleanNode('enable_annotations')->defaultFalse()->end()
|
||||
->scalarNode('translation_domain')->defaultValue('validators')->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
|
@ -65,6 +65,9 @@ class FrameworkExtension extends Extension
|
||||
$container->setParameter('kernel.secret', $config['secret']);
|
||||
}
|
||||
|
||||
$container->setParameter('kernel.trusted_proxies', $config['trusted_proxies']);
|
||||
|
||||
// @deprecated, to be removed in 2.3
|
||||
$container->setParameter('kernel.trust_proxy_headers', $config['trust_proxy_headers']);
|
||||
|
||||
$container->setParameter('kernel.default_locale', $config['default_locale']);
|
||||
@ -147,6 +150,8 @@ class FrameworkExtension extends Extension
|
||||
* @param array $config A configuration array
|
||||
* @param ContainerBuilder $container A ContainerBuilder instance
|
||||
* @param XmlFileLoader $loader An XmlFileLoader instance
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
private function registerFormConfiguration($config, ContainerBuilder $container, XmlFileLoader $loader)
|
||||
{
|
||||
@ -184,6 +189,8 @@ class FrameworkExtension extends Extension
|
||||
* @param array $config A profiler configuration array
|
||||
* @param ContainerBuilder $container A ContainerBuilder instance
|
||||
* @param XmlFileLoader $loader An XmlFileLoader instance
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
private function registerProfilerConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
|
||||
{
|
||||
@ -520,6 +527,11 @@ class FrameworkExtension extends Extension
|
||||
|
||||
$dirs[] = dirname($r->getFilename()).'/Resources/translations';
|
||||
}
|
||||
if (class_exists('Symfony\Component\Security\Core\Exception\AuthenticationException')) {
|
||||
$r = new \ReflectionClass('Symfony\Component\Security\Core\Exception\AuthenticationException');
|
||||
|
||||
$dirs[] = dirname($r->getFilename()).'/../../Resources/translations';
|
||||
}
|
||||
$overridePath = $container->getParameter('kernel.root_dir').'/Resources/%s/translations';
|
||||
foreach ($container->getParameter('kernel.bundles') as $bundle => $class) {
|
||||
$reflection = new \ReflectionClass($class);
|
||||
@ -567,6 +579,7 @@ class FrameworkExtension extends Extension
|
||||
{
|
||||
$loader->load('validator.xml');
|
||||
|
||||
$container->setParameter('validator.translation_domain', $config['translation_domain']);
|
||||
$container->setParameter('validator.mapping.loader.xml_files_loader.mapping_files', $this->getValidatorXmlMappingFiles($container));
|
||||
$container->setParameter('validator.mapping.loader.yaml_files_loader.mapping_files', $this->getValidatorYamlMappingFiles($container));
|
||||
|
||||
|
@ -19,7 +19,7 @@ use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Sets the session on the request.
|
||||
* Sets the session in the request.
|
||||
*
|
||||
* This will also start the session if it was already started during a previous
|
||||
* request.
|
||||
|
@ -67,11 +67,10 @@ class TestSessionListener implements EventSubscriberInterface
|
||||
return;
|
||||
}
|
||||
|
||||
if ($session = $event->getRequest()->getSession()) {
|
||||
$session = $event->getRequest()->getSession();
|
||||
if ($session && $session->isStarted()) {
|
||||
$session->save();
|
||||
|
||||
$params = session_get_cookie_params();
|
||||
|
||||
$event->getResponse()->headers->setCookie(new Cookie($session->getName(), $session->getId(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly']));
|
||||
}
|
||||
}
|
||||
|
@ -40,8 +40,10 @@ class FrameworkBundle extends Bundle
|
||||
{
|
||||
public function boot()
|
||||
{
|
||||
if ($this->container->getParameter('kernel.trust_proxy_headers')) {
|
||||
Request::trustProxyData();
|
||||
if ($trustedProxies = $this->container->getParameter('kernel.trusted_proxies')) {
|
||||
Request::setTrustedProxies($trustedProxies);
|
||||
} elseif ($this->container->getParameter('kernel.trust_proxy_headers')) {
|
||||
Request::trustProxyData(); // @deprecated, to be removed in 2.3
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,78 +84,61 @@ class HttpKernel extends BaseHttpKernel
|
||||
*
|
||||
* Available options:
|
||||
*
|
||||
* * attributes: An array of request attributes (only when the first argument is a controller)
|
||||
* * query: An array of request query parameters (only when the first argument is a controller)
|
||||
* * ignore_errors: true to return an empty string in case of an error
|
||||
* * alt: an alternative controller to execute in case of an error (can be a controller, a URI, or an array with the controller, the attributes, and the query arguments)
|
||||
* * alt: an alternative URI to execute in case of an error
|
||||
* * standalone: whether to generate an esi:include tag or not when ESI is supported
|
||||
* * comment: a comment to add when returning an esi:include tag
|
||||
*
|
||||
* @param string $controller A controller name to execute (a string like BlogBundle:Post:index), or a relative URI
|
||||
* @param string $uri A URI
|
||||
* @param array $options An array of options
|
||||
*
|
||||
* @return string The Response content
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function render($controller, array $options = array())
|
||||
public function render($uri, array $options = array())
|
||||
{
|
||||
$request = $this->container->get('request');
|
||||
|
||||
$options = array_merge(array(
|
||||
'attributes' => array(),
|
||||
'query' => array(),
|
||||
'ignore_errors' => !$this->container->getParameter('kernel.debug'),
|
||||
'alt' => array(),
|
||||
'alt' => null,
|
||||
'standalone' => false,
|
||||
'comment' => '',
|
||||
'default' => null,
|
||||
), $options);
|
||||
|
||||
if (!is_array($options['alt'])) {
|
||||
$options['alt'] = array($options['alt']);
|
||||
}
|
||||
|
||||
if (null === $this->esiSupport) {
|
||||
$this->esiSupport = $this->container->has('esi') && $this->container->get('esi')->hasSurrogateEsiCapability($this->container->get('request'));
|
||||
$this->esiSupport = $this->container->has('esi') && $this->container->get('esi')->hasSurrogateEsiCapability($request);
|
||||
}
|
||||
|
||||
if ($this->esiSupport && (true === $options['standalone'] || 'esi' === $options['standalone'])) {
|
||||
$uri = $this->generateInternalUri($controller, $options['attributes'], $options['query']);
|
||||
|
||||
$alt = '';
|
||||
if ($options['alt']) {
|
||||
$alt = $this->generateInternalUri($options['alt'][0], isset($options['alt'][1]) ? $options['alt'][1] : array(), isset($options['alt'][2]) ? $options['alt'][2] : array());
|
||||
}
|
||||
|
||||
return $this->container->get('esi')->renderIncludeTag($uri, $alt, $options['ignore_errors'], $options['comment']);
|
||||
return $this->container->get('esi')->renderIncludeTag($uri, $options['alt'], $options['ignore_errors'], $options['comment']);
|
||||
}
|
||||
|
||||
if ('js' === $options['standalone']) {
|
||||
$uri = $this->generateInternalUri($controller, $options['attributes'], $options['query'], false);
|
||||
$defaultContent = null;
|
||||
|
||||
if ($template = $this->container->getParameter('templating.hinclude.default_template')) {
|
||||
$defaultContent = $this->container->get('templating')->render($template);
|
||||
$templating = $this->container->get('templating');
|
||||
|
||||
if ($options['default']) {
|
||||
if ($templating->exists($options['default'])) {
|
||||
$defaultContent = $templating->render($options['default']);
|
||||
} else {
|
||||
$defaultContent = $options['default'];
|
||||
}
|
||||
} elseif ($template = $this->container->getParameter('templating.hinclude.default_template')) {
|
||||
$defaultContent = $templating->render($template);
|
||||
}
|
||||
|
||||
return $this->renderHIncludeTag($uri, $defaultContent);
|
||||
}
|
||||
|
||||
$request = $this->container->get('request');
|
||||
|
||||
// controller or URI?
|
||||
if (0 === strpos($controller, '/')) {
|
||||
$subRequest = Request::create($request->getUriForPath($controller), 'get', array(), $request->cookies->all(), array(), $request->server->all());
|
||||
$subRequest = Request::create($uri, 'get', array(), $request->cookies->all(), array(), $request->server->all());
|
||||
if ($session = $request->getSession()) {
|
||||
$subRequest->setSession($session);
|
||||
}
|
||||
} else {
|
||||
$options['attributes']['_controller'] = $controller;
|
||||
|
||||
if (!isset($options['attributes']['_format'])) {
|
||||
$options['attributes']['_format'] = $request->getRequestFormat();
|
||||
}
|
||||
|
||||
$options['attributes']['_route'] = '_internal';
|
||||
$subRequest = $request->duplicate($options['query'], null, $options['attributes']);
|
||||
$subRequest->setMethod('GET');
|
||||
}
|
||||
|
||||
$level = ob_get_level();
|
||||
try {
|
||||
@ -174,10 +157,8 @@ class HttpKernel extends BaseHttpKernel
|
||||
if ($options['alt']) {
|
||||
$alt = $options['alt'];
|
||||
unset($options['alt']);
|
||||
$options['attributes'] = isset($alt[1]) ? $alt[1] : array();
|
||||
$options['query'] = isset($alt[2]) ? $alt[2] : array();
|
||||
|
||||
return $this->render($alt[0], $options);
|
||||
return $this->render($alt, $options);
|
||||
}
|
||||
|
||||
if (!$options['ignore_errors']) {
|
||||
@ -191,43 +172,13 @@ class HttpKernel extends BaseHttpKernel
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an internal URI for a given controller.
|
||||
*
|
||||
* This method uses the "_internal" route, which should be available.
|
||||
*
|
||||
* @param string $controller A controller name to execute (a string like BlogBundle:Post:index), or a relative URI
|
||||
* @param array $attributes An array of request attributes
|
||||
* @param array $query An array of request query parameters
|
||||
* @param boolean $secure
|
||||
*
|
||||
* @return string An internal URI
|
||||
*/
|
||||
public function generateInternalUri($controller, array $attributes = array(), array $query = array(), $secure = true)
|
||||
{
|
||||
if (0 === strpos($controller, '/')) {
|
||||
return $controller;
|
||||
}
|
||||
|
||||
$path = http_build_query($attributes, '', '&');
|
||||
$uri = $this->container->get('router')->generate($secure ? '_internal' : '_internal_public', array(
|
||||
'controller' => $controller,
|
||||
'path' => $path ?: 'none',
|
||||
'_format' => $this->container->get('request')->getRequestFormat(),
|
||||
));
|
||||
|
||||
if ($queryString = http_build_query($query, '', '&')) {
|
||||
$uri .= '?'.$queryString;
|
||||
}
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders an HInclude tag.
|
||||
*
|
||||
* @param string $uri A URI
|
||||
* @param string $defaultContent Default content
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function renderHIncludeTag($uri, $defaultContent = null)
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2004-2012 Fabien Potencier
|
||||
Copyright (c) 2004-2013 Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -17,41 +17,41 @@
|
||||
|
||||
<services>
|
||||
<service id="data_collector.config" class="%data_collector.config.class%" public="false">
|
||||
<tag name="data_collector" template="WebProfilerBundle:Collector:config" id="config" priority="255" />
|
||||
<call method="setKernel"><argument type="service" id="kernel" /></call>
|
||||
<tag name="data_collector" template="@WebProfiler/Collector/config.html.twig" id="config" priority="255" />
|
||||
<call method="setKernel"><argument type="service" id="kernel" on-invalid="ignore" /></call>
|
||||
</service>
|
||||
|
||||
<service id="data_collector.request" class="%data_collector.request.class%">
|
||||
<tag name="kernel.event_subscriber" />
|
||||
<tag name="data_collector" template="WebProfilerBundle:Collector:request" id="request" priority="255" />
|
||||
<tag name="data_collector" template="@WebProfiler/Collector/request.html.twig" id="request" priority="255" />
|
||||
</service>
|
||||
|
||||
<service id="data_collector.exception" class="%data_collector.exception.class%" public="false">
|
||||
<tag name="data_collector" template="WebProfilerBundle:Collector:exception" id="exception" priority="255" />
|
||||
<tag name="data_collector" template="@WebProfiler/Collector/exception.html.twig" id="exception" priority="255" />
|
||||
</service>
|
||||
|
||||
<service id="data_collector.events" class="%data_collector.events.class%" public="false">
|
||||
<tag name="data_collector" template="WebProfilerBundle:Collector:events" id="events" priority="255" />
|
||||
<tag name="data_collector" template="@WebProfiler/Collector/events.html.twig" id="events" priority="255" />
|
||||
</service>
|
||||
|
||||
<service id="data_collector.logger" class="%data_collector.logger.class%" public="false">
|
||||
<tag name="data_collector" template="WebProfilerBundle:Collector:logger" id="logger" priority="255" />
|
||||
<tag name="data_collector" template="@WebProfiler/Collector/logger.html.twig" id="logger" priority="255" />
|
||||
<tag name="monolog.logger" channel="profiler" />
|
||||
<argument type="service" id="logger" on-invalid="ignore" />
|
||||
</service>
|
||||
|
||||
<service id="data_collector.time" class="%data_collector.time.class%" public="false">
|
||||
<tag name="data_collector" template="WebProfilerBundle:Collector:time" id="time" priority="255" />
|
||||
<argument type="service" id="kernel" />
|
||||
<tag name="data_collector" template="@WebProfiler/Collector/time.html.twig" id="time" priority="255" />
|
||||
<argument type="service" id="kernel" on-invalid="ignore" />
|
||||
</service>
|
||||
|
||||
<service id="data_collector.memory" class="%data_collector.memory.class%" public="false">
|
||||
<tag name="data_collector" template="WebProfilerBundle:Collector:memory" id="memory" priority="255" />
|
||||
<tag name="data_collector" template="@WebProfiler/Collector/memory.html.twig" id="memory" priority="255" />
|
||||
</service>
|
||||
|
||||
<service id="data_collector.router" class="%data_collector.router.class%" >
|
||||
<tag name="kernel.event_listener" event="kernel.controller" method="onKernelController"/>
|
||||
<tag name="data_collector" template="WebProfilerBundle:Collector:router" id="router" priority="255" />
|
||||
<tag name="data_collector" template="@WebProfiler/Collector/router.html.twig" id="router" priority="255" />
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
||||
|
@ -10,6 +10,7 @@
|
||||
<parameter key="form.factory.class">Symfony\Component\Form\FormFactory</parameter>
|
||||
<parameter key="form.extension.class">Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension</parameter>
|
||||
<parameter key="form.type_guesser.validator.class">Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser</parameter>
|
||||
<parameter key="property_accessor.class">Symfony\Component\PropertyAccess\PropertyAccessor</parameter>
|
||||
</parameters>
|
||||
|
||||
<services>
|
||||
@ -53,11 +54,15 @@
|
||||
<argument type="service" id="validator.mapping.class_metadata_factory" />
|
||||
</service>
|
||||
|
||||
<!-- PropertyAccessor -->
|
||||
<service id="property_accessor" class="%property_accessor.class%" />
|
||||
|
||||
<!-- CoreExtension -->
|
||||
<service id="form.type.field" class="Symfony\Component\Form\Extension\Core\Type\FieldType">
|
||||
<tag name="form.type" alias="field" />
|
||||
</service>
|
||||
<service id="form.type.form" class="Symfony\Component\Form\Extension\Core\Type\FormType">
|
||||
<argument type="service" id="property_accessor"/>
|
||||
<tag name="form.type" alias="form" />
|
||||
</service>
|
||||
<service id="form.type.birthday" class="Symfony\Component\Form\Extension\Core\Type\BirthdayType">
|
||||
|
@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<routes xmlns="http://symfony.com/schema/routing"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
|
||||
|
||||
<route id="_internal" pattern="/secure/{controller}/{path}.{_format}">
|
||||
<default key="_controller">FrameworkBundle:Internal:index</default>
|
||||
<requirement key="path">.+</requirement>
|
||||
<requirement key="_format">[^.]+</requirement>
|
||||
</route>
|
||||
|
||||
<route id="_internal_public" pattern="/{controller}/{path}.{_format}">
|
||||
<default key="_controller">FrameworkBundle:Internal:index</default>
|
||||
<requirement key="path">.+</requirement>
|
||||
<requirement key="_format">[^.]+</requirement>
|
||||
</route>
|
||||
</routes>
|
@ -24,6 +24,7 @@
|
||||
<!-- charset is deprecated and will be removed in 2.2 -->
|
||||
<xsd:attribute name="charset" type="xsd:string" />
|
||||
<xsd:attribute name="trust-proxy-headers" type="xsd:string" />
|
||||
<xsd:attribute name="trusted-proxies" type="xsd:string" />
|
||||
<xsd:attribute name="ide" type="xsd:string" />
|
||||
<xsd:attribute name="secret" type="xsd:string" />
|
||||
<xsd:attribute name="default-locale" type="xsd:string" />
|
||||
|
@ -13,7 +13,7 @@
|
||||
<parameter key="translation.loader.xliff.class">Symfony\Component\Translation\Loader\XliffFileLoader</parameter>
|
||||
<parameter key="translation.loader.po.class">Symfony\Component\Translation\Loader\PoFileLoader</parameter>
|
||||
<parameter key="translation.loader.mo.class">Symfony\Component\Translation\Loader\MoFileLoader</parameter>
|
||||
<parameter key="translation.loader.qt.class">Symfony\Component\Translation\Loader\QtTranslationsLoader</parameter>
|
||||
<parameter key="translation.loader.qt.class">Symfony\Component\Translation\Loader\QtFileLoader</parameter>
|
||||
<parameter key="translation.loader.csv.class">Symfony\Component\Translation\Loader\CsvFileLoader</parameter>
|
||||
<parameter key="translation.loader.res.class">Symfony\Component\Translation\Loader\IcuResFileLoader</parameter>
|
||||
<parameter key="translation.loader.dat.class">Symfony\Component\Translation\Loader\IcuDatFileLoader</parameter>
|
||||
|
@ -23,6 +23,8 @@
|
||||
<service id="validator" class="%validator.class%">
|
||||
<argument type="service" id="validator.mapping.class_metadata_factory" />
|
||||
<argument type="service" id="validator.validator_factory" />
|
||||
<argument type="service" id="translator.default" />
|
||||
<argument>%validator.translation_domain%</argument>
|
||||
<argument type="collection" />
|
||||
</service>
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
<?php echo $view['form']->block($form, 'widget_attributes') ?>
|
||||
<?php if ($multiple): ?> multiple="multiple"<?php endif ?>
|
||||
>
|
||||
<?php if (null !== $empty_value): ?><option value=""><?php echo $view->escape($view['translator']->trans($empty_value, array(), $translation_domain)) ?></option><?php endif; ?>
|
||||
<?php if (null !== $empty_value): ?><option value="" disabled="disabled"<?php if (empty($value) && "0" !== $value): ?> selected="selected"<?php endif ?>><?php echo $view->escape($view['translator']->trans($empty_value, array(), $translation_domain)) ?></option><?php endif; ?>
|
||||
<?php if (count($preferred_choices) > 0): ?>
|
||||
<?php echo $view['form']->block($form, 'choice_widget_options', array('choices' => $preferred_choices)) ?>
|
||||
<?php if (count($choices) > 0 && null !== $separator): ?>
|
||||
|
@ -1,21 +1,7 @@
|
||||
<?php if ($errors): ?>
|
||||
<ul>
|
||||
<?php foreach ($errors as $error): ?>
|
||||
<li><?php
|
||||
if (null === $error->getMessagePluralization()) {
|
||||
echo $view['translator']->trans(
|
||||
$error->getMessageTemplate(),
|
||||
$error->getMessageParameters(),
|
||||
'validators'
|
||||
);
|
||||
} else {
|
||||
echo $view['translator']->transChoice(
|
||||
$error->getMessageTemplate(),
|
||||
$error->getMessagePluralization(),
|
||||
$error->getMessageParameters(),
|
||||
'validators'
|
||||
);
|
||||
}?></li>
|
||||
<li><?php echo $error->getMessage() ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif ?>
|
||||
|
@ -6,8 +6,11 @@
|
||||
// There should be no spaces between the colons and the widgets, that's why
|
||||
// this block is written in a single PHP tag
|
||||
echo $view['form']->widget($form['hour'], array('attr' => array('size' => 1)));
|
||||
|
||||
if ($with_minutes) {
|
||||
echo ':';
|
||||
echo $view['form']->widget($form['minute'], array('attr' => array('size' => 1)));
|
||||
}
|
||||
|
||||
if ($with_seconds) {
|
||||
echo ':';
|
||||
|
@ -1,21 +0,0 @@
|
||||
<?php if ($errors): ?>
|
||||
<ul>
|
||||
<?php foreach ($errors as $error): ?>
|
||||
<li><?php
|
||||
if (null === $error->getMessagePluralization()) {
|
||||
echo $view['translator']->trans(
|
||||
$error->getMessageTemplate(),
|
||||
$error->getMessageParameters(),
|
||||
'validators'
|
||||
);
|
||||
} else {
|
||||
echo $view['translator']->transChoice(
|
||||
$error->getMessageTemplate(),
|
||||
$error->getMessagePluralization(),
|
||||
$error->getMessageParameters(),
|
||||
'validators'
|
||||
);
|
||||
}?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif ?>
|
@ -14,7 +14,7 @@ namespace Symfony\Bundle\FrameworkBundle\Routing;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
|
||||
use Symfony\Component\Config\Loader\DelegatingLoader as BaseDelegatingLoader;
|
||||
use Symfony\Component\Config\Loader\LoaderResolverInterface;
|
||||
use Symfony\Component\HttpKernel\Log\LoggerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* DelegatingLoader delegates route loading to other loaders using a loader resolver.
|
||||
|
@ -12,7 +12,7 @@
|
||||
namespace Symfony\Bundle\FrameworkBundle\Templating;
|
||||
|
||||
use Symfony\Component\Templating\DebuggerInterface;
|
||||
use Symfony\Component\HttpKernel\Log\LoggerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Binds the Symfony templating loader debugger to the Symfony logger.
|
||||
|
@ -12,6 +12,10 @@
|
||||
namespace Symfony\Bundle\FrameworkBundle\Templating;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
use Symfony\Component\Security\Core\SecurityContext;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* GlobalVariables is the entry point for Symfony global variables in Twig templates.
|
||||
@ -30,7 +34,7 @@ class GlobalVariables
|
||||
/**
|
||||
* Returns the security context service.
|
||||
*
|
||||
* @return Symfony\Component\Security\Core\SecurityContext|void The security context
|
||||
* @return SecurityContext|null The security context
|
||||
*/
|
||||
public function getSecurity()
|
||||
{
|
||||
@ -44,7 +48,7 @@ class GlobalVariables
|
||||
*
|
||||
* @return mixed|void
|
||||
*
|
||||
* @see Symfony\Component\Security\Core\Authentication\Token\TokenInterface::getUser()
|
||||
* @see TokenInterface::getUser()
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
@ -67,7 +71,7 @@ class GlobalVariables
|
||||
/**
|
||||
* Returns the current request.
|
||||
*
|
||||
* @return Symfony\Component\HttpFoundation\Request|void The http request object
|
||||
* @return Request|null The http request object
|
||||
*/
|
||||
public function getRequest()
|
||||
{
|
||||
@ -79,7 +83,7 @@ class GlobalVariables
|
||||
/**
|
||||
* Returns the current session.
|
||||
*
|
||||
* @return Symfony\Component\HttpFoundation\Session\Session|void The session
|
||||
* @return Session|null The session
|
||||
*/
|
||||
public function getSession()
|
||||
{
|
||||
|
@ -34,19 +34,18 @@ class ActionsHelper extends Helper
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Response content for a given controller or URI.
|
||||
* Returns the Response content for a given URI.
|
||||
*
|
||||
* @param string $controller A controller name to execute (a string like BlogBundle:Post:index), or a relative URI
|
||||
* @param array $attributes An array of request attributes
|
||||
* @param string $uri A URI
|
||||
* @param array $options An array of options
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @see Symfony\Bundle\FrameworkBundle\HttpKernel::render()
|
||||
*/
|
||||
public function render($controller, array $attributes = array(), array $options = array())
|
||||
public function render($uri, array $options = array())
|
||||
{
|
||||
$options['attributes'] = $attributes;
|
||||
|
||||
return $this->kernel->render($controller, $options);
|
||||
return $this->kernel->render($uri, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -122,6 +122,15 @@ class CodeHelper extends Helper
|
||||
public function fileExcerpt($file, $line)
|
||||
{
|
||||
if (is_readable($file)) {
|
||||
if (extension_loaded('fileinfo')) {
|
||||
$finfo = new \Finfo();
|
||||
|
||||
// Check if the file is an application/octet-stream (eg. Phar file) because hightlight_file cannot parse these files
|
||||
if ('application/octet-stream' === $finfo->file($file, FILEINFO_MIME_TYPE)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$code = highlight_file($file, true);
|
||||
// remove main code/span tags
|
||||
$code = preg_replace('#^<code.*?>\s*<span.*?>(.*)</span>\s*</code>#s', '\\1', $code);
|
||||
|
@ -84,7 +84,7 @@ class FormHelper extends Helper
|
||||
*
|
||||
* <?php echo view['form']->widget(array('attr' => array('class' => 'foo'))) ?>
|
||||
*
|
||||
* <?php echo view['form']->widget(array('separator' => '+++++)) ?>
|
||||
* <?php echo view['form']->widget(array('separator' => '+++++')) ?>
|
||||
*
|
||||
* @param FormView $view The view for which to render the widget
|
||||
* @param array $variables Additional variables passed to the template
|
||||
|
@ -39,6 +39,8 @@ class RequestHelper extends Helper
|
||||
* @param string $key The name of the parameter
|
||||
* @param string $default A default value
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @see Symfony\Component\HttpFoundation\Request::get()
|
||||
*/
|
||||
public function getParameter($key, $default = null)
|
||||
|
@ -38,13 +38,15 @@ class RouterHelper extends Helper
|
||||
*
|
||||
* @param string $name The name of the route
|
||||
* @param mixed $parameters An array of parameters
|
||||
* @param Boolean $absolute Whether to generate an absolute URL
|
||||
* @param Boolean|string $referenceType The type of reference (one of the constants in UrlGeneratorInterface)
|
||||
*
|
||||
* @return string The generated URL
|
||||
*
|
||||
* @see UrlGeneratorInterface
|
||||
*/
|
||||
public function generate($name, $parameters = array(), $absolute = false)
|
||||
public function generate($name, $parameters = array(), $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH)
|
||||
{
|
||||
return $this->generator->generate($name, $parameters, $absolute);
|
||||
return $this->generator->generate($name, $parameters, $referenceType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -40,7 +40,7 @@ class FilesystemLoader implements LoaderInterface
|
||||
*
|
||||
* @param TemplateReferenceInterface $template A template
|
||||
*
|
||||
* @return Storage|Boolean false if the template cannot be loaded, a Storage instance otherwise
|
||||
* @return FileStorage|Boolean false if the template cannot be loaded, a Storage instance otherwise
|
||||
*/
|
||||
public function load(TemplateReferenceInterface $template)
|
||||
{
|
||||
@ -58,6 +58,8 @@ class FilesystemLoader implements LoaderInterface
|
||||
*
|
||||
* @param TemplateReferenceInterface $template The template name as an array
|
||||
* @param integer $time The last modification time of the cached template (timestamp)
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public function isFresh(TemplateReferenceInterface $template, $time)
|
||||
{
|
||||
|
@ -55,6 +55,8 @@ abstract class WebTestCase extends \PHPUnit_Framework_TestCase
|
||||
* If not, override this method in your test classes.
|
||||
*
|
||||
* @return string The directory where phpunit.xml(.dist) is stored
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected static function getPhpUnitXmlDir()
|
||||
{
|
||||
@ -113,6 +115,8 @@ abstract class WebTestCase extends \PHPUnit_Framework_TestCase
|
||||
* When the Kernel is located, the file is required.
|
||||
*
|
||||
* @return string The Kernel class name
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected static function getKernelClass()
|
||||
{
|
||||
|
@ -0,0 +1,81 @@
|
||||
<?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\Bundle\FrameworkBundle\Tests\DependencyInjection;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Configuration;
|
||||
use Symfony\Component\Config\Definition\Processor;
|
||||
|
||||
class ConfigurationTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider getTestConfigTreeData
|
||||
*/
|
||||
public function testConfigTree($options, $results)
|
||||
{
|
||||
$processor = new Processor();
|
||||
$configuration = new Configuration(array());
|
||||
$config = $processor->processConfiguration($configuration, array($options));
|
||||
|
||||
$this->assertEquals($results, $config);
|
||||
}
|
||||
|
||||
public function getTestConfigTreeData()
|
||||
{
|
||||
return array(
|
||||
array(array('secret' => 's3cr3t'), array('secret' => 's3cr3t', 'trusted_proxies' => array(), 'trust_proxy_headers' => false, 'ide' => NULL, 'annotations' => array('cache' => 'file', 'file_cache_dir' => '%kernel.cache_dir%/annotations', 'debug' => '%kernel.debug%'), 'default_locale' => 'en', 'charset' => null)),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getTestValidTrustedProxiesData
|
||||
*/
|
||||
public function testValidTrustedProxies($options, $results)
|
||||
{
|
||||
$processor = new Processor();
|
||||
$configuration = new Configuration(array());
|
||||
$config = $processor->processConfiguration($configuration, array($options));
|
||||
|
||||
$this->assertEquals($results, $config);
|
||||
}
|
||||
|
||||
public function getTestValidTrustedProxiesData()
|
||||
{
|
||||
return array(
|
||||
array(array('secret' => 's3cr3t', 'trusted_proxies' => array('127.0.0.1')), array('secret' => 's3cr3t', 'trusted_proxies' => array('127.0.0.1'), 'trust_proxy_headers' => false, 'ide' => NULL, 'annotations' => array('cache' => 'file', 'file_cache_dir' => '%kernel.cache_dir%/annotations', 'debug' => '%kernel.debug%'), 'default_locale' => 'en', 'charset' => null)),
|
||||
array(array('secret' => 's3cr3t', 'trusted_proxies' => array('::1')), array('secret' => 's3cr3t', 'trusted_proxies' => array('::1'), 'trust_proxy_headers' => false, 'ide' => NULL, 'annotations' => array('cache' => 'file', 'file_cache_dir' => '%kernel.cache_dir%/annotations', 'debug' => '%kernel.debug%'), 'default_locale' => 'en', 'charset' => null)),
|
||||
array(array('secret' => 's3cr3t', 'trusted_proxies' => array('127.0.0.1', '::1')), array('secret' => 's3cr3t', 'trusted_proxies' => array('127.0.0.1', '::1'), 'trust_proxy_headers' => false, 'ide' => NULL, 'annotations' => array('cache' => 'file', 'file_cache_dir' => '%kernel.cache_dir%/annotations', 'debug' => '%kernel.debug%'), 'default_locale' => 'en', 'charset' => null)),
|
||||
array(array('secret' => 's3cr3t', 'trusted_proxies' => null), array('secret' => 's3cr3t', 'trusted_proxies' => array(), 'trust_proxy_headers' => false, 'ide' => NULL, 'annotations' => array('cache' => 'file', 'file_cache_dir' => '%kernel.cache_dir%/annotations', 'debug' => '%kernel.debug%'), 'default_locale' => 'en', 'charset' => null)),
|
||||
array(array('secret' => 's3cr3t', 'trusted_proxies' => false), array('secret' => 's3cr3t', 'trusted_proxies' => array(), 'trust_proxy_headers' => false, 'ide' => NULL, 'annotations' => array('cache' => 'file', 'file_cache_dir' => '%kernel.cache_dir%/annotations', 'debug' => '%kernel.debug%'), 'default_locale' => 'en', 'charset' => null)),
|
||||
array(array('secret' => 's3cr3t', 'trusted_proxies' => array()), array('secret' => 's3cr3t', 'trusted_proxies' => array(), 'trust_proxy_headers' => false, 'ide' => NULL, 'annotations' => array('cache' => 'file', 'file_cache_dir' => '%kernel.cache_dir%/annotations', 'debug' => '%kernel.debug%'), 'default_locale' => 'en', 'charset' => null)),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
|
||||
*/
|
||||
public function testInvalidTypeTrustedProxies()
|
||||
{
|
||||
$processor = new Processor();
|
||||
$configuration = new Configuration(array());
|
||||
$config = $processor->processConfiguration($configuration, array(array('secret' => 's3cr3t', 'trusted_proxies' => 'Not an IP address')));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
|
||||
*/
|
||||
public function testInvalidValueTrustedProxies()
|
||||
{
|
||||
$processor = new Processor();
|
||||
$configuration = new Configuration(array());
|
||||
$config = $processor->processConfiguration($configuration, array(array('secret' => 's3cr3t', 'trusted_proxies' => array('Not an IP address'))));
|
||||
}
|
||||
}
|
@ -4,6 +4,8 @@ $container->loadFromExtension('framework', array(
|
||||
'secret' => 's3cr3t',
|
||||
'default_locale' => 'fr',
|
||||
'form' => null,
|
||||
'trust_proxy_headers' => true,
|
||||
'trusted_proxies' => array('127.0.0.1', '10.0.0.1'),
|
||||
'csrf_protection' => array(
|
||||
'enabled' => true,
|
||||
'field_name' => '_csrf',
|
||||
|
@ -6,7 +6,7 @@
|
||||
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" ide="file%%link%%format" default-locale="fr">
|
||||
<framework:config secret="s3cr3t" ide="file%%link%%format" default-locale="fr" trust-proxy-headers="true" trusted-proxies="127.0.0.1, 10.0.0.1">
|
||||
<framework:csrf-protection enabled="true" field-name="_csrf" />
|
||||
<framework:form />
|
||||
<framework:esi enabled="true" />
|
||||
|
@ -2,6 +2,8 @@ framework:
|
||||
secret: s3cr3t
|
||||
default_locale: fr
|
||||
form: ~
|
||||
trust_proxy_headers: true
|
||||
trusted_proxies: ['127.0.0.1', '10.0.0.1']
|
||||
csrf_protection:
|
||||
enabled: true
|
||||
field_name: _csrf
|
||||
|
@ -33,6 +33,14 @@ abstract class FrameworkExtensionTest extends TestCase
|
||||
$this->assertEquals('s3cr3t', $container->getParameterBag()->resolveValue($container->findDefinition('form.csrf_provider')->getArgument(1)));
|
||||
}
|
||||
|
||||
public function testProxies()
|
||||
{
|
||||
$container = $this->createContainerFromFile('full');
|
||||
|
||||
$this->assertTrue($container->getParameter('kernel.trust_proxy_headers'));
|
||||
$this->assertEquals(array('127.0.0.1', '10.0.0.1'), $container->getParameter('kernel.trusted_proxies'));
|
||||
}
|
||||
|
||||
public function testEsi()
|
||||
{
|
||||
$container = $this->createContainerFromFile('full');
|
||||
@ -65,7 +73,7 @@ abstract class FrameworkExtensionTest extends TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
|
||||
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
|
||||
*/
|
||||
public function testRouterRequiresResourceOption()
|
||||
{
|
||||
@ -197,13 +205,18 @@ abstract class FrameworkExtensionTest extends TestCase
|
||||
$files,
|
||||
'->registerTranslatorConfiguration() finds Form translation resources'
|
||||
);
|
||||
$this->assertContains(
|
||||
'Symfony/Component/Security/Resources/translations/security.en.xlf',
|
||||
$files,
|
||||
'->registerTranslatorConfiguration() finds Security translation resources'
|
||||
);
|
||||
|
||||
$calls = $container->getDefinition('translator.default')->getMethodCalls();
|
||||
$this->assertEquals('fr', $calls[0][1][0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
|
||||
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
|
||||
*/
|
||||
public function testTemplatingRequiresAtLeastOneEngine()
|
||||
{
|
||||
|
@ -16,6 +16,7 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
|
||||
/**
|
||||
* SessionListenerTest.
|
||||
@ -26,7 +27,14 @@ use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
*/
|
||||
class TestSessionListenerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @var TestSessionListener
|
||||
*/
|
||||
private $listener;
|
||||
|
||||
/**
|
||||
* @var SessionInterface
|
||||
*/
|
||||
private $session;
|
||||
|
||||
protected function setUp()
|
||||
@ -43,6 +51,7 @@ class TestSessionListenerTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testShouldSaveMasterRequestSession()
|
||||
{
|
||||
$this->sessionHasBeenStarted();
|
||||
$this->sessionMustBeSaved();
|
||||
|
||||
$this->filterResponse(new Request());
|
||||
@ -57,6 +66,8 @@ class TestSessionListenerTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testDoesNotDeleteCookieIfUsingSessionLifetime()
|
||||
{
|
||||
$this->sessionHasBeenStarted();
|
||||
|
||||
$params = session_get_cookie_params();
|
||||
session_set_cookie_params(0, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
|
||||
|
||||
@ -66,6 +77,14 @@ class TestSessionListenerTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals(0, reset($cookies)->getExpiresTime());
|
||||
}
|
||||
|
||||
public function testUnstartedSessionIsNotSave()
|
||||
{
|
||||
$this->sessionHasNotBeenStarted();
|
||||
$this->sessionMustNotBeSaved();
|
||||
|
||||
$this->filterResponse(new Request());
|
||||
}
|
||||
|
||||
private function filterResponse(Request $request, $type = HttpKernelInterface::MASTER_REQUEST)
|
||||
{
|
||||
$request->setSession($this->session);
|
||||
@ -92,6 +111,20 @@ class TestSessionListenerTest extends \PHPUnit_Framework_TestCase
|
||||
->method('save');
|
||||
}
|
||||
|
||||
private function sessionHasBeenStarted()
|
||||
{
|
||||
$this->session->expects($this->once())
|
||||
->method('isStarted')
|
||||
->will($this->returnValue(true));
|
||||
}
|
||||
|
||||
private function sessionHasNotBeenStarted()
|
||||
{
|
||||
$this->session->expects($this->once())
|
||||
->method('isStarted')
|
||||
->will($this->returnValue(false));
|
||||
}
|
||||
|
||||
private function getSession()
|
||||
{
|
||||
$mock = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\Session')
|
||||
|
@ -116,47 +116,6 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase
|
||||
}
|
||||
}
|
||||
|
||||
public function testGenerateInternalUriHandlesNullValues()
|
||||
{
|
||||
$request = new Request();
|
||||
|
||||
$router = $this->getMock('Symfony\\Component\\Routing\\RouterInterface');
|
||||
$container = $this->getMock('Symfony\\Component\\DependencyInjection\\ContainerInterface');
|
||||
$container
|
||||
->expects($this->at(0))
|
||||
->method('get')
|
||||
->with($this->equalTo('router'))
|
||||
->will($this->returnValue($router))
|
||||
;
|
||||
$container
|
||||
->expects($this->at('1'))
|
||||
->method('get')
|
||||
->with($this->equalTo('request'))
|
||||
->will($this->returnValue($request))
|
||||
;
|
||||
|
||||
$controller = 'AController';
|
||||
$attributes = array('anAttribute' => null);
|
||||
$query = array('aQueryParam' => null);
|
||||
|
||||
$expectedPath = 'none';
|
||||
|
||||
$routeParameters = array('controller' => $controller, 'path' => $expectedPath, '_format' => 'html');
|
||||
$router
|
||||
->expects($this->once())
|
||||
->method('generate')
|
||||
->with($this->equalTo('_internal'), $this->equalTo($routeParameters))
|
||||
->will($this->returnValue('GENERATED_URI'))
|
||||
;
|
||||
|
||||
$dispatcher = new EventDispatcher();
|
||||
$resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface');
|
||||
$kernel = new HttpKernel($dispatcher, $container, $resolver);
|
||||
|
||||
$uri = $kernel->generateInternalUri($controller, $attributes, $query);
|
||||
$this->assertEquals('GENERATED_URI', $uri);
|
||||
}
|
||||
|
||||
public function getProviderTypes()
|
||||
{
|
||||
return array(
|
||||
@ -172,22 +131,22 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase
|
||||
$container = $this->getMock('Symfony\\Component\\DependencyInjection\\ContainerInterface');
|
||||
$container
|
||||
->expects($this->at(0))
|
||||
->method('get')
|
||||
->with($this->equalTo('request'))
|
||||
->will($this->returnValue($request))
|
||||
;
|
||||
$container
|
||||
->expects($this->at(1))
|
||||
->method('getParameter')
|
||||
->with($this->equalTo('kernel.debug'))
|
||||
->will($this->returnValue(false))
|
||||
;
|
||||
$container
|
||||
->expects($this->at(1))
|
||||
->expects($this->at(2))
|
||||
->method('has')
|
||||
->with($this->equalTo('esi'))
|
||||
->will($this->returnValue(false))
|
||||
;
|
||||
$container
|
||||
->expects($this->at(2))
|
||||
->method('get')
|
||||
->with($this->equalTo('request'))
|
||||
->will($this->returnValue($request))
|
||||
;
|
||||
|
||||
$dispatcher = new EventDispatcher();
|
||||
$resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface');
|
||||
|
@ -68,6 +68,8 @@ class FormHelperDivLayoutTest extends AbstractDivLayoutTest
|
||||
protected function tearDown()
|
||||
{
|
||||
$this->engine = null;
|
||||
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
protected function renderEnctype(FormView $view)
|
||||
|
@ -69,6 +69,8 @@ class FormHelperTableLayoutTest extends AbstractTableLayoutTest
|
||||
protected function tearDown()
|
||||
{
|
||||
$this->engine = null;
|
||||
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
protected function renderEnctype(FormView $view)
|
||||
|
@ -39,6 +39,8 @@ class Translator extends BaseTranslator
|
||||
* @param MessageSelector $selector The message selector for pluralization
|
||||
* @param array $loaderIds An array of loader Ids
|
||||
* @param array $options An array of options
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct(ContainerInterface $container, MessageSelector $selector, $loaderIds = array(), array $options = array())
|
||||
{
|
||||
|
@ -14,6 +14,7 @@ namespace Symfony\Bundle\FrameworkBundle\Validator;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidatorFactoryInterface;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
|
||||
/**
|
||||
* Uses a service container to create constraint validators.
|
||||
@ -57,7 +58,7 @@ class ConstraintValidatorFactory implements ConstraintValidatorFactoryInterface
|
||||
*
|
||||
* @param Constraint $constraint A constraint
|
||||
*
|
||||
* @return Symfony\Component\Validator\ConstraintValidator A validator for the supplied constraint
|
||||
* @return ConstraintValidator A validator for the supplied constraint
|
||||
*/
|
||||
public function getInstance(Constraint $constraint)
|
||||
{
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user