HEX
Server: Apache/2
System: Linux server1c 2.6.32-042stab145.3 #1 SMP Thu Jun 11 14:05:04 MSK 2020 x86_64
User: jandjware (1008)
PHP: 8.2.23
Disabled: exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname
Upload Files
File: /home/jandjware/public_html/wp-content/plugins/hostinger/vue-frontend/src/views/HostingerTools.vue
<script lang="ts" setup>
import SectionCard from "@/components/HostingerTools/SectionCard.vue";
import { useModal } from "@/composables";
import {SectionItem, ModalName, ToggleableSettingsData, SettingsData, Header} from "@/types";
import { useSettingsStore, useGeneralStoreData } from "@/stores";
import {
  getAssetSource,
  isNewerVerison,
  getBaseUrl,
  translate,
} from "@/utils/helpers";
import ToolVersionCard from "@/components/HostingerTools/ToolVersionCard.vue";
import { computed, ref } from "vue";
import { storeToRefs } from "pinia";
import { kebabToCamel } from "@/utils/helpers";
import http from "@/utils/services/httpService";

const { fetchSettingsData, updateSettingsData, regenerateByPassCode } =
  useSettingsStore();

const { settingsData } = storeToRefs(useSettingsStore());
const { siteUrl, llmstxtFileUrl, llmstxtFileUserGenerated, mcpChoice, aiPluginCompatibility, nonce, restBaseUrl } = useGeneralStoreData();

const WORDPRESS_UPDATE_LINK = getBaseUrl(location.href) + "update-core.php";

const isPageLoading = ref(false);

const HOSTINGER_FREE_DOMAINS = /hostingersite\.com|hostinger\.dev/;

const initialMcpChoice = ref(false);

const maintenanceSection = computed(() => [
  {
    id: "maintenance-mode",
    title: translate("hostinger_tools_maintenance_mode"),
    description: translate("hostinger_tools_disable_public_access"),
    isVisible: true,
    toggleValue: settingsData.value?.maintenanceMode,
  },
  {
    id: "bypass-link",
    title: translate("hostinger_tools_bypass_link"),
    description: translate("hostinger_tools_skip_link_maintenance_mode"),
    sideButton: {
      text: translate("hostinger_tools_reset_link"),
      onClick: () => {
        openModal(
          ModalName.ByPassLinkResetModal,
          {
            data: {
              onConfirm: () => {
                regenerateByPassCode();
              },
            },
          },
          { isLG: true }
        );
      },
    },
    copyLink:
      settingsData.value?.bypassCode &&
      // @ts-ignore
      `${siteUrl}/?bypass_code=${settingsData.value.bypassCode}`,
  },
]);

const securitySection = computed(() => [
    {
        id: "disable-xml-rpc",
        title: translate("hostinger_tools_disable_xml_rpc"),
        description: translate("hostinger_tools_xml_rpc_description"),
        isVisible: true,
        toggleValue: settingsData.value?.disableXmlRpc,
    },
    {
        id: "disable-authentication-password",
        title: translate("hostinger_tools_disable_authentication_password"),
        description: translate("hostinger_tools_authentication_password_description"),
        isVisible: true,
        toggleValue: settingsData.value?.disableAuthenticationPassword,
    },
]);

const redirectsSection = computed(() => {
  let sections = [
    {
      id: "force-https",
      title: translate("hostinger_tools_force_https"),
      description: translate("hostinger_tools_force_https_description"),
      isVisible: true,
      toggleValue: settingsData.value?.forceHttps,
    },
  ];

  sections.push({
    id: "force-www",
    title: translate("hostinger_tools_force_www"),
    description: !settingsData.value?.isEligibleWwwRedirect
      ? translate("hostinger_tools_force_www_description_not_available")
      : translate("hostinger_tools_force_www_description"),
    isVisible: !!settingsData.value?.isEligibleWwwRedirect,
    toggleValue: settingsData.value?.forceWww,
  });

  return sections.filter((section) => section.isVisible);
});

const llmsSection = computed(() => [
	{
		id: "enable-llms-txt",
		title: translate("hostinger_tools_enable_llms_txt"),
		description: translate("hostinger_tools_llms_txt_description"),
		isVisible: true,
		toggleValue: settingsData.value?.enableLlmsTxt,
		learn_more_link: "https://llmstxt.org/",
	},
	{
		id: "optin-mcp",
		title: translate("hostinger_tools_optin_mcp"),
		description: translate("hostinger_tools_optin_mcp_description"),
		isVisible: isHostingerPlatform.value && ! isFreeDomain.value,
		toggleValue: settingsData.value?.optinMcp,
		learn_more_link: "https://support.hostinger.com/en/articles/11729400-ai-agent-access-smart-ai-discovery",
	},
]);

const aiSection = computed(() => [
	{
		id: "switch-mcp-choice",
		title: translate("hostinger_tools_mcp_choice"),
		description: translate("hostinger_tools_mcp_description"),
		isVisible: true,
		toggleValue: initialMcpChoice.value,
	},
]);

const llmsSectionHeaderButtons = computed(() => settingsData.value?.enableLlmsTxt ? [
  {
    id: 'hostinger_tools_llms_txt_llmstxt',
    text: translate("hostinger_tools_llms_txt_llmstxt"),
    to: llmstxtFileUrl,
    variant: 'text'
  },
  {
    id: 'hostinger_tools_llms_txt_check_validity',
    text: translate("hostinger_tools_llms_txt_check_validity"),
    to: `https://llmstxtvalidator.org/?url=${llmstxtFileUrl}`,
    variant: 'outline'
  }
] : [] );

const { openModal } = useModal();

const isWordPressUpdateDisplayed = computed(() => {
  if (!settingsData.value) {
    return false;
  }

  return isNewerVerison({
    currentVersion: settingsData.value.currentWpVersion,
    newVersion: settingsData.value.newestWpVersion,
  });
});

const isPhpUpdateDisplayed = computed(() => {
  if (!settingsData.value) {
    return false;
  }

  return isNewerVerison({
    currentVersion: settingsData.value.phpVersion,
    newVersion: "8.2", // Hardcoded for now
  });
});

const isHostingerPlatform = computed(() => {
    return parseInt(hostinger_tools_data.hplatform) > 0;
});

const isFreeDomain = computed(() => {
	return HOSTINGER_FREE_DOMAINS.test(String(siteUrl));
});


const phpVersionCard = computed(() => ({
  title: translate("hostinger_tools_php_version"),
  toolImageSrc: getAssetSource("images/icons/icon-php.svg"),
  version: settingsData.value?.phpVersion,
  actionButton: isHostingerPlatform.value && isPhpUpdateDisplayed.value
    ? {
        onClick: () => {
          window.open(
            `https://auth.${resellerLocale.value}/login?r=/section/php-configuration/domain/${location.host}`,
            "_blank"
          );
        },
      }
    : undefined,
}));


const resellerLocale = computed(() => {
  {
    const { pluginUrl } = useGeneralStoreData();

    return pluginUrl.match(/^[^/]+/)![0] || "hostinger.com";
  }
});

const wordPressVersionCard = computed(() => ({
  title: translate("hostinger_tools_wordpress_version"),
  toolImageSrc: getAssetSource("images/icons/icon-wordpress-light.svg"),
  version: settingsData.value?.currentWpVersion,
  actionButton: isWordPressUpdateDisplayed.value
    ? {
        onClick: () => {
          window.location.href = WORDPRESS_UPDATE_LINK; // redirects to wp update page in wp admin
        },
      }
    : undefined,
}));

const onSaveSection = (value: boolean, item: SectionItem) => {
  const IMPORTANT_SECTIONS = ["disable-xml-rpc"];

  const isTurnedOn = value === false;

  if (IMPORTANT_SECTIONS.includes(item.id) && isTurnedOn) {
    openModal(
      ModalName.XmlSecurityModal,
      {
        data: {
          onConfirm: () => {
            onUpdateSettings(value, item);
          },
        },
      },
      { isLG: true }
    );

    return;
  }

  onUpdateSettings(value, item);
};

const onSaveLLmsSection = (isEnabled: boolean, item: SectionItem) => {

  if ( llmstxtFileUserGenerated && isEnabled ) {
    openModal(
        ModalName.EnableLlmsTxtModal,
        {
          data: {
            onConfirm: () => {
              onUpdateSettings(isEnabled, item);
            },
          },
        },
        { isLG: true }
    );

    return;
  }

  onUpdateSettings(isEnabled, item);
};

const onSaveAiSection = async (isEnabled: boolean, item: SectionItem) => {
	try {
		await http.post<SettingsData>(
			`${restBaseUrl}hostinger-ai-assistant/v1/toggle-mcp-plugin`,
			{ 'action': isEnabled ? 'setup' : 'deny' },
			{
				headers: { [Header.WP_NONCE]: nonce },
			}
		);

		initialMcpChoice.value = isEnabled;

		window.dispatchEvent(
			new CustomEvent('mcp-choice-changed', { detail: {
				choice: initialMcpChoice.value
				} })
		);

	} catch (error) {
		console.error('Failed to save MCP choice: ', error);
	}

	initialMcpChoice.value = isEnabled;
}

const onUpdateSettings = async (value: boolean, item: SectionItem) => {
  if (!settingsData.value) return;

  const id = kebabToCamel(item.id) as keyof ToggleableSettingsData;

  const updatedSettings = {
    ...settingsData.value,
    [id]: value,
  };

  const success = await updateSettingsData(updatedSettings);

  if (success && settingsData.value) {
    settingsData.value[id] = value;
  }
};


(async () => {
  isPageLoading.value = true;
  await fetchSettingsData();
  isPageLoading.value = false;

  if(parseInt(mcpChoice) === 1) {
	  initialMcpChoice.value = true;
  }
})();
</script>

<template>
  <div v-if="settingsData">
    <div class="hostinger-tools__tool-version-cards">
      <ToolVersionCard
        :is-loading="isPageLoading"
        v-bind="wordPressVersionCard"
        class="h-mr-16"
      />
      <ToolVersionCard
          :is-loading="isPageLoading"
          v-bind="phpVersionCard"
      />
    </div>
    <div>
      <SectionCard
        :is-loading="isPageLoading"
        @save-section="onSaveSection"
        :title="translate('hostinger_tools_maintenance')"
        :section-items="maintenanceSection"
      />
      <SectionCard
        :is-loading="isPageLoading"
        @save-section="onSaveSection"
        :title="translate('hostinger_tools_security')"
        :section-items="securitySection"
      />
      <SectionCard
        :is-loading="isPageLoading"
        @save-section="onSaveSection"
        :title="translate('hostinger_tools_redirects')"
        :section-items="redirectsSection"
      />
      <SectionCard
        :is-loading="isPageLoading"
        @save-section="onSaveLLmsSection"
        :title="translate('hostinger_tools_llms')"
        :section-items="llmsSection.filter((section) => section.isVisible)"
        :header-buttons="llmsSectionHeaderButtons"
        :warning="llmstxtFileUserGenerated ? translate('hostinger_tools_llms_txt_external_file_found') : ''"
      />
		<SectionCard
			v-if="aiPluginCompatibility"
			:is-loading="isPageLoading"
			@save-section="onSaveAiSection"
			:title="translate('hostinger_tools_ai')"
			:section-items="aiSection"
		/>
    </div>
  </div>
</template>

<style lang="scss">
.hostinger-tools {
  &__tool-version-cards {
    display: flex;
    width: 100%;

    @media (max-width: 590px) {
      flex-direction: column;
    }
  }
}
</style>