File manager - Edit - /home/vblioqus/dlskitsurl.com/wp-content/plugins/jetpack/_inc/site-switcher.js
Back
/** * Site Switcher for Command Palette * Adds a dynamic "Switch to Site" command that searches across all user's WordPress.com sites * * Requires WordPress 6.9+ for admin-wide command palette support * * @package */ import apiFetch from '@wordpress/api-fetch'; import { useCommandLoader } from '@wordpress/commands'; import { useMemo, useState, useEffect } from '@wordpress/element'; import { sprintf, __ } from '@wordpress/i18n'; import { siteLogo } from '@wordpress/icons'; const userId = window.jetpackSiteSwitcherConfig?.userId || 0; const CACHE_KEY = `jetpack_site_switcher_sites_${ userId }`; const CACHE_DURATION = 3600000; // 1 hour in milliseconds /** * Get cached sites from localStorage */ function getCachedSites() { try { const cached = localStorage.getItem( CACHE_KEY ); if ( ! cached ) { return null; } const { sites, timestamp } = JSON.parse( cached ); // Check if cache is still valid if ( Date.now() - timestamp < CACHE_DURATION ) { return sites; } // Cache expired, remove it localStorage.removeItem( CACHE_KEY ); return null; } catch { // If localStorage is not available or JSON parsing fails, return null return null; } } /** * Save sites to localStorage cache */ function setCachedSites( sites ) { try { localStorage.setItem( CACHE_KEY, JSON.stringify( { sites, timestamp: Date.now(), } ) ); } catch { // Silently fail if localStorage is not available (e.g., private browsing) } } /** * Fetch compact sites list from WordPress.com API */ async function fetchSitesFromWordPressCom() { // Check localStorage cache first const cachedSites = getCachedSites(); if ( cachedSites ) { return cachedSites; } const apiPath = window.jetpackSiteSwitcherConfig?.apiPath; try { const data = await apiFetch( { path: apiPath, method: 'GET', global: true, } ); const sites = data.sites || []; setCachedSites( sites ); return sites; } catch { return []; } } /** * Safely extract hostname from a URL string * * @param {string} urlString - The URL to parse * @return {string} The hostname, or empty string if invalid */ function getHostnameFromURL( urlString ) { if ( ! urlString ) { return ''; } try { return new URL( urlString ).hostname; } catch { return ''; } } /** * Remove trailing slash from a URL string * * @param {string} url - The URL to process * @return {string} URL without trailing slash */ function untrailingslashit( url ) { return url ? url.replace( /\/+$/, '' ) : url; } /** * Escape special regex characters in a string * * @param {string} str - String to escape * @return {string} Escaped string safe for use in RegExp */ function escapeRegex( str ) { return str.replace( /[.*+?^${}()|[\]\\]/g, '\\$&' ); } /** * Custom hook to load site-switching commands based on search term * * @param {Object} props - Hook properties * @param {string} props.search - Search term to filter sites * @return {Object} Object containing commands array and loading state */ function useSiteSwitcherCommandLoader( { search } ) { const [ sites, setSites ] = useState( [] ); const [ isLoading, setIsLoading ] = useState( true ); // Fetch sites on mount useEffect( () => { fetchSitesFromWordPressCom() .then( fetchedSites => { setSites( fetchedSites ); setIsLoading( false ); } ) .catch( () => { setIsLoading( false ); } ); }, [] ); // Generate and filter commands based on search term const commands = useMemo( () => { if ( ! sites || sites.length === 0 ) { return []; } const searchLower = search ? search.toLowerCase() : ''; // Strip generic keywords from search to allow queries like "site dean" to find sites with "dean" const genericKeywords = [ __( 'site', 'jetpack' ).toLowerCase(), __( 'switch', 'jetpack' ).toLowerCase(), __( 'switch site', 'jetpack' ).toLowerCase(), ]; let cleanedSearch = searchLower; genericKeywords.forEach( keyword => { cleanedSearch = cleanedSearch.replace( new RegExp( `\\b${ escapeRegex( keyword ) }\\b`, 'g' ), ' ' ); } ); cleanedSearch = cleanedSearch.trim().replace( /\s+/g, ' ' ); // Check if the search is a prefix of any generic keyword (e.g., "swit" matches "switch") // If so, treat it as a generic search and show all sites const isGenericKeywordPrefix = cleanedSearch && genericKeywords.some( keyword => keyword.startsWith( cleanedSearch ) ); // If search is empty after stripping generic keywords, or is a prefix of a generic keyword, show all sites const filteredSites = ! cleanedSearch || isGenericKeywordPrefix ? sites : sites.filter( site => { const domain = getHostnameFromURL( site.URL ); return ( ( site.name && site.name.toLowerCase().includes( cleanedSearch ) ) || domain.toLowerCase().includes( cleanedSearch ) ); } ); // Filter out sites with invalid URLs (can't navigate to them anyway) const validSites = filteredSites.filter( site => { return site.URL && getHostnameFromURL( site.URL ) !== ''; } ); // Exclude the current site from the list const currentURL = untrailingslashit( window.location.href.toLowerCase() ); const otherSites = validSites.filter( site => { // Normalize site URL for comparison const siteURL = untrailingslashit( site.URL.toLowerCase() ); // Check if current URL starts with site URL (handles multisite subdirectory installs) // e.g., current: example.com/site1/wp-admin matches site: example.com/site1 return ! currentURL.startsWith( siteURL ); } ); return otherSites.map( site => { // Extract domain from URL for display - don't want to display the protocol. const domain = getHostnameFromURL( site.URL ); const iconElement = site.icon?.img ? <img src={ site.icon.img } alt="" /> : siteLogo; // Use site name if available, otherwise just show domain const label = site.name ? sprintf( /* translators: %1$s: site name, %2$s: site domain */ __( 'Switch to %1$s (%2$s)', 'jetpack' ), site.name, domain ) : sprintf( /* translators: %s: site domain */ __( 'Switch to %s', 'jetpack' ), domain ); return { name: `jetpack/switch-to-site-${ domain }`, label, icon: iconElement, callback: ( { close } ) => { try { window.location.href = new URL( '/wp-admin', site.URL ).href; } catch { // If URL is malformed, don't navigate } close(); }, keywords: [ site.name, domain, __( 'site', 'jetpack' ), __( 'switch site', 'jetpack' ), ].filter( Boolean ), }; } ); }, [ sites, search ] ); return { commands, isLoading, }; } /** * Component that registers the site switcher command loader */ function JetpackSiteSwitcher() { useCommandLoader( { name: 'jetpack/site-switcher', hook: useSiteSwitcherCommandLoader, } ); return null; } // Render the site switcher into wp-admin // This works with WordPress 6.9+ admin-wide command palette if ( typeof window !== 'undefined' && window.wp && window.wp.element && window.wp.commands ) { const { createRoot, createElement } = window.wp.element; // Create a container for our site switcher const container = document.createElement( 'div' ); container.id = 'jetpack-site-switcher'; container.style.display = 'none'; // Hidden, as we only need the hooks to run // Wait for DOM to be ready if ( document.readyState === 'loading' ) { document.addEventListener( 'DOMContentLoaded', () => { document.body.appendChild( container ); createRoot( container ).render( createElement( JetpackSiteSwitcher ) ); } ); } else { document.body.appendChild( container ); createRoot( container ).render( createElement( JetpackSiteSwitcher ) ); } }
| ver. 1.4 |
Github
|
.
| PHP 8.2.30 | Generation time: 0 |
proxy
|
phpinfo
|
Settings