Add .editorconfig, .gitignore, and CLAUDE.md project documentation. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
8.4 KiB
WooCommerce Plugin for licensed Products
Author: Marco Graetsch Author URL: https://src.bundespruefstelle.ch/magdev Author Email: magdev3.0@gmail.com Repository URL: https://src.bundespruefstelle.ch/magdev/wc-licensed-product Issues URL: https://src.bundespruefstelle.ch/magdev/wc-licensed-product/issues
Project Overview
This plugin adds a new product type named licensed to sell software products using license keys. It implements an endpoint to check valid licenses against the WooCommerce payment database. License keys are generated are bounded to a specific domain, which must be defined within the checkout process, and will be available as soon as an order is marked as paid. License keys can optionally be bound to major software versions. Customer can view their purchased license keys in their customer profile.
Features
- Add a new product type named
licensed - Generate license keys based on purchased releases, bounded to a specific domain, if the related payment is marked as completed
Frontend
- Customers can view their purchased licenses in the customer area
Administration
- Add CRUD for license keys
- Manage different versions of the same licensed product
Known Bugs
No known bugs at this time.
Key Fact: 100% AI-Generated
This project is proudly "vibe-coded" using Claude.AI - the entire codebase was created through AI assistance.
Temporary Roadmap
Note for AI Assistants: Clean this section after the specific features are done or new releases are made. Effective changes are tracked in CHANGELOG.md
Version 0.0.1
- Create the basic structure for a Wordpress/WooCommerce plugin, define
woocommerceas required dependency - Find a reasonable solution to implement a rather safe license management using a client-server-model, bound to single domains. The license server hooks into the existing Wordpress REST API
- Start to implement an initial version with the features defined and figured out so far
Technical Stack
- Language: PHP 8.3.x
- Framework: Latest WordPress Plugin API
- E-commerce: WooCommerce 10.0+
- Template Engine: Twig 3.0 (via Composer)
- Wordpress Base Theme twentytwentyfive
- Frontend: Vanilla JavaScript
- Styling: Custom CSS
- Dependency Management: Composer
- Internationalization: WordPress i18n (.pot/.po/.mo files)
- Canonical Plugin Name:
wc-licensed-product
Security Best Practices
- All user inputs are sanitized (integers for quantities/prices)
- Nonce verification on form submissions
- Output escaping in templates (
esc_attr,esc_html,esc_js) - Direct file access prevention via
ABSPATHcheck
Translation Ready
All user-facing strings use:
__('Text to translate', 'wc-licensed-product')
_e('Text to translate', 'wc-licensed-product')
Text domain: wc-licensed-product
Translation Template
- Base
.potfile created:languages/wc-licensed-product.pot - Ready for translation to any locale
- All translatable strings properly marked with text domain
Available Translations
en_US- English (United States) [base language - .pot template]de_CH- German (Switzerland, formal)
To compile translations to .mo files for production:
for po in languages/*.po; do msgfmt -o "${po%.po}.mo" "$po"; done
Create releases
- The
vendor/directory MUST be included in releases (Dependencies required for runtime) - Don't create any release files until version 0.1.x and up!
- CRITICAL: Build
vendor/for the MINIMUM supported PHP version, not the development version- Use
composer config platform.php 8.3.0before building release packages - Run
composer update --no-dev --optimize-autoloaderto rebuild dependencies
- Use
- CRITICAL: WordPress requires plugins in a subdirectory structure
- Run zip from the
plugins/parent directory, NOT from within the plugin directory - Package must extract to
wc-licensed-product/subdirectory with main file atwc-licensed-product/wc-licensed-product.php - Correct command:
cd /wp-content/plugins/ && zip -r wc-licensed-product/releases/wc-licensed-product-x.x.x.zip wc-licensed-product ... - Wrong: Running zip from inside the plugin directory creates files at root level
- Run zip from the
- CRITICAL: Exclude symlinks explicitly - zip follows symlinks by default
- Always use
-x "wc-licensed-product/wp-core" -x "wc-licensed-product/wp-core/*" -x "wc-licensed-product/wp-plugins" -x "wc-licensed-product/wp-plugins/*"to exclude development symlinks - Otherwise the entire linked directory contents will be included in the package
- Always use
- Exclusion patterns must match the relative path structure used in zip command
- Always verify the package structure with
unzip -lbefore distribution- Check all files are prefixed with
wc-licensed-product/ - Verify main file is at
wc-licensed-product/wc-licensed-product.php - Check for duplicate entries (indicates multiple builds in same archive)
- Check all files are prefixed with
- Test installation on the minimum supported PHP version before final deployment
- Releases are stored in
releases/including checksums - Track release changes in a single
CHANGELOG.mdfile - Bump the version number to either bugfix release versions or on new features minor release versions
- CRITICAL: WordPress reads version from TWO places - BOTH must be updated:
- Plugin header comment
Version: x.x.x(line ~6 in wp-artists.php) - WordPress uses THIS for admin display - PHP constant
WC_LICENSED_PRODUCT_VERSION(line ~25) - Used internally by the plugin
- If only the constant is updated, WordPress will show the old version in Plugins list
- Plugin header comment
Important Git Notes:
- Default branch while development is
dev - Create releases from branch
mainafter merging branchdev - Tags should use format
vX.X.X(e.g.,v1.1.22), start with v0.1.0 - Use annotated tags (
-a) not lightweight tags - Commit messages should follow the established format with Claude Code attribution
.claude/settings.local.jsonchanges are typically local-only (stash before rebasing)
What Gets Released
- All plugin source files
- Compiled vendor dependencies
- Translation files (.mo compiled from .po)
- Assets (CSS, JS)
- Documentation (README, CHANGELOG, etc.)
What's Excluded
- Git metadata (
.git/) - Development files (
.vscode/,.claude/,CLAUDE.md,wp-core,wp-plugins) - Logs and cache files
- Previous releases
composer.lock(butvendor/is included)
For AI Assistants:
When starting a new session on this project:
- Read this CLAUDE.md file first
- Semantic versioning follows the
MAJOR.MINOR.BUGFIXpattern - Check git log for recent changes
- Verify you're on the
devbranch before making changes - Run
composer installif vendor/ is missing - Test changes before committing
- Follow commit message format with Claude Code attribution
- Update this session history section with learnings
- Never commit backup files (
*.po~,*.bak, etc.) - checkgit statusbefore committing - Follow markdown linting rules (see below)
Always refer to this document when starting work on this project.
Markdown Linting Rules
When editing CLAUDE.md or other markdown files, follow these rules to avoid linting errors:
-
MD031 - Blank lines around fenced code blocks: Always add a blank line before and after fenced code blocks, even when they follow list items. Example of correct format:
-
Item label:
(blank line here) ```php code example ``` (blank line here)
-
-
MD056 - Table column count: Table separators must have matching column counts and proper spacing. Use consistent dash lengths that match column header widths.
-
MD009 - No trailing spaces: Remove trailing whitespace from lines
-
MD012 - No multiple consecutive blank lines: Use only single blank lines between sections
-
MD040 - Fenced code blocks should have a language specified: Always add a language identifier to code blocks (e.g.,
txt,bash,php). For shortcode examples, usetxt. -
MD032 - Lists should be surrounded by blank lines: Add a blank line before AND after list blocks, including after bold labels like
**Attributes:**. -
MD034 - Bare URLs: Wrap URLs in angle brackets (e.g.,
<https://example.com>) or use markdown link syntax[text](url). -
Author section formatting: Use a heading (
### Name) instead of bold (**Name**) for the author name to maintain consistent document structure.