de.espend.idea.shopware.util.ShopwareUtil.java Source code

Java tutorial

Introduction

Here is the source code for de.espend.idea.shopware.util.ShopwareUtil.java

Source

package de.espend.idea.shopware.util;

import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.patterns.PsiElementPattern;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.php.PhpIndex;
import com.jetbrains.php.lang.psi.elements.*;
import com.jetbrains.php.lang.psi.elements.impl.AssignmentExpressionImpl;
import com.jetbrains.smarty.SmartyFile;
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
import fr.adrienbrault.idea.symfony2plugin.util.PsiElementUtils;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author Daniel Espendiller <daniel@espendiller.net>
 */
public class ShopwareUtil {

    public static Set<String> PLUGIN_CONFIGS = ContainerUtil.newHashSet();

    final public static String[] PLUGIN_CONFIG_TYPES = new String[] { "text", "color", "datetime", "html",
            "interval", "mediaselection", "number", "select", "combo", "textarea", "time" };

    final public static String[] PLUGIN_CONFIG_OPTIONS = new String[] { "label", "value", "scope", "description",
            "required", "attributes", "store", "inputType" };

    final public static String[] PLUGIN_INFO = new String[] { "version", "author", "label", "license", "copyright",
            "support", "link" };

    final public static String[] CONTAINER_SERVICE_PREFIX = new String[] { "Enlight_Bootstrap_AfterInitResource_",
            "Enlight_Bootstrap_AfterRegisterResource_", "Enlight_Bootstrap_InitResource_" };

    // Get the attribute tables from MYSQL with
    /*
    SELECT TABLE_NAME
    FROM information_schema.TABLES
    WHERE TABLE_SCHEMA = SCHEMA()
    AND TABLE_NAME LIKE '%attributes'
     */
    final public static String[] MODEL_STATIC_ATTRIBUTES = new String[] {
            "s_article_configurator_groups_attributes", "s_article_configurator_options_attributes",
            "s_article_configurator_template_prices_attributes", "s_article_configurator_templates_attributes",
            "s_articles_attributes", "s_articles_downloads_attributes", "s_articles_esd_attributes",
            "s_articles_img_attributes", "s_articles_information_attributes", "s_articles_prices_attributes",
            "s_articles_supplier_attributes", "s_blog_attributes", "s_categories_attributes",
            "s_cms_static_attributes", "s_cms_support_attributes", "s_core_auth_attributes",
            "s_core_config_mails_attributes", "s_core_countries_attributes", "s_core_countries_states_attributes",
            "s_core_customergroups_attributes", "s_core_paymentmeans_attributes", "s_emarketing_banners_attributes",
            "s_emarketing_partner_attributes", "s_emarketing_vouchers_attributes", "s_emotion_attributes",
            "s_export_attributes", "s_filter_attributes", "s_filter_options_attributes",
            "s_filter_values_attributes", "s_media_attributes", "s_order_attributes", "s_order_basket_attributes",
            "s_order_billingaddress_attributes", "s_order_details_attributes", "s_order_documents_attributes",
            "s_order_shippingaddress_attributes", "s_premium_dispatch_attributes", "s_product_streams_attributes",
            "s_user_addresses_attributes", "s_user_attributes", "s_user_billingaddress_attributes",
            "s_user_shippingaddress_attributes" };

    final public static String[] MODEL_STATIC_ATTRIBUTE_TYPES = new String[] { "int(11)", "int(1)", "varchar(255)",
            "datetime", "mediumtext", "date", "decimal(10,2)", "double", "text" };

    final public static String[] ROUTE_ASSEMBLE = new String[] { "module", "controller", "appendSession", "action",
            "fullPath", "module" };

    final public static String[] ATTRIBUTE_DATA_TYPES = new String[] { "string", "text", "html", "integer", "float",
            "boolean", "date", "datetime", "combobox", "single_selection", "multi_selection" };

    final public static String[] ATTRIBUTE_BACKEND_VIEWS = new String[] { "label", "supportText", "helpText",
            "translatable", "displayInBackend", "entity", "position", "custom", "arrayStore" };

    public static void collectControllerClass(Project project, ControllerClassVisitor controllerClassVisitor) {
        collectControllerClass(project, controllerClassVisitor, "Frontend", "Backend", "Core", "Widgets");
    }

    public static void collectControllerClass(Project project, ControllerClassVisitor controllerClassVisitor,
            String... modules) {

        PhpIndex phpIndex = PhpIndex.getInstance(project);
        Collection<PhpClass> phpClasses = phpIndex.getAllSubclasses("\\Enlight_Controller_Action");

        Pattern pattern = Pattern.compile(".*_(" + StringUtils.join(modules, "|") + ")_(\\w+)",
                Pattern.CASE_INSENSITIVE);

        for (PhpClass phpClass : phpClasses) {

            String className = phpClass.getName();
            Matcher matcher = pattern.matcher(className);

            if (matcher.find()) {
                String moduleName = matcher.group(1);
                String controller = matcher.group(2);
                controllerClassVisitor.visitClass(phpClass, moduleName, controller);
            }

        }

    }

    public interface ControllerClassVisitor {
        void visitClass(PhpClass phpClass, String moduleName, String controllerName);
    }

    public static void collectControllerActionSmartyWrapper(PsiElement psiElement,
            ControllerActionVisitor visitor) {
        collectControllerActionSmartyWrapper(psiElement, visitor, "Frontend", "Backend", "Core");
    }

    public static void collectControllerActionSmartyWrapper(PsiElement psiElement, ControllerActionVisitor visitor,
            String... modules) {

        Pattern pattern = Pattern.compile("controller=[\"|']*(\\w+)[\"|']*");
        Matcher matcher = pattern.matcher(psiElement.getParent().getText());
        if (!matcher.find()) {
            return;
        }

        String controllerName = toCamelCase(matcher.group(1), false);
        collectControllerAction(psiElement.getProject(), controllerName, visitor, modules);
    }

    public static void collectControllerAction(Project project, String controllerName,
            ControllerActionVisitor visitor, String... modules) {

        for (String moduleName : modules) {
            PhpClass phpClass = PhpElementsUtil.getClass(project,
                    String.format("Shopware_Controllers_%s_%s", moduleName, controllerName));
            if (phpClass != null) {
                for (Method method : phpClass.getMethods()) {
                    if (method.getAccess().isPublic() && method.getName().endsWith("Action")) {
                        visitor.visitMethod(method, method.getName().substring(0, method.getName().length() - 6),
                                moduleName, controllerName);
                    }
                }
            }
        }

    }

    public interface ControllerActionVisitor {
        void visitMethod(Method method, String methodStripped, String moduleName, String controllerName);
    }

    @Nullable
    public static Method getControllerActionOnSmartyFile(SmartyFile smartyFile) {
        return getControllerActionOnSmartyFile(smartyFile, "frontend", "backend", "core");
    }

    @Nullable
    public static Method getControllerActionOnSmartyFile(SmartyFile smartyFile, String... modules) {

        String relativeFilename = TemplateUtil.getTemplateName(smartyFile.getProject(),
                smartyFile.getVirtualFile());
        if (relativeFilename == null) {
            return null;
        }

        Pattern pattern = Pattern.compile(".*[/]*(" + StringUtils.join(modules, "|") + ")/(\\w+)/(\\w+)\\.tpl");
        Matcher matcher = pattern.matcher(relativeFilename);

        if (!matcher.find()) {
            return null;
        }

        // Shopware_Controllers_Frontend_Account
        String moduleName = toCamelCase(matcher.group(1), false);
        String controller = toCamelCase(matcher.group(2), false);
        String action = toCamelCase(matcher.group(3), true);

        // build class name
        String className = String.format("\\Shopware_Controllers_%s_%s", moduleName, controller);
        PhpClass phpClass = PhpElementsUtil.getClassInterface(smartyFile.getProject(), className);
        if (phpClass == null) {
            return null;
        }

        return phpClass.findMethodByName(action + "Action");

    }

    public static String toCamelCase(String value, boolean startWithLowerCase) {
        String[] strings = StringUtils.split(value.toLowerCase(), "_");
        for (int i = startWithLowerCase ? 1 : 0; i < strings.length; i++) {
            strings[i] = StringUtils.capitalize(strings[i]);
        }
        return StringUtils.join(strings);
    }

    public static void collectControllerViewVariable(Method method,
            ControllerViewVariableVisitor controllerViewVariableVisitor) {

        // Views()->test;
        for (FieldReference fieldReference : PsiTreeUtil.collectElementsOfType(method, FieldReference.class)) {
            PsiElement methodReference = fieldReference.getFirstChild();
            if (methodReference instanceof MethodReference) {
                if (((MethodReference) methodReference).getCanonicalText().equals("View")) {

                    PsiElement parentElement = fieldReference.getParent();
                    if (parentElement instanceof AssignmentExpressionImpl) {
                        controllerViewVariableVisitor.visitVariable(fieldReference.getName(), methodReference,
                                ((AssignmentExpressionImpl) parentElement).getValue());
                    } else {
                        // need this ???
                        //controllerViewVariableVisitor.visitVariable(fieldReference.getName(), null);
                    }

                }
            }
        }

        // Views()->assign('test'); // Views()->assign(['test' => 'test'])
        for (MethodReference methodReference : PsiTreeUtil.collectElementsOfType(method, MethodReference.class)) {

            if ("assign".equals(methodReference.getName())) {
                PsiElement firstParameter = PsiElementUtils.getMethodParameterPsiElementAt(methodReference, 0);
                if (firstParameter instanceof ArrayCreationExpression) {
                    for (String keyName : PhpElementsUtil
                            .getArrayCreationKeys((ArrayCreationExpression) firstParameter)) {
                        // @TODO: add source and type resolve
                        controllerViewVariableVisitor.visitVariable(keyName, firstParameter, null);
                    }
                } else {
                    String value = PhpElementsUtil.getStringValue(firstParameter);
                    if (value != null) {
                        // @TODO: add source and type resolve
                        controllerViewVariableVisitor.visitVariable(value, firstParameter, null);
                    }
                }
            }

        }
    }

    public interface ControllerViewVariableVisitor {
        void visitVariable(String variableName, @NotNull PsiElement sourceType, @Nullable PsiElement typeElement);
    }

    public static Map<String, PhpClass> getResourceClasses(Project project) {

        Map<String, PhpClass> phpClassMap = new HashMap<>();

        for (PhpClass phpClass : PhpIndex.getInstance(project)
                .getAllSubclasses("\\Shopware\\Components\\Api\\Resource\\Resource")) {
            phpClassMap.put(phpClass.getName(), phpClass);
        }

        return phpClassMap;
    }

    @Nullable
    public static PhpClass getResourceClass(Project project, String resourceName) {

        for (PhpClass phpClass : PhpIndex.getInstance(project)
                .getAllSubclasses("\\Shopware\\Components\\Api\\Resource\\Resource")) {
            if (resourceName.equalsIgnoreCase(phpClass.getName())) {
                return phpClass;
            }
        }

        return null;
    }

    public static PsiElementPattern.Capture<PsiElement> getBootstrapPathPattern() {
        // @TODO add method reference filter
        return PlatformPatterns.psiElement()
                .withParent(PlatformPatterns.psiElement(StringLiteralExpression.class).afterLeafSkipping(
                        PlatformPatterns.psiElement(PsiWhiteSpace.class),
                        PlatformPatterns.psiElement().withText(".")));
    }

    public static void collectBootstrapFiles(StringLiteralExpression literalExpression,
            final BootstrapFileVisitor visitor) {

        MethodReference methodReference = PsiElementUtils.getPrevSiblingOfType(literalExpression, PlatformPatterns
                .psiElement(MethodReference.class).withText(PlatformPatterns.string().contains("Path()")));
        if (methodReference == null) {
            return;
        }

        PsiFile currentFile = literalExpression.getContainingFile();
        final PsiDirectory psiDirectory = currentFile.getParent();
        if (psiDirectory == null) {
            return;
        }

        VfsUtil.processFilesRecursively(psiDirectory.getVirtualFile(), virtualFile -> {

            if (virtualFile.isDirectory() || "php".equalsIgnoreCase(virtualFile.getExtension())) {
                String relativePath = VfsUtil.getRelativePath(virtualFile, psiDirectory.getVirtualFile(), '/');
                if (StringUtils.isNotBlank(relativePath)) {
                    visitor.visitVariable(virtualFile, relativePath);
                }
            }

            return true;
        });
    }

    public interface BootstrapFileVisitor {
        void visitVariable(VirtualFile virtualFile, String relativePath);
    }

    public static Set<String> getLookupHooks(String content) {
        return getHookCompletionNameCleanup(getCamelizeHook(content));
    }

    public static String getCamelizeHook(String content) {

        content = content.replaceAll("_+", "_").replaceAll(":+", "_").replaceAll("\\\\+", "_");

        List<String> items = new ArrayList<>();
        for (String s : content.split("(?=\\p{Lu})")) {
            if (s.length() > 1) {
                items.add(s);
            }
        }

        return toCamelCase(StringUtils.join(items, "_").toLowerCase(), true);
    }

    public static Set<String> getHookCompletionNameCleanup(String content) {

        Set<String> set = new HashSet<>();
        set.add("on" + ucfirst(content));

        for (String startCleanup : new String[] { "shopware", "shopwareControllers", "enlightController", "enlight",
                "shopwareControllers" }) {
            if (content.startsWith(startCleanup) && content.length() - startCleanup.length() > 1) {
                set.add("on" + ucfirst(content.substring(startCleanup.length())));
            }
        }

        return set;
    }

    private static String ucfirst(String subject) {
        return Character.toUpperCase(subject.charAt(0)) + subject.substring(1);
    }

    /**
     * "Enlight_Controller_Action_PostDispatchSecure_Frontend_Payment" _> Shopware_Controllers_Frontend_Payment
     */
    @Nullable
    public static PhpClass getControllerOnActionSubscriberName(@NotNull Project project,
            @NotNull String subscriberName) {
        Pattern pattern = Pattern.compile("Enlight_Controller_Action_\\w+_(Frontend|Backend|Core|Widgets)_(\\w+)");
        Matcher matcher = pattern.matcher(subscriberName);

        if (matcher.find()) {
            PhpClass phpClass = PhpElementsUtil.getClass(project,
                    String.format("Shopware_Controllers_%s_%s", matcher.group(1), matcher.group(2)));
            if (phpClass != null) {
                return phpClass;
            }
        }

        return null;
    }
}