Skip to content

Commit 58c4d36

Browse files
authored
Merge pull request #1416 from Haehnchen/feature/user-implementation-twig
support user implementation resolving for Twig "app.user" usages
2 parents 50b96f3 + d114e7f commit 58c4d36

File tree

2 files changed

+47
-7
lines changed

2 files changed

+47
-7
lines changed

src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/util/TwigTypeResolveUtil.java

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import fr.adrienbrault.idea.symfony2plugin.templating.variable.TwigFileVariableCollector;
2424
import fr.adrienbrault.idea.symfony2plugin.templating.variable.TwigFileVariableCollectorParameter;
2525
import fr.adrienbrault.idea.symfony2plugin.templating.variable.TwigTypeContainer;
26+
import fr.adrienbrault.idea.symfony2plugin.templating.variable.collector.StaticVariableCollector;
2627
import fr.adrienbrault.idea.symfony2plugin.templating.variable.dict.PsiVariable;
2728
import fr.adrienbrault.idea.symfony2plugin.templating.variable.resolver.FormFieldResolver;
2829
import fr.adrienbrault.idea.symfony2plugin.templating.variable.resolver.FormVarsResolver;
@@ -34,7 +35,6 @@
3435
import org.jetbrains.annotations.NotNull;
3536

3637
import java.util.*;
37-
import java.util.function.BiConsumer;
3838
import java.util.regex.Matcher;
3939
import java.util.regex.Pattern;
4040
import java.util.stream.Collectors;
@@ -442,10 +442,18 @@ private static Collection<TwigTypeContainer> resolveTwigMethodName(Collection<Tw
442442
if(phpNamedElement.getPhpNamedElement() != null) {
443443
for(PhpNamedElement target : getTwigPhpNameTargets(phpNamedElement.getPhpNamedElement(), typeName)) {
444444
PhpType phpType = target.getType();
445-
for(String typeString: phpType.getTypes()) {
446-
PhpNamedElement phpNamedElement1 = PhpElementsUtil.getClassInterface(phpNamedElement.getPhpNamedElement().getProject(), typeString);
447-
if(phpNamedElement1 != null) {
448-
phpNamedElements.add(new TwigTypeContainer(phpNamedElement1));
445+
446+
// @TODO: provide extension
447+
// custom resolving for Twig here: "app.user" => can also be a general solution just support the "getToken()->getUser()"
448+
if (target instanceof Method && StaticVariableCollector.isUserMethod((Method) target)) {
449+
phpNamedElements.addAll(getApplicationUserImplementations(target.getProject()));
450+
}
451+
452+
// @TODO: use full resolving for object, that would allow using TypeProviders and core PhpStorm feature
453+
for (String typeString: phpType.filterPrimitives().getTypes()) {
454+
PhpClass phpClass = PhpElementsUtil.getClassInterface(phpNamedElement.getPhpNamedElement().getProject(), typeString);
455+
if(phpClass != null) {
456+
phpNamedElements.add(new TwigTypeContainer(phpClass));
449457
}
450458
}
451459
}
@@ -460,6 +468,19 @@ private static Collection<TwigTypeContainer> resolveTwigMethodName(Collection<Tw
460468
return phpNamedElements;
461469
}
462470

471+
/**
472+
* Get possible suitable UserInterface implementation from the application scope
473+
*/
474+
@NotNull
475+
private static Collection<TwigTypeContainer> getApplicationUserImplementations(@NotNull Project project) {
476+
return PhpIndex.getInstance(project)
477+
.getAllSubclasses("\\Symfony\\Component\\Security\\Core\\User\\UserInterface")
478+
.stream()
479+
.filter(phpClass -> !phpClass.isInterface()) // filter out implementation like AdvancedUserInterface
480+
.map(TwigTypeContainer::new)
481+
.collect(Collectors.toList());
482+
}
483+
463484
private static Set<String> resolveTwigMethodName(Project project, Collection<String> previousElement, String typeName) {
464485

465486
Set<String> types = new HashSet<>();
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,36 @@
11
package fr.adrienbrault.idea.symfony2plugin.templating.variable.collector;
22

3+
import com.jetbrains.php.lang.psi.elements.Method;
34
import fr.adrienbrault.idea.symfony2plugin.templating.variable.TwigFileVariableCollector;
45
import fr.adrienbrault.idea.symfony2plugin.templating.variable.TwigFileVariableCollectorParameter;
6+
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
57
import org.jetbrains.annotations.NotNull;
68

7-
import java.util.*;
9+
import java.util.Arrays;
10+
import java.util.HashSet;
11+
import java.util.Map;
12+
import java.util.Set;
813

914
/**
15+
* Provide support for Twig global "app".
16+
*
17+
* Its just a static fallback if no other implementation is able to catch up
18+
*
1019
* @author Daniel Espendiller <[email protected]>
1120
*/
1221
public class StaticVariableCollector implements TwigFileVariableCollector {
22+
private static final HashSet<String> APP_CLASSES = new HashSet<>(Arrays.asList(
23+
"\\Symfony\\Bundle\\FrameworkBundle\\Templating\\GlobalVariables", // valid inside Symfony < 5
24+
"\\Symfony\\Bridge\\Twig\\AppVariable"
25+
));
26+
1327
@Override
1428
public void collect(@NotNull TwigFileVariableCollectorParameter parameter, @NotNull Map<String, Set<String>> variables) {
15-
variables.put("app", new HashSet<>(Collections.singletonList("\\Symfony\\Bundle\\FrameworkBundle\\Templating\\GlobalVariables")));
29+
variables.put("app", new HashSet<>(APP_CLASSES)); // const must be a copy
30+
}
31+
32+
public static boolean isUserMethod(@NotNull Method method) {
33+
return APP_CLASSES.stream()
34+
.anyMatch(phpClass -> PhpElementsUtil.isMethodInstanceOf(method, phpClass, "getUser"));
1635
}
1736
}

0 commit comments

Comments
 (0)