versionManager = $versionManager; $this->registerHooks(); } /** * Register WordPress hooks */ private function registerHooks(): void { // Add versions meta box to licensed products add_action('add_meta_boxes', [$this, 'addVersionsMetaBox']); // Handle AJAX actions for version management add_action('wp_ajax_wc_licensed_product_add_version', [$this, 'ajaxAddVersion']); add_action('wp_ajax_wc_licensed_product_delete_version', [$this, 'ajaxDeleteVersion']); add_action('wp_ajax_wc_licensed_product_toggle_version', [$this, 'ajaxToggleVersion']); // Enqueue scripts for product edit page add_action('admin_enqueue_scripts', [$this, 'enqueueScripts']); } /** * Add versions meta box to product edit page */ public function addVersionsMetaBox(): void { add_meta_box( 'wc_licensed_product_versions', __('Product Versions', 'wc-licensed-product'), [$this, 'renderVersionsMetaBox'], 'product', 'normal', 'high' ); } /** * Render versions meta box */ public function renderVersionsMetaBox(\WP_Post $post): void { $versions = $this->versionManager->getVersionsByProduct($post->ID); wp_nonce_field('wc_licensed_product_versions', 'wc_licensed_product_versions_nonce'); ?>


getVersion()); ?> getEffectiveDownloadUrl(); $filename = $version->getDownloadFilename(); if ($effectiveUrl): ?> getAttachmentId()): ?> getReleaseNotes() ? wp_trim_words($version->getReleaseNotes(), 10) : '—'); ?> isActive() ? esc_html__('Active', 'wc-licensed-product') : esc_html__('Inactive', 'wc-licensed-product'); ?> getReleasedAt()->format(get_option('date_format'))); ?>
post_type !== 'product') { return; } // Enqueue WordPress media uploader wp_enqueue_media(); wp_enqueue_script( 'wc-licensed-product-versions', WC_LICENSED_PRODUCT_PLUGIN_URL . 'assets/js/versions.js', ['jquery'], WC_LICENSED_PRODUCT_VERSION, true ); wp_localize_script('wc-licensed-product-versions', 'wcLicensedProductVersions', [ 'ajaxUrl' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('wc_licensed_product_versions'), 'strings' => [ 'confirmDelete' => __('Are you sure you want to delete this version?', 'wc-licensed-product'), 'versionRequired' => __('Please enter a version number.', 'wc-licensed-product'), 'versionInvalid' => __('Please enter a valid version number (e.g., 1.0.0).', 'wc-licensed-product'), 'error' => __('An error occurred. Please try again.', 'wc-licensed-product'), 'selectFile' => __('Select Download File', 'wc-licensed-product'), 'useThisFile' => __('Use this file', 'wc-licensed-product'), ], ]); wp_enqueue_style( 'wc-licensed-product-admin', WC_LICENSED_PRODUCT_PLUGIN_URL . 'assets/css/admin.css', [], WC_LICENSED_PRODUCT_VERSION ); } /** * AJAX handler for adding a version */ public function ajaxAddVersion(): void { check_ajax_referer('wc_licensed_product_versions', 'nonce'); if (!current_user_can('manage_woocommerce')) { wp_send_json_error(['message' => __('Permission denied.', 'wc-licensed-product')]); } $productId = absint($_POST['product_id'] ?? 0); $version = sanitize_text_field($_POST['version'] ?? ''); $downloadUrl = esc_url_raw($_POST['download_url'] ?? ''); $releaseNotes = sanitize_textarea_field($_POST['release_notes'] ?? ''); $attachmentId = absint($_POST['attachment_id'] ?? 0); if (!$productId || !$version) { wp_send_json_error(['message' => __('Product ID and version are required.', 'wc-licensed-product')]); } // Validate version format if (!preg_match('/^\d+\.\d+\.\d+$/', $version)) { wp_send_json_error(['message' => __('Invalid version format. Use semantic versioning (e.g., 1.0.0).', 'wc-licensed-product')]); } // Check if version already exists if ($this->versionManager->versionExists($productId, $version)) { wp_send_json_error(['message' => __('This version already exists.', 'wc-licensed-product')]); } $newVersion = $this->versionManager->createVersion( $productId, $version, $releaseNotes ?: null, $downloadUrl ?: null, $attachmentId ?: null ); if (!$newVersion) { wp_send_json_error(['message' => __('Failed to create version.', 'wc-licensed-product')]); } // Also update the product's current version meta update_post_meta($productId, '_licensed_current_version', $version); wp_send_json_success([ 'message' => __('Version added successfully.', 'wc-licensed-product'), 'version' => $newVersion->toArray(), 'html' => $this->getVersionRowHtml($newVersion), ]); } /** * AJAX handler for deleting a version */ public function ajaxDeleteVersion(): void { check_ajax_referer('wc_licensed_product_versions', 'nonce'); if (!current_user_can('manage_woocommerce')) { wp_send_json_error(['message' => __('Permission denied.', 'wc-licensed-product')]); } $versionId = absint($_POST['version_id'] ?? 0); if (!$versionId) { wp_send_json_error(['message' => __('Version ID is required.', 'wc-licensed-product')]); } $result = $this->versionManager->deleteVersion($versionId); if (!$result) { wp_send_json_error(['message' => __('Failed to delete version.', 'wc-licensed-product')]); } wp_send_json_success(['message' => __('Version deleted successfully.', 'wc-licensed-product')]); } /** * AJAX handler for toggling version status */ public function ajaxToggleVersion(): void { check_ajax_referer('wc_licensed_product_versions', 'nonce'); if (!current_user_can('manage_woocommerce')) { wp_send_json_error(['message' => __('Permission denied.', 'wc-licensed-product')]); } $versionId = absint($_POST['version_id'] ?? 0); $currentlyActive = (bool) ($_POST['currently_active'] ?? false); if (!$versionId) { wp_send_json_error(['message' => __('Version ID is required.', 'wc-licensed-product')]); } $result = $this->versionManager->updateVersion($versionId, null, null, !$currentlyActive); if (!$result) { wp_send_json_error(['message' => __('Failed to update version.', 'wc-licensed-product')]); } wp_send_json_success([ 'message' => __('Version updated successfully.', 'wc-licensed-product'), 'isActive' => !$currentlyActive, ]); } /** * Get HTML for a version table row */ private function getVersionRowHtml(\Jeremias\WcLicensedProduct\Product\ProductVersion $version): string { ob_start(); ?> getVersion()); ?> getEffectiveDownloadUrl(); $filename = $version->getDownloadFilename(); if ($effectiveUrl): ?> getAttachmentId()): ?> getReleaseNotes() ? wp_trim_words($version->getReleaseNotes(), 10) : '—'); ?> isActive() ? esc_html__('Active', 'wc-licensed-product') : esc_html__('Inactive', 'wc-licensed-product'); ?> getReleasedAt()->format(get_option('date_format'))); ?>