Package fr.adrienbrault.idea.symfony2plugin.templating.variable.resolver

Source Code of fr.adrienbrault.idea.symfony2plugin.templating.variable.resolver.FormFieldResolver

package fr.adrienbrault.idea.symfony2plugin.templating.variable.resolver;

import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.php.lang.psi.elements.Method;
import com.jetbrains.php.lang.psi.elements.MethodReference;
import com.jetbrains.php.lang.psi.elements.PhpClass;
import com.jetbrains.php.lang.psi.elements.Variable;
import fr.adrienbrault.idea.symfony2plugin.Symfony2InterfacesUtil;
import fr.adrienbrault.idea.symfony2plugin.form.util.FormUtil;
import fr.adrienbrault.idea.symfony2plugin.templating.variable.TwigTypeContainer;
import fr.adrienbrault.idea.symfony2plugin.templating.variable.dict.PsiVariable;
import fr.adrienbrault.idea.symfony2plugin.templating.variable.resolver.holder.FormDataHolder;
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
import fr.adrienbrault.idea.symfony2plugin.util.PsiElementUtils;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class FormFieldResolver implements TwigTypeResolver {

    public void resolve(Collection<TwigTypeContainer> targets, Collection<TwigTypeContainer> previousElement, String typeName, Collection<List<TwigTypeContainer>> previousElements, @Nullable List<PsiVariable> psiVariables) {

        if(targets.size() == 0 || psiVariables == null || previousElements == null || previousElements.size() != 0) {
            return;
        }

        Symfony2InterfacesUtil symfony2InterfacesUtil = new Symfony2InterfacesUtil();
        TwigTypeContainer twigTypeContainer = targets.iterator().next();

        if(twigTypeContainer.getPhpNamedElement() instanceof PhpClass) {
            if(symfony2InterfacesUtil.isInstanceOf((PhpClass) twigTypeContainer.getPhpNamedElement(), "\\Symfony\\Component\\Form\\FormView")) {
                if(psiVariables.size() > 0) {
                    PsiElement var = psiVariables.get(0).getElement();

                    // $form->createView()
                    if(var instanceof MethodReference) {
                        PsiElement form = var.getFirstChild();
                        if(form instanceof Variable) {
                            PsiElement varDecl = ((Variable) form).resolve();
                            if(varDecl instanceof Variable) {
                                MethodReference methodReference = PsiTreeUtil.getNextSiblingOfType(varDecl, MethodReference.class);
                                attachFormFields(methodReference, targets);
                            }
                        }
                    }


                    // nested resolve of form view; @TODO: should be some nicer
                    // 'foo2' => $form2 => $form2 = $form->createView() => $this->createForm(new Type();
                    if(var instanceof Variable) {
                        PsiElement varDecl = ((Variable) var).resolve();
                        if(varDecl instanceof Variable) {
                            MethodReference methodReference = PsiTreeUtil.getNextSiblingOfType(varDecl, MethodReference.class);
                            PsiElement scopeVar = methodReference.getFirstChild();

                            // $form2 = $form->createView()
                            if(scopeVar instanceof Variable) {
                                PsiElement varDeclParent = ((Variable) scopeVar).resolve();
                                if(varDeclParent instanceof Variable) {

                                    // "$form"->createView();
                                    PsiElement resolve = ((Variable) varDeclParent).resolve();
                                    if(resolve != null) {
                                        attachFormFields(PsiTreeUtil.getNextSiblingOfType(resolve, MethodReference.class), targets);
                                    }

                                }
                            }
                           
                        }
                    }

                }
            }

        }
    }

    private static void attachFormFields(@Nullable MethodReference methodReference, Collection<TwigTypeContainer> targets) {

        if(methodReference == null) {
            return;
        }

        Symfony2InterfacesUtil symfony2InterfacesUtil = new Symfony2InterfacesUtil();
        if(symfony2InterfacesUtil.isCallTo(methodReference, "\\Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller", "createForm")) {
            PsiElement formType = PsiElementUtils.getMethodParameterPsiElementAt(methodReference, 0);
            if(formType != null) {
                PhpClass phpClass = FormUtil.getFormTypeClassOnParameter(formType);

                if(phpClass == null) {
                    return;
                }

                Method method = PhpElementsUtil.getClassMethod(phpClass, "buildForm");
                if(method == null) {
                    return;
                }

                targets.addAll(getTwigTypeContainer(method));
            }

        }

    }

    public static List<TwigTypeContainer> getTwigTypeContainer(Method method) {

        MethodReference[] formBuilderTypes = FormUtil.getFormBuilderTypes(method);
        List<TwigTypeContainer> twigTypeContainers = new ArrayList<TwigTypeContainer>();

        for(MethodReference methodReference: formBuilderTypes) {

            String fieldName = PsiElementUtils.getMethodParameterAt(methodReference, 0);
            PsiElement psiElement = PsiElementUtils.getMethodParameterPsiElementAt(methodReference, 1);
            TwigTypeContainer twigTypeContainer = new TwigTypeContainer(fieldName);

            // find form field type
            if(psiElement != null) {
                PhpClass phpClass = FormUtil.getFormTypeClassOnParameter(psiElement);
                if(phpClass != null) {
                    twigTypeContainer.withDataHolder(new FormDataHolder(phpClass));
                }
            }

            twigTypeContainers.add(twigTypeContainer);
        }

        return twigTypeContainers;
    }

}
TOP

Related Classes of fr.adrienbrault.idea.symfony2plugin.templating.variable.resolver.FormFieldResolver

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.