Skip to content

Commit 77569cd

Browse files
committed
Merge pull request #641 from xabbuh/issue-626
add support for format related configuration options to the RestYamlColl...
2 parents 84127da + 2ecf566 commit 77569cd

File tree

8 files changed

+449
-27
lines changed

8 files changed

+449
-27
lines changed

Resources/config/routing.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,18 @@
3131
<service id="fos_rest.routing.loader.yaml_collection" class="%fos_rest.routing.loader.yaml_collection.class%">
3232
<argument type="service" id="file_locator" />
3333
<argument type="service" id="fos_rest.routing.loader.processor" />
34+
<argument>%fos_rest.routing.loader.include_format%</argument>
35+
<argument>%fos_rest.formats%</argument>
36+
<argument>%fos_rest.routing.loader.default_format%</argument>
3437
<tag name="routing.loader" />
3538
</service>
3639

3740
<service id="fos_rest.routing.loader.xml_collection" class="%fos_rest.routing.loader.xml_collection.class%">
3841
<argument type="service" id="file_locator" />
3942
<argument type="service" id="fos_rest.routing.loader.processor" />
43+
<argument>%fos_rest.routing.loader.include_format%</argument>
44+
<argument>%fos_rest.formats%</argument>
45+
<argument>%fos_rest.routing.loader.default_format%</argument>
4046
<tag name="routing.loader" />
4147
</service>
4248

Routing/Loader/RestXmlCollectionLoader.php

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,7 @@
1414
use Symfony\Component\Config\FileLocatorInterface;
1515
use Symfony\Component\Routing\Loader\XmlFileLoader;
1616
use Symfony\Component\Routing\RouteCollection;
17-
use Symfony\Component\Routing\Route;
18-
1917
use FOS\RestBundle\Routing\RestRouteCollection;
20-
use FOS\RestBundle\Routing\Loader\RestRouteProcessor;
21-
2218
use Symfony\Component\Config\Util\XmlUtils;
2319

2420
/**
@@ -37,12 +33,23 @@ class RestXmlCollectionLoader extends XmlFileLoader
3733
*
3834
* @param FileLocatorInterface $locator locator
3935
* @param RestRouteProcessor $processor route processor
36+
* @param boolean $includeFormat whether or not the requested view format must be included in the route path
37+
* @param string[] $formats supported view formats
38+
* @param string $defaultFormat default view format
4039
*/
41-
public function __construct(FileLocatorInterface $locator, RestRouteProcessor $processor)
42-
{
40+
public function __construct(
41+
FileLocatorInterface $locator,
42+
RestRouteProcessor $processor,
43+
$includeFormat = true,
44+
array $formats = array(),
45+
$defaultFormat = null
46+
) {
4347
parent::__construct($locator);
4448

4549
$this->processor = $processor;
50+
$this->includeFormat = $includeFormat;
51+
$this->formats = $formats;
52+
$this->defaultFormat = $defaultFormat;
4653
}
4754

4855
/**
@@ -89,6 +96,65 @@ protected function parseNode(RouteCollection $collection, \DOMElement $node, $pa
8996
}
9097
}
9198

99+
/**
100+
* {@inheritDoc}
101+
*/
102+
protected function parseRoute(RouteCollection $collection, \DOMElement $node, $path)
103+
{
104+
// the Symfony Routing component uses a path attribute since Symfony 2.2
105+
// instead of the deprecated pattern attribute0
106+
if (!$node->hasAttribute('path')) {
107+
$node->setAttribute('path', $node->getAttribute('pattern'));
108+
$node->removeAttribute('pattern');
109+
}
110+
111+
if ($this->includeFormat) {
112+
$path = $node->getAttribute('path');
113+
// append format placeholder if not present
114+
if (false === strpos($path, '{_format}')) {
115+
$node->setAttribute('path', $path.'.{_format}');
116+
}
117+
118+
// set format requirement if configured globally
119+
$requirements = $node->getElementsByTagNameNS(self::NAMESPACE_URI, 'requirement');
120+
$format = null;
121+
for ($i = 0; $i < $requirements->length; $i++) {
122+
$item = $requirements->item($i);
123+
if ($item instanceof \DOMElement && $item->hasAttribute('_format')) {
124+
$format = $item->getAttribute('_format');
125+
break;
126+
}
127+
}
128+
if (null === $format && !empty($this->formats)) {
129+
$requirement = $node->ownerDocument->createElementNs(
130+
self::NAMESPACE_URI,
131+
'requirement',
132+
implode('|', array_keys($this->formats))
133+
);
134+
$requirement->setAttribute('key', '_format');
135+
$node->appendChild($requirement);
136+
137+
/*$doc =new \DOMDocument();
138+
$doc->appendChild($doc->importNode($node, true));
139+
echo $doc->saveHTML();*/
140+
}
141+
}
142+
143+
// set the default format if configured
144+
if (null !== $this->defaultFormat) {
145+
$config['defaults']['_format'] = $this->defaultFormat;
146+
$defaultFormatNode = $node->ownerDocument->createElementNS(
147+
self::NAMESPACE_URI,
148+
'default',
149+
$this->defaultFormat
150+
);
151+
$defaultFormatNode->setAttribute('key', '_format');
152+
$node->appendChild($defaultFormatNode);
153+
}
154+
155+
parent::parseRoute($collection, $node, $path);
156+
}
157+
92158
/**
93159
* Returns true if this class supports the given resource.
94160
*

Routing/Loader/RestYamlCollectionLoader.php

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@
1616
use Symfony\Component\Yaml\Yaml;
1717
use Symfony\Component\Routing\Loader\YamlFileLoader;
1818
use Symfony\Component\Routing\RouteCollection;
19-
use Symfony\Component\Routing\Route;
20-
2119
use FOS\RestBundle\Routing\RestRouteCollection;
22-
use FOS\RestBundle\Routing\Loader\RestRouteProcessor;
2320

2421
/**
2522
* RestYamlCollectionLoader YAML file collections loader.
@@ -30,17 +27,34 @@ class RestYamlCollectionLoader extends YamlFileLoader
3027

3128
private $processor;
3229

30+
private $includeFormat;
31+
32+
private $formats;
33+
34+
private $defaultFormat;
35+
3336
/**
3437
* Initializes yaml loader.
3538
*
36-
* @param FileLocatorInterface $locator locator
37-
* @param RestRouteProcessor $processor route processor
39+
* @param FileLocatorInterface $locator locator
40+
* @param RestRouteProcessor $processor route processor
41+
* @param boolean $includeFormat whether or not the requested view format must be included in the route path
42+
* @param string[] $formats supported view formats
43+
* @param string $defaultFormat default view format
3844
*/
39-
public function __construct(FileLocatorInterface $locator, RestRouteProcessor $processor)
40-
{
45+
public function __construct(
46+
FileLocatorInterface $locator,
47+
RestRouteProcessor $processor,
48+
$includeFormat = true,
49+
array $formats = array(),
50+
$defaultFormat = null
51+
) {
4152
parent::__construct($locator);
4253

4354
$this->processor = $processor;
55+
$this->includeFormat = $includeFormat;
56+
$this->formats = $formats;
57+
$this->defaultFormat = $defaultFormat;
4458
}
4559

4660
/**
@@ -93,6 +107,29 @@ public function load($file, $type = null)
93107
$imported->addPrefix($prefix);
94108
$collection->addCollection($imported);
95109
} elseif (isset($config['pattern']) || isset($config['path'])) {
110+
// the YamlFileLoader of the Routing component only checks for
111+
// the path option
112+
if (!isset($config['path'])) {
113+
$config['path'] = $config['pattern'];
114+
}
115+
116+
if ($this->includeFormat) {
117+
// append format placeholder if not present
118+
if (false === strpos($config['path'], '{_format}')) {
119+
$config['path'].='.{_format}';
120+
}
121+
122+
// set format requirement if configured globally
123+
if (!isset($config['requirements']['_format']) && !empty($this->formats)) {
124+
$config['requirements']['_format'] = implode('|', array_keys($this->formats));
125+
}
126+
}
127+
128+
// set the default format if configured
129+
if (null !== $this->defaultFormat) {
130+
$config['defaults']['_format'] = $this->defaultFormat;
131+
}
132+
96133
$this->parseRoute($collection, $name, $config, $path);
97134
} else {
98135
throw new \InvalidArgumentException(sprintf('Unable to parse the "%s" route.', $name));

0 commit comments

Comments
 (0)