| 1 |
<?php |
| 2 |
/** |
| 3 |
* Helper Functions. |
| 4 |
*/ |
| 5 |
|
| 6 |
// --------------------------------------------------------------------------- |
| 7 |
// PHP 7.4 polyfills. |
| 8 |
// |
| 9 |
// WordPress ships these in wp-includes/compat.php from WP 5.9+, but the SDK |
| 10 |
// is loaded on `plugins_loaded` priority 1 — which on some boot paths runs |
| 11 |
// before WP's compat.php is guaranteed to have been included. Defining safely |
| 12 |
// guarded copies here means the SDK never references missing functions when |
| 13 |
// running on PHP 7.4 with an older WordPress. |
| 14 |
// --------------------------------------------------------------------------- |
| 15 |
|
| 16 |
if ( ! function_exists( 'str_starts_with' ) ) { |
| 17 |
function str_starts_with( string $haystack, string $needle ): bool { |
| 18 |
return 0 === strncmp( $haystack, $needle, strlen( $needle ) ); |
| 19 |
} |
| 20 |
} |
| 21 |
|
| 22 |
if ( ! function_exists( 'str_ends_with' ) ) { |
| 23 |
function str_ends_with( string $haystack, string $needle ): bool { |
| 24 |
if ( '' === $needle ) { |
| 25 |
return true; |
| 26 |
} |
| 27 |
$len = strlen( $needle ); |
| 28 |
return $len <= strlen( $haystack ) && 0 === substr_compare( $haystack, $needle, -$len ); |
| 29 |
} |
| 30 |
} |
| 31 |
|
| 32 |
if ( ! function_exists( 'str_contains' ) ) { |
| 33 |
function str_contains( string $haystack, string $needle ): bool { |
| 34 |
return '' === $needle || false !== strpos( $haystack, $needle ); |
| 35 |
} |
| 36 |
} |
| 37 |
|
| 38 |
if ( ! function_exists( 'se_license_init' ) ) { |
| 39 |
/** |
| 40 |
* Initialize the SDK. |
| 41 |
* |
| 42 |
* @param array{ |
| 43 |
* package_file?: string, // Optional product main filepath. If omitted SDK will try to detect it from the calling plugin/theme file. |
| 44 |
* basename?: string, // Optional plugin/theme basename. Auto-detected from `package_file` when omitted. |
| 45 |
* package_name?: string, // Optional product name. Auto-detected from plugin/theme metadata when omitted. |
| 46 |
* package_type?: string, // Optional package type: plugin or theme. Auto-detected when omitted. |
| 47 |
* is_free?: bool, // Is free or pro. For freemium set true. |
| 48 |
* product_id: int, // Product ID from the Store/Deployment site. |
| 49 |
* use_update?: bool, // Should enable updater, For pro/freemium this needs to be enabled, for free version if deployed with StoreEngine this needs to be enabled. If developer just using SDK for uninstall-tracking/analytics this should be false. |
| 50 |
* slug: string, // Plugin slug (without main file) |
| 51 |
* package_version?: string, // Optional current package version. Auto-detected from plugin/theme metadata when omitted. |
| 52 |
* allow_local?: bool, // Should plugin dev allow license activation from local environment. Recommended. |
| 53 |
* critical_paths?: array, // Package-relative paths (e.g. ['includes/autoload.php']) that must exist in an update package; if any is missing the update is aborted before the live folder is swapped. Declare the files your plugin hard-requires on boot. When omitted the SDK falls back to ['vendor/autoload.php'], but only if the installed build actually ships one — so a consumer that ships no vendor/ is never blocked by a path it never had. |
| 54 |
* requires_core?: string|array, // Core/free plugin this (pro) product depends on. Pass the slug, or ['slug'=>'', 'basename'=>'', 'name'=>'', 'min_version'=>'']. When set, the SDK updates the core plugin first and refuses to apply the pro update until the core plugin is active and at least the required version (the required version can also be supplied per-release by the license server). Prevents pro from out-running its free plugin during the wp.org 24h review delay. |
| 55 |
* license_grace_period?: int, // Seconds a previously-valid license keeps working when the license server is unreachable for its scheduled re-check. Default 14 days. Prevents a transient outage from deactivating a paying customer. 0 = fail closed immediately. |
| 56 |
* license_server: string, // Store URL (api backend for SDK). |
| 57 |
* activation_prompt?: null|string, // Custom activation nag (admin-notice) message. |
| 58 |
* purchase_url?: string, // Plugin store product URL. |
| 59 |
* store_dashboard_url?: string, // Plugin store user dashboard (where user can find their licenses they purchesed). |
| 60 |
* product_logo?: string, // Product logo |
| 61 |
* init_restapi?: bool, // Should initialize rest api for managing license. Useful if plugin developer uses custom 'manage-license' page. |
| 62 |
* script_handler?:string, // Localize js params on this handler for react/js based custom license managemnt page. Recommended if `init_restapi` is `true` |
| 63 |
* script_object?:string, // Object name for localized js params. Recommended if if `script_handler` is being used, must be qnique/prefixed. If not set SDK will set `SE_SDK_{PLUGIN_SLUG}` |
| 64 |
* menu?: false|string|array{ // False to disable built in 'manage-license' page, url for custom 'manage-license' page or menu config for adding builtin 'manage-license' page UI. |
| 65 |
* type: string, // menu type: menu, submenu. |
| 66 |
* parent_slug: string, // parent menu slug if type is submenu. |
| 67 |
* page_title: string, // Page title for the 'manage-license' page. |
| 68 |
* menu_title: string, // Menu title. |
| 69 |
* capability: string, // Permission for accessing the 'manage-license' page. |
| 70 |
* menu_slug: string, // Menu slug |
| 71 |
* icon_url: string, // Icon if type is 'menu' |
| 72 |
* position: int, // Menu position |
| 73 |
* }, |
| 74 |
* redirect_on_activation?:bool, // Should redirect to 'manage-license' page after user activates the plugin. Default is true. |
| 75 |
* init_insights?: bool, |
| 76 |
* should_show_optin?: bool, // Show analytics data collection (opt-in) notice. |
| 77 |
* first_install_time?: int, // Plugin first installation time. |
| 78 |
* optin_notice_delay?: int, // Opt-in notice delay in seconds (from first installation time). |
| 79 |
* data_being_collected?: array, // List of extra data being collect. E.g `['num_prod' => __( 'Number of products', 'textdomain' ), 'num_order' => __( 'Number of total orders', 'textdomain' ) ]` |
| 80 |
* terms_url?: string, // Terms url for the plugin/theme. |
| 81 |
* privacy_policy_url?: string, // Privacy policy page url for the plugin/theme. |
| 82 |
* support_url?: string, // Support portal URL for the plugin/theme. |
| 83 |
* ticket_recipient?: string, // Support recipient email address for sending support message directly from the dashboard. |
| 84 |
* support_ticket_response?: string, // Support form success response. |
| 85 |
* support_ticket_error_response?: string, // Support form error response. |
| 86 |
* init_promotions?: bool, |
| 87 |
* promo_cache_ttl?: int, |
| 88 |
* promo_source?: string |
| 89 |
* } $args |
| 90 |
* |
| 91 |
* @return SE_License_SDK_Client |
| 92 |
*/ |
| 93 |
function se_license_init( array $args ): SE_License_SDK_Client { |
| 94 |
$args = wp_parse_args( $args, [ |
| 95 |
'package_file' => '', |
| 96 |
'package_name' => '', |
| 97 |
'product_id' => 0, |
| 98 |
'is_free' => null, |
| 99 |
'use_update' => null, // is_org_compliant |
| 100 |
'slug' => null, |
| 101 |
'basename' => null, |
| 102 |
'package_type' => null, |
| 103 |
'package_version' => null, |
| 104 |
'allow_local' => true, |
| 105 |
'critical_paths' => null, // Package-relative paths that must exist in an update package; missing ones abort the update before the live folder is swapped. |
| 106 |
'requires_core' => null, // Core/free plugin dependency (slug or [slug, basename, name, min_version]); gates the pro update on the core plugin's version. |
| 107 |
'license_grace_period' => null, // Seconds a previously-valid license keeps working while the license server is unreachable. Default 14 days. 0 = fail closed immediately. |
| 108 |
'license_server' => null, |
| 109 |
'activation_prompt' => null, |
| 110 |
'purchase_url' => null, |
| 111 |
'store_dashboard_url' => null, |
| 112 |
'product_logo' => '', |
| 113 |
'init_restapi' => false, |
| 114 |
'script_handler' => '', |
| 115 |
'script_object' => '', |
| 116 |
'menu' => [ |
| 117 |
'type' => '', // Can be: menu, options, submenu. Default to menu. |
| 118 |
'parent_slug' => '', // Parent menu slug if rending as submenu. |
| 119 |
'page_title' => '', // Default: Manage License |
| 120 |
'menu_title' => '', // Default: Manage License |
| 121 |
'capability' => '', // default: manage_options |
| 122 |
'menu_slug' => '', // Default: [package-slug]-manage-license |
| 123 |
'icon_url' => '', // Menu icon (icon image/svg url or dashicons). |
| 124 |
'position' => null, // Menu render priority. Mostly render after the `Settings` menu. |
| 125 |
], |
| 126 |
'redirect_on_activation' => true, |
| 127 |
// Insight settings |
| 128 |
'init_insights' => true, |
| 129 |
'should_show_optin' => true, |
| 130 |
'first_install_time' => null, |
| 131 |
'optin_notice_delay' => null, // Default 3 * DAY_IN_SECONDS |
| 132 |
'data_being_collected' => [], |
| 133 |
'terms_url' => '', |
| 134 |
'privacy_policy_url' => '', |
| 135 |
'support_url' => '', |
| 136 |
'support_ticket_response' => '', |
| 137 |
'support_ticket_error_response' => '', |
| 138 |
'ticket_template' => '', // template file path. |
| 139 |
'ticket_recipient' => '', // ticket recipient email address. |
| 140 |
// Promo settings. |
| 141 |
'init_promotions' => true, |
| 142 |
'promo_cache_ttl' => null, // Default 12 * HOUR_IN_SECONDS. |
| 143 |
'promo_source' => null, // Default license server `promotions` route/endpoint. |
| 144 |
] ); |
| 145 |
|
| 146 |
return SE_License_SDK::register( $args['package_file'] ?? '', $args['package_name'] ?? '', $args ); |
| 147 |
} |
| 148 |
} |
| 149 |
|
| 150 |
// End of file functions.php. |
| 151 |
|