Skip to content

Commit 1864dd7

Browse files
committed
improvement template name resolving for overwrites: support parent bundle and app resources #437
1 parent eb9f6da commit 1864dd7

File tree

3 files changed

+111
-0
lines changed

3 files changed

+111
-0
lines changed

src/fr/adrienbrault/idea/symfony2plugin/TwigHelper.java

+53
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,61 @@ public static PsiFile[] getTemplatePsiElements(Project project, String templateN
228228

229229
}
230230

231+
psiFiles.addAll(getTemplateOverwrites(project, normalizedTemplateName));
232+
231233
return psiFiles.toArray(new PsiFile[psiFiles.size()]);
234+
}
235+
236+
/**
237+
* Collects overwritten templates
238+
*
239+
* app/Resources/MyUserBundle/views/layout.html.twig
240+
* src/Acme/UserBundle/Resources/views/layout.html.twig <- getParent = MyUserBundle
241+
*/
242+
private static Collection<PsiFile> getTemplateOverwrites(@NotNull Project project, @NotNull String normalizedTemplateName) {
243+
244+
// Bundle overwrite:
245+
if(normalizedTemplateName.startsWith(":") || normalizedTemplateName.startsWith("@")) {
246+
return Collections.emptyList();
247+
}
248+
249+
String templatePath = StringUtils.strip(normalizedTemplateName.replace(":", "/").replace("//", "/"), "/");
250+
251+
int i = templatePath.indexOf("Bundle/");
252+
if( i == -1) {
253+
return Collections.emptyList();
254+
}
255+
256+
Collection<VirtualFile> files = new HashSet<VirtualFile>();
257+
258+
String bundle = templatePath.substring(0, i + 6);
259+
260+
// invalid Bundle in path condition
261+
if(bundle.contains("/")) {
262+
return Collections.emptyList();
263+
}
264+
265+
VirtualFile relativeFile = VfsUtil.findRelativeFile(
266+
project.getBaseDir(),
267+
String.format("app/Resources/%s/views/%s", bundle, templatePath.substring(i + 7)).split("/")
268+
);
269+
270+
if(relativeFile != null) {
271+
files.add(relativeFile);
272+
}
273+
274+
// find parent bundles
275+
for (SymfonyBundle symfonyBundle : new SymfonyBundleUtil(project).getBundles()) {
276+
String parentBundle = PhpElementsUtil.getMethodReturnAsString(symfonyBundle.getPhpClass(), "getParent");
277+
if(parentBundle != null && bundle.equals(parentBundle)) {
278+
relativeFile = symfonyBundle.getRelative(String.format("Resources/views/%s", templatePath.substring(i + 7)));
279+
if(relativeFile != null) {
280+
files.add(relativeFile);
281+
}
282+
}
283+
}
232284

285+
return PsiElementUtils.convertVirtualFilesToPsiFiles(project, files);
233286
}
234287

235288
private static void addFileInsideTwigPath(Project project, String templatePath, Collection<PsiFile> psiFiles, TwigPath twigPath) {

src/fr/adrienbrault/idea/symfony2plugin/util/PhpElementsUtil.java

+36
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,42 @@ static public PsiElementPattern.Capture<StringLiteralExpression> getMethodReturn
332332
.withLanguage(PhpLanguage.INSTANCE);
333333
}
334334

335+
/**
336+
* Find a string return value of a method context "function() { return 'foo'}"
337+
* First match wins
338+
*/
339+
@Nullable
340+
static public String getMethodReturnAsString(@NotNull PhpClass phpClass, @NotNull String methodName) {
341+
342+
Method method = phpClass.findMethodByName(methodName);
343+
if(method == null) {
344+
return null;
345+
}
346+
347+
final Set<String> values = new HashSet<String>();
348+
method.acceptChildren(new PsiRecursiveElementWalkingVisitor() {
349+
@Override
350+
public void visitElement(PsiElement element) {
351+
352+
if(PhpElementsUtil.getMethodReturnPattern().accepts(element)) {
353+
String value = PhpElementsUtil.getStringValue(element);
354+
if(value != null && StringUtils.isNotBlank(value)) {
355+
values.add(value);
356+
}
357+
}
358+
359+
super.visitElement(element);
360+
}
361+
});
362+
363+
if(values.size() == 0) {
364+
return null;
365+
}
366+
367+
// we support only first item
368+
return values.iterator().next();
369+
}
370+
335371
@Nullable
336372
static public PhpClass getClass(Project project, String className) {
337373
return getClass(PhpIndex.getInstance(project), className);

src/fr/adrienbrault/idea/symfony2plugin/util/PsiElementUtils.java

+22
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.util.ArrayList;
2020
import java.util.Collection;
21+
import java.util.HashSet;
2122
import java.util.List;
2223

2324
/**
@@ -327,4 +328,25 @@ public static String getStringBeforeCursor(StringLiteralExpression literal, int
327328
return content.length() >= cursorOffsetClean ? content.substring(0, cursorOffsetClean) : null;
328329
}
329330

331+
@NotNull
332+
public static Collection<PsiFile> convertVirtualFilesToPsiFiles(@NotNull Project project, @NotNull Collection<VirtualFile> files) {
333+
334+
Collection<PsiFile> psiFiles = new HashSet<PsiFile>();
335+
336+
PsiManager psiManager = null;
337+
for (VirtualFile file : files) {
338+
339+
if(psiManager == null) {
340+
psiManager = PsiManager.getInstance(project);
341+
}
342+
343+
PsiFile psiFile = psiManager.findFile(file);
344+
if(psiFile != null) {
345+
psiFiles.add(psiFile);
346+
}
347+
}
348+
349+
return psiFiles;
350+
}
351+
330352
}

0 commit comments

Comments
 (0)