HEX
Server: LiteSpeed
System: Linux server902.web-hosting.com 4.18.0-553.54.1.lve.el8.x86_64 #1 SMP Wed Jun 4 13:01:13 UTC 2025 x86_64
User: deshuvsd (2181)
PHP: 8.1.33
Disabled: NONE
Upload Files
File: /home/deshuvsd/www/wp-content/plugins/surerank/src/apps/admin-dashboard/use-plugins-and-themes.js
import { useState, useCallback } from '@wordpress/element';
import { sprintf, __ } from '@wordpress/i18n';
import apiFetch from '@wordpress/api-fetch';
import { toast } from '@bsf/force-ui';
import { FETCH_STATUS, themesAndPlugins } from './dashboard-constants';
import { GET_INSTALLED_PLUGINS_AND_THEMES_URL } from '@Global/constants/api';

/**
 * Utility function to handle plugin/theme operations (install/activate)
 *
 * @param {Object} plugin    - The plugin object
 * @param {string} operation - The operation to perform ('install' or 'activate')
 * @return {Promise} - Resolves when operation is complete
 */
const handlePluginAndThemeOperation = ( plugin, operation ) => {
	return new Promise( async ( resolve, reject ) => {
		const isInstall = operation === 'install';

		if ( ! wp.updates ) {
			reject(
				new Error(
					__( 'WordPress updates API not available.', 'surerank' )
				)
			);
			return;
		}

		// Set the operation function based on the theme or plugin type.
		const itemType = plugin.type === 'theme' ? 'theme' : 'plugin';

		const operationFunction = isInstall
			? wp.updates[
					`install${
						itemType.charAt( 0 ).toUpperCase() + itemType.slice( 1 )
					}`
			  ]
			: wp.ajax.send;

		const data = {
			slug:
				itemType === 'theme' || isInstall
					? plugin.slug
					: `${ plugin.slug }/${ plugin.slug }.php`,
			_ajax_nonce: window.surerank_globals?._ajax_nonce,
		};

		const commonOptions = {
			success: () => resolve( true ),
			error: ( error ) => {
				const errorMessage =
					error?.errorMessage ||
					sprintf(
						// translators: %1$s is the plugin name, %2$s is the operation (installation or activation), %3$s is the error message
						__( '%1$s %2$s failed: %3$s', 'surerank' ),
						plugin.name,
						isInstall
							? __( 'installation', 'surerank' )
							: __( 'activation', 'surerank' ),
						error?.statusText ||
							__( 'Unknown error occurred', 'surerank' )
					);
				reject( new Error( errorMessage ) );
			},
		};

		if ( isInstall ) {
			operationFunction( {
				...data,
				...commonOptions,
			} );
		} else {
			operationFunction( `surerank_activate_${ itemType }`, {
				data,
				...commonOptions,
			} );
		}
	} );
};

export const usePluginsAndThemes = () => {
	const [ installedThemesAndPlugins, setInstalledThemesAndPlugins ] =
		useState( {
			plugins: { installed: [], active: [] },
			themes: { installed: [], active: [] },
		} );
	const [ fetchStatus, setFetchStatus ] = useState( {
		slug: null,
		status: FETCH_STATUS.IDLE,
	} );

	const getProgressStatus = useCallback(
		( item ) => {
			return (
				fetchStatus.slug === item.slug &&
				[ FETCH_STATUS.INSTALLING, FETCH_STATUS.ACTIVATING ].includes(
					fetchStatus.status
				)
			);
		},
		[ fetchStatus ]
	);

	const getPluginStatus = useCallback(
		( item ) => {
			const itemType = item.type === 'theme' ? 'themes' : 'plugins';
			if (
				installedThemesAndPlugins[ itemType ].active.includes(
					item.slug
				)
			) {
				return 'active';
			}
			if (
				installedThemesAndPlugins[ itemType ].installed.includes(
					item.slug
				) &&
				! installedThemesAndPlugins[ itemType ].active.includes(
					item.slug
				)
			) {
				return 'activate';
			}
			return 'install';
		},
		[ installedThemesAndPlugins ]
	);

	const fetchInstalledPluginsAndThemes = async () => {
		try {
			setFetchStatus( ( prev ) => ( {
				...prev,
				status: FETCH_STATUS.LOADING,
			} ) );

			const response = await apiFetch( {
				path: GET_INSTALLED_PLUGINS_AND_THEMES_URL,
			} );

			if ( ! response.success ) {
				throw new Error( response.message );
			}

			const getInstalledAndActiveItems = ( items, type ) => {
				const installed = items
					.map( ( item ) =>
						response.data[ type ].installed.includes( item.slug )
							? item.slug
							: null
					)
					.filter( Boolean );
				const active = items
					.map( ( item ) =>
						response.data[ type ].active.includes( item.slug )
							? item.slug
							: null
					)
					.filter( Boolean );
				return { installed, active };
			};

			const { installed: installedPlugins, active: activePlugins } =
				getInstalledAndActiveItems( themesAndPlugins, 'plugins' );
			const { installed: installedThemes, active: activeThemes } =
				getInstalledAndActiveItems( themesAndPlugins, 'themes' );

			setInstalledThemesAndPlugins( {
				plugins: {
					installed: installedPlugins,
					active: activePlugins,
				},
				themes: {
					installed: installedThemes,
					active: activeThemes,
				},
			} );
		} catch ( error ) {
			toast.error(
				__( 'Failed to fetch plugins and themes', 'surerank' ),
				{
					description:
						error?.message ||
						__( 'Something went wrong', 'surerank' ),
				}
			);
		} finally {
			setFetchStatus( ( prev ) => ( {
				...prev,
				status: FETCH_STATUS.IDLE,
			} ) );
		}
	};

	const handleInstallThemeOrPlugin = async ( plugin ) => {
		if (
			!! fetchStatus.slug &&
			[ FETCH_STATUS.INSTALLING, FETCH_STATUS.ACTIVATING ].includes(
				fetchStatus.status
			)
		) {
			toast.warning(
				__(
					'Another operation is in progress. Please wait.',
					'surerank'
				)
			);
			return;
		}

		const type = plugin.type === 'theme' ? 'themes' : 'plugins';
		const isActive = installedThemesAndPlugins[ type ].active.includes(
			plugin.slug
		);

		if ( isActive ) {
			toast.info(
				sprintf(
					// translators: %1$s is the plugin name
					__(
						'%1$s is already installed and activated.',
						'surerank'
					),
					plugin.name
				)
			);
			return;
		}

		const isInstalled = installedThemesAndPlugins[
			type
		].installed.includes( plugin.slug );
		try {
			if ( ! isInstalled ) {
				setFetchStatus( {
					slug: plugin.slug,
					status: FETCH_STATUS.INSTALLING,
				} );
				await handlePluginAndThemeOperation( plugin, 'install' );
			}

			setFetchStatus( {
				slug: plugin.slug,
				status: FETCH_STATUS.ACTIVATING,
			} );
			await handlePluginAndThemeOperation( plugin, 'activate' );

			setInstalledThemesAndPlugins( ( prev ) => ( {
				...prev,
				[ type ]: {
					installed: isInstalled
						? prev[ type ].installed
						: [ ...prev[ type ].installed, plugin.slug ],
					active: [ ...prev[ type ].active, plugin.slug ],
				},
			} ) );

			toast.success(
				isInstalled
					? sprintf(
							// translators: %1$s is the plugin name
							__( '%1$s activated successfully', 'surerank' ),
							plugin.name
					  )
					: sprintf(
							// translators: %1$s is the plugin name
							__(
								'%1$s installed and activated successfully',
								'surerank'
							),
							plugin.name
					  )
			);
		} catch ( error ) {
			toast.error(
				error.message || __( 'Operation failed', 'surerank' )
			);
		} finally {
			setFetchStatus( {
				slug: null,
				status: FETCH_STATUS.IDLE,
			} );
		}
	};

	const getRecommendedPlugin = useCallback(
		( sequencedPlugins ) => {
			// Remove duplicates
			const uniquePlugins = sequencedPlugins.filter(
				( item, index, self ) =>
					index ===
					self.findIndex( ( plugin ) => plugin.slug === item.slug )
			);

			// Priority 1: Not installed plugins
			const notInstalledPlugin = uniquePlugins.find(
				( item ) => getPluginStatus( item ) === 'install'
			);
			if ( notInstalledPlugin ) {
				return notInstalledPlugin;
			}

			// Priority 2: Installed but inactive plugins
			const inactivePlugin = uniquePlugins.find(
				( item ) => getPluginStatus( item ) === 'activate'
			);
			if ( inactivePlugin ) {
				return inactivePlugin;
			}

			// Priority 3: If all are installed and active, show random one
			const randomPlugin =
				uniquePlugins[
					Math.floor( Math.random() * uniquePlugins.length )
				];
			return randomPlugin || null;
		},
		[ getPluginStatus ]
	);

	return {
		installedThemesAndPlugins,
		fetchStatus,
		fetchInstalledPluginsAndThemes,
		handleInstallThemeOrPlugin,
		getProgressStatus,
		getPluginStatus,
		getRecommendedPlugin,
	};
};