package fr.adrienbrault.idea.symfony2plugin.routing.dic; import com.intellij.openapi.project.Project; import com.jetbrains.php.lang.psi.elements.Method; import com.jetbrains.php.lang.psi.elements.PhpClass; import fr.adrienbrault.idea.symfony2plugin.routing.Route; import fr.adrienbrault.idea.symfony2plugin.routing.RouteHelper; import fr.adrienbrault.idea.symfony2plugin.stubs.ContainerCollectionResolver; import fr.adrienbrault.idea.symfony2plugin.util.dict.ServiceUtil; import org.apache.commons.lang.StringUtils; import org.jetbrains.annotations.NotNull; import java.util.*; /** * @author Daniel Espendiller <daniel@espendiller.net> */ public class ServiceRouteContainer { private final Collection<Route> routes; private ContainerCollectionResolver.LazyServiceCollector lazyServiceCollector; private Map<String, PhpClass> serviceCache = new HashMap<>(); private ServiceRouteContainer(@NotNull Collection<Route> routes) { this.routes = routes; } public Set<String> getServiceNames() { Set<String> services = new HashSet<>(); for (Route route : this.routes) { String controller = route.getController(); if(controller == null) { continue; } String[] split = controller.split(":"); if(split.length > 1) { services.add(split[0]); } } return services; } @NotNull public Collection<Route> getMethodMatches(@NotNull Method method) { PhpClass originClass = method.getContainingClass(); if(originClass == null) { return Collections.emptyList(); } String classFqn = StringUtils.stripStart(originClass.getFQN(), "\\"); Collection<Route> routes = new ArrayList<>(); for (Route route : this.routes) { String serviceRoute = route.getController(); if(serviceRoute == null) { continue; } // if controller matches: // service_id:methodName String[] split = serviceRoute.split(":"); if(split.length != 2 || !split[1].equals(method.getName())) { continue; } // cache PhpClass resolve if(!serviceCache.containsKey(split[0])) { serviceCache.put(split[0], ServiceUtil.getResolvedClassDefinition(method.getProject(), split[0], getLazyServiceCollector(method.getProject()))); } PhpClass phpClass = serviceCache.get(split[0]); if(phpClass != null && classFqn.equals(phpClass.getPresentableFQN())) { Method targetMethod = phpClass.findMethodByName(split[1]); if(targetMethod != null) { routes.add(route); } } } return routes; } private ContainerCollectionResolver.LazyServiceCollector getLazyServiceCollector(Project project) { return this.lazyServiceCollector == null ? this.lazyServiceCollector = new ContainerCollectionResolver.LazyServiceCollector(project) : this.lazyServiceCollector; } /** * Build container which stores all service routes * * @param routes Unfiltered routes */ @NotNull public static ServiceRouteContainer build(@NotNull Map<String, Route> routes) { Collection<Route> serviceRoutes = new ArrayList<>(); for (Route route : routes.values()) { String controller = route.getController(); if(controller == null || !RouteHelper.isServiceController(controller)) { continue; } String[] split = controller.split(":"); if(split.length > 1) { serviceRoutes.add(route); } } return new ServiceRouteContainer(serviceRoutes); } }