278 lines
6.6 KiB
PHP
278 lines
6.6 KiB
PHP
|
<?php
|
||
|
/**
|
||
|
* Pass Manager
|
||
|
*
|
||
|
* Tool for determining what kind of pass, if any, is activated on the site.
|
||
|
*
|
||
|
* @package easy-digital-downloads
|
||
|
* @copyright Copyright (c) 2021, Sandhills Development, LLC
|
||
|
* @license GPL2+
|
||
|
* @since 2.10.6
|
||
|
*/
|
||
|
|
||
|
namespace EDD\Admin;
|
||
|
|
||
|
class Pass_Manager {
|
||
|
|
||
|
const PERSONAL_PASS_ID = 1245715;
|
||
|
const EXTENDED_PASS_ID = 1245716;
|
||
|
const PROFESSIONAL_PASS_ID = 1245717;
|
||
|
const ALL_ACCESS_PASS_ID = 1150319;
|
||
|
const ALL_ACCESS_PASS_LIFETIME_ID = 1464807;
|
||
|
|
||
|
/**
|
||
|
* ID of the highest tier pass that's activated.
|
||
|
*
|
||
|
* @var int|null
|
||
|
*/
|
||
|
public $highest_pass_id = null;
|
||
|
|
||
|
/**
|
||
|
* License key of the highest tier pass that's activated.
|
||
|
*
|
||
|
* @var string|null
|
||
|
*/
|
||
|
public $highest_license_key = null;
|
||
|
|
||
|
/**
|
||
|
* Pass data from the database. This will be an array with
|
||
|
* the key being the license key, and the value being another
|
||
|
* array with the `pass_id` and `time_checked`.
|
||
|
*
|
||
|
* @var array|null
|
||
|
*/
|
||
|
public $pass_data;
|
||
|
|
||
|
/**
|
||
|
* Whether or not we've stored any pass data yet.
|
||
|
* If no pass data has been stored, then that means the user
|
||
|
* might have a pass activated, we just haven't figured it out
|
||
|
* yet and we're still waiting for the first cron to run.
|
||
|
*
|
||
|
* @see \EDD_License::weekly_license_check()
|
||
|
* @see \EDD_License::activate_license()
|
||
|
* @see \EDD_License::maybe_set_pass_flag()
|
||
|
*
|
||
|
* @var bool
|
||
|
*/
|
||
|
public $has_pass_data = false;
|
||
|
|
||
|
/**
|
||
|
* Number of license keys entered on this site.
|
||
|
*
|
||
|
* @var int
|
||
|
*/
|
||
|
public $number_license_keys;
|
||
|
|
||
|
/**
|
||
|
* Hierarchy of passes. This helps us determine if one pass
|
||
|
* is "higher" than another.
|
||
|
*
|
||
|
* @see Pass_Manager::pass_compare()
|
||
|
*
|
||
|
* @var int[]
|
||
|
*/
|
||
|
private static $pass_hierarchy = array(
|
||
|
self::PERSONAL_PASS_ID => 10,
|
||
|
self::EXTENDED_PASS_ID => 20,
|
||
|
self::PROFESSIONAL_PASS_ID => 30,
|
||
|
self::ALL_ACCESS_PASS_ID => 40,
|
||
|
self::ALL_ACCESS_PASS_LIFETIME_ID => 50
|
||
|
);
|
||
|
|
||
|
/**
|
||
|
* Pass_Manager constructor.
|
||
|
*/
|
||
|
public function __construct() {
|
||
|
$pass_data = get_option( 'edd_pass_licenses' );
|
||
|
if ( false !== $pass_data ) {
|
||
|
$this->pass_data = json_decode( $pass_data, true );
|
||
|
$this->has_pass_data = true;
|
||
|
}
|
||
|
|
||
|
// Set up the highest pass data.
|
||
|
$this->set_highest_pass_data();
|
||
|
|
||
|
$this->number_license_keys = count( \EDD\Extensions\get_licensed_extension_slugs() );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the highest pass and defines its data.
|
||
|
*
|
||
|
* @since 2.11.4
|
||
|
* @return void
|
||
|
*/
|
||
|
private function set_highest_pass_data() {
|
||
|
|
||
|
if ( ! $this->has_pass_data || ! is_array( $this->pass_data ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$highest_license_key = null;
|
||
|
$highest_pass_id = null;
|
||
|
|
||
|
foreach ( $this->pass_data as $license_key => $pass_data ) {
|
||
|
/*
|
||
|
* If this pass was last verified more than 2 months ago, we're not using it.
|
||
|
* This ensures we never deal with a "stale" record for a pass that's no longer
|
||
|
* actually activated, but still exists in our DB array for some reason.
|
||
|
*
|
||
|
* Our cron job should always be updating with active data once per week.
|
||
|
*/
|
||
|
if ( empty( $pass_data['time_checked'] ) || strtotime( '-2 months' ) > $pass_data['time_checked'] ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// We need a pass ID.
|
||
|
if ( empty( $pass_data['pass_id'] ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// If we don't yet have a "highest pass", then this one is it automatically.
|
||
|
if ( empty( $highest_pass_id ) ) {
|
||
|
$highest_license_key = $license_key;
|
||
|
$highest_pass_id = intval( $pass_data['pass_id'] );
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Otherwise, this pass only takes over the highest pass if it's actually higher.
|
||
|
if ( self::pass_compare( (int) $pass_data['pass_id'], $highest_pass_id, '>' ) ) {
|
||
|
$highest_license_key = $license_key;
|
||
|
$highest_pass_id = intval( $pass_data['pass_id'] );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$this->highest_license_key = $highest_license_key;
|
||
|
$this->highest_pass_id = $highest_pass_id;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Whether or not a pass is activated.
|
||
|
*
|
||
|
* @since 2.10.6
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function has_pass() {
|
||
|
return ! empty( $this->highest_pass_id );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* If this is a "free install". That means there are no à la carte or pass licenses activated.
|
||
|
*
|
||
|
* @since 2.11.4
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function isFree() {
|
||
|
return 0 === $this->number_license_keys;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* If this is a "pro install". This means they have the pro version of EDD installed.
|
||
|
*
|
||
|
* @since 3.1
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
public static function isPro() {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* If this site has an individual product license active (à la carte), but no pass active.
|
||
|
*
|
||
|
* @since 2.11.4
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function hasIndividualLicense() {
|
||
|
return ! $this->isFree() && ! $this->has_pass();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* If this site has a Personal Pass active.
|
||
|
*
|
||
|
* @since 2.11.4
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function hasPersonalPass() {
|
||
|
try {
|
||
|
return self::pass_compare( $this->highest_pass_id, self::PERSONAL_PASS_ID, '=' );
|
||
|
} catch ( \Exception $e ) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* If this site has an Extended Pass active.
|
||
|
*
|
||
|
* @since 2.11.4
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function hasExtendedPass() {
|
||
|
try {
|
||
|
return self::pass_compare( $this->highest_pass_id, self::EXTENDED_PASS_ID, '=' );
|
||
|
} catch ( \Exception $e ) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* If this site has a Professional Pass active.
|
||
|
*
|
||
|
* @since 2.11.4
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function hasProfessionalPass() {
|
||
|
try {
|
||
|
return self::pass_compare( $this->highest_pass_id, self::PROFESSIONAL_PASS_ID, '=' );
|
||
|
} catch( \Exception $e ) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* If this site has an All Access Pass active.
|
||
|
* Note: This uses >= to account for both All Access and lifetime All Access.
|
||
|
*
|
||
|
* @since 2.11.4
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function hasAllAccessPass() {
|
||
|
try {
|
||
|
return self::pass_compare( $this->highest_pass_id, self::ALL_ACCESS_PASS_ID, '>=' );
|
||
|
} catch( \Exception $e ) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Compares two passes with each other according to the supplied operator.
|
||
|
*
|
||
|
* @since 2.10.6
|
||
|
*
|
||
|
* @param int $pass_1 ID of the first pass.
|
||
|
* @param int $pass_2 ID of the second pass
|
||
|
* @param string $comparison Comparison operator.
|
||
|
*
|
||
|
* @return bool
|
||
|
* @throws \InvalidArgumentException
|
||
|
*/
|
||
|
public static function pass_compare( $pass_1, $pass_2, $comparison = '>' ) {
|
||
|
if ( ! array_key_exists( $pass_1, self::$pass_hierarchy ) ) {
|
||
|
throw new \InvalidArgumentException( 'Invalid pass 1: ' . $pass_1 );
|
||
|
}
|
||
|
if ( ! array_key_exists( $pass_2, self::$pass_hierarchy ) ) {
|
||
|
throw new \InvalidArgumentException( 'Invalid pass 2: ' . $pass_2 );
|
||
|
}
|
||
|
|
||
|
return version_compare( self::$pass_hierarchy[ $pass_1 ], self::$pass_hierarchy[ $pass_2 ], $comparison );
|
||
|
}
|
||
|
|
||
|
}
|