HEX
Server: nginx
System: Linux pool195-106-36.bur.atomicsites.net 6.12.57+deb12-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.57-1~bpo12+1 (2025-11-17) x86_64
User: (0)
PHP: 8.3.32
Disabled: pcntl_fork
Upload Files
File: /wordpress/plugins/wp-cloud-client/1.2.2/src/Handler/CheckPluginUpdatesHandler.php
<?php

declare(strict_types=1);

namespace VPlugins\WPCloudClient\Handler;

/**
 * Checks for available updates for WordPress plugins.
 *
 * Action name: check_plugin_updates
 *
 * Optional params:
 *   - slug (string) - Specific plugin slug to check (e.g., "woocommerce/woocommerce").
 *                     If not provided, checks all installed plugins for updates.
 *
 * Example response for specific plugin:
 * {
 *   "has_updates": true,
 *   "updates": [
 *     {
 *       "slug": "woocommerce/woocommerce",
 *       "name": "WooCommerce",
 *       "current_version": "8.0.0",
 *       "new_version": "8.1.0",
 *       "download_url": "https://...",
 *       "requires_wp": "6.0",
 *       "requires_php": "7.4"
 *     }
 *   ]
 * }
 */
final class CheckPluginUpdatesHandler extends AbstractHandler {

	/**
	 * Return the action name.
	 *
	 * @return string
	 */
	public function action(): string {
		return 'check_plugin_updates';
	}

	/**
	 * Check for plugin updates.
	 *
	 * @param array<string, mixed> $params Action parameters.
	 * @return array<string, mixed> Update status.
	 * @throws \InvalidArgumentException When required parameters are invalid.
	 */
	public function execute( array $params ): array {
		$slug = isset( $params['slug'] ) ? (string) $params['slug'] : null;

		if ( null !== $slug && empty( $slug ) ) {
			throw new \InvalidArgumentException( 'Plugin slug cannot be empty.' );
		}

		// Get the plugin update transient.
		$transient = get_site_transient( 'update_plugins' );
		$updates   = [];

		if ( null !== $slug ) {
			// Check specific plugin.
			$pluginData = $this->getPluginData( $slug );
			if ( null === $pluginData ) {
				throw new \InvalidArgumentException( sprintf( 'Plugin "%s" not found.', $slug ) );
			}

			if ( $this->hasUpdate( $transient, $slug ) ) {
				$updateData = $this->extractUpdateInfo( $slug, $pluginData, $transient );
				if ( null !== $updateData ) {
					$updates[] = $updateData;
				}
			}
		} else {
			// Check all plugins.
			$pluginsData = get_plugins();

			foreach ( $pluginsData as $pluginFile => $pluginInfo ) {
				if ( $this->hasUpdate( $transient, $pluginFile ) ) {
					$updateData = $this->extractUpdateInfo( $pluginFile, $pluginInfo, $transient );
					if ( null !== $updateData ) {
						$updates[] = $updateData;
					}
				}
			}
		}

		return [
			'has_updates' => ! empty( $updates ),
			'updates'     => $updates,
		];
	}

	/**
	 * Get plugin data by slug.
	 *
	 * @param string $slug Plugin slug (e.g., "woocommerce/woocommerce" or "hello-dolly/hello").
	 * @return array<string, mixed>|null Plugin data or null if not found.
	 */
	private function getPluginData( string $slug ): ?array {
		$plugins = get_plugins();

		foreach ( $plugins as $pluginFile => $pluginInfo ) {
			if ( $pluginFile === $slug ) {
				return $pluginInfo;
			}
		}

		return null;
	}

	/**
	 * Check if a plugin has an available update.
	 *
	 * @param mixed  $transient Update transient object.
	 * @param string $slug      Plugin slug.
	 * @return bool True if update is available.
	 */
	private function hasUpdate( $transient, string $slug ): bool {
		if ( ! is_object( $transient ) || ! isset( $transient->response ) ) {
			return false;
		}

		if ( ! is_array( $transient->response ) && ! is_object( $transient->response ) ) {
			return false;
		}

		return isset( $transient->response[ $slug ] );
	}

	/**
	 * Extract update information from transient.
	 *
	 * @param string               $slug        Plugin slug.
	 * @param array<string, mixed> $pluginInfo  Current plugin info.
	 * @param mixed                $transient   Update transient.
	 * @return array<string, mixed>|null Extracted update info or null.
	 */
	private function extractUpdateInfo( string $slug, array $pluginInfo, $transient ): ?array {
		if ( ! is_object( $transient ) || ! isset( $transient->response[ $slug ] ) ) {
			return null;
		}

		$updateData = $transient->response[ $slug ];

		$currentVersion = $pluginInfo['Version'] ?? 'unknown';
		$newVersion     = $updateData->new_version ?? '';
		$name           = $pluginInfo['Name'] ?? $slug;

		return [
			'slug'            => $slug,
			'name'            => $name,
			'current_version' => $currentVersion,
			'new_version'     => $newVersion,
			'download_url'    => $updateData->package ?? '',
			'requires_wp'     => $updateData->requires ?? '',
			'requires_php'    => $updateData->requires_php ?? '',
			'tested_up_to'    => $updateData->tested ?? '',
			'plugin_url'      => $updateData->url ?? '',
		];
	}
}