Skip to content

Commit 85d464a

Browse files
committed
[Validator] Fixed: The state of the XML/YAML loaders was changed even if an exception was thrown upon loading
1 parent 60d006d commit 85d464a

File tree

13 files changed

+328
-142
lines changed

13 files changed

+328
-142
lines changed

src/Symfony/Component/Validator/Mapping/Loader/AbstractLoader.php

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,24 @@
1414
use Symfony\Component\Validator\Exception\MappingException;
1515
use Symfony\Component\Validator\Constraint;
1616

17+
/**
18+
* Base loader for validation metadata.
19+
*
20+
* This loader supports the loading of constraints from Symfony's default
21+
* namespace (see {@link DEFAULT_NAMESPACE}) using the short class names of
22+
* those constraints. Constraints can also be loaded using their fully
23+
* qualified class names. At last, namespace aliases can be defined to load
24+
* constraints with the syntax "alias:ShortName".
25+
*
26+
* @author Bernhard Schussek <[email protected]>
27+
*/
1728
abstract class AbstractLoader implements LoaderInterface
1829
{
30+
/**
31+
* The namespace to load constraints from by default.
32+
*/
33+
const DEFAULT_NAMESPACE = '\\Symfony\\Component\\Validator\\Constraints\\';
34+
1935
/**
2036
* Contains all known namespaces indexed by their prefix
2137
* @var array
@@ -25,6 +41,13 @@ abstract class AbstractLoader implements LoaderInterface
2541
/**
2642
* Adds a namespace alias.
2743
*
44+
* The namespace alias can be used to reference constraints from specific
45+
* namespaces in {@link newConstraint()}:
46+
*
47+
* $this->addNamespaceAlias('mynamespace', '\\Acme\\Package\\Constraints\\');
48+
*
49+
* $constraint = $this->newConstraint('mynamespace:NotNull');
50+
*
2851
* @param string $alias The alias
2952
* @param string $namespace The PHP namespace
3053
*/
@@ -38,14 +61,17 @@ protected function addNamespaceAlias($alias, $namespace)
3861
*
3962
* @param string $name The constraint name. Either a constraint relative
4063
* to the default constraint namespace, or a fully
41-
* qualified class name
64+
* qualified class name. Alternatively, the constraint
65+
* may be preceded by a namespace alias and a colon.
66+
* The namespace alias must have been defined using
67+
* {@link addNamespaceAlias()}.
4268
* @param mixed $options The constraint options
4369
*
4470
* @return Constraint
4571
*
4672
* @throws MappingException If the namespace prefix is undefined
4773
*/
48-
protected function newConstraint($name, $options)
74+
protected function newConstraint($name, $options = null)
4975
{
5076
if (strpos($name, '\\') !== false && class_exists($name)) {
5177
$className = (string) $name;
@@ -58,7 +84,7 @@ protected function newConstraint($name, $options)
5884

5985
$className = $this->namespaces[$prefix].$className;
6086
} else {
61-
$className = 'Symfony\\Component\\Validator\\Constraints\\'.$name;
87+
$className = self::DEFAULT_NAMESPACE.$name;
6288
}
6389

6490
return new $className($options);

src/Symfony/Component/Validator/Mapping/Loader/AnnotationLoader.php

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,40 @@
1818
use Symfony\Component\Validator\Constraints\GroupSequenceProvider;
1919
use Symfony\Component\Validator\Constraint;
2020

21+
/**
22+
* Loads validation metadata using a Doctrine annotation {@link Reader}.
23+
*
24+
* @author Bernhard Schussek <[email protected]>
25+
*/
2126
class AnnotationLoader implements LoaderInterface
2227
{
28+
/**
29+
* @var Reader
30+
*/
2331
protected $reader;
2432

33+
/**
34+
* Creates a new loader.
35+
*
36+
* @param Reader $reader The annotation reader to use.
37+
*/
2538
public function __construct(Reader $reader)
2639
{
2740
$this->reader = $reader;
2841
}
2942

3043
/**
31-
* {@inheritdoc}
44+
* Loads the metadata using annotations defined in the class.
45+
*
46+
* @param ClassMetadata $metadata The class metadata to load
47+
*
48+
* @return bool Whether the loader succeeded
3249
*/
3350
public function loadClassMetadata(ClassMetadata $metadata)
3451
{
3552
$reflClass = $metadata->getReflectionClass();
3653
$className = $reflClass->name;
37-
$loaded = false;
54+
$success = false;
3855

3956
foreach ($this->reader->getClassAnnotations($reflClass) as $constraint) {
4057
if ($constraint instanceof GroupSequence) {
@@ -45,7 +62,7 @@ public function loadClassMetadata(ClassMetadata $metadata)
4562
$metadata->addConstraint($constraint);
4663
}
4764

48-
$loaded = true;
65+
$success = true;
4966
}
5067

5168
foreach ($reflClass->getProperties() as $property) {
@@ -55,7 +72,7 @@ public function loadClassMetadata(ClassMetadata $metadata)
5572
$metadata->addPropertyConstraint($property->name, $constraint);
5673
}
5774

58-
$loaded = true;
75+
$success = true;
5976
}
6077
}
6178
}
@@ -71,11 +88,11 @@ public function loadClassMetadata(ClassMetadata $metadata)
7188
}
7289
}
7390

74-
$loaded = true;
91+
$success = true;
7592
}
7693
}
7794
}
7895

79-
return $loaded;
96+
return $success;
8097
}
8198
}

src/Symfony/Component/Validator/Mapping/Loader/FileLoader.php

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,42 @@
1313

1414
use Symfony\Component\Validator\Exception\MappingException;
1515

16+
/**
17+
* Base loader for loading validation metadata from a file.
18+
*
19+
* @author Bernhard Schussek <[email protected]>
20+
*
21+
* @see YamlFileLoader
22+
* @see XmlFileLoader
23+
*/
1624
abstract class FileLoader extends AbstractLoader
1725
{
26+
/**
27+
* The file to load.
28+
*
29+
* @var string
30+
*/
1831
protected $file;
1932

2033
/**
21-
* Constructor.
34+
* Creates a new loader.
2235
*
2336
* @param string $file The mapping file to load
2437
*
25-
* @throws MappingException if the mapping file does not exist
26-
* @throws MappingException if the mapping file is not readable
38+
* @throws MappingException If the file does not exist or is not readable
2739
*/
2840
public function __construct($file)
2941
{
3042
if (!is_file($file)) {
31-
throw new MappingException(sprintf('The mapping file %s does not exist', $file));
43+
throw new MappingException(sprintf('The mapping file "%s" does not exist', $file));
3244
}
3345

3446
if (!is_readable($file)) {
35-
throw new MappingException(sprintf('The mapping file %s is not readable', $file));
47+
throw new MappingException(sprintf('The mapping file "%s" is not readable', $file));
48+
}
49+
50+
if (!stream_is_local($this->file)) {
51+
throw new MappingException(sprintf('The mapping file "%s" is not a local file', $file));
3652
}
3753

3854
$this->file = $file;

src/Symfony/Component/Validator/Mapping/Loader/FilesLoader.php

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,37 +12,37 @@
1212
namespace Symfony\Component\Validator\Mapping\Loader;
1313

1414
/**
15-
* Creates mapping loaders for array of files.
16-
*
17-
* Abstract class, used by
15+
* Base loader for loading validation metadata from a list of files.
1816
*
1917
* @author Bulat Shakirzyanov <[email protected]>
18+
* @author Bernhard Schussek <[email protected]>
2019
*
21-
* @see Symfony\Component\Validator\Mapping\Loader\YamlFileLoader
22-
* @see Symfony\Component\Validator\Mapping\Loader\XmlFileLoader
20+
* @see YamlFilesLoader
21+
* @see XmlFilesLoader
2322
*/
2423
abstract class FilesLoader extends LoaderChain
2524
{
2625
/**
27-
* Array of mapping files.
26+
* Creates a new loader.
2827
*
29-
* @param array $paths Array of file paths
28+
* @param array $paths An array of file paths
3029
*/
3130
public function __construct(array $paths)
3231
{
3332
parent::__construct($this->getFileLoaders($paths));
3433
}
3534

3635
/**
37-
* Array of mapping files.
36+
* Returns an array of file loaders for the given file paths.
3837
*
39-
* @param array $paths Array of file paths
38+
* @param array $paths An array of file paths
4039
*
41-
* @return LoaderInterface[] Array of metadata loaders
40+
* @return LoaderInterface[] The metadata loaders
4241
*/
4342
protected function getFileLoaders($paths)
4443
{
4544
$loaders = array();
45+
4646
foreach ($paths as $path) {
4747
$loaders[] = $this->getFileLoaderInstance($path);
4848
}
@@ -51,11 +51,11 @@ protected function getFileLoaders($paths)
5151
}
5252

5353
/**
54-
* Takes mapping file path.
54+
* Creates a loader for the given file path.
5555
*
56-
* @param string $file
56+
* @param string $path The file path
5757
*
58-
* @return LoaderInterface
58+
* @return LoaderInterface The created loader
5959
*/
60-
abstract protected function getFileLoaderInstance($file);
60+
abstract protected function getFileLoaderInstance($path);
6161
}

src/Symfony/Component/Validator/Mapping/Loader/LoaderChain.php

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,27 @@
1515
use Symfony\Component\Validator\Mapping\ClassMetadata;
1616

1717
/**
18-
* Calls multiple LoaderInterface instances in a chain
18+
* Loads validation metadata from multiple {@link LoaderInterface} instances.
1919
*
20-
* This class accepts multiple instances of LoaderInterface to be passed to the
21-
* constructor. When loadClassMetadata() is called, the same method is called
22-
* in <em>all</em> of these loaders, regardless of whether any of them was
23-
* successful or not.
20+
* Pass the loaders when constructing the chain. Once
21+
* {@link loadClassMetadata()} is called, that method will be called on all
22+
* loaders in the chain.
2423
*
2524
* @author Bernhard Schussek <[email protected]>
2625
*/
2726
class LoaderChain implements LoaderInterface
2827
{
28+
/**
29+
* @var LoaderInterface[]
30+
*/
2931
protected $loaders;
3032

3133
/**
32-
* Accepts a list of LoaderInterface instances
34+
* Creates a new loader chain.
3335
*
34-
* @param LoaderInterface[] $loaders An array of LoaderInterface instances
36+
* @param LoaderInterface[] $loaders The metadata loaders to use
3537
*
36-
* @throws MappingException If any of the loaders does not implement LoaderInterface
38+
* @throws MappingException If any of the loaders has an invalid type
3739
*/
3840
public function __construct(array $loaders)
3941
{
@@ -47,7 +49,12 @@ public function __construct(array $loaders)
4749
}
4850

4951
/**
50-
* {@inheritdoc}
52+
* Calls {@link LoaderInterface::loadClassMetadata()} on all loaders in
53+
* the chain.
54+
*
55+
* @param ClassMetadata $metadata The metadata to load
56+
*
57+
* @return bool Whether the loader succeeded
5158
*/
5259
public function loadClassMetadata(ClassMetadata $metadata)
5360
{

src/Symfony/Component/Validator/Mapping/Loader/LoaderInterface.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,19 @@
1313

1414
use Symfony\Component\Validator\Mapping\ClassMetadata;
1515

16+
/**
17+
* Loads validation metadata into {@link ClassMetadata} instances.
18+
*
19+
* @author Bernhard Schussek <[email protected]>
20+
*/
1621
interface LoaderInterface
1722
{
1823
/**
19-
* Load a Class Metadata.
24+
* Loads validation metadata into a {@link ClassMetadata} instance.
2025
*
21-
* @param ClassMetadata $metadata A metadata
26+
* @param ClassMetadata $metadata The metadata to load
2227
*
23-
* @return bool
28+
* @return bool Whether the loader succeeded
2429
*/
2530
public function loadClassMetadata(ClassMetadata $metadata);
2631
}

src/Symfony/Component/Validator/Mapping/Loader/StaticMethodLoader.php

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,38 @@
1414
use Symfony\Component\Validator\Exception\MappingException;
1515
use Symfony\Component\Validator\Mapping\ClassMetadata;
1616

17+
/**
18+
* Loads validation metadata by calling a static method on the loaded class.
19+
*
20+
* @author Bernhard Schussek <[email protected]>
21+
*/
1722
class StaticMethodLoader implements LoaderInterface
1823
{
24+
/**
25+
* The name of the method to call.
26+
*
27+
* @var string
28+
*/
1929
protected $methodName;
2030

31+
/**
32+
* Creates a new loader.
33+
*
34+
* @param string $methodName The name of the static method to call
35+
*/
2136
public function __construct($methodName = 'loadValidatorMetadata')
2237
{
2338
$this->methodName = $methodName;
2439
}
2540

2641
/**
27-
* {@inheritdoc}
42+
* Loads validation metadata by calling a static method in the class.
43+
*
44+
* The name of the static method is passed to {@link __construct()}.
45+
*
46+
* @param ClassMetadata $metadata The metadata to load
47+
*
48+
* @return bool Whether the loader succeeded
2849
*/
2950
public function loadClassMetadata(ClassMetadata $metadata)
3051
{

0 commit comments

Comments
 (0)