You've already forked wc-licensed-product
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6770ec5201 | |||
| 6f1ea3c6fa | |||
| 10453360ad | |||
| 8ada21afb0 | |||
| 27dc1b67c5 | |||
| a73b7cc550 | |||
| 89c5a40f56 | |||
| 79b9c2cefd | |||
| f8b88e4c98 | |||
| 1008617623 | |||
| 45531f86d6 | |||
| ff9b27e811 | |||
| a59631aec3 | |||
| 0e3b57482e | |||
| b3cf3e114b |
8
.claude/settings.json
Normal file
8
.claude/settings.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(composer config:*)",
|
||||
"Bash(composer update:*)"
|
||||
]
|
||||
}
|
||||
}
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,3 +3,4 @@
|
||||
wp-plugins
|
||||
wp-core
|
||||
vendor/
|
||||
releases/*
|
||||
|
||||
29
CHANGELOG.md
29
CHANGELOG.md
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.0.11] - 2026-01-22
|
||||
|
||||
### Added
|
||||
|
||||
- Created date column in admin license overview
|
||||
|
||||
### Technical Details
|
||||
|
||||
- Added "Created" column to licenses table in admin (Twig template and PHP fallback)
|
||||
- Shows when each license was generated
|
||||
|
||||
## [0.0.10] - 2026-01-21
|
||||
|
||||
### Added
|
||||
@@ -17,13 +28,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- View licenses table showing all licenses for an order
|
||||
- Link to full licenses management page from order view
|
||||
- Support for both classic orders and HPOS (High-Performance Order Storage)
|
||||
- Inline editing for license fields (status, expiry date, domain) in admin
|
||||
- Copy license key button in admin licenses overview
|
||||
- Live search for licenses in admin overview
|
||||
- Settings link in plugin actions
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed 404 error on licenses menu item
|
||||
- Fixed Twig template cache issues with auto_reload
|
||||
|
||||
### Technical Details
|
||||
|
||||
- New `OrderLicenseController` class for order page integration
|
||||
- New `getLicensesByOrder()` method in LicenseManager
|
||||
- New `updateLicenseExpiry()` method in LicenseManager
|
||||
- JavaScript file `order-licenses.js` for inline domain editing
|
||||
- JavaScript file `admin-licenses.js` for live search and inline editing
|
||||
- AJAX handlers for updating order domain and license domains
|
||||
- AJAX handlers for inline editing (status, expiry, domain updates)
|
||||
|
||||
## [0.0.9] - 2026-01-21
|
||||
|
||||
@@ -252,7 +275,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- WordPress REST API integration
|
||||
- Custom WooCommerce product type extending WC_Product
|
||||
|
||||
[Unreleased]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.0.7...HEAD
|
||||
[Unreleased]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.0.11...HEAD
|
||||
[0.0.11]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.0.10...v0.0.11
|
||||
[0.0.10]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.0.9...v0.0.10
|
||||
[0.0.9]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.0.8...v0.0.9
|
||||
[0.0.8]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.0.7...v0.0.8
|
||||
[0.0.7]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.0.6...v0.0.7
|
||||
[0.0.6]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.0.5...v0.0.6
|
||||
[0.0.5]: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/compare/v0.0.4...v0.0.5
|
||||
|
||||
84
CLAUDE.md
84
CLAUDE.md
@@ -34,11 +34,7 @@ This project is proudly **"vibe-coded"** using Claude.AI - the entire codebase w
|
||||
|
||||
### Known Bugs
|
||||
|
||||
None currently known.
|
||||
|
||||
### Version 0.0.11 (planned)
|
||||
|
||||
- TBD - no specific features planned yet
|
||||
No known bugs at the moment
|
||||
|
||||
## Technical Stack
|
||||
|
||||
@@ -554,17 +550,79 @@ Full API documentation available in `openapi.json` (OpenAPI 3.1 specification).
|
||||
- Inline edit UI with save/cancel for license domains
|
||||
- Links to full licenses management page for advanced actions
|
||||
|
||||
**Bug fix (post v0.0.10):**
|
||||
**Additional features added in this session:**
|
||||
|
||||
- Inline editing for license fields (status, expiry date, domain) in admin licenses overview
|
||||
- Copy license key button with clipboard API and fallback for older browsers
|
||||
- Live search for licenses in admin overview with AJAX-powered results dropdown
|
||||
- Settings link added to plugin action links in Plugins list
|
||||
- Fixed 404 error on licenses menu item in customer account
|
||||
- Fixed Twig template cache issues with `auto_reload` option
|
||||
|
||||
**New files:**
|
||||
|
||||
- `assets/js/admin-licenses.js` - JavaScript for live search, inline editing, and copy functionality
|
||||
|
||||
**New methods in LicenseManager:**
|
||||
|
||||
- `updateLicenseExpiry()` - Update license expiry date with auto-reactivation for expired licenses
|
||||
|
||||
**AJAX handlers added to AdminController:**
|
||||
|
||||
- `handleAjaxStatusUpdate()` - Update license status via AJAX
|
||||
- `handleAjaxExpiryUpdate()` - Update license expiry date via AJAX
|
||||
- `handleAjaxDomainUpdate()` - Update license domain via AJAX
|
||||
- `handleAjaxRevoke()` - Revoke license via AJAX
|
||||
|
||||
**Technical notes:**
|
||||
|
||||
- Live search uses 300ms debounce and keyboard navigation (arrows, enter, escape)
|
||||
- Inline editing shows edit icons on hover, supports enter to save and escape to cancel
|
||||
- Copy button uses Clipboard API with textarea fallback for older browsers
|
||||
- All AJAX handlers use nonce verification (`wclp_inline_edit` nonce)
|
||||
- Twig configured with `auto_reload => true` for development to always check template changes
|
||||
|
||||
**Bug fix:**
|
||||
|
||||
- Fixed: Licenses menu item in customer account page resulted in 404 error
|
||||
- Root cause: WooCommerce My Account endpoints require both `add_rewrite_endpoint()` AND registration with `woocommerce_get_query_vars` filter
|
||||
- Fix: Added `addLicensesQueryVar()` method to register the endpoint query var with WooCommerce
|
||||
|
||||
**Root cause:**
|
||||
**Release v0.0.10:**
|
||||
|
||||
- WooCommerce My Account endpoints require both `add_rewrite_endpoint()` AND registration with `woocommerce_get_query_vars` filter
|
||||
- The endpoint also needs to be registered before rewrite rules are flushed during activation
|
||||
- Created release package: `releases/wc-licensed-product-0.0.10.zip` (472 KB)
|
||||
- SHA256: `3f4a093f6d4d02389082c3a88c00542f477ab3ad4d4a0c65079e524ef0739620`
|
||||
- Tagged as `v0.0.10` and pushed to `main` branch
|
||||
|
||||
**Fix:**
|
||||
### 2026-01-21 - Version 0.0.11 Features
|
||||
|
||||
- Added `addLicensesQueryVar()` method to register the endpoint query var with WooCommerce
|
||||
- Updated Installer to register endpoint before flushing rewrite rules on activation
|
||||
- Existing installations may need to visit Settings > Permalinks and click Save to regenerate rewrite rules
|
||||
**Implemented:**
|
||||
|
||||
- Created date column added to admin license overview
|
||||
- License Statistics page under WooCommerce menu (WooCommerce > License Statistics)
|
||||
- REST API endpoints for analytics data with time-series support
|
||||
- WooCommerce Analytics integration via submenu page
|
||||
|
||||
**New files:**
|
||||
|
||||
- `src/Admin/AnalyticsController.php` - WooCommerce Analytics integration
|
||||
- `templates/admin/statistics.html.twig` - Statistics page template
|
||||
|
||||
**New REST API endpoints:**
|
||||
|
||||
- `GET /wp-json/wc-licensed-product/v1/analytics/stats` - License statistics with time-series data (supports day/week/month/quarter/year intervals)
|
||||
- `GET /wp-json/wc-licensed-product/v1/analytics/products` - License counts by product
|
||||
|
||||
**Modified files:**
|
||||
|
||||
- `templates/admin/licenses.html.twig` - Added "Created" column
|
||||
- `src/Admin/AdminController.php` - Added "Created" column to fallback rendering
|
||||
- `src/Plugin.php` - Added AnalyticsController initialization and `getInstance()` alias
|
||||
|
||||
**Technical notes:**
|
||||
|
||||
- Statistics page accessible via WooCommerce > License Statistics submenu
|
||||
- REST API endpoints support date range filtering (`after`, `before` parameters)
|
||||
- Time-series data aggregation supports multiple intervals (day, week, month, quarter, year)
|
||||
- AnalyticsController registers REST routes and renders statistics page
|
||||
- Page uses existing dashboard CSS styles for consistent appearance
|
||||
|
||||
Binary file not shown.
@@ -3,7 +3,7 @@
|
||||
# This file is distributed under the GPL-2.0-or-later.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: WC Licensed Product 0.0.10\n"
|
||||
"Project-Id-Version: WC Licensed Product 0.0.11\n"
|
||||
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/issues\n"
|
||||
"POT-Creation-Date: 2026-01-21T00:00:00+00:00\n"
|
||||
"PO-Revision-Date: 2026-01-21T00:00:00+00:00\n"
|
||||
@@ -939,3 +939,7 @@ msgstr "Fehler beim Speichern. Bitte versuchen Sie es erneut."
|
||||
|
||||
msgid "Failed to update license domain."
|
||||
msgstr "Lizenz-Domain konnte nicht aktualisiert werden."
|
||||
|
||||
#. Admin - License Overview (Created column)
|
||||
msgid "Created"
|
||||
msgstr "Erstellt"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# This file is distributed under the GPL-2.0-or-later.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: WC Licensed Product 0.0.10\n"
|
||||
"Project-Id-Version: WC Licensed Product 0.0.11\n"
|
||||
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/issues\n"
|
||||
"POT-Creation-Date: 2026-01-21T00:00:00+00:00\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -939,3 +939,7 @@ msgstr ""
|
||||
|
||||
msgid "Failed to update license domain."
|
||||
msgstr ""
|
||||
|
||||
#. Admin - License Overview (Created column)
|
||||
msgid "Created"
|
||||
msgstr ""
|
||||
|
||||
@@ -1253,6 +1253,7 @@ final class AdminController
|
||||
<th><?php esc_html_e('Customer', 'wc-licensed-product'); ?></th>
|
||||
<th><?php esc_html_e('Domain', 'wc-licensed-product'); ?></th>
|
||||
<th><?php esc_html_e('Status', 'wc-licensed-product'); ?></th>
|
||||
<th><?php esc_html_e('Created', 'wc-licensed-product'); ?></th>
|
||||
<th><?php esc_html_e('Expires', 'wc-licensed-product'); ?></th>
|
||||
<th><?php esc_html_e('Actions', 'wc-licensed-product'); ?></th>
|
||||
</tr>
|
||||
@@ -1260,7 +1261,7 @@ final class AdminController
|
||||
<tbody>
|
||||
<?php if (empty($enrichedLicenses)): ?>
|
||||
<tr>
|
||||
<td colspan="8"><?php esc_html_e('No licenses found.', 'wc-licensed-product'); ?></td>
|
||||
<td colspan="9"><?php esc_html_e('No licenses found.', 'wc-licensed-product'); ?></td>
|
||||
</tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($enrichedLicenses as $item): ?>
|
||||
@@ -1320,6 +1321,9 @@ final class AdminController
|
||||
<button type="button" class="wclp-cancel-btn button button-small"><?php esc_html_e('Cancel', 'wc-licensed-product'); ?></button>
|
||||
</div>
|
||||
</td>
|
||||
<td class="wclp-created-cell">
|
||||
<?php echo esc_html($item['license']->getCreatedAt()->format(get_option('date_format'))); ?>
|
||||
</td>
|
||||
<td class="wclp-editable-cell" data-field="expiry" data-license-id="<?php echo esc_attr($item['license']->getId()); ?>">
|
||||
<?php $expiresAt = $item['license']->getExpiresAt(); ?>
|
||||
<span class="wclp-display-value">
|
||||
@@ -1387,6 +1391,7 @@ final class AdminController
|
||||
<th><?php esc_html_e('Customer', 'wc-licensed-product'); ?></th>
|
||||
<th><?php esc_html_e('Domain', 'wc-licensed-product'); ?></th>
|
||||
<th><?php esc_html_e('Status', 'wc-licensed-product'); ?></th>
|
||||
<th><?php esc_html_e('Created', 'wc-licensed-product'); ?></th>
|
||||
<th><?php esc_html_e('Expires', 'wc-licensed-product'); ?></th>
|
||||
<th><?php esc_html_e('Actions', 'wc-licensed-product'); ?></th>
|
||||
</tr>
|
||||
|
||||
@@ -68,6 +68,14 @@ final class Plugin
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get singleton instance (alias for instance())
|
||||
*/
|
||||
public static function getInstance(): Plugin
|
||||
{
|
||||
return self::instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor for singleton
|
||||
*/
|
||||
|
||||
@@ -95,6 +95,7 @@
|
||||
<th>{{ __('Customer') }}</th>
|
||||
<th>{{ __('Domain') }}</th>
|
||||
<th>{{ __('Status') }}</th>
|
||||
<th>{{ __('Created') }}</th>
|
||||
<th>{{ __('Expires') }}</th>
|
||||
<th>{{ __('Actions') }}</th>
|
||||
</tr>
|
||||
@@ -102,7 +103,7 @@
|
||||
<tbody>
|
||||
{% if licenses is empty %}
|
||||
<tr>
|
||||
<td colspan="8">{{ __('No licenses found.') }}</td>
|
||||
<td colspan="9">{{ __('No licenses found.') }}</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
{% for item in licenses %}
|
||||
@@ -160,6 +161,9 @@
|
||||
<button type="button" class="wclp-cancel-btn button button-small">{{ __('Cancel') }}</button>
|
||||
</div>
|
||||
</td>
|
||||
<td class="wclp-created-cell">
|
||||
{{ item.license.createdAt|date('Y-m-d') }}
|
||||
</td>
|
||||
<td class="wclp-editable-cell" data-field="expiry" data-license-id="{{ item.license.id }}">
|
||||
<span class="wclp-display-value">
|
||||
{% if item.license.expiresAt %}
|
||||
@@ -219,6 +223,7 @@
|
||||
<th>{{ __('Customer') }}</th>
|
||||
<th>{{ __('Domain') }}</th>
|
||||
<th>{{ __('Status') }}</th>
|
||||
<th>{{ __('Created') }}</th>
|
||||
<th>{{ __('Expires') }}</th>
|
||||
<th>{{ __('Actions') }}</th>
|
||||
</tr>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Plugin Name: WooCommerce Licensed Product
|
||||
* Plugin URI: https://src.bundespruefstelle.ch/magdev/wc-licensed-product
|
||||
* Description: WooCommerce plugin to sell software products using license keys with domain-based validation.
|
||||
* Version: 0.0.10
|
||||
* Version: 0.0.11
|
||||
* Author: Marco Graetsch
|
||||
* Author URI: https://src.bundespruefstelle.ch/magdev
|
||||
* License: GPL-2.0-or-later
|
||||
@@ -28,7 +28,7 @@ if (!defined('ABSPATH')) {
|
||||
}
|
||||
|
||||
// Plugin constants
|
||||
define('WC_LICENSED_PRODUCT_VERSION', '0.0.10');
|
||||
define('WC_LICENSED_PRODUCT_VERSION', '0.0.11');
|
||||
define('WC_LICENSED_PRODUCT_PLUGIN_FILE', __FILE__);
|
||||
define('WC_LICENSED_PRODUCT_PLUGIN_DIR', plugin_dir_path(__FILE__));
|
||||
define('WC_LICENSED_PRODUCT_PLUGIN_URL', plugin_dir_url(__FILE__));
|
||||
|
||||
Reference in New Issue
Block a user