__  __    __   __  _____      _            _          _____ _          _ _ 
 |  \/  |   \ \ / / |  __ \    (_)          | |        / ____| |        | | |
 | \  / |_ __\ V /  | |__) | __ ___   ____ _| |_ ___  | (___ | |__   ___| | |
 | |\/| | '__|> <   |  ___/ '__| \ \ / / _` | __/ _ \  \___ \| '_ \ / _ \ | |
 | |  | | |_ / . \  | |   | |  | |\ V / (_| | ||  __/  ____) | | | |  __/ | |
 |_|  |_|_(_)_/ \_\ |_|   |_|  |_| \_/ \__,_|\__\___| |_____/|_| |_|\___V 2.1
 if you need WebShell for Seo everyday contact me on Telegram
 Telegram Address : @jackleet
        
        
For_More_Tools: Telegram: @jackleet | Bulk Smtp support mail sender | Business Mail Collector | Mail Bouncer All Mail | Bulk Office Mail Validator | Html Letter private



Upload:

Command:

[email protected]: ~ $
<?php

namespace WPForms\Pro\Admin;

// phpcs:disable WPForms.PHP.UseStatement.UnusedUseStatement
use WP_Plugins_List_Table;
use stdClass;
use WPForms\Admin\Addons\AddonsCache;
// phpcs:enable WPForms.PHP.UseStatement.UnusedUseStatement

/**
 * Class PluginList.
 *
 * Notice displayed in the Plugins page for Pro users.
 *
 * @since 1.8.6
 */
class PluginList {

	/**
	 * License Statuses.
	 *
	 * @since 1.8.6
	 * @since 1.9.5 Added new `limit_reached` and `flagged` statuses.
	 */
	const LICENSE_STATUS_EMPTY         = 'empty';
	const LICENSE_STATUS_VALID         = 'valid';
	const LICENSE_STATUS_EXPIRED       = 'expired';
	const LICENSE_STATUS_DISABLED      = 'disabled';
	const LICENSE_STATUS_INVALID       = 'invalid';
	const LICENSE_STATUS_LIMIT_REACHED = 'limit_reached';
	const LICENSE_STATUS_FLAGGED       = 'flagged';

	/**
	 * Plugin slug.
	 *
	 * @since 1.8.6
	 *
	 * @var string
	 */
	private $plugin_slug;

	/**
	 * Plugin path (relative to the plugins' dir).
	 *
	 * @since 1.8.6
	 *
	 * @var string
	 */
	private $plugin_path;

	/**
	 * The license status.
	 *
	 * @since 1.8.6
	 *
	 * @var string|null
	 */
	private $license_status;

	/**
	 * The latest version fetched from a remote source.
	 *
	 * @since 1.8.6
	 *
	 * @var null|string
	 */
	private $remote_latest_version;

	/**
	 * Whether this site is using the latest version of WPForms Pro.
	 *
	 * @since 1.8.6
	 *
	 * @var bool
	 */
	private $is_using_latest_version;

	/**
	 * Internal set_site_transient_update_addons cache.
	 *
	 * @since 1.9.0
	 *
	 * @var object|null
	 */
	private $update_addons_cache;

	/**
	 * Instance of AddonsCache.
	 *
	 * @since 1.9.0
	 *
	 * @var AddonsCache|null
	 */
	private $addons_cache_obj;

	/**
	 * Init.
	 *
	 * @since 1.8.6
	 *
	 * @return void
	 */
	public function init() {

		$this->plugin_slug      = defined( 'WPFORMS_PLUGIN_DIR' ) ? plugin_basename( WPFORMS_PLUGIN_DIR ) : 'wpforms';
		$this->plugin_path      = $this->plugin_slug . '/wpforms.php';
		$this->addons_cache_obj = wpforms()->obj( 'addons_cache' );

		( new PluginListDisabler() )->init( $this->is_valid_license() );

		$this->hooks();
	}

	/**
	 * Register hooks.
	 *
	 * @since 1.8.6
	 *
	 * @return void
	 */
	private function hooks() {

		global $pagenow;

		if ( empty( $pagenow ) || $pagenow !== 'plugins.php' ) {
			return;
		}

		add_action( 'admin_init', [ $this, 'update_addons_cache' ] );
		add_filter( 'site_transient_update_plugins', [ $this, 'site_transient_update_addons' ] );
		add_filter( 'set_site_transient_update_plugins', [ $this, 'set_site_transient_update_addons' ] );
		add_action( 'admin_head', [ $this, 'add_style' ] );
		add_action( "after_plugin_row_{$this->plugin_path}", [ $this, 'show_plugin_notice' ], 0 );
	}

	/**
	 * Update addons cache.
	 *
	 * @since 1.9.0
	 *
	 * @return void
	 */
	public function update_addons_cache() {

		if ( $this->addons_cache_obj ) {
			$this->addons_cache_obj->update();
		}
	}

	/**
	 * Add CSS styles.
	 *
	 * @since 1.8.6
	 *
	 * @return void
	 */
	public function add_style() {

		printf(
			'<style>
				#wpforms-update td.plugin-update {
					box-shadow: 0 1px 0 0 rgba(0,0,0,.1);
					transform: translateY(-1px);
				}

				.plugins tr.update[data-slug="%1$s"] .second,
				.plugins tr.update[data-slug="%1$s"] .row-actions {
					padding-bottom: 0;
				}

				.wpforms-wrong-license {
					color: #dc3232;
					font-weight: bold;
				}

				@media screen and (max-width: 782px) {
					.plugins tr[data-slug="%1$s"].plugin-update-tr.active:before {
						background-color: #f0f6fc;
						border-left: 4px solid #72aee6;
					}

					.plugins .plugin-update-tr .wpforms-update-message {
						margin-left: 0;
					}
				}
			</style>',
			esc_attr( $this->plugin_slug )
		);
	}

	/**
	 * Filters `update_plugins` transient in Admin Plugins page.
	 *
	 * This method removes the "update" of the Pro plugin.
	 * Doing this fixes the edge case where both the default WP plugin update notice
	 * and our custom notice is displayed at the same time.
	 *
	 * @since 1.8.6
	 * @deprecated 1.9.0
	 *
	 * @param mixed $value Value of site transient.
	 *
	 * @return object $value Amended WordPress update object.
	 */
	public function site_transient_update_plugins( $value ) {

		// We don't need current method anymore.
		_deprecated_function( __METHOD__, '1.9.0 of the WPForms plugin' );

		return $value;
	}

	/**
	 * Filters `update_plugins` transient in Admin Plugins page.
	 *
	 * This method checks available addon updates.
	 *
	 * @since 1.9.0
	 *
	 * @param mixed $value Value of site transient.
	 *
	 * @return object $value Amended WordPress update object.
	 */
	public function site_transient_update_addons( $value ) {  // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks, Generic.Metrics.CyclomaticComplexity.TooHigh

		global $current_screen;

		// We only want this filter in the Dashboard -> Plugins page.
		if ( is_null( $current_screen ) || $current_screen->id !== 'plugins' ) {
			return $value;
		}

		if ( $this->update_addons_cache !== null ) {
			return $this->update_addons_cache;
		}

		if ( ! is_object( $value ) ) {
			$value = new stdClass();
		}

		$addons = $this->addons_cache_obj ? $this->addons_cache_obj->get() : [];

		/**
		 * Filter the addons list cache.
		 *
		 * @since 1.9.2
		 *
		 * @param array $addons Addons list cache.
		 */
		$addons = apply_filters( 'wpforms_pro_admin_list_addons_cache', $addons );

		foreach ( get_plugins() as $name => $plugin ) {
			$slug = explode( '/', $name )[0];

			if ( ! array_key_exists( $slug, $addons ) ) {
				continue;
			}

			$addon = $addons[ $slug ];

			if ( version_compare( $plugin['Version'], $addon['version'], '<' ) ) {
				// Do not set 'slug' here, only 'url', to form $details_url in after_plugin_row() properly.
				$url = add_query_arg(
					[
						'utm_source'   => 'WordPress',
						'utm_campaign' => 'plugin',
						'utm_medium'   => 'addons',
						'utm_content'  => $addon['title'],
					],
					$addon['url']
				);

				$icon_url = WPFORMS_PLUGIN_URL . 'assets/images/' . ( $addon['icon'] ?? 'sullie.png' );
				$icons    = [
					'1x'      => $icon_url,
					'2x'      => $icon_url,
					'default' => $icon_url,
				];

				$value->response[ $name ] = (object) [
					'id'               => $addon['id'],
					'plugin'           => $name,
					'version'          => $plugin['Version'],
					'new_version'      => $addon['version'] ?? $plugin['Version'],
					'url'              => $url,
					'package'          => $value->response[ $name ]->package ?? '',
					'icons'            => $icons,
					'banners'          => [],
					'banners_rtl'      => [],
					'requires'         => $addon['required_versions']['wp'] ?? '5.5',
					'requires_php'     => $addon['required_versions']['php'] ?? '7.2',
					'requires_wpforms' => $addon['required_versions']['wpforms'] ?? WPFORMS_VERSION,
					'requires_plugin'  => 'wpforms/wpforms.php',
				];
			}

			add_action( "after_plugin_row_{$name}", [ $this, 'after_plugin_row' ], 0, 2 );
		}

		$this->update_addons_cache = $value;

		return $value;
	}

	/**
	 * Set site transient update plugins action.
	 *
	 * Method site_transient_update_addons() is called multiple times,
	 * so we cache it's result internally in this class.
	 *
	 * On set_transient_update_plugins action, we flush internal caches.
	 *
	 * @since 1.9.0
	 *
	 * @return void
	 */
	public function set_site_transient_update_addons() {

		$this->update_addons_cache = null;
	}

	/**
	 * Displays update information for a plugin.
	 * Form of the wp_plugin_update_row().
	 *
	 * @since 1.9.0
	 *
	 * @param string $file        Plugin basename.
	 * @param array  $plugin_data Plugin information.
	 *
	 * @return void|false
	 * @noinspection HtmlUnknownAttribute
	 */
	public function after_plugin_row( string $file, array $plugin_data ) {  // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks, Generic.Metrics.CyclomaticComplexity.TooHigh

		// Remove WP Core action, as we override its functionality for the plugin.
		remove_action( "after_plugin_row_{$file}", 'wp_plugin_update_row' );

		$current = get_site_transient( 'update_plugins' );

		if ( ! isset( $current->response[ $file ] ) ) {
			return false;
		}

		$response = $current->response[ $file ];

		$plugins_allowed_tags = [
			'a'       => [
				'href'  => [],
				'title' => [],
			],
			'abbr'    => [ 'title' => [] ],
			'acronym' => [ 'title' => [] ],
			'code'    => [],
			'em'      => [],
			'strong'  => [],
		];

		$plugin_name   = wp_kses( $plugin_data['Name'], $plugins_allowed_tags );
		$plugin_chunks = explode( '/', $file );
		$plugin_slug   = $plugin_chunks[0] ?? $response->id;

		// We need to remove wordpress.com filter to get proper self_admin_url here.
		$wp_com_priority = has_filter( 'self_admin_url', 'wpcomsh_update_plugin_link_destination' );

		if ( $wp_com_priority ) {
			remove_filter( 'self_admin_url', 'wpcomsh_update_plugin_link_destination' );
		}

		$details_url = add_query_arg(
			[
				'tab'       => 'plugin-information',
				'plugin'    => $plugin_slug,
				'section'   => 'changelog',
				'TB_iframe' => 'true',
				'width'     => 772,
				'height'    => 771,
			],
			self_admin_url( 'plugin-install.php' )
		);

		// Restore wordpress.com filter.
		if ( $wp_com_priority ) {
			add_filter( 'self_admin_url', 'wpcomsh_update_plugin_link_destination', $wp_com_priority, 2 );
		}

		/**
		 * WP List Table.
		 *
		 * @var WP_Plugins_List_Table $wp_list_table
		 */
		$wp_list_table = _get_list_table(
			'WP_Plugins_List_Table',
			[
				'screen' => get_current_screen(),
			]
		);

		if ( ! is_network_admin() && is_multisite() ) {
			return;
		}

		if ( is_network_admin() ) {
			$active_class = is_plugin_active_for_network( $file ) ? ' active' : '';
		} else {
			$active_class = is_plugin_active( $file ) ? ' active' : '';
		}

		$requires_php     = $response->requires_php ?? '';
		$requires_wp      = $response->requires ?? '';
		$requires_wpforms = $response->requires_wpforms ?? '';

		$compatible['php']     = is_php_version_compatible( $requires_php ) ? true : 'PHP ' . $requires_php;
		$compatible['wp']      = is_wp_version_compatible( $requires_wp ) ? true : 'WordPress ' . $requires_wp;
		$compatible['wpforms'] = self::is_wpforms_version_compatible( $requires_wpforms ) ? true : 'WPForms ' . $requires_wpforms;

		$notice_type = 'notice-warning';

		foreach ( $compatible as $value ) {
			if ( $value !== true ) {
				$notice_type = 'notice-error';

				break;
			}
		}

		printf(
			'<tr class="plugin-update-tr%s" id="%s" data-slug="%s" data-plugin="%s">
				<td colspan="%s" class="plugin-update colspanchange">
				<div class="wpforms-update-message update-message notice inline %s notice-alt"><p>',
			esc_attr( $active_class ),
			esc_attr( $plugin_slug . '-update' ),
			esc_attr( $plugin_slug ),
			esc_attr( $file ),
			esc_attr( $wp_list_table->get_column_count() ),
			esc_attr( $notice_type )
		);

		$this->print_addon_update_message( $plugin_name, $details_url, $response, $compatible, $file );

		/**
		 * Fires at the end of the update message container in each
		 * row of the plugins' list table.
		 *
		 * The dynamic portion of the hook name, `$file`, refers to the path
		 * of the plugin's primary file relative to the plugins' directory.
		 *
		 * @since 2.8.0
		 *
		 * @param array   $plugin_data      An array of plugin metadata. See get_plugin_data()
		 *                                  and the {@see 'plugin_row_meta'} filter for the list
		 *                                  of possible values.
		 * @param object  $response         {
		 *                                  An object of metadata about the available plugin update.
		 *
		 * @type string   $id               Plugin ID, e.g. `w.org/plugins/[plugin-name]`.
		 * @type string   $slug             Plugin slug.
		 * @type string   $plugin           Plugin basename.
		 * @type string   $new_version      New plugin version.
		 * @type string   $url              Plugin URL.
		 * @type string   $package          Plugin update package URL.
		 * @type string[] $icons            An array of plugin icon URLs.
		 * @type string[] $banners          An array of plugin banner URLs.
		 * @type string[] $banners_rtl      An array of plugin RTL banner URLs.
		 * @type string   $requires         The version of WordPress which the plugin requires.
		 * @type string   $tested           The version of WordPress the plugin is tested against.
		 * @type string   $requires_php     The version of PHP which the plugin requires.
		 * @type string   $requires_wp      The version of WP which the plugin requires.
		 * @type string   $requires_wpforms The version of WPForms which the plugin requires.
		 *                                  }
		 */
		do_action( "in_plugin_update_message-{$file}", $plugin_data, $response ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName, WordPress.NamingConventions.ValidHookName.UseUnderscores

		echo '</p></div></td></tr>';
	}

	/**
	 * Get the license status.
	 *
	 * @since 1.8.6
	 *
	 * @return string
	 */
	private function get_license_status(): string {

		if ( ! is_null( $this->license_status ) ) {
			return $this->license_status;
		}

		$license_type = wpforms_get_license_type();
		$license_key  = wpforms_get_license_key();

		$this->license_status = self::LICENSE_STATUS_VALID;

		if ( empty( $license_key ) || empty( $license_type ) ) {
			$this->license_status = self::LICENSE_STATUS_EMPTY;

			return $this->license_status;
		}

		$this->license_status = wpforms_setting( 'is_expired', false, 'wpforms_license' ) ?
			self::LICENSE_STATUS_EXPIRED :
			$this->license_status;
		$this->license_status = wpforms_setting( 'is_disabled', false, 'wpforms_license' ) ?
			self::LICENSE_STATUS_DISABLED :
			$this->license_status;
		$this->license_status = wpforms_setting( 'is_invalid', false, 'wpforms_license' ) ?
			self::LICENSE_STATUS_INVALID :
			$this->license_status;
		$this->license_status = wpforms_setting( 'is_limit_reached', false, 'wpforms_license' ) ?
			self::LICENSE_STATUS_LIMIT_REACHED :
			$this->license_status;
		$this->license_status = wpforms_setting( 'is_flagged', false, 'wpforms_license' ) ?
			self::LICENSE_STATUS_FLAGGED :
			$this->license_status;

		return $this->license_status;
	}

	/**
	 * Check if the license is valid.
	 *
	 * @since 1.9.0
	 *
	 * @return bool
	 */
	public function is_valid_license(): bool {

		return $this->get_license_status() === self::LICENSE_STATUS_VALID;
	}

	/**
	 * Adds custom plugin notice for Pro users without a valid license.
	 *
	 * @since 1.8.6
	 *
	 * @param string $plugin_file Path to the plugin file relative to the `plugins` directory.
	 *
	 * @return void
	 */
	public function show_plugin_notice( string $plugin_file ) { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks

		if ( $plugin_file !== $this->plugin_path ) {
			return;
		}

		// Remove WP Core action, as we override its functionality for the plugin.
		remove_action( "after_plugin_row_{$plugin_file}", 'wp_plugin_update_row' );

		$update_notice = $this->get_update_notice();

		if ( empty( $update_notice ) ) {
			return;
		}

		global $wp_list_table;

		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		echo wpforms_render(
			'admin/plugins-list/update-notice',
			[
				'plugin_slug'   => $this->plugin_slug,
				'plugin_path'   => $this->plugin_path,
				'columns_count' => empty( $wp_list_table ) ? 4 : $wp_list_table->get_column_count(),
				'update_notice' => $update_notice,
			],
			true
		);
	}

	/**
	 * Get the update notice.
	 *
	 * @since 1.8.6
	 *
	 * @return string
	 */
	private function get_update_notice(): string {

		$status = $this->get_license_status();

		if ( $status === self::LICENSE_STATUS_VALID ) {
			return $this->is_using_latest_version() ? '' : $this->get_new_version_available_notice();
		}

		return $status === self::LICENSE_STATUS_EMPTY ?
			$this->get_no_license_notice() :
			$this->get_wrong_license_notice( $status );
	}

	/**
	 * Get the notice for users without a license key.
	 *
	 * @since 1.8.6
	 *
	 * @return string
	 * @noinspection HtmlUnknownTarget
	 */
	private function get_no_license_notice(): string {

		$activate_url = add_query_arg( [ 'page' => 'wpforms-settings' ], admin_url( 'admin.php' ) );
		$purchase_url = wpforms_utm_link( 'https://wpforms.com/pricing/', 'no license', 'purchase one now' );

		if ( $this->is_using_latest_version() ) {
			return sprintf( /* translators: %1$s - WPForms Pro URL; %2$s - WPForms Pro purchase link. */
				__(
					'<a href="%1$s">Activate WPForms Pro</a> to receive features, updates, and support. Don\'t have a license? <a target="_blank" href="%2$s" rel="noopener noreferrer">Purchase one now</a>.',
					'wpforms'
				),
				esc_url( $activate_url ),
				esc_url( $purchase_url )
			);
		}

		return $this->get_new_version_available_notice()
			. '<br />'
			. sprintf( /* translators: %1$s - WPForms Pro URL; %2$s - WPForms Pro purchase link. */
				__(
					'<a href="%1$s">Activate</a> your license to access this update, new features, and support. Don\'t have a license? <a target="_blank" href="%2$s" rel="noopener noreferrer">Purchase one now</a>.',
					'wpforms'
				),
				esc_url( $activate_url ),
				esc_url( $purchase_url )
			);
	}

	/**
	 * Get the notice for users with expired license key.
	 *
	 * @since 1.8.6
	 *
	 * @param string $status License status.
	 *
	 * @return string
	 * @noinspection HtmlUnknownTarget
	 */
	private function get_wrong_license_notice( string $status ): string {

		$message = $this->is_using_latest_version() ? '' : $this->get_new_version_available_notice() . '<br>';

		$status_messages = [
			self::LICENSE_STATUS_EXPIRED       => esc_html__( 'Your WPForms Pro license is expired.', 'wpforms' ),
			self::LICENSE_STATUS_DISABLED      => esc_html__( 'Your WPForms Pro license is disabled.', 'wpforms' ),
			self::LICENSE_STATUS_INVALID       => esc_html__( 'Your WPForms Pro license is invalid.', 'wpforms' ),
			self::LICENSE_STATUS_LIMIT_REACHED => esc_html__( 'Your WPForms Pro license has no activations left.', 'wpforms' ),
			self::LICENSE_STATUS_FLAGGED       => esc_html__( 'Your WPForms Pro license needs support.', 'wpforms' ),
		];

		$status_message = $status_messages[ $status ] ?? '';

		if ( $status === self::LICENSE_STATUS_FLAGGED ) {
			$flagged_msg = sprintf( /* translators: %s - WPForms Pro key support link. */
				__(
					'Before you can activate this key, we\'d like to check in with you. Please <a href="%1$s" target="_blank" rel="noopener noreferrer">reach out to support here.</a>',
					'wpforms'
				),
				esc_url( wpforms_utm_link( 'https://wpforms.com/account/key-support/', 'all-plugins', 'Verify Key - Reach out to Support' ) )
			);

			return "$message<span class='wpforms-wrong-license'>$status_message</span> $flagged_msg";
		}

		$renew_msg = sprintf( /* translators: %s - WPForms Pro renew link. */
			__(
				'<a target="_blank" href="%1$s" rel="noopener noreferrer">Renew now</a> to receive new features, updates, and support.',
				'wpforms'
			),
			esc_url( wpforms_utm_link( 'https://wpforms.com/account/licenses/', 'plugins list expired license', 'WPForms' ) )
		);

		return "$message<span class='wpforms-wrong-license'>$status_message</span> $renew_msg";
	}

	/**
	 * Get the notice to show when a new version of WPForms Pro is available.
	 *
	 * @since 1.8.6
	 *
	 * @return string
	 * @noinspection HtmlUnknownTarget
	 */
	private function get_new_version_available_notice(): string {

		$details_url =
			self_admin_url( 'plugin-install.php?tab=plugin-information&plugin=wpforms&section=changelog&TB_iframe=true&width=772&height=771' );

		$upgrade_url = wp_nonce_url(
			self_admin_url( 'update.php?action=upgrade-plugin&plugin=' . $this->plugin_path ),
			'upgrade-plugin_' . $this->plugin_path
		);
		$new_version = $this->get_latest_version();

		// Message without "update now" link.
		$new_version_message = sprintf( /* translators: %1$s - WPForms Pro Changelog link; %2$s - WPForms Pro latest version. */
			__(
				'There is a new version of WPForms available. <a class="thickbox open-plugin-details-modal" href="%1$s" rel="noopener noreferrer">View version %2$s details</a>',
				'wpforms'
			),
			esc_url( $details_url ),
			esc_html( $new_version )
		);

		if ( $this->get_license_status() !== self::LICENSE_STATUS_VALID ) {
			return $new_version_message . '.';
		}

		// Message with "update now" link.
		return $new_version_message . ' ' .
			sprintf( /* translators: %1$s - WPForms Pro upgrade URL; %2$s - Update now link aria-label attribute. */
				__(
					'or <a href="%1$s" class="update-link" aria-label="%2$s">update now</a>.',
					'wpforms'
				),
				esc_url( $upgrade_url ),
				esc_attr__( 'Update Now', 'wpforms' )
			);
	}

	/**
	 * Whether this site is using the latest version of WPForms Pro.
	 *
	 * @since 1.8.6
	 *
	 * @return bool
	 */
	private function is_using_latest_version(): bool {

		if ( ! is_null( $this->is_using_latest_version ) ) {
			return $this->is_using_latest_version;
		}

		$this->is_using_latest_version = version_compare( WPFORMS_VERSION, $this->get_latest_version(), '>=' );

		return $this->is_using_latest_version;
	}

	/**
	 * Get the latest version.
	 *
	 * @since 1.8.6
	 *
	 * @return string
	 */
	private function get_latest_version() {

		if ( ! is_null( $this->remote_latest_version ) ) {
			return $this->remote_latest_version;
		}

		// WP core updates this transient.
		// We use it to get the latest version of WPForms Pro.
		// We have a hook on `pre_set_site_transient_update_plugins` in the `WPForms_Updater` class
		// that checks the remote API and adds the update for WPForms Pro to this transient.
		$transient = get_site_transient( 'update_plugins' );

		$this->remote_latest_version = $transient->response[ $this->plugin_path ]->new_version ?? WPFORMS_VERSION;

		return $this->remote_latest_version;
	}

	/**
	 * Print addon update message.
	 *
	 * @since 1.9.0
	 *
	 * @param string $plugin_name Plugin name.
	 * @param string $details_url Details URL.
	 * @param object $response    Response.
	 * @param array  $compatible  Compatibility array.
	 * @param string $file        Filename.
	 *
	 * @return void
	 * @noinspection HtmlUnknownTarget
	 * @noinspection HtmlUnknownAttribute
	 */
	public function print_addon_update_message( string $plugin_name, string $details_url, $response, array $compatible, string $file ) {

		$link_attr = sprintf(
			'class="thickbox open-plugin-details-modal" aria-label="%s"',
			esc_attr(
				sprintf(
					/* translators: 1: Plugin name, 2: Version number. */
					__( 'View %1$s version %2$s details', 'wpforms' ),
					$plugin_name,
					$response->new_version
				)
			)
		);

		// Prepare incompatible components.
		$incompatible = [];

		foreach ( $compatible as $key => $value ) {
			if ( $value !== true ) {
				$incompatible[ $key ] = $value;
			}
		}

		// Compatible updates.
		if ( empty( $incompatible ) ) {
			$this->print_addon_compatible_update_message( $plugin_name, $details_url, $response, $link_attr, $file );

			return;
		}

		// Incompatible updates available.

		// Details URL with disabled update button.
		$details_url = add_query_arg(
			[
				'update'    => 'disabled',
				'TB_iframe' => 'true',
				'width'     => 772,
				'height'    => 771,
			],
			// Remove query args that is added after `update=disabled`.
			// This is necessary because WP removes everything from URL after `TB_iframe=true&width=772&height=771`.
			remove_query_arg( [ 'TB_iframe', 'width', 'height' ], $details_url )
		);

		$available = wp_kses(
			sprintf(
				/* translators: 1: Plugin name, 2: Details URL, 3: Link attributes, 4: Version number, 5: Components. */
				__(
					'Sorry, the %1$s addon can\'t be updated to <a href="%2$s" %3$s>version %4$s</a> because it requires %5$s.',
					'wpforms'
				),
				esc_html( $plugin_name ),
				esc_url( $details_url ),
				$link_attr,
				esc_html( $response->new_version ),
				wpforms_list_array( $incompatible )
			),
			[
				'a' => [
					'href'       => [],
					'class'      => [],
					'aria-label' => [],
				],
			]
		);

		$check_updates = wp_kses(
			sprintf( /* translators: 1: Details URL, 2: Additional link attributes, 3: Version number. */
				__( 'If no update is available, try <a href="%1$s">checking for new plugin updates</a>.', 'wpforms' ),
				esc_url( admin_url( 'update-core.php' ) )
			),
			[
				'a' => [
					'href' => [],
				],
			]
		);

		$php_update = '';

		if ( ! empty( $incompatible['php'] ) ) {
			$php_update = sprintf(
				wp_kses(
					/* translators: 1:URL to Update PHP page. */
					__( 'Learn more about <a href="%1$s" target="_blank" rel="noopener noreferrer">updating PHP</a>.', 'wpforms' ),
					[
						'a' => [
							'href'   => [],
							'target' => [],
							'rel'    => [],
						],
					]
				),
				esc_url( wp_get_update_php_url() )
			);
		}

		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		echo $available . ' ' . $check_updates . ' ' . $php_update;

		wp_update_php_annotation( '<br><em>', '</em>' );
	}

	/**
	 * Print addon compatible update message.
	 *
	 * @since 1.9.0
	 *
	 * @param string $plugin_name Plugin name.
	 * @param string $details_url Details URL.
	 * @param object $response    Response.
	 * @param string $link_attr   Additional link attributes.
	 * @param string $file        Filename.
	 *
	 * @return void
	 * @noinspection HtmlUnknownTarget
	 * @noinspection HtmlUnknownAttribute
	 */
	public function print_addon_compatible_update_message( string $plugin_name, string $details_url, $response, string $link_attr, string $file ) {

		$update_now = '';

		if ( $this->is_valid_license() && current_user_can( 'update_plugins' ) ) {
			$update_now = sprintf(
				' or <a href="%1$s" %2$s>update now</a>',
				esc_url( wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $file, 'upgrade-plugin_' . $file ) ),
				sprintf(
					'class="update-link" aria-label="%s"',
					/* translators: %s: Plugin name. */
					esc_attr( sprintf( __( 'Update %s now', 'wpforms' ), $plugin_name ) )
				)
			);
		}

		echo wp_kses(
			sprintf(
				/* translators: 1: Plugin name, 2: Details URL, 3: Additional link attributes, 4: Version number, 5: Update URL, 6: Additional link attributes. */
				__(
					'There is a new version of %1$s available. <a href="%2$s" %3$s>View version %4$s details</a>%5$s.',
					'wpforms'
				),
				$plugin_name,
				esc_url( $details_url ),
				$link_attr,
				esc_attr( $response->new_version ),
				$update_now
			),
			[
				'a' => [
					'href'       => [],
					'class'      => [],
					'aria-label' => [],
				],
			]
		);
	}

	/**
	 * Checks compatibility with the current WPForms version.
	 *
	 * @since 1.9.0
	 *
	 * @param string $required Minimum required WPForms version.
	 *
	 * @return bool True if a required version is compatible or empty, false if not.
	 */
	public static function is_wpforms_version_compatible( string $required ): bool {

		return empty( $required ) || version_compare( WPFORMS_VERSION, $required, '>=' );
	}
}

Filemanager

Name Type Size Permission Actions
Addons Folder 0750
Builder Folder 0750
Education Folder 0750
Entries Folder 0750
Pages Folder 0750
Settings Folder 0750
AdminBarMenu.php File 2.26 KB 0640
CoreInfoCache.php File 2.04 KB 0640
DashboardWidget.php File 31.6 KB 0640
PluginList.php File 26.46 KB 0640
PluginListDisabler.php File 1.83 KB 0640
SiteHealth.php File 4.31 KB 0640
Filemanager