Skip to content

Commit

Permalink
add form Twig fields widget generator
Browse files Browse the repository at this point in the history
  • Loading branch information
Haehnchen committed Jun 24, 2023
1 parent b7b1de2 commit 8bac4fd
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1053,18 +1053,23 @@ public boolean accepts(@NotNull String s, ProcessingContext processingContext) {
continue;
}

PsiElement element = entry.getValue().getElement();
if (element == null) {
continue;
}

String typeText = null;
Collection<PhpClass> formTypeFromFormFactory = FormFieldResolver.getFormTypeFromFormFactory(entry.getValue().getElement());
Collection<PhpClass> formTypeFromFormFactory = FormFieldResolver.getFormTypeFromFormFactory(element);
if (formTypeFromFormFactory.size() > 0) {
typeText = StringUtils.stripStart(formTypeFromFormFactory.iterator().next().getFQN(), "\\");
}

for (String s : new String[]{"form_start", "form_rest", "form_end", "form_errors"}) {
LookupElementBuilder element = LookupElementBuilder.create(s + "(" + entry.getKey() + ")")
LookupElementBuilder lookupElement = LookupElementBuilder.create(s + "(" + entry.getKey() + ")")
.withTypeText(typeText)
.withIcon(Symfony2Icons.FORM_TYPE);

resultSet.addElement(element);
resultSet.addElement(lookupElement);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,18 @@ public static void visitFormReferencesFields(PsiElement formReference, @NotNull
return;
}

for (TwigTypeContainer twigTypeContainer : getTwigTypeContainer(method, phpClass)) {
consumer.accept(twigTypeContainer);
}
visitFormReferencesFields(phpClass, consumer);
}
}

public static void visitFormReferencesFields(@NotNull PhpClass phpClass, @NotNull Consumer<TwigTypeContainer> consumer) {
Method method = phpClass.findMethodByName("buildForm");
if(method == null) {
return;
}

for (TwigTypeContainer twigTypeContainer : getTwigTypeContainer(method, phpClass)) {
consumer.accept(twigTypeContainer);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package fr.adrienbrault.idea.symfony2plugin.twig.action;

import com.intellij.codeInsight.CodeInsightActionHandler;
import com.intellij.codeInsight.actions.CodeInsightAction;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.html.HtmlFileImpl;
import com.jetbrains.php.PhpIndex;
import com.jetbrains.php.completion.insert.PhpInsertHandlerUtil;
import com.jetbrains.php.lang.psi.elements.PhpClass;
import com.jetbrains.php.lang.psi.resolve.types.PhpType;
import com.jetbrains.twig.TwigFile;
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
import fr.adrienbrault.idea.symfony2plugin.templating.util.TwigTypeResolveUtil;
import fr.adrienbrault.idea.symfony2plugin.templating.util.TwigUtil;
import fr.adrienbrault.idea.symfony2plugin.templating.variable.dict.PsiVariable;
import fr.adrienbrault.idea.symfony2plugin.templating.variable.resolver.FormFieldResolver;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;

import java.util.*;

/**
* @author Daniel Espendiller <[email protected]>
*/
public class TwigFormFieldGenerator extends CodeInsightAction {
@Override
protected boolean isValidForFile(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
return Symfony2ProjectComponent.isEnabled(project) && (
file instanceof TwigFile
|| (file instanceof HtmlFileImpl && file.getName().toLowerCase().endsWith(".twig"))
|| TwigUtil.getInjectedTwigElement(file, editor) != null
);
}

protected CodeInsightActionHandler getHandler() {
return new TwigFormFieldGenerator.MyCodeInsightActionHandler();
}

private static class MyCodeInsightActionHandler implements CodeInsightActionHandler {
@Override
public void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile psiFile) {
PsiElement psiElement = TwigUtil.getInjectedTwigElement(psiFile, editor);
if (psiElement == null) {
return;
}

Collection<JBFormFieldItem> phpClasses = new ArrayList<>();

for (Map.Entry<String, PsiVariable> entry : TwigTypeResolveUtil.collectScopeVariables(psiElement).entrySet()) {
PhpType phpType = PhpIndex.getInstance(project).completeType(project, PhpType.from(entry.getValue().getTypes().toArray(new String[0])), new HashSet<>());
if (phpType.types().noneMatch(s -> s.equals("\\Symfony\\Component\\Form\\FormView"))) {
continue;
}

PsiElement element = entry.getValue().getElement();
if (element == null) {
continue;
}

for (PhpClass phpClass : FormFieldResolver.getFormTypeFromFormFactory(element)) {
phpClasses.add(new JBFormFieldItem(entry.getKey(), phpClass));
}
}

if (phpClasses.size() == 1) {
extracted(project, editor, phpClasses.stream().iterator().next());
return;
}

JBPopupFactory.getInstance().createPopupChooserBuilder(new ArrayList<>(phpClasses))
.setTitle("Symfony: Select FormType")
.setItemChosenCallback(strings -> WriteCommandAction.runWriteCommandAction(project, "", null, () -> {
extracted(project, editor, strings);
}))
.createPopup()
.showInBestPositionFor(editor);
}

private static void extracted(@NotNull Project project, @NotNull Editor editor, @NotNull TwigFormFieldGenerator.JBFormFieldItem next) {
Collection<String> fields = new HashSet<>();
FormFieldResolver.visitFormReferencesFields(next.phpClass(), twigTypeContainer -> fields.add(twigTypeContainer.getStringElement()));

JBPopupFactory.getInstance().createPopupChooserBuilder(new ArrayList<>(fields))
.setTitle(String.format("Symfony: Select Form Fields \"%s\"", StringUtils.abbreviate(next.phpClass.getName(), 20)))
.setItemsChosenCallback(strings -> WriteCommandAction.runWriteCommandAction(project, "", null, () -> {
StringBuilder s = new StringBuilder();

for (String string : strings) {
s.append(String.format("{{ form_widget(%s.%s) }}\n", next.key, string));
}

PhpInsertHandlerUtil.insertStringAtCaret(editor, s.toString());
}))
.createPopup()
.showInBestPositionFor(editor);
}
}

public record JBFormFieldItem(@NotNull String key, @NotNull PhpClass phpClass) {
@Override
public String toString() {
return key + " => " + phpClass.getName();
}
}
}
4 changes: 4 additions & 0 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,10 @@
<add-to-group group-id="GenerateGroup" anchor="last" />
</action>

<action id="Symfony.TwigFormFieldGenerator" class="fr.adrienbrault.idea.symfony2plugin.twig.action.TwigFormFieldGenerator" text="Form Fields" icon="SymfonyIcons.FormType">
<add-to-group group-id="GenerateGroup" anchor="last" />
</action>

<group id="Symfony2Group" text="Symfony" popup="false">
<group id="Symfony2GroupService" class="com.intellij.ide.actions.NonTrivialActionGroup" text="Service" popup="true" icon="SymfonyIcons.Symfony">
<action id="Symfony2NewXmlService" class="fr.adrienbrault.idea.symfony2plugin.action.NewXmlServiceAction"/>
Expand Down

0 comments on commit 8bac4fd

Please sign in to comment.