Prechádzať zdrojové kódy

[Kernel] Make locateResource() throws an exception when a resource from a Bundle hides a custom resource

Victor Berchet 14 rokov pred
rodič
commit
7ed18bf829

+ 23 - 8
src/Symfony/Component/HttpKernel/Kernel.php

@@ -204,15 +204,17 @@ abstract class Kernel implements KernelInterface
      *
      * The resource name must follow the following pattern:
      *
-     *     @BundleName/path/to/a/file.something
+     *     @<BundleName>/path/to/a/file.something
      *
      * where BundleName is the name of the bundle
      * and the remaining part is the relative path in the bundle.
      *
-     * If $dir is passed, and the first segment of the path is Resources,
+     * If $dir is passed, and the first segment of the path is "Resources",
      * this method will look for a file named:
      *
-     *     $dir/BundleName/path/without/Resources
+     *     $dir/<BundleName>Bundle/path/without/Resources
+     *
+     * before looking in the bundle resource folder.
      *
      * @param string  $name  A resource name to locate
      * @param string  $dir   A directory where to look for the resource first
@@ -221,7 +223,8 @@ abstract class Kernel implements KernelInterface
      * @return string|array The absolute path of the resource or an array if $first is false
      *
      * @throws \InvalidArgumentException if the file cannot be found or the name is not valid
-     * @throws \RuntimeException         if the name contains invalid/unsafe characters
+     * @throws \RuntimeException         if the name contains invalid/unsafe
+     * @throws \RuntimeException         if a custom resource is hidden by a resource in a derived bundle
      */
     public function locateResource($name, $dir = null, $first = true)
     {
@@ -238,9 +241,20 @@ abstract class Kernel implements KernelInterface
 
         $isResource = 0 === strpos($path, 'Resources') && null !== $dir;
         $overridePath = substr($path, 9);
+        $resourceBundle = null;
+        $bundles = $this->getBundle($bundleName, false);
         
-        foreach ($this->getBundle($bundleName, false) as $bundle) {
+        foreach ($bundles as $bundle) {
             if ($isResource && file_exists($file = $dir.'/'.$bundle->getName().'Bundle'.$overridePath)) {
+                if (null !== $resourceBundle) {
+                    throw new \RuntimeException(sprintf('"%s" resource is hidden by a resource from the "%s" derived bundle. ' .
+                        'Create a "%s" file to override the bundle resource.',
+                        $file,
+                        $resourceBundle,
+                        $dir.'/'.$bundles[0]->getName().'Bundle'.$overridePath
+                    ));
+                }
+
                 if ($first) {
                     return $file;
                 }
@@ -248,15 +262,16 @@ abstract class Kernel implements KernelInterface
             }
 
             if (file_exists($file = $bundle->getPath().'/'.$path)) {
-                if ($first) {
+                if ($first && !$isResource) {
                     return $file;
                 }
                 $files[] = $file;
+                $resourceBundle = $bundle->getName();
             }
         }
 
-        if ($files) {
-            return $files;
+        if (count($files) > 0) {
+            return $first && $isResource ? $files[0] : $files;
         }
 
         throw new \InvalidArgumentException(sprintf('Unable to find file "@%s".', $name));

+ 0 - 0
tests/Symfony/Tests/Component/HttpKernel/Fixtures/BaseBundle/Resources/hide.txt


+ 0 - 0
tests/Symfony/Tests/Component/HttpKernel/Fixtures/ChildBundle/Resources/hide.txt


+ 0 - 0
tests/Symfony/Tests/Component/HttpKernel/Fixtures/Resources/BaseBundle/hide.txt


+ 19 - 2
tests/Symfony/Tests/Component/HttpKernel/KernelTest.php

@@ -444,7 +444,7 @@ EOF;
 
         $kernel = $this->getKernel();
         $kernel
-            ->expects($this->once())
+            ->expects($this->exactly(4))
             ->method('getBundle')
             ->will($this->returnValue(array($child, $parent)))
         ;
@@ -454,8 +454,25 @@ EOF;
             __DIR__.'/Fixtures/ChildBundle/Resources/foo.txt',
             __DIR__.'/Fixtures/BaseBundle/Resources/foo.txt',
             ),
-            $kernel->locateResource('@Child/Resources/foo.txt', __DIR__.'/Fixtures/Resources', false)
+            $kernel->locateResource('@Base/Resources/foo.txt', __DIR__.'/Fixtures/Resources', false)
+        );
+
+        $this->assertEquals(
+            __DIR__.'/Fixtures/Resources/ChildBundle/foo.txt',
+            $kernel->locateResource('@Base/Resources/foo.txt', __DIR__.'/Fixtures/Resources')
         );
+
+        try {
+            $kernel->locateResource('@Base/Resources/hide.txt', __DIR__.'/Fixtures/Resources', false);
+            $this->fail('Hidden resources should raise an exception when returning an array of matching paths');
+        } catch (\RuntimeException $e) {
+        }
+
+        try {
+            $kernel->locateResource('@Base/Resources/hide.txt', __DIR__.'/Fixtures/Resources', true);
+            $this->fail('Hidden resources should raise an exception when returning the first matching path');
+        } catch (\RuntimeException $e) {
+        }
     }
 
     public function testLocateResourceOnDirectories()