Implement version 0.0.1 - Licensed Product type for WooCommerce

Add complete plugin infrastructure for selling software with license keys:

- New "Licensed Product" WooCommerce product type
- License key generation (XXXX-XXXX-XXXX-XXXX format) on order completion
- Domain-based license validation system
- REST API endpoints (validate, status, activate, deactivate)
- Customer My Account "Licenses" page
- Admin license management under WooCommerce > Licenses
- Checkout domain field for licensed products
- Custom database tables for licenses and product versions
- Twig template engine integration
- Full i18n support with German (de_CH) translation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-21 18:55:18 +01:00
parent 8a4802248c
commit 404083f023
22 changed files with 3746 additions and 0 deletions

138
src/Installer.php Normal file
View File

@@ -0,0 +1,138 @@
<?php
/**
* Plugin Installer
*
* @package Jeremias\WcLicensedProduct
*/
declare(strict_types=1);
namespace Jeremias\WcLicensedProduct;
/**
* Handles plugin activation and deactivation
*/
final class Installer
{
/**
* Database table name for licenses
*/
public const TABLE_LICENSES = 'wc_licensed_product_licenses';
/**
* Database table name for product versions
*/
public const TABLE_PRODUCT_VERSIONS = 'wc_licensed_product_versions';
/**
* Run on plugin activation
*/
public static function activate(): void
{
self::createTables();
self::createCacheDir();
// Set version in options
update_option('wc_licensed_product_version', WC_LICENSED_PRODUCT_VERSION);
// Flush rewrite rules for REST API
flush_rewrite_rules();
}
/**
* Run on plugin deactivation
*/
public static function deactivate(): void
{
// Flush rewrite rules
flush_rewrite_rules();
}
/**
* Create database tables
*/
private static function createTables(): void
{
global $wpdb;
$charsetCollate = $wpdb->get_charset_collate();
$licensesTable = $wpdb->prefix . self::TABLE_LICENSES;
$versionsTable = $wpdb->prefix . self::TABLE_PRODUCT_VERSIONS;
$sqlLicenses = "CREATE TABLE {$licensesTable} (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
license_key VARCHAR(64) NOT NULL,
order_id BIGINT UNSIGNED NOT NULL,
product_id BIGINT UNSIGNED NOT NULL,
customer_id BIGINT UNSIGNED NOT NULL,
domain VARCHAR(255) NOT NULL,
version_id BIGINT UNSIGNED DEFAULT NULL,
status ENUM('active', 'inactive', 'expired', 'revoked') NOT NULL DEFAULT 'active',
activations_count INT UNSIGNED NOT NULL DEFAULT 0,
max_activations INT UNSIGNED NOT NULL DEFAULT 1,
expires_at DATETIME DEFAULT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY license_key (license_key),
KEY order_id (order_id),
KEY product_id (product_id),
KEY customer_id (customer_id),
KEY domain (domain),
KEY status (status)
) {$charsetCollate};";
$sqlVersions = "CREATE TABLE {$versionsTable} (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
product_id BIGINT UNSIGNED NOT NULL,
version VARCHAR(32) NOT NULL,
major_version INT UNSIGNED NOT NULL,
minor_version INT UNSIGNED NOT NULL,
patch_version INT UNSIGNED NOT NULL,
release_notes TEXT DEFAULT NULL,
download_url VARCHAR(512) DEFAULT NULL,
is_active TINYINT(1) NOT NULL DEFAULT 1,
released_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY product_version (product_id, version),
KEY product_id (product_id),
KEY major_version (major_version),
KEY is_active (is_active)
) {$charsetCollate};";
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
dbDelta($sqlLicenses);
dbDelta($sqlVersions);
}
/**
* Create Twig cache directory
*/
private static function createCacheDir(): void
{
$cacheDir = WP_CONTENT_DIR . '/cache/wc-licensed-product/twig';
if (!file_exists($cacheDir)) {
wp_mkdir_p($cacheDir);
}
}
/**
* Get licenses table name
*/
public static function getLicensesTable(): string
{
global $wpdb;
return $wpdb->prefix . self::TABLE_LICENSES;
}
/**
* Get product versions table name
*/
public static function getVersionsTable(): string
{
global $wpdb;
return $wpdb->prefix . self::TABLE_PRODUCT_VERSIONS;
}
}