diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/util/TwigUtil.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/util/TwigUtil.java index c8f9c6be9..875a6d2ca 100644 --- a/src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/util/TwigUtil.java +++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/util/TwigUtil.java @@ -144,65 +144,93 @@ public static String[] getControllerMethodShortcut(@NotNull Method method) { return new String[0]; } + String shortcutName = null; + String shortcutNameForOldNotation = null; + SymfonyBundleUtil symfonyBundleUtil = new SymfonyBundleUtil(method.getProject()); SymfonyBundle symfonyBundle = symfonyBundleUtil.getContainingBundle(phpClass); - if(symfonyBundle == null) { - return new String[0]; - } - - // check if files is in /Controller/* - PhpClass bundleClass = symfonyBundle.getPhpClass(); - if(!phpClass.getNamespaceName().startsWith(bundleClass.getNamespaceName() + "Controller\\")) { - return new String[0]; - } - - // strip the controller folder name - String templateFolderName = phpClass.getNamespaceName().substring(bundleClass.getNamespaceName().length() + 11); + if(symfonyBundle != null) { + // check if files is in /Controller/* + PhpClass bundleClass = symfonyBundle.getPhpClass(); + if(!phpClass.getNamespaceName().startsWith(bundleClass.getNamespaceName() + "Controller\\")) { + return new String[0]; + } + + // strip the controller folder name + String templateFolderName = phpClass.getNamespaceName().substring(bundleClass.getNamespaceName().length() + 11); + + // HomeBundle:default:indexes + // HomeBundle:default/Test:indexes + templateFolderName = templateFolderName.replace("\\", "/"); + + // Foobar without (.html.twig) + String templateName = className.substring(0, className.lastIndexOf("Controller")); + + if(methodName.equals("__invoke")) { + // AppBundle::foo_bar.html.twig + shortcutName = String.format( + "%s::%s%s", + symfonyBundle.getName(), + underscore(templateFolderName), + underscore(templateName) + ); - // HomeBundle:default:indexes - // HomeBundle:default/Test:indexes - templateFolderName = templateFolderName.replace("\\", "/"); + // AppBundle::FooBar.html.twig + shortcutNameForOldNotation = String.format( + "%s::%s%s", + symfonyBundle.getName(), + templateFolderName, + templateName + ); + } else { + // FooBundle:foo_bar:foo_bar.html.twig + shortcutName = String.format( + "%s:%s%s:%s", + symfonyBundle.getName(), + underscore(templateFolderName), + underscore(templateName), + underscore(StringUtils.removeEnd(methodName, "Action")) + ); - String shortcutName; - String shortcutNameForOldNotation; + // FooBundle:FooBar:fooBar.html.twig + shortcutNameForOldNotation = String.format( + "%s:%s%s:%s", + symfonyBundle.getName(), + templateFolderName, + templateName, + StringUtils.removeEnd(methodName, "Action") + ); + } + } else { + // https://github.com/sensiolabs/SensioFrameworkExtraBundle/blob/master/src/Templating/TemplateGuesser.php + String fqn = phpClass.getFQN(); + Matcher matcher = Pattern.compile("Controller\\\\(.+)Controller$").matcher(fqn); + if(matcher.find()) { + String domain = matcher.group(1); + + String matchController = domain.replaceAll("\\\\", "/"); + + String matchAction = null; + if (!"__invoke".equals(methodName)) { + matchAction = methodName.replaceAll("Action$", ""); + matchAction = matchAction; + } - // Foobar without (.html.twig) - String templateName = className.substring(0, className.lastIndexOf("Controller")); + List parts = new ArrayList<>( + Arrays.asList(matchController.split("/")) + ); - if(methodName.equals("__invoke")) { - // AppBundle::foo_bar.html.twig - shortcutName = String.format( - "%s::%s%s", - symfonyBundle.getName(), - underscore(templateFolderName), - underscore(templateName) - ); + if (matchAction != null) { + parts.add(matchAction); + } - // AppBundle::FooBar.html.twig - shortcutNameForOldNotation = String.format( - "%s::%s%s", - symfonyBundle.getName(), - templateFolderName, - templateName - ); - } else { - // FooBundle:foo_bar:foo_bar.html.twig - shortcutName = String.format( - "%s:%s%s:%s", - symfonyBundle.getName(), - underscore(templateFolderName), - underscore(templateName), - underscore(StringUtils.removeEnd(methodName, "Action")) - ); + shortcutNameForOldNotation = String.join("/", parts); + shortcutName = underscore(String.join("/", parts)); + } + } - // FooBundle:FooBar:fooBar.html.twig - shortcutNameForOldNotation = String.format( - "%s:%s%s:%s", - symfonyBundle.getName(), - templateFolderName, - templateName, - StringUtils.removeEnd(methodName, "Action") - ); + if (shortcutName == null || shortcutNameForOldNotation == null) { + return new String[0]; } // @TODO: we should support types later on; but nicer diff --git a/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/templating/inspection/TemplateExistsAnnotationPhpAttributeLocalInspectionTest.java b/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/templating/inspection/TemplateExistsAnnotationPhpAttributeLocalInspectionTest.java index 73e22cfff..04a354820 100644 --- a/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/templating/inspection/TemplateExistsAnnotationPhpAttributeLocalInspectionTest.java +++ b/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/templating/inspection/TemplateExistsAnnotationPhpAttributeLocalInspectionTest.java @@ -10,6 +10,7 @@ public class TemplateExistsAnnotationPhpAttributeLocalInspectionTest extends SymfonyLightCodeInsightFixtureTestCase { public void setUp() throws Exception { super.setUp(); + myFixture.copyFileToProject("classes.php"); } @@ -139,4 +140,23 @@ public void testThatTemplateCreationForInvokeMethodProvidesQuickfix() { "Twig: Missing Template" ); } + + public void testThatMissingTemplateForGlobalNamespaceWithoutBundleScopeForController() { + assertLocalInspectionContains("foobar.php", "late()\n" + + " */\n" + + " public function fooAction()\n" + + " {\n" + + " }\n" + + "}\n" + + "", + "Twig: Missing Template" + ); + } } diff --git a/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/templating/util/TwigUtilTest.java b/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/templating/util/TwigUtilTest.java index 5e23fe568..ea2ec54b0 100644 --- a/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/templating/util/TwigUtilTest.java +++ b/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/templating/util/TwigUtilTest.java @@ -471,6 +471,74 @@ public void testGetControllerMethodShortcutForInvokeWithSnakeCase() { assertContainsElements(strings, "FooBundle::FooBar.text.twig"); } + public void testGetControllerMethodShortcutForInvokeForGlobalNamespace() { + myFixture.configureByText(PhpFileType.INSTANCE, "Action() {}\n" + + "" + + "}\n" + ); + + PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); + + List strings = Arrays.asList(TwigUtil.getControllerMethodShortcut((Method) psiElement.getParent())); + + assertContainsElements(strings, "foo_bar/foo.html.twig"); + assertContainsElements(strings, "foo_bar/foo.json.twig"); + assertContainsElements(strings, "foo_bar/foo.xml.twig"); + assertContainsElements(strings, "foo_bar/foo.text.twig"); + + assertContainsElements(strings, "FooBar/foo.html.twig"); + assertContainsElements(strings, "FooBar/foo.json.twig"); + assertContainsElements(strings, "FooBar/foo.xml.twig"); + assertContainsElements(strings, "FooBar/foo.text.twig"); + } + + public void testGetControllerMethodShortcutForInvokeForGlobalNamespaceInInvoke() { + myFixture.configureByText(PhpFileType.INSTANCE, "oke() {}\n" + + "" + + "}\n" + ); + + PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); + + List strings = Arrays.asList(TwigUtil.getControllerMethodShortcut((Method) psiElement.getParent())); + + assertContainsElements(strings, "foo_bar.html.twig"); + assertContainsElements(strings, "foo_bar.json.twig"); + assertContainsElements(strings, "foo_bar.xml.twig"); + assertContainsElements(strings, "foo_bar.text.twig"); + + assertContainsElements(strings, "FooBar.html.twig"); + assertContainsElements(strings, "FooBar.json.twig"); + assertContainsElements(strings, "FooBar.xml.twig"); + assertContainsElements(strings, "FooBar.text.twig"); + } + + public void testGetControllerMethodShortcutForInvokeForGlobalNamespaceInInvokeWIthPath() { + myFixture.configureByText(PhpFileType.INSTANCE, "Action() {}\n" + + "" + + "}\n" + ); + + PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); + + List strings = Arrays.asList(TwigUtil.getControllerMethodShortcut((Method) psiElement.getParent())); + + assertContainsElements(strings, "my_admin/out_of_bundle/index.html.twig"); + assertContainsElements(strings, "MyAdmin/OutOfBundle/index.html.twig"); + } + public void testFindTwigFileController() { myFixture.copyFileToProject("bundle.php");