4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\Validator\Mapping\Loader;
14 use Symfony\Component\Validator\Mapping\ClassMetadata;
15 use Symfony\Component\Yaml\Exception\ParseException;
16 use Symfony\Component\Yaml\Parser as YamlParser;
19 * Loads validation metadata from a YAML file.
21 * @author Bernhard Schussek <bschussek@gmail.com>
23 class YamlFileLoader extends FileLoader
26 * An array of YAML class descriptions.
30 protected $classes = null;
33 * Caches the used YAML parser.
42 public function loadClassMetadata(ClassMetadata $metadata)
44 if (null === $this->classes) {
45 if (null === $this->yamlParser) {
46 $this->yamlParser = new YamlParser();
49 $this->classes = $this->parseFile($this->file);
51 if (isset($this->classes['namespaces'])) {
52 foreach ($this->classes['namespaces'] as $alias => $namespace) {
53 $this->addNamespaceAlias($alias, $namespace);
56 unset($this->classes['namespaces']);
60 if (isset($this->classes[$metadata->getClassName()])) {
61 $classDescription = $this->classes[$metadata->getClassName()];
63 $this->loadClassMetadataFromYaml($metadata, $classDescription);
72 * Parses a collection of YAML nodes.
74 * @param array $nodes The YAML nodes
76 * @return array An array of values or Constraint instances
78 protected function parseNodes(array $nodes)
82 foreach ($nodes as $name => $childNodes) {
83 if (is_numeric($name) && is_array($childNodes) && 1 === count($childNodes)) {
84 $options = current($childNodes);
86 if (is_array($options)) {
87 $options = $this->parseNodes($options);
90 $values[] = $this->newConstraint(key($childNodes), $options);
92 if (is_array($childNodes)) {
93 $childNodes = $this->parseNodes($childNodes);
96 $values[$name] = $childNodes;
104 * Loads the YAML class descriptions from the given file.
106 * @param string $path The path of the YAML file
108 * @return array The class descriptions
110 * @throws \InvalidArgumentException If the file could not be loaded or did
111 * not contain a YAML array
113 private function parseFile($path)
116 $classes = $this->yamlParser->parse(file_get_contents($path));
117 } catch (ParseException $e) {
118 throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e);
122 if (null === $classes) {
127 if (!is_array($classes)) {
128 throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $this->file));
135 * Loads the validation metadata from the given YAML class description.
137 * @param ClassMetadata $metadata The metadata to load
138 * @param array $classDescription The YAML class description
140 private function loadClassMetadataFromYaml(ClassMetadata $metadata, array $classDescription)
142 if (isset($classDescription['group_sequence_provider'])) {
143 $metadata->setGroupSequenceProvider(
144 (bool) $classDescription['group_sequence_provider']
148 if (isset($classDescription['group_sequence'])) {
149 $metadata->setGroupSequence($classDescription['group_sequence']);
152 if (isset($classDescription['constraints']) && is_array($classDescription['constraints'])) {
153 foreach ($this->parseNodes($classDescription['constraints']) as $constraint) {
154 $metadata->addConstraint($constraint);
158 if (isset($classDescription['properties']) && is_array($classDescription['properties'])) {
159 foreach ($classDescription['properties'] as $property => $constraints) {
160 if (null !== $constraints) {
161 foreach ($this->parseNodes($constraints) as $constraint) {
162 $metadata->addPropertyConstraint($property, $constraint);
168 if (isset($classDescription['getters']) && is_array($classDescription['getters'])) {
169 foreach ($classDescription['getters'] as $getter => $constraints) {
170 if (null !== $constraints) {
171 foreach ($this->parseNodes($constraints) as $constraint) {
172 $metadata->addGetterConstraint($getter, $constraint);