You've already forked wc-tier-and-package-prices
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e17bdefe06 | |||
| fa26247d1b | |||
| a4b84f7e41 | |||
| 2e9c948a07 | |||
| dd4333bd11 | |||
| b909221ae2 | |||
| d80c9d90f9 | |||
| 2bf0cd82fe | |||
| 9451cc1965 | |||
| 02b0308058 | |||
| 38e9506d4e | |||
| 74cc56005e | |||
| 136eed2bdd | |||
| 178f86f3e6 | |||
| 7286459ff2 | |||
| cbe758267e |
217
.gitea/workflows/release.yml
Normal file
217
.gitea/workflows/release.yml
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
name: Create Release Package
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Setup PHP
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: '8.3'
|
||||||
|
extensions: mbstring, xml, zip, intl, gettext
|
||||||
|
tools: composer:v2
|
||||||
|
|
||||||
|
- name: Get version from tag
|
||||||
|
id: version
|
||||||
|
run: |
|
||||||
|
VERSION=${GITHUB_REF_NAME#v}
|
||||||
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||||
|
echo "Building version: $VERSION"
|
||||||
|
|
||||||
|
- name: Validate composer.json
|
||||||
|
run: composer validate --strict
|
||||||
|
|
||||||
|
- name: Install Composer dependencies (production)
|
||||||
|
run: |
|
||||||
|
composer config platform.php 8.3.0
|
||||||
|
composer install --no-dev --optimize-autoloader --no-interaction
|
||||||
|
|
||||||
|
- name: Install gettext
|
||||||
|
run: apt-get update && apt-get install -y gettext
|
||||||
|
|
||||||
|
- name: Compile translations
|
||||||
|
run: |
|
||||||
|
for po in languages/*.po; do
|
||||||
|
if [ -f "$po" ]; then
|
||||||
|
mo="${po%.po}.mo"
|
||||||
|
echo "Compiling $po to $mo"
|
||||||
|
msgfmt -o "$mo" "$po"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Verify plugin version matches tag
|
||||||
|
run: |
|
||||||
|
PLUGIN_VERSION=$(grep -oP "Version:\s*\K[0-9]+\.[0-9]+\.[0-9]+" wc-tier-and-package-prices.php | head -1)
|
||||||
|
TAG_VERSION=${{ steps.version.outputs.version }}
|
||||||
|
if [ "$PLUGIN_VERSION" != "$TAG_VERSION" ]; then
|
||||||
|
echo "Error: Plugin version ($PLUGIN_VERSION) does not match tag version ($TAG_VERSION)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "Version verified: $PLUGIN_VERSION"
|
||||||
|
|
||||||
|
- name: Create release directory
|
||||||
|
run: mkdir -p releases
|
||||||
|
|
||||||
|
- name: Build release package
|
||||||
|
run: |
|
||||||
|
VERSION=${{ steps.version.outputs.version }}
|
||||||
|
PLUGIN_NAME="wc-tier-and-package-prices"
|
||||||
|
RELEASE_FILE="releases/${PLUGIN_NAME}-${VERSION}.zip"
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
zip -r "${PLUGIN_NAME}/${RELEASE_FILE}" "${PLUGIN_NAME}" \
|
||||||
|
-x "${PLUGIN_NAME}/.git/*" \
|
||||||
|
-x "${PLUGIN_NAME}/.gitea/*" \
|
||||||
|
-x "${PLUGIN_NAME}/.github/*" \
|
||||||
|
-x "${PLUGIN_NAME}/.vscode/*" \
|
||||||
|
-x "${PLUGIN_NAME}/.idea/*" \
|
||||||
|
-x "${PLUGIN_NAME}/.claude/*" \
|
||||||
|
-x "${PLUGIN_NAME}/CLAUDE.md" \
|
||||||
|
-x "${PLUGIN_NAME}/wordpress" \
|
||||||
|
-x "${PLUGIN_NAME}/wordpress/*" \
|
||||||
|
-x "${PLUGIN_NAME}/core" \
|
||||||
|
-x "${PLUGIN_NAME}/core/*" \
|
||||||
|
-x "${PLUGIN_NAME}/wp-core" \
|
||||||
|
-x "${PLUGIN_NAME}/wp-core/*" \
|
||||||
|
-x "${PLUGIN_NAME}/releases/*" \
|
||||||
|
-x "${PLUGIN_NAME}/composer.lock" \
|
||||||
|
-x "${PLUGIN_NAME}/*.log" \
|
||||||
|
-x "${PLUGIN_NAME}/logs/*" \
|
||||||
|
-x "${PLUGIN_NAME}/.gitignore" \
|
||||||
|
-x "${PLUGIN_NAME}/.gitmodules" \
|
||||||
|
-x "${PLUGIN_NAME}/.editorconfig" \
|
||||||
|
-x "${PLUGIN_NAME}/phpcs.xml*" \
|
||||||
|
-x "${PLUGIN_NAME}/phpunit.xml*" \
|
||||||
|
-x "${PLUGIN_NAME}/tests/*" \
|
||||||
|
-x "${PLUGIN_NAME}/templates/cache/*" \
|
||||||
|
-x "${PLUGIN_NAME}/notes.*" \
|
||||||
|
-x "${PLUGIN_NAME}/*.po~" \
|
||||||
|
-x "${PLUGIN_NAME}/*.bak" \
|
||||||
|
-x "${PLUGIN_NAME}/lib/*/.git/*" \
|
||||||
|
-x "${PLUGIN_NAME}/lib/*/CLAUDE.md" \
|
||||||
|
-x "${PLUGIN_NAME}/vendor/magdev/*/.git/*" \
|
||||||
|
-x "${PLUGIN_NAME}/vendor/magdev/*/CLAUDE.md" \
|
||||||
|
-x "*.DS_Store" \
|
||||||
|
-x "*Thumbs.db"
|
||||||
|
|
||||||
|
cd "${PLUGIN_NAME}"
|
||||||
|
echo "Created: ${RELEASE_FILE}"
|
||||||
|
ls -lh "${RELEASE_FILE}"
|
||||||
|
|
||||||
|
- name: Generate checksums
|
||||||
|
run: |
|
||||||
|
VERSION=${{ steps.version.outputs.version }}
|
||||||
|
PLUGIN_NAME="wc-tier-and-package-prices"
|
||||||
|
RELEASE_FILE="releases/${PLUGIN_NAME}-${VERSION}.zip"
|
||||||
|
|
||||||
|
cd releases
|
||||||
|
sha256sum "${PLUGIN_NAME}-${VERSION}.zip" > "${PLUGIN_NAME}-${VERSION}.zip.sha256"
|
||||||
|
echo "SHA256:"
|
||||||
|
cat "${PLUGIN_NAME}-${VERSION}.zip.sha256"
|
||||||
|
|
||||||
|
- name: Verify package structure
|
||||||
|
run: |
|
||||||
|
set +o pipefail
|
||||||
|
VERSION=${{ steps.version.outputs.version }}
|
||||||
|
PLUGIN_NAME="wc-tier-and-package-prices"
|
||||||
|
|
||||||
|
echo "Package contents (first 50 entries):"
|
||||||
|
unzip -l "releases/${PLUGIN_NAME}-${VERSION}.zip" | head -50 || true
|
||||||
|
|
||||||
|
# Verify main plugin file exists
|
||||||
|
if unzip -l "releases/${PLUGIN_NAME}-${VERSION}.zip" | grep -q "${PLUGIN_NAME}/${PLUGIN_NAME}.php"; then
|
||||||
|
echo "✓ Main plugin file at correct location"
|
||||||
|
else
|
||||||
|
echo "✗ Error: Main plugin file not found at ${PLUGIN_NAME}/${PLUGIN_NAME}.php"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify vendor directory included
|
||||||
|
if unzip -l "releases/${PLUGIN_NAME}-${VERSION}.zip" | grep -q "${PLUGIN_NAME}/vendor/"; then
|
||||||
|
echo "✓ Vendor directory included"
|
||||||
|
else
|
||||||
|
echo "✗ Error: Vendor directory not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify excluded files are not present
|
||||||
|
if unzip -l "releases/${PLUGIN_NAME}-${VERSION}.zip" | grep -qE "CLAUDE\.md|\.claude/|\.git/|wordpress/"; then
|
||||||
|
echo "✗ Error: Excluded files found in package"
|
||||||
|
unzip -l "releases/${PLUGIN_NAME}-${VERSION}.zip" | grep -E "CLAUDE\.md|\.claude/|\.git/|wordpress/"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "✓ No excluded files in package"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Extract changelog for release notes
|
||||||
|
id: changelog
|
||||||
|
run: |
|
||||||
|
VERSION=${{ steps.version.outputs.version }}
|
||||||
|
|
||||||
|
# Extract release notes from CHANGELOG.md
|
||||||
|
NOTES=$(sed -n "/^## \[${VERSION}\]/,/^## \[/p" CHANGELOG.md | sed '$ d' | tail -n +2)
|
||||||
|
if [ -z "$NOTES" ]; then
|
||||||
|
NOTES="Release version ${VERSION}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$NOTES" > release_notes.txt
|
||||||
|
echo "Release notes extracted"
|
||||||
|
|
||||||
|
- name: Create Gitea Release
|
||||||
|
env:
|
||||||
|
GITEA_TOKEN: ${{ secrets.SRC_GITEA_TOKEN }}
|
||||||
|
run: |
|
||||||
|
VERSION=${{ steps.version.outputs.version }}
|
||||||
|
TAG_NAME=${{ github.ref_name }}
|
||||||
|
PLUGIN_NAME="wc-tier-and-package-prices"
|
||||||
|
|
||||||
|
# Check if this is a prerelease (contains hyphen like v1.0.0-beta)
|
||||||
|
PRERELEASE="false"
|
||||||
|
if [[ "$TAG_NAME" == *-* ]]; then
|
||||||
|
PRERELEASE="true"
|
||||||
|
fi
|
||||||
|
|
||||||
|
BODY=$(cat release_notes.txt)
|
||||||
|
|
||||||
|
# Create release via Gitea API
|
||||||
|
RELEASE_RESPONSE=$(curl -s -X POST \
|
||||||
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{\"tag_name\": \"${TAG_NAME}\", \"name\": \"Release ${VERSION}\", \"body\": $(echo "$BODY" | jq -Rs .), \"draft\": false, \"prerelease\": ${PRERELEASE}}" \
|
||||||
|
"${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}/releases")
|
||||||
|
|
||||||
|
RELEASE_ID=$(echo "$RELEASE_RESPONSE" | jq -r '.id')
|
||||||
|
|
||||||
|
if [ "$RELEASE_ID" == "null" ] || [ -z "$RELEASE_ID" ]; then
|
||||||
|
echo "Failed to create release:"
|
||||||
|
echo "$RELEASE_RESPONSE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Created release ID: $RELEASE_ID"
|
||||||
|
|
||||||
|
# Upload release assets
|
||||||
|
for file in "releases/${PLUGIN_NAME}-${VERSION}.zip" "releases/${PLUGIN_NAME}-${VERSION}.zip.sha256"; do
|
||||||
|
if [ -f "$file" ]; then
|
||||||
|
FILENAME=$(basename "$file")
|
||||||
|
echo "Uploading $FILENAME..."
|
||||||
|
curl -s -X POST \
|
||||||
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
|
-H "Content-Type: application/octet-stream" \
|
||||||
|
--data-binary "@$file" \
|
||||||
|
"${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets?name=${FILENAME}"
|
||||||
|
echo "Uploaded $FILENAME"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Release created successfully: ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/releases/tag/${TAG_NAME}"
|
||||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -37,3 +37,9 @@ wp-core
|
|||||||
|
|
||||||
# Releases (not tracked in git)
|
# Releases (not tracked in git)
|
||||||
/releases/
|
/releases/
|
||||||
|
|
||||||
|
# Claude Code local settings
|
||||||
|
.claude/settings.json
|
||||||
|
|
||||||
|
# Marketing texts (not for public distribution)
|
||||||
|
MARKETING.md
|
||||||
|
|||||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "lib/wc-licensed-product-client"]
|
||||||
|
path = lib/wc-licensed-product-client
|
||||||
|
url = ../wc-licensed-product-client.git
|
||||||
111
CHANGELOG.md
111
CHANGELOG.md
@@ -5,6 +5,117 @@ All notable changes to WooCommerce Tier and Package Prices will be documented in
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [1.4.1] - 2026-02-03
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **Localhost License Bypass**: License validation is automatically bypassed for localhost environments
|
||||||
|
- Supports localhost, 127.0.0.1, ::1 (IPv6), `*.localhost`, `*.local`, `*.test`, `*.example`, `*.invalid`
|
||||||
|
- Private IP ranges (Docker, VMs) are also recognized as localhost
|
||||||
|
- Displays "(Localhost environment - license validation bypassed)" in License Status
|
||||||
|
|
||||||
|
- **Self-Licensing Bypass**: License validation is bypassed when the site URL matches the license server URL
|
||||||
|
- Useful for testing the plugin on the license server itself
|
||||||
|
- Displays "(Self-licensing server - license validation bypassed)" in License Status
|
||||||
|
|
||||||
|
- **Auto-Update System**: Plugin can now receive updates directly from the license server
|
||||||
|
- New "Auto-Updates" settings tab under WooCommerce > Tier & Package Prices
|
||||||
|
- **Enable Update Notifications**: Toggle to check for available updates (default: enabled)
|
||||||
|
- **Automatically Install Updates**: Optional auto-install when WordPress performs background updates
|
||||||
|
- **Check Frequency**: Configurable hours between update checks (1-168 hours, default: 12)
|
||||||
|
- **Update Status**: Shows current version and available update with "Check for Updates" button
|
||||||
|
- Updates appear in WordPress Dashboard > Updates with full plugin info
|
||||||
|
|
||||||
|
- **New Classes**:
|
||||||
|
- `WC_TPP_License_Checker`: Singleton class handling license validation with localhost/self-licensing bypass
|
||||||
|
- `WC_TPP_Update_Checker`: Singleton class integrating with WordPress plugin update system
|
||||||
|
|
||||||
|
### Technical Details
|
||||||
|
|
||||||
|
**License Checker Features**:
|
||||||
|
|
||||||
|
- `is_localhost()`: Detects localhost environments using multiple patterns
|
||||||
|
- `is_self_licensing()`: Compares license server URL with site URL
|
||||||
|
- `is_license_valid()`: Main entry point with bypass logic
|
||||||
|
- `get_bypass_reason()`: Returns 'localhost', 'self_licensing', or null
|
||||||
|
- Cached validation (1 hour success, 5 minutes error)
|
||||||
|
|
||||||
|
**Update Checker Features**:
|
||||||
|
|
||||||
|
- Hooks into `pre_set_site_transient_update_plugins` for update detection
|
||||||
|
- Hooks into `plugins_api` for update modal information
|
||||||
|
- Hooks into `http_request_args` for license authentication
|
||||||
|
- Hooks into `auto_update_plugin` for background updates
|
||||||
|
- Can be disabled via `WC_TPP_DISABLE_AUTO_UPDATE` constant
|
||||||
|
|
||||||
|
**New Settings Options**:
|
||||||
|
|
||||||
|
- `wc_tpp_update_notification_enabled` (yes/no, default: yes)
|
||||||
|
- `wc_tpp_auto_install_enabled` (yes/no, default: no)
|
||||||
|
- `wc_tpp_update_check_frequency` (number, default: 12)
|
||||||
|
|
||||||
|
**Update Server Endpoint**:
|
||||||
|
|
||||||
|
- POST to `/wp-json/wc-licensed-product/v1/update-check`
|
||||||
|
- Request body: `{license_key, domain, plugin_slug, current_version}`
|
||||||
|
- Response: `{success, update_available, version, download_url, ...}`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [1.4.0] - 2026-01-29
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **Gitea CI/CD Release Pipeline**: Automated release workflow triggered on version tags
|
||||||
|
- Validates plugin version matches tag version
|
||||||
|
- Installs production Composer dependencies
|
||||||
|
- Compiles translation files (.po to .mo)
|
||||||
|
- Creates release package with proper exclusions
|
||||||
|
- Generates SHA256 checksum
|
||||||
|
- Publishes release to Gitea with changelog notes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [1.3.1] - 2026-01-27
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **Switched to SecureLicenseClient**: Upgraded from basic `LicenseClient` to `SecureLicenseClient` with HMAC-SHA256 response signature verification for enhanced security against tampering and replay attacks
|
||||||
|
|
||||||
|
- **Added Server Secret Configuration**: New "Server Secret" field in License settings for secure communication with the license server
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **Rate Limit Handling**: Added proper handling of `RateLimitExceededException` with user-friendly messages showing retry wait time
|
||||||
|
- **Signature Verification Error Handling**: Added dedicated handling for `SignatureException` when response signatures fail verification
|
||||||
|
- **URL Validation Error Handling**: Added handling for `InvalidArgumentException` from SSRF protection in the license client
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- Response signatures are now verified using HMAC-SHA256 with license-specific derived keys (RFC 5869 HKDF)
|
||||||
|
- The license client now validates server URLs to prevent SSRF attacks (blocks private IP ranges)
|
||||||
|
- HTTP connections require HTTPS unless explicitly allowed for localhost testing
|
||||||
|
|
||||||
|
### Technical Details
|
||||||
|
|
||||||
|
**License Client Upgrade**:
|
||||||
|
|
||||||
|
- Changed from `LicenseClient` to `SecureLicenseClient`
|
||||||
|
- Added `serverSecret` parameter for signature verification
|
||||||
|
- Library updated from `v0.1.0` to `dev-main` with new security features
|
||||||
|
|
||||||
|
**New Exception Handling**:
|
||||||
|
|
||||||
|
- `RateLimitExceededException` - shows retry time to user
|
||||||
|
- `SignatureException` - indicates server secret mismatch
|
||||||
|
- `InvalidArgumentException` - invalid/blocked URL detected
|
||||||
|
|
||||||
|
**New Settings Field**:
|
||||||
|
|
||||||
|
- `wc_tpp_license_server_secret` (password type) for the shared secret
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## [1.3.0] - 2026-01-25
|
## [1.3.0] - 2026-01-25
|
||||||
|
|
||||||
### Breaking Changes
|
### Breaking Changes
|
||||||
|
|||||||
411
CLAUDE.md
411
CLAUDE.md
@@ -1,7 +1,7 @@
|
|||||||
# WooCommerce Tier and Package Prices - AI Context Document
|
# WooCommerce Tier and Package Prices - AI Context Document
|
||||||
|
|
||||||
**Last Updated:** 2026-01-25
|
**Last Updated:** 2026-02-03
|
||||||
**Current Version:** 1.3.0
|
**Current Version:** 1.4.1
|
||||||
**Author:** Marco Graetsch
|
**Author:** Marco Graetsch
|
||||||
**Project Status:** Production-ready WordPress plugin
|
**Project Status:** Production-ready WordPress plugin
|
||||||
|
|
||||||
@@ -20,9 +20,9 @@ This project is proudly **"vibe-coded"** using Claude.AI - the entire codebase w
|
|||||||
|
|
||||||
**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`. Do not add completed versions here - document them in the Session History section at the end of this file. Always keep the `Known Bugs` section and create a section with the next bugfix and minor version after a release.
|
**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`. Do not add completed versions here - document them in the Session History section at the end of this file. Always keep the `Known Bugs` section and create a section with the next bugfix and minor version after a release.
|
||||||
|
|
||||||
### Version 1.3.1
|
### Version 1.4.2
|
||||||
|
|
||||||
- TBD
|
- No planned features yet
|
||||||
|
|
||||||
## Technical Stack
|
## Technical Stack
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ This project is proudly **"vibe-coded"** using Claude.AI - the entire codebase w
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"twig/twig": "^3.0",
|
"twig/twig": "^3.0",
|
||||||
"magdev/wc-licensed-product-client": "^0.1",
|
"magdev/wc-licensed-product-client": "dev-main",
|
||||||
"symfony/http-client": "^7.0",
|
"symfony/http-client": "^7.0",
|
||||||
"psr/log": "^3.0",
|
"psr/log": "^3.0",
|
||||||
"psr/cache": "^3.0",
|
"psr/cache": "^3.0",
|
||||||
@@ -55,6 +55,8 @@ This project is proudly **"vibe-coded"** using Claude.AI - the entire codebase w
|
|||||||
```txt
|
```txt
|
||||||
wc-tier-and-package-prices/
|
wc-tier-and-package-prices/
|
||||||
├── wc-tier-and-package-prices.php # Main plugin file (entry point)
|
├── wc-tier-and-package-prices.php # Main plugin file (entry point)
|
||||||
|
├── .gitea/workflows/
|
||||||
|
│ └── release.yml # CI/CD release pipeline
|
||||||
├── includes/ # PHP classes
|
├── includes/ # PHP classes
|
||||||
│ ├── class-wc-tpp-admin.php # Admin settings integration
|
│ ├── class-wc-tpp-admin.php # Admin settings integration
|
||||||
│ ├── class-wc-tpp-settings.php # WooCommerce settings page
|
│ ├── class-wc-tpp-settings.php # WooCommerce settings page
|
||||||
@@ -81,7 +83,9 @@ wc-tier-and-package-prices/
|
|||||||
│ ├── *.pot # Translation template
|
│ ├── *.pot # Translation template
|
||||||
│ ├── *.po # Translation sources
|
│ ├── *.po # Translation sources
|
||||||
│ └── *.mo # Compiled translations
|
│ └── *.mo # Compiled translations
|
||||||
├── vendor/ # Composer dependencies (included in releases)
|
├── lib/ # Bundled libraries (git submodules)
|
||||||
|
│ └── wc-licensed-product-client/ # License client library (v0.2.x)
|
||||||
|
├── vendor/ # Composer dependencies (generated)
|
||||||
├── releases/ # Release packages (not in git)
|
├── releases/ # Release packages (not in git)
|
||||||
└── *.md # Documentation files
|
└── *.md # Documentation files
|
||||||
|
|
||||||
@@ -353,136 +357,133 @@ Symptom: Help icon appearing far from label text at container edge
|
|||||||
|
|
||||||
## Release Process
|
## Release Process
|
||||||
|
|
||||||
### Version Bumping
|
### Automated CI/CD Pipeline (Recommended)
|
||||||
|
|
||||||
Update version in 3 places:
|
Since v1.4.0, releases are automated via Gitea CI/CD. The pipeline is triggered when a version tag is pushed.
|
||||||
|
|
||||||
1. `wc-tier-and-package-prices.php` - Plugin header comment (line 7)
|
**Workflow:**
|
||||||
2. `wc-tier-and-package-prices.php` - `WC_TPP_VERSION` constant (line 26)
|
|
||||||
3. `composer.json` - version field (optional, not critical)
|
|
||||||
|
|
||||||
### Creating Release Package
|
|
||||||
|
|
||||||
**CRITICAL:** The zip command must be run from the **parent directory** of the plugin folder to create proper archive structure.
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# From parent directory (/home/magdev/workspaces/php)
|
# 1. Update version in 3 places
|
||||||
cd /home/magdev/workspaces/php
|
# - wc-tier-and-package-prices.php (header comment, line 7)
|
||||||
|
# - wc-tier-and-package-prices.php (WC_TPP_VERSION constant)
|
||||||
|
# - composer.json (version field)
|
||||||
|
|
||||||
# Create zip excluding dev files - note the correct path structure
|
# 2. Update CHANGELOG.md with release notes
|
||||||
zip -r wc-tier-and-package-prices/releases/wc-tier-and-package-prices-X.X.X.zip wc-tier-and-package-prices/ \
|
|
||||||
-x 'wc-tier-and-package-prices/.git*' \
|
|
||||||
'wc-tier-and-package-prices/*.log' \
|
|
||||||
'wc-tier-and-package-prices/.claude/*' \
|
|
||||||
'wc-tier-and-package-prices/CLAUDE.md' \
|
|
||||||
'wc-tier-and-package-prices/releases/*' \
|
|
||||||
'wc-tier-and-package-prices/node_modules/*' \
|
|
||||||
'wc-tier-and-package-prices/.DS_Store' \
|
|
||||||
'wc-tier-and-package-prices/Thumbs.db' \
|
|
||||||
'wc-tier-and-package-prices/.vscode/*' \
|
|
||||||
'wc-tier-and-package-prices/.idea/*' \
|
|
||||||
'wc-tier-and-package-prices/*.sublime-*' \
|
|
||||||
'wc-tier-and-package-prices/notes.*' \
|
|
||||||
'wc-tier-and-package-prices/logs/*' \
|
|
||||||
'wc-tier-and-package-prices/templates/cache/*' \
|
|
||||||
'wc-tier-and-package-prices/composer.lock'
|
|
||||||
|
|
||||||
# Return to project directory
|
# 3. Commit and push to dev
|
||||||
cd wc-tier-and-package-prices
|
git add -A && git commit -m "Version X.X.X - [description]
|
||||||
|
|
||||||
# Generate SHA256 checksum
|
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>"
|
||||||
cd releases
|
|
||||||
sha256sum wc-tier-and-package-prices-X.X.X.zip > wc-tier-and-package-prices-X.X.X.zip.sha256
|
|
||||||
cd ..
|
|
||||||
```
|
|
||||||
|
|
||||||
**IMPORTANT NOTES:**
|
|
||||||
|
|
||||||
- The `vendor/` directory MUST be included in releases (Twig dependency required for runtime)
|
|
||||||
- Running zip from wrong directory creates empty or malformed archives
|
|
||||||
- Exclusion patterns must match the relative path structure used in zip command
|
|
||||||
- Always verify the package with `unzip -l` and test extraction before committing
|
|
||||||
|
|
||||||
### Verification Steps
|
|
||||||
|
|
||||||
After creating the release package, always verify:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Check package size (should be ~400-450KB, NOT 8MB+ or near 0)
|
|
||||||
ls -lh releases/wc-tier-and-package-prices-X.X.X.zip
|
|
||||||
|
|
||||||
# Verify exclusions worked
|
|
||||||
unzip -l releases/wc-tier-and-package-prices-X.X.X.zip | grep -E "CLAUDE\.md|\.claude/|\.git" && echo "ERROR: Excluded files found!" || echo "OK: No excluded files"
|
|
||||||
|
|
||||||
# Test extraction
|
|
||||||
cd /tmp && rm -rf test-extract && unzip -q /path/to/releases/wc-tier-and-package-prices-X.X.X.zip -d test-extract && ls -la test-extract/wc-tier-and-package-prices/
|
|
||||||
|
|
||||||
# Verify version in extracted package
|
|
||||||
head -30 /tmp/test-extract/wc-tier-and-package-prices/wc-tier-and-package-prices.php | grep -E "Version:|WC_TPP_VERSION"
|
|
||||||
|
|
||||||
# Verify template changes (if applicable)
|
|
||||||
grep 'class="regular"' /tmp/test-extract/wc-tier-and-package-prices/templates/admin/*.twig
|
|
||||||
```
|
|
||||||
|
|
||||||
### Git Workflow for Releases
|
|
||||||
|
|
||||||
**Standard workflow:** Work on `dev` branch → merge to `main` → tag → push
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. Ensure you're on dev branch with all changes committed
|
|
||||||
git checkout dev
|
|
||||||
git add [files]
|
|
||||||
git commit -m "Release version X.X.X - [description]
|
|
||||||
|
|
||||||
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
|
||||||
|
|
||||||
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>"
|
|
||||||
|
|
||||||
# 2. Merge dev to main
|
|
||||||
git checkout main
|
|
||||||
git merge dev --no-edit # Should be fast-forward
|
|
||||||
|
|
||||||
# 3. Create annotated tag
|
|
||||||
git tag -a vX.X.X -m "Release version X.X.X - [description]"
|
|
||||||
|
|
||||||
# 4. Push everything
|
|
||||||
git push origin main
|
|
||||||
git push origin vX.X.X
|
|
||||||
|
|
||||||
# 5. Update dev and push
|
|
||||||
git checkout dev
|
|
||||||
git rebase main # Should be up-to-date already
|
|
||||||
git push origin dev
|
git push origin dev
|
||||||
|
|
||||||
# 6. If you have uncommitted local changes (like .claude/settings.local.json)
|
# 4. Merge to main and push
|
||||||
git stash push -m "Local development settings"
|
git checkout main && git merge dev --no-edit && git push origin main
|
||||||
# ... do git operations ...
|
|
||||||
git stash pop
|
# 5. Create and push tag (triggers CI/CD)
|
||||||
|
git tag -a vX.X.X -m "Release version X.X.X - [description]"
|
||||||
|
git push origin vX.X.X
|
||||||
|
|
||||||
|
# 6. Switch back to dev
|
||||||
|
git checkout dev
|
||||||
```
|
```
|
||||||
|
|
||||||
**Important Git Notes:**
|
**What the CI/CD Pipeline Does:**
|
||||||
|
|
||||||
- Always commit from `dev` branch first
|
1. Checks out code with git submodules (`submodules: recursive`)
|
||||||
- Tags should use format `vX.X.X` (e.g., `v1.1.22`)
|
2. Sets up PHP 8.3 with required extensions
|
||||||
- Use annotated tags (`-a`) not lightweight tags
|
3. Validates `composer.json`
|
||||||
- Commit messages should follow the established format with Claude Code attribution
|
4. Installs production Composer dependencies (`--no-dev`)
|
||||||
- `.claude/settings.local.json` changes are typically local-only (stash before rebasing)
|
5. Compiles translation files (.po → .mo)
|
||||||
|
6. Validates plugin version matches tag version
|
||||||
|
7. Creates release package with proper exclusions
|
||||||
|
8. Generates SHA256 checksum
|
||||||
|
9. Verifies package structure
|
||||||
|
10. Extracts changelog notes for release description
|
||||||
|
11. Creates Gitea release with assets
|
||||||
|
|
||||||
|
**Pipeline Location:** `.gitea/workflows/release.yml`
|
||||||
|
|
||||||
|
**Required Secret:** `SRC_GITEA_TOKEN` - Gitea API token for creating releases
|
||||||
|
|
||||||
|
### Git Submodule: wc-licensed-product-client
|
||||||
|
|
||||||
|
The `magdev/wc-licensed-product-client` library is bundled as a git submodule in `lib/` to avoid private repository authentication during CI/CD and to prevent conflicts with Composer's `vendor/` directory.
|
||||||
|
|
||||||
|
**Location:** `lib/wc-licensed-product-client/`
|
||||||
|
|
||||||
|
**Submodule URL:** Relative path `../wc-licensed-product-client.git` (works with Gitea CI/CD)
|
||||||
|
|
||||||
|
**Updating the submodule:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Update to a specific tag
|
||||||
|
cd lib/wc-licensed-product-client
|
||||||
|
git fetch --tags
|
||||||
|
git checkout v0.2.3 # or desired version
|
||||||
|
cd ../..
|
||||||
|
git add lib/wc-licensed-product-client
|
||||||
|
git commit -m "Update wc-licensed-product-client to v0.2.3"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Composer Configuration:**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"repositories": [
|
||||||
|
{
|
||||||
|
"type": "path",
|
||||||
|
"url": "lib/wc-licensed-product-client"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"magdev/wc-licensed-product-client": "^0.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Composer creates a symlink in `vendor/magdev/wc-licensed-product-client` pointing to `lib/wc-licensed-product-client`.
|
||||||
|
|
||||||
|
### Manual Release (Legacy)
|
||||||
|
|
||||||
|
For manual releases without CI/CD, run from the **parent directory**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/magdev/workspaces/php/wordpress/wp-content/plugins
|
||||||
|
|
||||||
|
zip -r wc-tier-and-package-prices/releases/wc-tier-and-package-prices-X.X.X.zip wc-tier-and-package-prices/ \
|
||||||
|
-x 'wc-tier-and-package-prices/.git/*' \
|
||||||
|
-x 'wc-tier-and-package-prices/.gitea/*' \
|
||||||
|
-x 'wc-tier-and-package-prices/.claude/*' \
|
||||||
|
-x 'wc-tier-and-package-prices/CLAUDE.md' \
|
||||||
|
-x 'wc-tier-and-package-prices/releases/*' \
|
||||||
|
-x 'wc-tier-and-package-prices/composer.lock' \
|
||||||
|
-x 'wc-tier-and-package-prices/*.log' \
|
||||||
|
-x 'wc-tier-and-package-prices/.gitignore' \
|
||||||
|
-x 'wc-tier-and-package-prices/.gitmodules' \
|
||||||
|
-x 'wc-tier-and-package-prices/vendor/*/.git/*' \
|
||||||
|
-x '*.DS_Store'
|
||||||
|
|
||||||
|
cd wc-tier-and-package-prices/releases
|
||||||
|
sha256sum wc-tier-and-package-prices-X.X.X.zip > wc-tier-and-package-prices-X.X.X.zip.sha256
|
||||||
|
```
|
||||||
|
|
||||||
### What Gets Released
|
### What Gets Released
|
||||||
|
|
||||||
- All plugin source files
|
- All plugin source files
|
||||||
- Compiled vendor dependencies
|
- Compiled vendor dependencies (including submodule)
|
||||||
- Translation files (.mo compiled from .po)
|
- Translation files (.mo compiled from .po)
|
||||||
- Assets (CSS, JS)
|
- Assets (CSS, JS)
|
||||||
- Documentation (README, CHANGELOG, etc.)
|
- Documentation (README, CHANGELOG, etc.)
|
||||||
|
|
||||||
### What's Excluded
|
### What's Excluded
|
||||||
|
|
||||||
- Git metadata (`.git/`)
|
- Git metadata (`.git/`, `.gitmodules`)
|
||||||
|
- CI/CD workflows (`.gitea/`)
|
||||||
- Development files (`.vscode/`, `.claude/`, `CLAUDE.md`)
|
- Development files (`.vscode/`, `.claude/`, `CLAUDE.md`)
|
||||||
- Logs and cache files
|
- Logs and cache files
|
||||||
- Previous releases
|
- Previous releases
|
||||||
- `composer.lock` (but `vendor/` is included)
|
- `composer.lock`
|
||||||
|
|
||||||
## Testing Checklist
|
## Testing Checklist
|
||||||
|
|
||||||
@@ -1101,8 +1102,8 @@ if (!empty($tiers)) {
|
|||||||
|
|
||||||
### PHP
|
### PHP
|
||||||
|
|
||||||
- Minimum: 7.4
|
- Minimum: 8.3 (breaking change in v1.3.0)
|
||||||
- Uses modern PHP features (type hints acceptable in new code)
|
- Uses modern PHP features (type hints, named arguments, etc.)
|
||||||
- Composer autoloader handles namespacing
|
- Composer autoloader handles namespacing
|
||||||
|
|
||||||
### Browsers
|
### Browsers
|
||||||
@@ -1138,4 +1139,188 @@ The plugin architecture is solid and well-tested. Most bugs arise from:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Session History
|
||||||
|
|
||||||
|
### v1.3.0 Release Session (2026-01-25)
|
||||||
|
|
||||||
|
**Accomplished:**
|
||||||
|
|
||||||
|
1. Fixed known bugs from CLAUDE.md:
|
||||||
|
- Removed all releases from git tracking (`git rm --cached -r releases/`)
|
||||||
|
- Deleted all MD5 checksum files, keeping only SHA256
|
||||||
|
- Updated `.gitignore` to exclude `/releases/`
|
||||||
|
|
||||||
|
2. Implemented v1.3.0 features:
|
||||||
|
- Bumped PHP requirement from 7.4 to 8.3 (breaking change)
|
||||||
|
- Added PHP version check with admin notice for incompatible servers
|
||||||
|
- Added `magdev/wc-licensed-product-client` library integration
|
||||||
|
- Refactored settings page to use WooCommerce modern sub-tabs pattern (`get_own_sections()`)
|
||||||
|
- Created "General" and "License" sub-tabs
|
||||||
|
- Implemented license management with AJAX validation/activation
|
||||||
|
- Added license status caching via WordPress transients
|
||||||
|
- Added CSS styling for license status display
|
||||||
|
|
||||||
|
3. Updated all translation files:
|
||||||
|
- Added 28 new translation strings for license management
|
||||||
|
- Updated .pot template and all 7 .po files
|
||||||
|
- Compiled all .mo files
|
||||||
|
|
||||||
|
4. Created release package:
|
||||||
|
- Package size: 737KB (increased due to new dependencies)
|
||||||
|
- 642 files included (more due to license client library)
|
||||||
|
- SHA256 checksum generated
|
||||||
|
|
||||||
|
**Key Learnings:**
|
||||||
|
|
||||||
|
- WooCommerce settings sub-tabs use `get_own_sections()` and `get_settings_for_{section}_section()` pattern
|
||||||
|
- License client library `magdev/wc-licensed-product-client` is from private Gitea repo - requires `repositories` config in composer.json
|
||||||
|
- Package version was `^0.1` not `^1.0` - always check available versions before setting constraint
|
||||||
|
- Release package size increased from ~430KB to ~737KB due to new Composer dependencies
|
||||||
|
|
||||||
|
### v1.3.1 Release Session (2026-01-27)
|
||||||
|
|
||||||
|
**Accomplished:**
|
||||||
|
|
||||||
|
1. Reviewed server-implementation.md from license client library
|
||||||
|
2. Upgraded from `LicenseClient` to `SecureLicenseClient`:
|
||||||
|
- Added "Server Secret" configuration field in License settings tab
|
||||||
|
- Updated `get_license_client()` to use `SecureLicenseClient` with HMAC-SHA256 signature verification
|
||||||
|
- Updated JavaScript to pass `server_secret` in AJAX requests
|
||||||
|
|
||||||
|
3. Added comprehensive exception handling:
|
||||||
|
- `RateLimitExceededException` - Shows retry time to user
|
||||||
|
- `SignatureException` - Reports signature verification failures
|
||||||
|
- `InvalidArgumentException` - SSRF protection for private IP blocking
|
||||||
|
|
||||||
|
4. Updated Composer dependencies:
|
||||||
|
- Changed `magdev/wc-licensed-product-client` from `^0.1` to `dev-main`
|
||||||
|
- Library includes new security features (SSRF protection, response signatures)
|
||||||
|
|
||||||
|
5. Updated translations:
|
||||||
|
- Added 7 new translation strings for v1.3.1
|
||||||
|
- All 7 language files updated and compiled
|
||||||
|
|
||||||
|
6. Created release package:
|
||||||
|
- Package size: 775KB (after proper exclusions)
|
||||||
|
- 650 files included
|
||||||
|
- SHA256 checksum generated
|
||||||
|
|
||||||
|
7. Updated README.md:
|
||||||
|
- Documented license management feature
|
||||||
|
- Updated PHP requirement to 8.3
|
||||||
|
- Added v1.3.0 and v1.3.1 changelog entries
|
||||||
|
|
||||||
|
8. Re-released v1.3.1:
|
||||||
|
- Fixed release package exclusions (vendor .git dirs were included)
|
||||||
|
- Added `.claude/settings.json` to .gitignore
|
||||||
|
|
||||||
|
**Key Learnings:**
|
||||||
|
|
||||||
|
- `SecureLicenseClient` requires `serverSecret` parameter for HMAC verification
|
||||||
|
- The library's exception classes are in `Magdev\WcLicensedProductClient\Exception\` and `Magdev\WcLicensedProductClient\Security\` namespaces
|
||||||
|
- `RateLimitExceededException` has a `retryAfter` property (int seconds)
|
||||||
|
- Always check library documentation in `docs/server-implementation.md` for implementation requirements
|
||||||
|
|
||||||
|
**Release Package Learnings (CRITICAL):**
|
||||||
|
|
||||||
|
- Vendor directories installed via Composer (dev-main) contain their own `.git/` folders
|
||||||
|
- Release exclusion patterns must include `'wc-tier-and-package-prices/vendor/*/.git/*'` and `'wc-tier-and-package-prices/vendor/*/CLAUDE.md'`
|
||||||
|
- Run zip from `/home/magdev/workspaces/php/wordpress/wp-content/plugins/` (NOT `/home/magdev/workspaces/php/`)
|
||||||
|
- Always verify exclusions with: `unzip -l package.zip | grep -E "\.git/|CLAUDE\.md"`
|
||||||
|
|
||||||
|
### v1.4.0 Release Session (2026-01-29)
|
||||||
|
|
||||||
|
**Accomplished:**
|
||||||
|
|
||||||
|
1. Created Gitea CI/CD release pipeline:
|
||||||
|
- `.gitea/workflows/release.yml` - Automated release workflow
|
||||||
|
- Triggers on version tags (`v*`)
|
||||||
|
- Validates plugin version matches tag
|
||||||
|
- Installs production Composer dependencies
|
||||||
|
- Compiles translations (.po → .mo)
|
||||||
|
- Creates release package with proper exclusions
|
||||||
|
- Generates SHA256 checksum
|
||||||
|
- Publishes release to Gitea with changelog notes
|
||||||
|
|
||||||
|
2. Added git submodule for license client:
|
||||||
|
- Initially placed in `vendor/magdev/` - **FAILED** (Composer conflicts)
|
||||||
|
- Fixed: Moved to `lib/wc-licensed-product-client/` like wp-fedistream
|
||||||
|
- Uses relative URL `../wc-licensed-product-client.git`
|
||||||
|
- Pinned to v0.2.2 tag
|
||||||
|
- Avoids private repository authentication during CI/CD
|
||||||
|
|
||||||
|
3. Updated documentation:
|
||||||
|
- README.md - Added CI/CD section, updated file structure
|
||||||
|
- CLAUDE.md - Updated release process, added submodule docs
|
||||||
|
|
||||||
|
**Key Learnings:**
|
||||||
|
|
||||||
|
- **CRITICAL:** Git submodules should be in `lib/` NOT `vendor/` to avoid Composer conflicts
|
||||||
|
- Composer manages `vendor/` directory - don't put submodules there
|
||||||
|
- Use relative submodule URL (`../repo.git`) for Gitea CI/CD compatibility
|
||||||
|
- Use version constraint `^0.2` instead of `@dev` for stability
|
||||||
|
- Git submodules require `submodules: recursive` in checkout action
|
||||||
|
- Composer creates symlink from `vendor/` to `lib/` automatically
|
||||||
|
|
||||||
|
**CI/CD Pipeline Notes:**
|
||||||
|
|
||||||
|
- Pipeline file: `.gitea/workflows/release.yml`
|
||||||
|
- Required secret: `SRC_GITEA_TOKEN` for Gitea API access
|
||||||
|
- Uses `shivammathur/setup-php@v2` for PHP setup
|
||||||
|
- Uses `actions/checkout@v4` with `submodules: recursive`
|
||||||
|
- Modeled after working wp-fedistream implementation
|
||||||
|
|
||||||
|
### v1.4.1 Release Session (2026-02-03)
|
||||||
|
|
||||||
|
**Accomplished:**
|
||||||
|
|
||||||
|
1. Implemented localhost license bypass:
|
||||||
|
- Created `WC_TPP_License_Checker` class (singleton pattern)
|
||||||
|
- `is_localhost()` detects localhost environments: localhost, 127.0.0.1, ::1, `*.localhost`, `*.local`, `*.test`, `*.example`, `*.invalid`, and private IP ranges
|
||||||
|
- `is_self_licensing()` compares license server URL with site URL
|
||||||
|
- `is_license_valid()` returns true for localhost/self-licensing without server check
|
||||||
|
- Updated license status display to show bypass reason
|
||||||
|
|
||||||
|
2. Implemented auto-update system:
|
||||||
|
- Created `WC_TPP_Update_Checker` class (singleton pattern)
|
||||||
|
- Hooks into WordPress plugin update system (`pre_set_site_transient_update_plugins`, `plugins_api`, `http_request_args`, `auto_update_plugin`)
|
||||||
|
- Fetches update info from license server API endpoint
|
||||||
|
- Supports auto-install when WordPress performs background updates
|
||||||
|
- Configurable check frequency (1-168 hours)
|
||||||
|
|
||||||
|
3. Added Auto-Updates settings tab:
|
||||||
|
- Enable Update Notifications (checkbox, default: yes)
|
||||||
|
- Automatically Install Updates (checkbox, default: no, requires valid license)
|
||||||
|
- Check Frequency in Hours (number, default: 12)
|
||||||
|
- Update Status display with "Check for Updates" button
|
||||||
|
- AJAX handler for manual update checks
|
||||||
|
|
||||||
|
4. Updated all translation files:
|
||||||
|
- Added 23 new translation strings for v1.4.1
|
||||||
|
- All 7 language variants updated (de_DE, de_DE_informal, de_CH, de_CH_informal, fr_CH, it_CH, en_US)
|
||||||
|
- Compiled all .mo files
|
||||||
|
|
||||||
|
**Key Implementation Details:**
|
||||||
|
|
||||||
|
- License checker uses 1-hour cache for successful validation, 5-minute cache for errors
|
||||||
|
- Update checker respects `WC_TPP_DISABLE_AUTO_UPDATE` constant to disable updates
|
||||||
|
- Update server endpoint: `POST /wp-json/wc-licensed-product/v1/update-check`
|
||||||
|
- Both new classes are instantiated in main plugin's `includes()` method
|
||||||
|
- Auto-install requires valid license (disabled when no license active)
|
||||||
|
|
||||||
|
**New Files:**
|
||||||
|
|
||||||
|
- `includes/class-wc-tpp-license-checker.php`
|
||||||
|
- `includes/class-wc-tpp-update-checker.php`
|
||||||
|
|
||||||
|
**Modified Files:**
|
||||||
|
|
||||||
|
- `wc-tier-and-package-prices.php` - Version bump, include new classes
|
||||||
|
- `includes/class-wc-tpp-settings.php` - Added Auto-Updates tab, updated license status display
|
||||||
|
- All translation files (.pot, .po, .mo)
|
||||||
|
- `CHANGELOG.md` - v1.4.1 release notes
|
||||||
|
- `CLAUDE.md` - Updated version and session history
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
Always refer to this document when starting work on this project. Good luck!
|
Always refer to this document when starting work on this project. Good luck!
|
||||||
|
|||||||
77
README.md
77
README.md
@@ -20,10 +20,11 @@ A powerful WooCommerce plugin that adds tier pricing and package pricing functio
|
|||||||
|
|
||||||
### Admin Features
|
### Admin Features
|
||||||
- Easy-to-use product meta boxes for adding tiers and packages
|
- Easy-to-use product meta boxes for adding tiers and packages
|
||||||
- Global settings page under WooCommerce menu
|
- Global settings page under WooCommerce menu with sub-tabs
|
||||||
- Configure display position (before/after add to cart, after price)
|
- Configure display position (before/after add to cart, after price)
|
||||||
- Enable/disable tier or package pricing independently
|
- Enable/disable tier or package pricing independently
|
||||||
- Sortable pricing rules
|
- Sortable pricing rules
|
||||||
|
- License management with secure HMAC signature verification
|
||||||
|
|
||||||
### Frontend Features
|
### Frontend Features
|
||||||
- Beautiful pricing tables on product pages
|
- Beautiful pricing tables on product pages
|
||||||
@@ -39,6 +40,20 @@ A powerful WooCommerce plugin that adds tier pricing and package pricing functio
|
|||||||
2. Activate the plugin through the 'Plugins' menu in WordPress
|
2. Activate the plugin through the 'Plugins' menu in WordPress
|
||||||
3. Make sure WooCommerce is installed and activated
|
3. Make sure WooCommerce is installed and activated
|
||||||
|
|
||||||
|
### Automated Releases
|
||||||
|
|
||||||
|
This project uses a Gitea CI/CD pipeline for automated releases. When a version tag (e.g., `v1.4.0`) is pushed:
|
||||||
|
|
||||||
|
1. Code is checked out with git submodules (dependencies bundled)
|
||||||
|
2. The pipeline validates the plugin version matches the tag
|
||||||
|
3. Composer dependencies are installed (production only)
|
||||||
|
4. Translation files are compiled (.po → .mo)
|
||||||
|
5. A release package is created with proper exclusions
|
||||||
|
6. SHA256 checksum is generated
|
||||||
|
7. Release is published to Gitea with changelog notes extracted from CHANGELOG.md
|
||||||
|
|
||||||
|
The `magdev/wc-licensed-product-client` library is bundled as a git submodule to avoid private repository authentication during CI/CD.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
### Global Settings
|
### Global Settings
|
||||||
@@ -110,7 +125,9 @@ When editing a product, scroll to the **Product data** panel:
|
|||||||
|
|
||||||
```
|
```
|
||||||
wc-tier-and-package-prices/
|
wc-tier-and-package-prices/
|
||||||
├── wc-tier-and-package-prices.php # Main plugin file (v1.1.20)
|
├── wc-tier-and-package-prices.php # Main plugin file (v1.4.0)
|
||||||
|
├── .gitea/workflows/
|
||||||
|
│ └── release.yml # CI/CD release pipeline
|
||||||
├── includes/
|
├── includes/
|
||||||
│ ├── class-wc-tpp-admin.php # Admin settings integration
|
│ ├── class-wc-tpp-admin.php # Admin settings integration
|
||||||
│ ├── class-wc-tpp-settings.php # WooCommerce settings page
|
│ ├── class-wc-tpp-settings.php # WooCommerce settings page
|
||||||
@@ -137,7 +154,9 @@ wc-tier-and-package-prices/
|
|||||||
│ ├── wc-tier-package-prices.pot # Translation template
|
│ ├── wc-tier-package-prices.pot # Translation template
|
||||||
│ ├── wc-tier-package-prices-*.po # Translation sources
|
│ ├── wc-tier-package-prices-*.po # Translation sources
|
||||||
│ └── wc-tier-package-prices-*.mo # Compiled translations
|
│ └── wc-tier-package-prices-*.mo # Compiled translations
|
||||||
├── vendor/ # Composer dependencies (Twig)
|
├── lib/ # Bundled libraries (git submodules)
|
||||||
|
│ └── wc-licensed-product-client/ # License client library
|
||||||
|
├── vendor/ # Composer dependencies (generated)
|
||||||
├── CHANGELOG.md # Complete version history
|
├── CHANGELOG.md # Complete version history
|
||||||
├── INSTALLATION.md # Installation guide
|
├── INSTALLATION.md # Installation guide
|
||||||
├── QUICKSTART.md # Quick start guide
|
├── QUICKSTART.md # Quick start guide
|
||||||
@@ -149,7 +168,7 @@ wc-tier-and-package-prices/
|
|||||||
|
|
||||||
- WordPress 6.0 or higher (tested up to 6.9.x)
|
- WordPress 6.0 or higher (tested up to 6.9.x)
|
||||||
- WooCommerce 8.0 or higher (tested up to 10.x)
|
- WooCommerce 8.0 or higher (tested up to 10.x)
|
||||||
- PHP 7.4 or higher
|
- PHP 8.3 or higher (required since v1.3.0)
|
||||||
|
|
||||||
### Compatibility
|
### Compatibility
|
||||||
|
|
||||||
@@ -183,9 +202,39 @@ This plugin is licensed under the GPL v2 or later.
|
|||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
### Version 1.4.0 - 2026-01-29
|
||||||
|
|
||||||
|
__Current Release__ - CI/CD Release Pipeline
|
||||||
|
|
||||||
|
- __New__: Gitea CI/CD release pipeline for automated builds and releases
|
||||||
|
- __New__: Git submodule for `magdev/wc-licensed-product-client` library
|
||||||
|
- __Changed__: Composer now uses path repository for bundled license client
|
||||||
|
- __DevOps__: Automated version validation, translation compilation, and release publishing
|
||||||
|
|
||||||
|
See [CHANGELOG.md](CHANGELOG.md) for complete details.
|
||||||
|
|
||||||
|
### Version 1.3.1 - 2026-01-27
|
||||||
|
|
||||||
|
Secure License Client
|
||||||
|
|
||||||
|
- __Changed__: Switched to `SecureLicenseClient` with HMAC-SHA256 response signature verification
|
||||||
|
- __New__: Server Secret configuration field for secure communication with license server
|
||||||
|
- __Security__: Response signatures verified using HMAC-SHA256 with license-specific derived keys
|
||||||
|
|
||||||
|
### Version 1.3.0 - 2026-01-25
|
||||||
|
|
||||||
|
__Breaking Changes__ - PHP 8.3+ Required
|
||||||
|
|
||||||
|
- __Breaking__: Minimum PHP version increased from 7.4 to 8.3
|
||||||
|
- __New__: License management via `magdev/wc-licensed-product-client` library
|
||||||
|
- __New__: Settings page split into "General" and "License" sub-tabs
|
||||||
|
- __New__: AJAX-based license validation and activation with visual feedback
|
||||||
|
- __New__: License status caching with daily auto-refresh
|
||||||
|
- __New__: PHP version check with admin notice for incompatible servers
|
||||||
|
|
||||||
### Version 1.2.0 - 2025-12-29
|
### Version 1.2.0 - 2025-12-29
|
||||||
|
|
||||||
__Current Release__ - Variable Product Support
|
Variable Product Support
|
||||||
|
|
||||||
- __New__: Full support for WooCommerce variable products with variation-level pricing
|
- __New__: Full support for WooCommerce variable products with variation-level pricing
|
||||||
- __New__: Each variation can have independent tier and package pricing configuration
|
- __New__: Each variation can have independent tier and package pricing configuration
|
||||||
@@ -194,24 +243,6 @@ __Current Release__ - Variable Product Support
|
|||||||
- __Fixed__: Quantity restrictions now work correctly per-variation
|
- __Fixed__: Quantity restrictions now work correctly per-variation
|
||||||
- 100% backward compatible - no breaking changes
|
- 100% backward compatible - no breaking changes
|
||||||
|
|
||||||
See [CHANGELOG.md](CHANGELOG.md) for complete details.
|
|
||||||
|
|
||||||
### Version 1.1.22 - 2025-12-23
|
|
||||||
|
|
||||||
- Increased width of label input fields in admin interface
|
|
||||||
|
|
||||||
#### Fixed
|
|
||||||
- **CRITICAL:** WooCommerce Blocks fatal error in mini-cart and cart blocks
|
|
||||||
- Fixed `woocommerce_store_api_product_quantity_editable` filter signature mismatch
|
|
||||||
- Filter now correctly accepts `WC_Product` object instead of cart item array
|
|
||||||
- Resolves "Cannot use object of type WC_Product_Simple as array" fatal error
|
|
||||||
|
|
||||||
#### Technical Details
|
|
||||||
- Updated `block_quantity_editable()` method signature to accept product object
|
|
||||||
- Changed parameter from `$cart_item` array to `WC_Product $product`
|
|
||||||
- Uses `$product->get_id()` instead of array access for product ID
|
|
||||||
- Full compatibility with WooCommerce Store API and block-based cart/checkout
|
|
||||||
|
|
||||||
### Recent Major Updates
|
### Recent Major Updates
|
||||||
|
|
||||||
#### Version 1.1.7 - Enhanced Tier Pricing
|
#### Version 1.1.7 - Enhanced Tier Pricing
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "magdev/wc-tier-package-prices",
|
"name": "magdev/wc-tier-package-prices",
|
||||||
"description": "WooCommerce plugin for tier pricing and package prices with Twig templates",
|
"description": "WooCommerce plugin for tier pricing and package prices with Twig templates",
|
||||||
"version": "1.3.0",
|
|
||||||
"type": "wordpress-plugin",
|
"type": "wordpress-plugin",
|
||||||
"license": "GPL-2.0-or-later",
|
"license": "GPL-2.0-or-later",
|
||||||
"authors": [
|
"authors": [
|
||||||
@@ -12,18 +11,26 @@
|
|||||||
],
|
],
|
||||||
"repositories": [
|
"repositories": [
|
||||||
{
|
{
|
||||||
"type": "vcs",
|
"type": "path",
|
||||||
"url": "https://src.bundespruefstelle.ch/magdev/wc-licensed-product-client.git"
|
"url": "lib/wc-licensed-product-client"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=8.3",
|
"php": ">=8.3",
|
||||||
"twig/twig": "^3.0",
|
"twig/twig": "^3.0",
|
||||||
"magdev/wc-licensed-product-client": "^0.1"
|
"magdev/wc-licensed-product-client": "^0.2"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"classmap": [
|
"classmap": [
|
||||||
"includes/"
|
"includes/"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"optimize-autoloader": true,
|
||||||
|
"platform": {
|
||||||
|
"php": "8.3.0"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"minimum-stability": "stable",
|
||||||
|
"prefer-stable": true
|
||||||
}
|
}
|
||||||
|
|||||||
333
includes/class-wc-tpp-license-checker.php
Normal file
333
includes/class-wc-tpp-license-checker.php
Normal file
@@ -0,0 +1,333 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* License Checker
|
||||||
|
*
|
||||||
|
* Handles license validation with localhost and self-licensing bypass
|
||||||
|
*
|
||||||
|
* @package WC_Tier_Package_Prices
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('ABSPATH')) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WC_TPP_License_Checker class
|
||||||
|
*/
|
||||||
|
if (!class_exists('WC_TPP_License_Checker')) {
|
||||||
|
class WC_TPP_License_Checker {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton instance
|
||||||
|
*
|
||||||
|
* @var WC_TPP_License_Checker|null
|
||||||
|
*/
|
||||||
|
private static $instance = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache key for license status
|
||||||
|
*/
|
||||||
|
private const CACHE_KEY = 'wc_tpp_license_status';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache TTL for successful validation (1 hour)
|
||||||
|
*/
|
||||||
|
private const CACHE_TTL_SUCCESS = 3600;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache TTL for failed validation (5 minutes)
|
||||||
|
*/
|
||||||
|
private const CACHE_TTL_ERROR = 300;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Localhost patterns
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private const LOCALHOST_HOSTS = ['localhost', '127.0.0.1', '::1'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Localhost TLDs
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private const LOCALHOST_TLDS = ['.localhost', '.local', '.test', '.example', '.invalid'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get singleton instance
|
||||||
|
*
|
||||||
|
* @return WC_TPP_License_Checker
|
||||||
|
*/
|
||||||
|
public static function get_instance(): WC_TPP_License_Checker {
|
||||||
|
if (null === self::$instance) {
|
||||||
|
self::$instance = new self();
|
||||||
|
}
|
||||||
|
return self::$instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
private function __construct() {
|
||||||
|
// Clear cache when license settings change
|
||||||
|
add_action('update_option_wc_tpp_license_key', array($this, 'clear_cache'));
|
||||||
|
add_action('update_option_wc_tpp_license_server_url', array($this, 'clear_cache'));
|
||||||
|
add_action('update_option_wc_tpp_license_server_secret', array($this, 'clear_cache'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current environment is localhost
|
||||||
|
*
|
||||||
|
* Matches patterns:
|
||||||
|
* - localhost
|
||||||
|
* - 127.0.0.1
|
||||||
|
* - ::1 (IPv6 localhost)
|
||||||
|
* - *.localhost (subdomains)
|
||||||
|
* - *.local (subdomains)
|
||||||
|
* - *.test (RFC 2606)
|
||||||
|
* - *.example (RFC 2606)
|
||||||
|
* - *.invalid (RFC 2606)
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function is_localhost(): bool {
|
||||||
|
$domain = $this->get_current_domain();
|
||||||
|
|
||||||
|
// Remove port number if present
|
||||||
|
$domain = preg_replace('/:[\d]+$/', '', $domain);
|
||||||
|
$domain = strtolower($domain);
|
||||||
|
|
||||||
|
// Check exact matches
|
||||||
|
if (in_array($domain, self::LOCALHOST_HOSTS, true)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check TLD patterns
|
||||||
|
foreach (self::LOCALHOST_TLDS as $tld) {
|
||||||
|
if (str_ends_with($domain, $tld)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for private IP ranges (Docker, VMs, etc.)
|
||||||
|
if ($this->is_private_ip($domain)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if domain is a private IP address
|
||||||
|
*
|
||||||
|
* @param string $domain The domain to check.
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function is_private_ip(string $domain): bool {
|
||||||
|
// Check if it's a valid IP first
|
||||||
|
if (!filter_var($domain, FILTER_VALIDATE_IP)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for private/reserved ranges
|
||||||
|
return !filter_var(
|
||||||
|
$domain,
|
||||||
|
FILTER_VALIDATE_IP,
|
||||||
|
FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current site is self-licensing
|
||||||
|
*
|
||||||
|
* Returns true if the license server URL and site URL are on the same domain.
|
||||||
|
* This allows the license server itself to use the plugin without a license.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function is_self_licensing(): bool {
|
||||||
|
$server_url = get_option('wc_tpp_license_server_url', '');
|
||||||
|
|
||||||
|
if (empty($server_url)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$server_domain = $this->normalize_domain($server_url);
|
||||||
|
$site_domain = $this->normalize_domain(get_site_url());
|
||||||
|
|
||||||
|
return $server_domain === $site_domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize a URL to its domain
|
||||||
|
*
|
||||||
|
* @param string $url The URL to normalize.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function normalize_domain(string $url): string {
|
||||||
|
$parsed = wp_parse_url($url);
|
||||||
|
$host = $parsed['host'] ?? '';
|
||||||
|
|
||||||
|
// Convert to lowercase
|
||||||
|
$host = strtolower($host);
|
||||||
|
|
||||||
|
// Remove www. prefix
|
||||||
|
$host = preg_replace('/^www\./', '', $host);
|
||||||
|
|
||||||
|
return $host;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current domain from site URL
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get_current_domain(): string {
|
||||||
|
$site_url = get_site_url();
|
||||||
|
$parsed = wp_parse_url($site_url);
|
||||||
|
$host = $parsed['host'] ?? 'localhost';
|
||||||
|
|
||||||
|
// Include port if non-standard
|
||||||
|
if (isset($parsed['port'])) {
|
||||||
|
$host .= ':' . $parsed['port'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return strtolower($host);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the license is valid
|
||||||
|
*
|
||||||
|
* This is the main entry point for license validation.
|
||||||
|
* It implements the bypass logic for localhost and self-licensing.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function is_license_valid(): bool {
|
||||||
|
// Always valid on localhost
|
||||||
|
if ($this->is_localhost()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always valid for self-licensing
|
||||||
|
if ($this->is_self_licensing()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check cached status
|
||||||
|
$cached = $this->get_cached_status();
|
||||||
|
if (false !== $cached) {
|
||||||
|
return !empty($cached['valid']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate against server
|
||||||
|
return $this->validate_license();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the license bypass reason if applicable
|
||||||
|
*
|
||||||
|
* @return string|null 'localhost', 'self_licensing', or null
|
||||||
|
*/
|
||||||
|
public function get_bypass_reason(): ?string {
|
||||||
|
if ($this->is_localhost()) {
|
||||||
|
return 'localhost';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->is_self_licensing()) {
|
||||||
|
return 'self_licensing';
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cached license status
|
||||||
|
*
|
||||||
|
* @return array|false
|
||||||
|
*/
|
||||||
|
public function get_cached_status() {
|
||||||
|
return get_transient(self::CACHE_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate license against the server
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function validate_license(): bool {
|
||||||
|
$license_key = get_option('wc_tpp_license_key', '');
|
||||||
|
$server_url = get_option('wc_tpp_license_server_url', '');
|
||||||
|
$server_secret = get_option('wc_tpp_license_server_secret', '');
|
||||||
|
|
||||||
|
// Can't validate without credentials
|
||||||
|
if (empty($license_key) || empty($server_url) || empty($server_secret)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$client = $this->get_license_client($server_url, $server_secret);
|
||||||
|
$domain = $this->get_current_domain();
|
||||||
|
|
||||||
|
// Remove port for validation
|
||||||
|
$domain = preg_replace('/:[\d]+$/', '', $domain);
|
||||||
|
|
||||||
|
$result = $client->validate($license_key, $domain);
|
||||||
|
|
||||||
|
// Cache successful validation
|
||||||
|
set_transient(self::CACHE_KEY, array(
|
||||||
|
'valid' => true,
|
||||||
|
'product_id' => $result->productId,
|
||||||
|
'expires_at' => $result->expiresAt?->format('Y-m-d H:i:s'),
|
||||||
|
'is_lifetime' => $result->isLifetime(),
|
||||||
|
'checked_at' => current_time('mysql'),
|
||||||
|
), self::CACHE_TTL_SUCCESS);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// Cache validation failure
|
||||||
|
set_transient(self::CACHE_KEY, array(
|
||||||
|
'valid' => false,
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
'checked_at' => current_time('mysql'),
|
||||||
|
), self::CACHE_TTL_ERROR);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get license client instance
|
||||||
|
*
|
||||||
|
* @param string $server_url License server URL.
|
||||||
|
* @param string $server_secret Shared secret for signature verification.
|
||||||
|
* @return \Magdev\WcLicensedProductClient\LicenseClientInterface
|
||||||
|
*/
|
||||||
|
private function get_license_client(string $server_url, string $server_secret): \Magdev\WcLicensedProductClient\LicenseClientInterface {
|
||||||
|
$httpClient = \Symfony\Component\HttpClient\HttpClient::create();
|
||||||
|
return new \Magdev\WcLicensedProductClient\SecureLicenseClient(
|
||||||
|
httpClient: $httpClient,
|
||||||
|
baseUrl: $server_url,
|
||||||
|
serverSecret: $server_secret,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the license cache
|
||||||
|
*/
|
||||||
|
public function clear_cache(): void {
|
||||||
|
delete_transient(self::CACHE_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force revalidation of the license
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function revalidate(): bool {
|
||||||
|
$this->clear_cache();
|
||||||
|
return $this->is_license_valid();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,6 +33,9 @@ if (!class_exists('WC_TPP_Settings')) {
|
|||||||
// Add AJAX handlers for license validation
|
// Add AJAX handlers for license validation
|
||||||
add_action('wp_ajax_wc_tpp_validate_license', array($this, 'ajax_validate_license'));
|
add_action('wp_ajax_wc_tpp_validate_license', array($this, 'ajax_validate_license'));
|
||||||
add_action('wp_ajax_wc_tpp_activate_license', array($this, 'ajax_activate_license'));
|
add_action('wp_ajax_wc_tpp_activate_license', array($this, 'ajax_activate_license'));
|
||||||
|
|
||||||
|
// Add AJAX handler for update checks
|
||||||
|
add_action('wp_ajax_wc_tpp_check_updates', array($this, 'ajax_check_updates'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,6 +47,7 @@ if (!class_exists('WC_TPP_Settings')) {
|
|||||||
return array(
|
return array(
|
||||||
'' => __('General', 'wc-tier-package-prices'),
|
'' => __('General', 'wc-tier-package-prices'),
|
||||||
'license' => __('License', 'wc-tier-package-prices'),
|
'license' => __('License', 'wc-tier-package-prices'),
|
||||||
|
'updates' => __('Auto-Updates', 'wc-tier-package-prices'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,6 +158,16 @@ if (!class_exists('WC_TPP_Settings')) {
|
|||||||
'desc_tip' => true,
|
'desc_tip' => true,
|
||||||
),
|
),
|
||||||
|
|
||||||
|
array(
|
||||||
|
'title' => __('Server Secret', 'wc-tier-package-prices'),
|
||||||
|
'desc' => __('The shared secret for secure communication with the license server.', 'wc-tier-package-prices'),
|
||||||
|
'id' => 'wc_tpp_license_server_secret',
|
||||||
|
'type' => 'password',
|
||||||
|
'default' => '',
|
||||||
|
'css' => 'min-width:400px;',
|
||||||
|
'desc_tip' => true,
|
||||||
|
),
|
||||||
|
|
||||||
array(
|
array(
|
||||||
'title' => __('License Status', 'wc-tier-package-prices'),
|
'title' => __('License Status', 'wc-tier-package-prices'),
|
||||||
'type' => 'wc_tpp_license_status',
|
'type' => 'wc_tpp_license_status',
|
||||||
@@ -167,6 +181,75 @@ if (!class_exists('WC_TPP_Settings')) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get settings for the Auto-Updates section
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function get_settings_for_updates_section() {
|
||||||
|
// Check if auto-install is available (requires valid license or bypass)
|
||||||
|
$license_checker = WC_TPP_License_Checker::get_instance();
|
||||||
|
$auto_install_disabled = !$license_checker->is_license_valid();
|
||||||
|
$auto_install_desc = __('Automatically install updates when available.', 'wc-tier-package-prices');
|
||||||
|
|
||||||
|
if ($auto_install_disabled) {
|
||||||
|
$auto_install_desc .= ' ' . __('(Requires a valid license)', 'wc-tier-package-prices');
|
||||||
|
}
|
||||||
|
|
||||||
|
return array(
|
||||||
|
array(
|
||||||
|
'title' => __('Auto-Update Settings', 'wc-tier-package-prices'),
|
||||||
|
'type' => 'title',
|
||||||
|
'desc' => __('Configure automatic plugin updates from the license server.', 'wc-tier-package-prices'),
|
||||||
|
'id' => 'wc_tpp_update_settings',
|
||||||
|
),
|
||||||
|
|
||||||
|
array(
|
||||||
|
'title' => __('Enable Update Notifications', 'wc-tier-package-prices'),
|
||||||
|
'desc' => __('Check for available plugin updates.', 'wc-tier-package-prices'),
|
||||||
|
'id' => 'wc_tpp_update_notification_enabled',
|
||||||
|
'default' => 'yes',
|
||||||
|
'type' => 'checkbox',
|
||||||
|
'desc_tip' => __('When enabled, the plugin will check for updates from the license server and show notifications in the WordPress admin.', 'wc-tier-package-prices'),
|
||||||
|
),
|
||||||
|
|
||||||
|
array(
|
||||||
|
'title' => __('Automatically Install Updates', 'wc-tier-package-prices'),
|
||||||
|
'desc' => $auto_install_desc,
|
||||||
|
'id' => 'wc_tpp_auto_install_enabled',
|
||||||
|
'default' => 'no',
|
||||||
|
'type' => 'checkbox',
|
||||||
|
'desc_tip' => __('When enabled, updates will be automatically installed when WordPress performs background updates.', 'wc-tier-package-prices'),
|
||||||
|
'custom_attributes' => $auto_install_disabled ? array('disabled' => 'disabled') : array(),
|
||||||
|
),
|
||||||
|
|
||||||
|
array(
|
||||||
|
'title' => __('Check Frequency (Hours)', 'wc-tier-package-prices'),
|
||||||
|
'desc' => __('How often to check for updates.', 'wc-tier-package-prices'),
|
||||||
|
'id' => 'wc_tpp_update_check_frequency',
|
||||||
|
'default' => '12',
|
||||||
|
'type' => 'number',
|
||||||
|
'css' => 'width: 80px;',
|
||||||
|
'desc_tip' => __('Number of hours between update checks. Default is 12 hours.', 'wc-tier-package-prices'),
|
||||||
|
'custom_attributes' => array(
|
||||||
|
'min' => '1',
|
||||||
|
'max' => '168',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
array(
|
||||||
|
'title' => __('Update Status', 'wc-tier-package-prices'),
|
||||||
|
'type' => 'wc_tpp_update_status',
|
||||||
|
'id' => 'wc_tpp_update_status_display',
|
||||||
|
),
|
||||||
|
|
||||||
|
array(
|
||||||
|
'type' => 'sectionend',
|
||||||
|
'id' => 'wc_tpp_update_settings',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get cached license status
|
* Get cached license status
|
||||||
*
|
*
|
||||||
@@ -188,13 +271,14 @@ if (!class_exists('WC_TPP_Settings')) {
|
|||||||
|
|
||||||
$license_key = sanitize_text_field(wp_unslash($_POST['license_key'] ?? ''));
|
$license_key = sanitize_text_field(wp_unslash($_POST['license_key'] ?? ''));
|
||||||
$server_url = esc_url_raw(wp_unslash($_POST['server_url'] ?? ''));
|
$server_url = esc_url_raw(wp_unslash($_POST['server_url'] ?? ''));
|
||||||
|
$server_secret = sanitize_text_field(wp_unslash($_POST['server_secret'] ?? ''));
|
||||||
|
|
||||||
if (empty($license_key) || empty($server_url)) {
|
if (empty($license_key) || empty($server_url) || empty($server_secret)) {
|
||||||
wp_send_json_error(array('message' => __('License key and server URL are required.', 'wc-tier-package-prices')));
|
wp_send_json_error(array('message' => __('License key, server URL, and server secret are required.', 'wc-tier-package-prices')));
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$client = $this->get_license_client($server_url);
|
$client = $this->get_license_client($server_url, $server_secret);
|
||||||
$domain = $this->get_current_domain();
|
$domain = $this->get_current_domain();
|
||||||
$result = $client->validate($license_key, $domain);
|
$result = $client->validate($license_key, $domain);
|
||||||
|
|
||||||
@@ -212,16 +296,37 @@ if (!class_exists('WC_TPP_Settings')) {
|
|||||||
'status' => $this->get_cached_license_status(),
|
'status' => $this->get_cached_license_status(),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
} catch (\Magdev\WcLicensedProductClient\Exception\RateLimitExceededException $e) {
|
||||||
|
wp_send_json_error(array(
|
||||||
|
'message' => sprintf(
|
||||||
|
/* translators: %d: Number of seconds to wait */
|
||||||
|
__('Rate limit exceeded. Please try again in %d seconds.', 'wc-tier-package-prices'),
|
||||||
|
$e->retryAfter ?? 60
|
||||||
|
),
|
||||||
|
'code' => 'rate_limit_exceeded',
|
||||||
|
'retry_after' => $e->retryAfter,
|
||||||
|
));
|
||||||
|
} catch (\Magdev\WcLicensedProductClient\Security\SignatureException $e) {
|
||||||
|
delete_transient('wc_tpp_license_status');
|
||||||
|
wp_send_json_error(array(
|
||||||
|
'message' => __('Response signature verification failed. Please check your server secret.', 'wc-tier-package-prices'),
|
||||||
|
'code' => 'signature_error',
|
||||||
|
));
|
||||||
} catch (\Magdev\WcLicensedProductClient\Exception\LicenseException $e) {
|
} catch (\Magdev\WcLicensedProductClient\Exception\LicenseException $e) {
|
||||||
delete_transient('wc_tpp_license_status');
|
delete_transient('wc_tpp_license_status');
|
||||||
wp_send_json_error(array(
|
wp_send_json_error(array(
|
||||||
'message' => $e->getMessage(),
|
'message' => $e->getMessage(),
|
||||||
'code' => $e->errorCode ?? 'unknown',
|
'code' => $e->errorCode ?? 'unknown',
|
||||||
));
|
));
|
||||||
|
} catch (\InvalidArgumentException $e) {
|
||||||
|
wp_send_json_error(array(
|
||||||
|
'message' => $e->getMessage(),
|
||||||
|
'code' => 'invalid_url',
|
||||||
|
));
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
delete_transient('wc_tpp_license_status');
|
delete_transient('wc_tpp_license_status');
|
||||||
wp_send_json_error(array(
|
wp_send_json_error(array(
|
||||||
'message' => $e->getMessage(),
|
'message' => __('An unexpected error occurred. Please try again.', 'wc-tier-package-prices'),
|
||||||
'code' => 'exception',
|
'code' => 'exception',
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -239,13 +344,14 @@ if (!class_exists('WC_TPP_Settings')) {
|
|||||||
|
|
||||||
$license_key = sanitize_text_field(wp_unslash($_POST['license_key'] ?? ''));
|
$license_key = sanitize_text_field(wp_unslash($_POST['license_key'] ?? ''));
|
||||||
$server_url = esc_url_raw(wp_unslash($_POST['server_url'] ?? ''));
|
$server_url = esc_url_raw(wp_unslash($_POST['server_url'] ?? ''));
|
||||||
|
$server_secret = sanitize_text_field(wp_unslash($_POST['server_secret'] ?? ''));
|
||||||
|
|
||||||
if (empty($license_key) || empty($server_url)) {
|
if (empty($license_key) || empty($server_url) || empty($server_secret)) {
|
||||||
wp_send_json_error(array('message' => __('License key and server URL are required.', 'wc-tier-package-prices')));
|
wp_send_json_error(array('message' => __('License key, server URL, and server secret are required.', 'wc-tier-package-prices')));
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$client = $this->get_license_client($server_url);
|
$client = $this->get_license_client($server_url, $server_secret);
|
||||||
$domain = $this->get_current_domain();
|
$domain = $this->get_current_domain();
|
||||||
$result = $client->activate($license_key, $domain);
|
$result = $client->activate($license_key, $domain);
|
||||||
|
|
||||||
@@ -269,14 +375,34 @@ if (!class_exists('WC_TPP_Settings')) {
|
|||||||
|
|
||||||
wp_send_json_error(array('message' => $result->message));
|
wp_send_json_error(array('message' => $result->message));
|
||||||
|
|
||||||
|
} catch (\Magdev\WcLicensedProductClient\Exception\RateLimitExceededException $e) {
|
||||||
|
wp_send_json_error(array(
|
||||||
|
'message' => sprintf(
|
||||||
|
/* translators: %d: Number of seconds to wait */
|
||||||
|
__('Rate limit exceeded. Please try again in %d seconds.', 'wc-tier-package-prices'),
|
||||||
|
$e->retryAfter ?? 60
|
||||||
|
),
|
||||||
|
'code' => 'rate_limit_exceeded',
|
||||||
|
'retry_after' => $e->retryAfter,
|
||||||
|
));
|
||||||
|
} catch (\Magdev\WcLicensedProductClient\Security\SignatureException $e) {
|
||||||
|
wp_send_json_error(array(
|
||||||
|
'message' => __('Response signature verification failed. Please check your server secret.', 'wc-tier-package-prices'),
|
||||||
|
'code' => 'signature_error',
|
||||||
|
));
|
||||||
} catch (\Magdev\WcLicensedProductClient\Exception\LicenseException $e) {
|
} catch (\Magdev\WcLicensedProductClient\Exception\LicenseException $e) {
|
||||||
wp_send_json_error(array(
|
wp_send_json_error(array(
|
||||||
'message' => $e->getMessage(),
|
'message' => $e->getMessage(),
|
||||||
'code' => $e->errorCode ?? 'unknown',
|
'code' => $e->errorCode ?? 'unknown',
|
||||||
));
|
));
|
||||||
} catch (\Exception $e) {
|
} catch (\InvalidArgumentException $e) {
|
||||||
wp_send_json_error(array(
|
wp_send_json_error(array(
|
||||||
'message' => $e->getMessage(),
|
'message' => $e->getMessage(),
|
||||||
|
'code' => 'invalid_url',
|
||||||
|
));
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
wp_send_json_error(array(
|
||||||
|
'message' => __('An unexpected error occurred. Please try again.', 'wc-tier-package-prices'),
|
||||||
'code' => 'exception',
|
'code' => 'exception',
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -285,14 +411,18 @@ if (!class_exists('WC_TPP_Settings')) {
|
|||||||
/**
|
/**
|
||||||
* Get license client instance
|
* Get license client instance
|
||||||
*
|
*
|
||||||
|
* Uses SecureLicenseClient for HMAC signature verification.
|
||||||
|
*
|
||||||
* @param string $server_url License server URL.
|
* @param string $server_url License server URL.
|
||||||
|
* @param string $server_secret Shared secret for signature verification.
|
||||||
* @return \Magdev\WcLicensedProductClient\LicenseClientInterface
|
* @return \Magdev\WcLicensedProductClient\LicenseClientInterface
|
||||||
*/
|
*/
|
||||||
private function get_license_client(string $server_url): \Magdev\WcLicensedProductClient\LicenseClientInterface {
|
private function get_license_client(string $server_url, string $server_secret): \Magdev\WcLicensedProductClient\LicenseClientInterface {
|
||||||
$httpClient = \Symfony\Component\HttpClient\HttpClient::create();
|
$httpClient = \Symfony\Component\HttpClient\HttpClient::create();
|
||||||
return new \Magdev\WcLicensedProductClient\LicenseClient(
|
return new \Magdev\WcLicensedProductClient\SecureLicenseClient(
|
||||||
httpClient: $httpClient,
|
httpClient: $httpClient,
|
||||||
baseUrl: $server_url,
|
baseUrl: $server_url,
|
||||||
|
serverSecret: $server_secret,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,8 +441,9 @@ if (!class_exists('WC_TPP_Settings')) {
|
|||||||
public function output() {
|
public function output() {
|
||||||
global $current_section;
|
global $current_section;
|
||||||
|
|
||||||
// Register custom field type for license status display
|
// Register custom field types
|
||||||
add_action('woocommerce_admin_field_wc_tpp_license_status', array($this, 'output_license_status_field'));
|
add_action('woocommerce_admin_field_wc_tpp_license_status', array($this, 'output_license_status_field'));
|
||||||
|
add_action('woocommerce_admin_field_wc_tpp_update_status', array($this, 'output_update_status_field'));
|
||||||
|
|
||||||
parent::output();
|
parent::output();
|
||||||
|
|
||||||
@@ -320,6 +451,11 @@ if (!class_exists('WC_TPP_Settings')) {
|
|||||||
if ('license' === $current_section) {
|
if ('license' === $current_section) {
|
||||||
$this->output_license_scripts();
|
$this->output_license_scripts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add JavaScript for updates section
|
||||||
|
if ('updates' === $current_section) {
|
||||||
|
$this->output_updates_scripts();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -358,6 +494,20 @@ if (!class_exists('WC_TPP_Settings')) {
|
|||||||
* @param array|false $status License status data.
|
* @param array|false $status License status data.
|
||||||
*/
|
*/
|
||||||
private function render_license_status_html($status) {
|
private function render_license_status_html($status) {
|
||||||
|
// Check for license bypass
|
||||||
|
$license_checker = WC_TPP_License_Checker::get_instance();
|
||||||
|
$bypass_reason = $license_checker->get_bypass_reason();
|
||||||
|
|
||||||
|
if ($bypass_reason) {
|
||||||
|
echo '<span class="wc-tpp-license-active">' . esc_html__('License Active', 'wc-tier-package-prices') . '</span>';
|
||||||
|
if ('localhost' === $bypass_reason) {
|
||||||
|
echo '<br><small>' . esc_html__('(Localhost environment - license validation bypassed)', 'wc-tier-package-prices') . '</small>';
|
||||||
|
} elseif ('self_licensing' === $bypass_reason) {
|
||||||
|
echo '<br><small>' . esc_html__('(Self-licensing server - license validation bypassed)', 'wc-tier-package-prices') . '</small>';
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($status)) {
|
if (empty($status)) {
|
||||||
echo '<span class="wc-tpp-license-inactive">' . esc_html__('No license activated', 'wc-tier-package-prices') . '</span>';
|
echo '<span class="wc-tpp-license-inactive">' . esc_html__('No license activated', 'wc-tier-package-prices') . '</span>';
|
||||||
return;
|
return;
|
||||||
@@ -386,6 +536,50 @@ if (!class_exists('WC_TPP_Settings')) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output update status custom field
|
||||||
|
*
|
||||||
|
* @param array $value Field configuration.
|
||||||
|
*/
|
||||||
|
public function output_update_status_field($value) {
|
||||||
|
$update_checker = WC_TPP_Update_Checker::get_instance();
|
||||||
|
$available_version = $update_checker->get_available_version();
|
||||||
|
?>
|
||||||
|
<tr valign="top">
|
||||||
|
<th scope="row" class="titledesc">
|
||||||
|
<label><?php esc_html_e('Update Status', 'wc-tier-package-prices'); ?></label>
|
||||||
|
</th>
|
||||||
|
<td class="forminp">
|
||||||
|
<div id="wc-tpp-update-status-container">
|
||||||
|
<?php $this->render_update_status_html($available_version); ?>
|
||||||
|
</div>
|
||||||
|
<p class="description" style="margin-top: 10px;">
|
||||||
|
<button type="button" class="button" id="wc-tpp-check-updates">
|
||||||
|
<?php esc_html_e('Check for Updates', 'wc-tier-package-prices'); ?>
|
||||||
|
</button>
|
||||||
|
<span class="spinner" id="wc-tpp-update-spinner"></span>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render update status HTML
|
||||||
|
*
|
||||||
|
* @param string|null $available_version Available update version.
|
||||||
|
*/
|
||||||
|
private function render_update_status_html(?string $available_version) {
|
||||||
|
echo '<p><strong>' . esc_html__('Current Version:', 'wc-tier-package-prices') . '</strong> ' . esc_html(WC_TPP_VERSION) . '</p>';
|
||||||
|
|
||||||
|
if ($available_version) {
|
||||||
|
echo '<p class="wc-tpp-update-available"><strong>' . esc_html__('Update Available:', 'wc-tier-package-prices') . '</strong> ' . esc_html($available_version) . '</p>';
|
||||||
|
echo '<p><a href="' . esc_url(admin_url('update-core.php')) . '" class="button button-primary">' . esc_html__('Update Now', 'wc-tier-package-prices') . '</a></p>';
|
||||||
|
} else {
|
||||||
|
echo '<p class="wc-tpp-up-to-date">' . esc_html__('You are running the latest version.', 'wc-tier-package-prices') . '</p>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Output JavaScript for license management
|
* Output JavaScript for license management
|
||||||
*/
|
*/
|
||||||
@@ -402,6 +596,7 @@ if (!class_exists('WC_TPP_Settings')) {
|
|||||||
return {
|
return {
|
||||||
license_key: $('#wc_tpp_license_key').val(),
|
license_key: $('#wc_tpp_license_key').val(),
|
||||||
server_url: $('#wc_tpp_license_server_url').val(),
|
server_url: $('#wc_tpp_license_server_url').val(),
|
||||||
|
server_secret: $('#wc_tpp_license_server_secret').val(),
|
||||||
nonce: '<?php echo esc_js($nonce); ?>'
|
nonce: '<?php echo esc_js($nonce); ?>'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -420,8 +615,8 @@ if (!class_exists('WC_TPP_Settings')) {
|
|||||||
|
|
||||||
$validateBtn.on('click', function() {
|
$validateBtn.on('click', function() {
|
||||||
var data = getLicenseData();
|
var data = getLicenseData();
|
||||||
if (!data.license_key || !data.server_url) {
|
if (!data.license_key || !data.server_url || !data.server_secret) {
|
||||||
alert('<?php echo esc_js(__('Please enter both license server URL and license key.', 'wc-tier-package-prices')); ?>');
|
alert('<?php echo esc_js(__('Please enter license server URL, license key, and server secret.', 'wc-tier-package-prices')); ?>');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,8 +638,8 @@ if (!class_exists('WC_TPP_Settings')) {
|
|||||||
|
|
||||||
$activateBtn.on('click', function() {
|
$activateBtn.on('click', function() {
|
||||||
var data = getLicenseData();
|
var data = getLicenseData();
|
||||||
if (!data.license_key || !data.server_url) {
|
if (!data.license_key || !data.server_url || !data.server_secret) {
|
||||||
alert('<?php echo esc_js(__('Please enter both license server URL and license key.', 'wc-tier-package-prices')); ?>');
|
alert('<?php echo esc_js(__('Please enter license server URL, license key, and server secret.', 'wc-tier-package-prices')); ?>');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,5 +662,87 @@ if (!class_exists('WC_TPP_Settings')) {
|
|||||||
</script>
|
</script>
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AJAX handler for checking updates
|
||||||
|
*/
|
||||||
|
public function ajax_check_updates() {
|
||||||
|
check_ajax_referer('wc_tpp_update_nonce', 'nonce');
|
||||||
|
|
||||||
|
if (!current_user_can('manage_woocommerce')) {
|
||||||
|
wp_send_json_error(array('message' => __('Permission denied.', 'wc-tier-package-prices')));
|
||||||
|
}
|
||||||
|
|
||||||
|
$update_checker = WC_TPP_Update_Checker::get_instance();
|
||||||
|
$update_info = $update_checker->force_check();
|
||||||
|
|
||||||
|
if ($update_info && !empty($update_info['update_available'])) {
|
||||||
|
wp_send_json_success(array(
|
||||||
|
'message' => sprintf(
|
||||||
|
/* translators: %s: Version number */
|
||||||
|
__('Update available: version %s', 'wc-tier-package-prices'),
|
||||||
|
$update_info['version']
|
||||||
|
),
|
||||||
|
'update_available' => true,
|
||||||
|
'version' => $update_info['version'],
|
||||||
|
'current_version' => WC_TPP_VERSION,
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
wp_send_json_success(array(
|
||||||
|
'message' => __('You are running the latest version.', 'wc-tier-package-prices'),
|
||||||
|
'update_available' => false,
|
||||||
|
'current_version' => WC_TPP_VERSION,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output JavaScript for update management
|
||||||
|
*/
|
||||||
|
private function output_updates_scripts() {
|
||||||
|
$nonce = wp_create_nonce('wc_tpp_update_nonce');
|
||||||
|
?>
|
||||||
|
<script type="text/javascript">
|
||||||
|
jQuery(function($) {
|
||||||
|
var $checkBtn = $('#wc-tpp-check-updates');
|
||||||
|
var $spinner = $('#wc-tpp-update-spinner');
|
||||||
|
var $container = $('#wc-tpp-update-status-container');
|
||||||
|
|
||||||
|
$checkBtn.on('click', function() {
|
||||||
|
$spinner.addClass('is-active');
|
||||||
|
$checkBtn.prop('disabled', true);
|
||||||
|
|
||||||
|
$.post(ajaxurl, {
|
||||||
|
action: 'wc_tpp_check_updates',
|
||||||
|
nonce: '<?php echo esc_js($nonce); ?>'
|
||||||
|
})
|
||||||
|
.done(function(response) {
|
||||||
|
if (response.success) {
|
||||||
|
var html = '<p><strong><?php echo esc_js(__('Current Version:', 'wc-tier-package-prices')); ?></strong> ' + response.data.current_version + '</p>';
|
||||||
|
|
||||||
|
if (response.data.update_available) {
|
||||||
|
html += '<p class="wc-tpp-update-available"><strong><?php echo esc_js(__('Update Available:', 'wc-tier-package-prices')); ?></strong> ' + response.data.version + '</p>';
|
||||||
|
html += '<p><a href="<?php echo esc_url(admin_url('update-core.php')); ?>" class="button button-primary"><?php echo esc_js(__('Update Now', 'wc-tier-package-prices')); ?></a></p>';
|
||||||
|
} else {
|
||||||
|
html += '<p class="wc-tpp-up-to-date"><?php echo esc_js(__('You are running the latest version.', 'wc-tier-package-prices')); ?></p>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$container.html(html);
|
||||||
|
} else {
|
||||||
|
alert(response.data.message || '<?php echo esc_js(__('Failed to check for updates.', 'wc-tier-package-prices')); ?>');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.fail(function() {
|
||||||
|
alert('<?php echo esc_js(__('Request failed. Please try again.', 'wc-tier-package-prices')); ?>');
|
||||||
|
})
|
||||||
|
.always(function() {
|
||||||
|
$spinner.removeClass('is-active');
|
||||||
|
$checkBtn.prop('disabled', false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
468
includes/class-wc-tpp-update-checker.php
Normal file
468
includes/class-wc-tpp-update-checker.php
Normal file
@@ -0,0 +1,468 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Update Checker
|
||||||
|
*
|
||||||
|
* Handles WordPress plugin updates from the license server
|
||||||
|
*
|
||||||
|
* @package WC_Tier_Package_Prices
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('ABSPATH')) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WC_TPP_Update_Checker class
|
||||||
|
*/
|
||||||
|
if (!class_exists('WC_TPP_Update_Checker')) {
|
||||||
|
class WC_TPP_Update_Checker {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton instance
|
||||||
|
*
|
||||||
|
* @var WC_TPP_Update_Checker|null
|
||||||
|
*/
|
||||||
|
private static $instance = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin slug
|
||||||
|
*/
|
||||||
|
private const PLUGIN_SLUG = 'wc-tier-and-package-prices';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update check cache key
|
||||||
|
*/
|
||||||
|
private const CACHE_KEY = 'wc_tpp_update_info';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default check frequency in hours
|
||||||
|
*/
|
||||||
|
private const DEFAULT_CHECK_FREQUENCY = 12;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get singleton instance
|
||||||
|
*
|
||||||
|
* @return WC_TPP_Update_Checker
|
||||||
|
*/
|
||||||
|
public static function get_instance(): WC_TPP_Update_Checker {
|
||||||
|
if (null === self::$instance) {
|
||||||
|
self::$instance = new self();
|
||||||
|
}
|
||||||
|
return self::$instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
private function __construct() {
|
||||||
|
// Only register if updates are not disabled
|
||||||
|
if ($this->is_disabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->register_hooks();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if auto-updates are disabled via constant
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function is_disabled(): bool {
|
||||||
|
return defined('WC_TPP_DISABLE_AUTO_UPDATE') && WC_TPP_DISABLE_AUTO_UPDATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register WordPress hooks
|
||||||
|
*/
|
||||||
|
private function register_hooks(): void {
|
||||||
|
// Check for updates
|
||||||
|
add_filter('pre_set_site_transient_update_plugins', array($this, 'check_for_updates'));
|
||||||
|
|
||||||
|
// Provide plugin information for update modal
|
||||||
|
add_filter('plugins_api', array($this, 'get_plugin_info'), 10, 3);
|
||||||
|
|
||||||
|
// Add authentication headers to download requests
|
||||||
|
add_filter('http_request_args', array($this, 'add_auth_headers'), 10, 2);
|
||||||
|
|
||||||
|
// Handle auto-install setting
|
||||||
|
add_filter('auto_update_plugin', array($this, 'handle_auto_install'), 10, 2);
|
||||||
|
|
||||||
|
// Clear cache when settings change
|
||||||
|
add_action('update_option_wc_tpp_license_key', array($this, 'clear_cache'));
|
||||||
|
add_action('update_option_wc_tpp_license_server_url', array($this, 'clear_cache'));
|
||||||
|
add_action('update_option_wc_tpp_update_notification_enabled', array($this, 'clear_cache'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if update notifications are enabled
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function is_update_notification_enabled(): bool {
|
||||||
|
return get_option('wc_tpp_update_notification_enabled', 'yes') === 'yes';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if auto-install is enabled
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function is_auto_install_enabled(): bool {
|
||||||
|
return get_option('wc_tpp_auto_install_enabled', 'no') === 'yes';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get update check frequency in hours
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public static function get_check_frequency(): int {
|
||||||
|
$frequency = (int) get_option('wc_tpp_update_check_frequency', self::DEFAULT_CHECK_FREQUENCY);
|
||||||
|
return max(1, min(168, $frequency)); // Clamp between 1 and 168 hours
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for plugin updates
|
||||||
|
*
|
||||||
|
* @param object $transient WordPress update transient.
|
||||||
|
* @return object
|
||||||
|
*/
|
||||||
|
public function check_for_updates($transient) {
|
||||||
|
if (empty($transient->checked)) {
|
||||||
|
return $transient;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip if notifications disabled
|
||||||
|
if (!self::is_update_notification_enabled()) {
|
||||||
|
return $transient;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get update info (cached)
|
||||||
|
$update_info = $this->get_update_info();
|
||||||
|
|
||||||
|
if (empty($update_info) || !$update_info['update_available']) {
|
||||||
|
return $transient;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build update object
|
||||||
|
$update_obj = $this->build_update_object($update_info);
|
||||||
|
|
||||||
|
if ($update_obj) {
|
||||||
|
$transient->response[WC_TPP_PLUGIN_BASENAME] = $update_obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $transient;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get plugin information for update modal
|
||||||
|
*
|
||||||
|
* @param false|object|array $result The result object or array.
|
||||||
|
* @param string $action The type of information being requested.
|
||||||
|
* @param object $args Plugin API arguments.
|
||||||
|
* @return false|object
|
||||||
|
*/
|
||||||
|
public function get_plugin_info($result, $action, $args) {
|
||||||
|
if ('plugin_information' !== $action) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($args->slug) || self::PLUGIN_SLUG !== $args->slug) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get update info
|
||||||
|
$update_info = $this->get_update_info(true); // Force fetch for full info
|
||||||
|
|
||||||
|
if (empty($update_info)) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build plugin info object
|
||||||
|
return $this->build_plugin_info_object($update_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add authentication headers to download requests
|
||||||
|
*
|
||||||
|
* @param array $args HTTP request arguments.
|
||||||
|
* @param string $url The request URL.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function add_auth_headers(array $args, string $url): array {
|
||||||
|
$server_url = get_option('wc_tpp_license_server_url', '');
|
||||||
|
|
||||||
|
// Only add headers for requests to our license server
|
||||||
|
if (empty($server_url) || strpos($url, $server_url) !== 0) {
|
||||||
|
return $args;
|
||||||
|
}
|
||||||
|
|
||||||
|
$license_key = get_option('wc_tpp_license_key', '');
|
||||||
|
|
||||||
|
if (!empty($license_key)) {
|
||||||
|
$args['headers']['X-License-Key'] = $license_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $args;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle auto-install setting
|
||||||
|
*
|
||||||
|
* @param bool|null $update Whether to auto-update.
|
||||||
|
* @param object $item The plugin update object.
|
||||||
|
* @return bool|null
|
||||||
|
*/
|
||||||
|
public function handle_auto_install($update, $item) {
|
||||||
|
// Check if this is our plugin
|
||||||
|
if (!isset($item->plugin) || WC_TPP_PLUGIN_BASENAME !== $item->plugin) {
|
||||||
|
return $update;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return our setting, or default behavior
|
||||||
|
if (self::is_auto_install_enabled()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $update;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get update info from cache or server
|
||||||
|
*
|
||||||
|
* @param bool $force_fetch Force fetching from server.
|
||||||
|
* @return array|null
|
||||||
|
*/
|
||||||
|
private function get_update_info(bool $force_fetch = false): ?array {
|
||||||
|
// Check cache first
|
||||||
|
if (!$force_fetch) {
|
||||||
|
$cached = get_transient(self::CACHE_KEY);
|
||||||
|
if (false !== $cached) {
|
||||||
|
return $cached;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch from server
|
||||||
|
$update_info = $this->fetch_update_info();
|
||||||
|
|
||||||
|
if ($update_info) {
|
||||||
|
// Cache the result
|
||||||
|
$cache_ttl = self::get_check_frequency() * HOUR_IN_SECONDS;
|
||||||
|
set_transient(self::CACHE_KEY, $update_info, $cache_ttl);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $update_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch update info from license server
|
||||||
|
*
|
||||||
|
* @return array|null
|
||||||
|
*/
|
||||||
|
private function fetch_update_info(): ?array {
|
||||||
|
$server_url = get_option('wc_tpp_license_server_url', '');
|
||||||
|
$license_key = get_option('wc_tpp_license_key', '');
|
||||||
|
$server_secret = get_option('wc_tpp_license_server_secret', '');
|
||||||
|
|
||||||
|
if (empty($server_url)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the update check endpoint
|
||||||
|
$endpoint = trailingslashit($server_url) . 'wp-json/wc-licensed-product/v1/update-check';
|
||||||
|
|
||||||
|
// Get license checker for domain
|
||||||
|
$license_checker = WC_TPP_License_Checker::get_instance();
|
||||||
|
$domain = $license_checker->get_current_domain();
|
||||||
|
|
||||||
|
// Remove port for API call
|
||||||
|
$domain = preg_replace('/:[\d]+$/', '', $domain);
|
||||||
|
|
||||||
|
// Prepare request body
|
||||||
|
$body = array(
|
||||||
|
'license_key' => $license_key,
|
||||||
|
'domain' => $domain,
|
||||||
|
'plugin_slug' => self::PLUGIN_SLUG,
|
||||||
|
'current_version' => WC_TPP_VERSION,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Make the request
|
||||||
|
$response = wp_remote_post($endpoint, array(
|
||||||
|
'timeout' => 15,
|
||||||
|
'headers' => array(
|
||||||
|
'Content-Type' => 'application/json',
|
||||||
|
'Accept' => 'application/json',
|
||||||
|
),
|
||||||
|
'body' => wp_json_encode($body),
|
||||||
|
));
|
||||||
|
|
||||||
|
if (is_wp_error($response)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$response_code = wp_remote_retrieve_response_code($response);
|
||||||
|
|
||||||
|
// Handle rate limiting
|
||||||
|
if (429 === $response_code) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle other errors
|
||||||
|
if ($response_code < 200 || $response_code >= 300) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$body = wp_remote_retrieve_body($response);
|
||||||
|
$data = json_decode($body, true);
|
||||||
|
|
||||||
|
if (empty($data) || !isset($data['success'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build WordPress update object
|
||||||
|
*
|
||||||
|
* @param array $update_info Update information from server.
|
||||||
|
* @return object|null
|
||||||
|
*/
|
||||||
|
private function build_update_object(array $update_info): ?object {
|
||||||
|
if (empty($update_info['version'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if update is actually available
|
||||||
|
if (version_compare(WC_TPP_VERSION, $update_info['version'], '>=')) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$obj = new \stdClass();
|
||||||
|
$obj->id = $update_info['id'] ?? self::PLUGIN_SLUG;
|
||||||
|
$obj->slug = $update_info['slug'] ?? self::PLUGIN_SLUG;
|
||||||
|
$obj->plugin = $update_info['plugin'] ?? WC_TPP_PLUGIN_BASENAME;
|
||||||
|
$obj->new_version = $update_info['version'];
|
||||||
|
$obj->url = $update_info['url'] ?? '';
|
||||||
|
$obj->package = $update_info['download_url'] ?? $update_info['package'] ?? '';
|
||||||
|
$obj->tested = $update_info['tested'] ?? '';
|
||||||
|
$obj->requires = $update_info['requires'] ?? '6.0';
|
||||||
|
$obj->requires_php = $update_info['requires_php'] ?? '8.3';
|
||||||
|
|
||||||
|
// Icons
|
||||||
|
if (!empty($update_info['icons'])) {
|
||||||
|
$obj->icons = $update_info['icons'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Banners
|
||||||
|
if (!empty($update_info['banners'])) {
|
||||||
|
$obj->banners = $update_info['banners'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build plugin info object for update modal
|
||||||
|
*
|
||||||
|
* @param array $update_info Update information from server.
|
||||||
|
* @return object
|
||||||
|
*/
|
||||||
|
private function build_plugin_info_object(array $update_info): object {
|
||||||
|
$obj = new \stdClass();
|
||||||
|
|
||||||
|
$obj->name = $update_info['name'] ?? 'WooCommerce Tier and Package Prices';
|
||||||
|
$obj->slug = $update_info['slug'] ?? self::PLUGIN_SLUG;
|
||||||
|
$obj->version = $update_info['version'] ?? WC_TPP_VERSION;
|
||||||
|
$obj->author = $update_info['author'] ?? '<a href="https://src.bundespruefstelle.ch/magdev">Marco Graetsch</a>';
|
||||||
|
$obj->author_profile = $update_info['author_profile'] ?? 'https://src.bundespruefstelle.ch/magdev';
|
||||||
|
$obj->homepage = $update_info['homepage'] ?? $update_info['url'] ?? '';
|
||||||
|
$obj->requires = $update_info['requires'] ?? '6.0';
|
||||||
|
$obj->tested = $update_info['tested'] ?? '';
|
||||||
|
$obj->requires_php = $update_info['requires_php'] ?? '8.3';
|
||||||
|
$obj->last_updated = $update_info['last_updated'] ?? '';
|
||||||
|
$obj->download_link = $update_info['download_url'] ?? $update_info['package'] ?? '';
|
||||||
|
|
||||||
|
// Sections (description, changelog, etc.)
|
||||||
|
$obj->sections = array();
|
||||||
|
|
||||||
|
if (!empty($update_info['sections']['description'])) {
|
||||||
|
$obj->sections['description'] = $update_info['sections']['description'];
|
||||||
|
} else {
|
||||||
|
$obj->sections['description'] = __('Add tier pricing and package prices to WooCommerce products with configurable quantities at fixed prices.', 'wc-tier-package-prices');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($update_info['sections']['changelog'])) {
|
||||||
|
$obj->sections['changelog'] = $update_info['sections']['changelog'];
|
||||||
|
} elseif (!empty($update_info['changelog'])) {
|
||||||
|
$obj->sections['changelog'] = $update_info['changelog'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($update_info['sections']['installation'])) {
|
||||||
|
$obj->sections['installation'] = $update_info['sections']['installation'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Icons
|
||||||
|
if (!empty($update_info['icons'])) {
|
||||||
|
$obj->icons = $update_info['icons'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Banners
|
||||||
|
if (!empty($update_info['banners'])) {
|
||||||
|
$obj->banners = $update_info['banners'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear update cache
|
||||||
|
*/
|
||||||
|
public function clear_cache(): void {
|
||||||
|
delete_transient(self::CACHE_KEY);
|
||||||
|
|
||||||
|
// Also clear WordPress plugin update transient to force recheck
|
||||||
|
delete_site_transient('update_plugins');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force check for updates
|
||||||
|
*
|
||||||
|
* @return array|null
|
||||||
|
*/
|
||||||
|
public function force_check(): ?array {
|
||||||
|
$this->clear_cache();
|
||||||
|
return $this->get_update_info(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the available update version if any
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function get_available_version(): ?string {
|
||||||
|
$update_info = $this->get_update_info();
|
||||||
|
|
||||||
|
if (empty($update_info) || empty($update_info['version'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if it's actually newer
|
||||||
|
if (version_compare(WC_TPP_VERSION, $update_info['version'], '>=')) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $update_info['version'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an update is available
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function is_update_available(): bool {
|
||||||
|
return null !== $this->get_available_version();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
@@ -1,12 +1,12 @@
|
|||||||
# German (Switzerland) translation for WooCommerce Tier and Package Prices
|
# German (Switzerland) translation for WooCommerce Tier and Package Prices
|
||||||
# Copyright (C) 2025 Marco Graetsch
|
# Copyright (C) 2026 Marco Graetsch
|
||||||
# This file is distributed under the GPL v2 or later.
|
# This file is distributed under the GPL v2 or later.
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: WooCommerce Tier and Package Prices 1.2.7\n"
|
"Project-Id-Version: WooCommerce Tier and Package Prices 1.4.1\n"
|
||||||
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/wc-tier-package-prices\n"
|
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/wc-tier-package-prices\n"
|
||||||
"POT-Creation-Date: 2025-12-30 00:00+0000\n"
|
"POT-Creation-Date: 2026-02-03 00:00+0000\n"
|
||||||
"PO-Revision-Date: 2025-12-30 00:00+0000\n"
|
"PO-Revision-Date: 2026-02-03 00:00+0000\n"
|
||||||
"Last-Translator: Marco Graetsch\n"
|
"Last-Translator: Marco Graetsch\n"
|
||||||
"Language-Team: German (Switzerland)\n"
|
"Language-Team: German (Switzerland)\n"
|
||||||
"Language: de_CH\n"
|
"Language: de_CH\n"
|
||||||
@@ -359,12 +359,33 @@ msgid "Permission denied."
|
|||||||
msgstr "Zugriff verweigert."
|
msgstr "Zugriff verweigert."
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "License key and server URL are required."
|
msgid "Server Secret"
|
||||||
msgstr "Lizenzschlüssel und Server-URL sind erforderlich."
|
msgstr "Server-Geheimnis"
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "Please enter both license server URL and license key."
|
msgid "The shared secret for secure communication with the license server."
|
||||||
msgstr "Bitte geben Sie sowohl die Lizenzserver-URL als auch den Lizenzschlüssel ein."
|
msgstr "Das gemeinsame Geheimnis für die sichere Kommunikation mit dem Lizenzserver."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "License key, server URL, and server secret are required."
|
||||||
|
msgstr "Lizenzschlüssel, Server-URL und Server-Geheimnis sind erforderlich."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
#. translators: %d: Number of seconds to wait
|
||||||
|
msgid "Rate limit exceeded. Please try again in %d seconds."
|
||||||
|
msgstr "Anfragelimit überschritten. Bitte versuchen Sie es in %d Sekunden erneut."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Response signature verification failed. Please check your server secret."
|
||||||
|
msgstr "Überprüfung der Antwortsignatur fehlgeschlagen. Bitte überprüfen Sie Ihr Server-Geheimnis."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "An unexpected error occurred. Please try again."
|
||||||
|
msgstr "Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es erneut."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Please enter license server URL, license key, and server secret."
|
||||||
|
msgstr "Bitte geben Sie die Lizenzserver-URL, den Lizenzschlüssel und das Server-Geheimnis ein."
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "Validation failed."
|
msgid "Validation failed."
|
||||||
@@ -377,3 +398,98 @@ msgstr "Aktivierung fehlgeschlagen."
|
|||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "Request failed. Please try again."
|
msgid "Request failed. Please try again."
|
||||||
msgstr "Anfrage fehlgeschlagen. Bitte versuchen Sie es erneut."
|
msgstr "Anfrage fehlgeschlagen. Bitte versuchen Sie es erneut."
|
||||||
|
|
||||||
|
#. v1.4.1 - Auto-Updates and License Bypass
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Auto-Updates"
|
||||||
|
msgstr "Auto-Updates"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Auto-Update Settings"
|
||||||
|
msgstr "Auto-Update Einstellungen"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Configure automatic plugin updates from the license server."
|
||||||
|
msgstr "Konfigurieren Sie automatische Plugin-Updates vom Lizenzserver."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Enable Update Notifications"
|
||||||
|
msgstr "Update-Benachrichtigungen aktivieren"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check for available plugin updates."
|
||||||
|
msgstr "Nach verfügbaren Plugin-Updates suchen."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "When enabled, the plugin will check for updates from the license server and show notifications in the WordPress admin."
|
||||||
|
msgstr "Wenn aktiviert, prüft das Plugin auf Updates vom Lizenzserver und zeigt Benachrichtigungen im WordPress-Admin an."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Automatically Install Updates"
|
||||||
|
msgstr "Updates automatisch installieren"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Automatically install updates when available."
|
||||||
|
msgstr "Updates automatisch installieren, wenn verfügbar."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Requires a valid license)"
|
||||||
|
msgstr "(Erfordert eine gültige Lizenz)"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "When enabled, updates will be automatically installed when WordPress performs background updates."
|
||||||
|
msgstr "Wenn aktiviert, werden Updates automatisch installiert, wenn WordPress Hintergrund-Updates durchführt."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check Frequency (Hours)"
|
||||||
|
msgstr "Prüfhäufigkeit (Stunden)"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "How often to check for updates."
|
||||||
|
msgstr "Wie oft nach Updates gesucht werden soll."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Number of hours between update checks. Default is 12 hours."
|
||||||
|
msgstr "Anzahl der Stunden zwischen Update-Prüfungen. Standard ist 12 Stunden."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Status"
|
||||||
|
msgstr "Update-Status"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check for Updates"
|
||||||
|
msgstr "Nach Updates suchen"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Current Version:"
|
||||||
|
msgstr "Aktuelle Version:"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Available:"
|
||||||
|
msgstr "Update verfügbar:"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "You are running the latest version."
|
||||||
|
msgstr "Sie verwenden die neueste Version."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Now"
|
||||||
|
msgstr "Jetzt aktualisieren"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
#. translators: %s: Version number
|
||||||
|
msgid "Update available: version %s"
|
||||||
|
msgstr "Update verfügbar: Version %s"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Failed to check for updates."
|
||||||
|
msgstr "Fehler beim Suchen nach Updates."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Localhost environment - license validation bypassed)"
|
||||||
|
msgstr "(Localhost-Umgebung - Lizenzvalidierung übersprungen)"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Self-licensing server - license validation bypassed)"
|
||||||
|
msgstr "(Selbstlizenzierender Server - Lizenzvalidierung übersprungen)"
|
||||||
|
|||||||
Binary file not shown.
@@ -1,12 +1,12 @@
|
|||||||
# German (Switzerland, Informal) translation for WooCommerce Tier and Package Prices
|
# German (Switzerland, Informal) translation for WooCommerce Tier and Package Prices
|
||||||
# Copyright (C) 2025 Marco Graetsch
|
# Copyright (C) 2026 Marco Graetsch
|
||||||
# This file is distributed under the GPL v2 or later.
|
# This file is distributed under the GPL v2 or later.
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: WooCommerce Tier and Package Prices 1.2.7\n"
|
"Project-Id-Version: WooCommerce Tier and Package Prices 1.4.1\n"
|
||||||
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/wc-tier-package-prices\n"
|
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/wc-tier-package-prices\n"
|
||||||
"POT-Creation-Date: 2025-12-30 00:00+0000\n"
|
"POT-Creation-Date: 2026-02-03 00:00+0000\n"
|
||||||
"PO-Revision-Date: 2025-12-30 00:00+0000\n"
|
"PO-Revision-Date: 2026-02-03 00:00+0000\n"
|
||||||
"Last-Translator: Marco Graetsch\n"
|
"Last-Translator: Marco Graetsch\n"
|
||||||
"Language-Team: German (Switzerland)\n"
|
"Language-Team: German (Switzerland)\n"
|
||||||
"Language: de_CH_informal\n"
|
"Language: de_CH_informal\n"
|
||||||
@@ -359,12 +359,33 @@ msgid "Permission denied."
|
|||||||
msgstr "Zugriff verweigert."
|
msgstr "Zugriff verweigert."
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "License key and server URL are required."
|
msgid "Server Secret"
|
||||||
msgstr "Lizenzschlüssel und Server-URL sind erforderlich."
|
msgstr "Server-Geheimnis"
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "Please enter both license server URL and license key."
|
msgid "The shared secret for secure communication with the license server."
|
||||||
msgstr "Bitte gib sowohl die Lizenzserver-URL als auch den Lizenzschlüssel ein."
|
msgstr "Das gemeinsame Geheimnis für die sichere Kommunikation mit dem Lizenzserver."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "License key, server URL, and server secret are required."
|
||||||
|
msgstr "Lizenzschlüssel, Server-URL und Server-Geheimnis sind erforderlich."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
#. translators: %d: Number of seconds to wait
|
||||||
|
msgid "Rate limit exceeded. Please try again in %d seconds."
|
||||||
|
msgstr "Anfragelimit überschritten. Bitte versuche es in %d Sekunden erneut."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Response signature verification failed. Please check your server secret."
|
||||||
|
msgstr "Überprüfung der Antwortsignatur fehlgeschlagen. Bitte überprüfe dein Server-Geheimnis."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "An unexpected error occurred. Please try again."
|
||||||
|
msgstr "Ein unerwarteter Fehler ist aufgetreten. Bitte versuche es erneut."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Please enter license server URL, license key, and server secret."
|
||||||
|
msgstr "Bitte gib die Lizenzserver-URL, den Lizenzschlüssel und das Server-Geheimnis ein."
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "Validation failed."
|
msgid "Validation failed."
|
||||||
@@ -377,3 +398,98 @@ msgstr "Aktivierung fehlgeschlagen."
|
|||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "Request failed. Please try again."
|
msgid "Request failed. Please try again."
|
||||||
msgstr "Anfrage fehlgeschlagen. Bitte versuche es erneut."
|
msgstr "Anfrage fehlgeschlagen. Bitte versuche es erneut."
|
||||||
|
|
||||||
|
#. v1.4.1 - Auto-Updates and License Bypass
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Auto-Updates"
|
||||||
|
msgstr "Auto-Updates"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Auto-Update Settings"
|
||||||
|
msgstr "Auto-Update Einstellungen"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Configure automatic plugin updates from the license server."
|
||||||
|
msgstr "Konfiguriere automatische Plugin-Updates vom Lizenzserver."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Enable Update Notifications"
|
||||||
|
msgstr "Update-Benachrichtigungen aktivieren"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check for available plugin updates."
|
||||||
|
msgstr "Nach verfügbaren Plugin-Updates suchen."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "When enabled, the plugin will check for updates from the license server and show notifications in the WordPress admin."
|
||||||
|
msgstr "Wenn aktiviert, prüft das Plugin auf Updates vom Lizenzserver und zeigt Benachrichtigungen im WordPress-Admin an."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Automatically Install Updates"
|
||||||
|
msgstr "Updates automatisch installieren"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Automatically install updates when available."
|
||||||
|
msgstr "Updates automatisch installieren, wenn verfügbar."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Requires a valid license)"
|
||||||
|
msgstr "(Erfordert eine gültige Lizenz)"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "When enabled, updates will be automatically installed when WordPress performs background updates."
|
||||||
|
msgstr "Wenn aktiviert, werden Updates automatisch installiert, wenn WordPress Hintergrund-Updates durchführt."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check Frequency (Hours)"
|
||||||
|
msgstr "Prüfhäufigkeit (Stunden)"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "How often to check for updates."
|
||||||
|
msgstr "Wie oft nach Updates gesucht werden soll."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Number of hours between update checks. Default is 12 hours."
|
||||||
|
msgstr "Anzahl der Stunden zwischen Update-Prüfungen. Standard ist 12 Stunden."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Status"
|
||||||
|
msgstr "Update-Status"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check for Updates"
|
||||||
|
msgstr "Nach Updates suchen"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Current Version:"
|
||||||
|
msgstr "Aktuelle Version:"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Available:"
|
||||||
|
msgstr "Update verfügbar:"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "You are running the latest version."
|
||||||
|
msgstr "Du verwendest die neueste Version."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Now"
|
||||||
|
msgstr "Jetzt aktualisieren"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
#. translators: %s: Version number
|
||||||
|
msgid "Update available: version %s"
|
||||||
|
msgstr "Update verfügbar: Version %s"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Failed to check for updates."
|
||||||
|
msgstr "Fehler beim Suchen nach Updates."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Localhost environment - license validation bypassed)"
|
||||||
|
msgstr "(Localhost-Umgebung - Lizenzvalidierung übersprungen)"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Self-licensing server - license validation bypassed)"
|
||||||
|
msgstr "(Selbstlizenzierender Server - Lizenzvalidierung übersprungen)"
|
||||||
|
|||||||
Binary file not shown.
@@ -1,12 +1,12 @@
|
|||||||
# German (Germany) translation for WooCommerce Tier and Package Prices
|
# German (Germany) translation for WooCommerce Tier and Package Prices
|
||||||
# Copyright (C) 2025 Marco Graetsch
|
# Copyright (C) 2026 Marco Graetsch
|
||||||
# This file is distributed under the GPL v2 or later.
|
# This file is distributed under the GPL v2 or later.
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: WooCommerce Tier and Package Prices 1.2.7\n"
|
"Project-Id-Version: WooCommerce Tier and Package Prices 1.4.1\n"
|
||||||
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/wc-tier-package-prices\n"
|
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/wc-tier-package-prices\n"
|
||||||
"POT-Creation-Date: 2025-12-30 00:00+0000\n"
|
"POT-Creation-Date: 2026-02-03 00:00+0000\n"
|
||||||
"PO-Revision-Date: 2025-12-30 00:00+0000\n"
|
"PO-Revision-Date: 2026-02-03 00:00+0000\n"
|
||||||
"Last-Translator: Marco Graetsch\n"
|
"Last-Translator: Marco Graetsch\n"
|
||||||
"Language-Team: German\n"
|
"Language-Team: German\n"
|
||||||
"Language: de_DE\n"
|
"Language: de_DE\n"
|
||||||
@@ -359,12 +359,33 @@ msgid "Permission denied."
|
|||||||
msgstr "Zugriff verweigert."
|
msgstr "Zugriff verweigert."
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "License key and server URL are required."
|
msgid "Server Secret"
|
||||||
msgstr "Lizenzschlüssel und Server-URL sind erforderlich."
|
msgstr "Server-Geheimnis"
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "Please enter both license server URL and license key."
|
msgid "The shared secret for secure communication with the license server."
|
||||||
msgstr "Bitte geben Sie sowohl die Lizenzserver-URL als auch den Lizenzschlüssel ein."
|
msgstr "Das gemeinsame Geheimnis für die sichere Kommunikation mit dem Lizenzserver."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "License key, server URL, and server secret are required."
|
||||||
|
msgstr "Lizenzschlüssel, Server-URL und Server-Geheimnis sind erforderlich."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
#. translators: %d: Number of seconds to wait
|
||||||
|
msgid "Rate limit exceeded. Please try again in %d seconds."
|
||||||
|
msgstr "Anfragelimit überschritten. Bitte versuchen Sie es in %d Sekunden erneut."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Response signature verification failed. Please check your server secret."
|
||||||
|
msgstr "Überprüfung der Antwortsignatur fehlgeschlagen. Bitte überprüfen Sie Ihr Server-Geheimnis."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "An unexpected error occurred. Please try again."
|
||||||
|
msgstr "Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es erneut."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Please enter license server URL, license key, and server secret."
|
||||||
|
msgstr "Bitte geben Sie die Lizenzserver-URL, den Lizenzschlüssel und das Server-Geheimnis ein."
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "Validation failed."
|
msgid "Validation failed."
|
||||||
@@ -377,3 +398,98 @@ msgstr "Aktivierung fehlgeschlagen."
|
|||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "Request failed. Please try again."
|
msgid "Request failed. Please try again."
|
||||||
msgstr "Anfrage fehlgeschlagen. Bitte versuchen Sie es erneut."
|
msgstr "Anfrage fehlgeschlagen. Bitte versuchen Sie es erneut."
|
||||||
|
|
||||||
|
#. v1.4.1 - Auto-Updates and License Bypass
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Auto-Updates"
|
||||||
|
msgstr "Auto-Updates"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Auto-Update Settings"
|
||||||
|
msgstr "Auto-Update Einstellungen"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Configure automatic plugin updates from the license server."
|
||||||
|
msgstr "Konfigurieren Sie automatische Plugin-Updates vom Lizenzserver."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Enable Update Notifications"
|
||||||
|
msgstr "Update-Benachrichtigungen aktivieren"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check for available plugin updates."
|
||||||
|
msgstr "Nach verfügbaren Plugin-Updates suchen."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "When enabled, the plugin will check for updates from the license server and show notifications in the WordPress admin."
|
||||||
|
msgstr "Wenn aktiviert, prüft das Plugin auf Updates vom Lizenzserver und zeigt Benachrichtigungen im WordPress-Admin an."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Automatically Install Updates"
|
||||||
|
msgstr "Updates automatisch installieren"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Automatically install updates when available."
|
||||||
|
msgstr "Updates automatisch installieren, wenn verfügbar."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Requires a valid license)"
|
||||||
|
msgstr "(Erfordert eine gültige Lizenz)"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "When enabled, updates will be automatically installed when WordPress performs background updates."
|
||||||
|
msgstr "Wenn aktiviert, werden Updates automatisch installiert, wenn WordPress Hintergrund-Updates durchführt."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check Frequency (Hours)"
|
||||||
|
msgstr "Prüfhäufigkeit (Stunden)"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "How often to check for updates."
|
||||||
|
msgstr "Wie oft nach Updates gesucht werden soll."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Number of hours between update checks. Default is 12 hours."
|
||||||
|
msgstr "Anzahl der Stunden zwischen Update-Prüfungen. Standard ist 12 Stunden."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Status"
|
||||||
|
msgstr "Update-Status"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check for Updates"
|
||||||
|
msgstr "Nach Updates suchen"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Current Version:"
|
||||||
|
msgstr "Aktuelle Version:"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Available:"
|
||||||
|
msgstr "Update verfügbar:"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "You are running the latest version."
|
||||||
|
msgstr "Sie verwenden die neueste Version."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Now"
|
||||||
|
msgstr "Jetzt aktualisieren"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
#. translators: %s: Version number
|
||||||
|
msgid "Update available: version %s"
|
||||||
|
msgstr "Update verfügbar: Version %s"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Failed to check for updates."
|
||||||
|
msgstr "Fehler beim Suchen nach Updates."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Localhost environment - license validation bypassed)"
|
||||||
|
msgstr "(Localhost-Umgebung - Lizenzvalidierung übersprungen)"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Self-licensing server - license validation bypassed)"
|
||||||
|
msgstr "(Selbstlizenzierender Server - Lizenzvalidierung übersprungen)"
|
||||||
|
|||||||
Binary file not shown.
@@ -1,12 +1,12 @@
|
|||||||
# German (Germany, Informal) translation for WooCommerce Tier and Package Prices
|
# German (Germany, Informal) translation for WooCommerce Tier and Package Prices
|
||||||
# Copyright (C) 2025 Marco Graetsch
|
# Copyright (C) 2026 Marco Graetsch
|
||||||
# This file is distributed under the GPL v2 or later.
|
# This file is distributed under the GPL v2 or later.
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: WooCommerce Tier and Package Prices 1.2.7\n"
|
"Project-Id-Version: WooCommerce Tier and Package Prices 1.4.1\n"
|
||||||
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/wc-tier-package-prices\n"
|
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/wc-tier-package-prices\n"
|
||||||
"POT-Creation-Date: 2025-12-30 00:00+0000\n"
|
"POT-Creation-Date: 2026-02-03 00:00+0000\n"
|
||||||
"PO-Revision-Date: 2025-12-30 00:00+0000\n"
|
"PO-Revision-Date: 2026-02-03 00:00+0000\n"
|
||||||
"Last-Translator: Marco Graetsch\n"
|
"Last-Translator: Marco Graetsch\n"
|
||||||
"Language-Team: German (Germany)\n"
|
"Language-Team: German (Germany)\n"
|
||||||
"Language: de_DE_informal\n"
|
"Language: de_DE_informal\n"
|
||||||
@@ -359,12 +359,33 @@ msgid "Permission denied."
|
|||||||
msgstr "Zugriff verweigert."
|
msgstr "Zugriff verweigert."
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "License key and server URL are required."
|
msgid "Server Secret"
|
||||||
msgstr "Lizenzschlüssel und Server-URL sind erforderlich."
|
msgstr "Server-Geheimnis"
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "Please enter both license server URL and license key."
|
msgid "The shared secret for secure communication with the license server."
|
||||||
msgstr "Bitte gib sowohl die Lizenzserver-URL als auch den Lizenzschlüssel ein."
|
msgstr "Das gemeinsame Geheimnis für die sichere Kommunikation mit dem Lizenzserver."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "License key, server URL, and server secret are required."
|
||||||
|
msgstr "Lizenzschlüssel, Server-URL und Server-Geheimnis sind erforderlich."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
#. translators: %d: Number of seconds to wait
|
||||||
|
msgid "Rate limit exceeded. Please try again in %d seconds."
|
||||||
|
msgstr "Anfragelimit überschritten. Bitte versuche es in %d Sekunden erneut."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Response signature verification failed. Please check your server secret."
|
||||||
|
msgstr "Überprüfung der Antwortsignatur fehlgeschlagen. Bitte überprüfe dein Server-Geheimnis."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "An unexpected error occurred. Please try again."
|
||||||
|
msgstr "Ein unerwarteter Fehler ist aufgetreten. Bitte versuche es erneut."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Please enter license server URL, license key, and server secret."
|
||||||
|
msgstr "Bitte gib die Lizenzserver-URL, den Lizenzschlüssel und das Server-Geheimnis ein."
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "Validation failed."
|
msgid "Validation failed."
|
||||||
@@ -377,3 +398,98 @@ msgstr "Aktivierung fehlgeschlagen."
|
|||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "Request failed. Please try again."
|
msgid "Request failed. Please try again."
|
||||||
msgstr "Anfrage fehlgeschlagen. Bitte versuche es erneut."
|
msgstr "Anfrage fehlgeschlagen. Bitte versuche es erneut."
|
||||||
|
|
||||||
|
#. v1.4.1 - Auto-Updates and License Bypass
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Auto-Updates"
|
||||||
|
msgstr "Auto-Updates"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Auto-Update Settings"
|
||||||
|
msgstr "Auto-Update Einstellungen"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Configure automatic plugin updates from the license server."
|
||||||
|
msgstr "Konfiguriere automatische Plugin-Updates vom Lizenzserver."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Enable Update Notifications"
|
||||||
|
msgstr "Update-Benachrichtigungen aktivieren"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check for available plugin updates."
|
||||||
|
msgstr "Nach verfügbaren Plugin-Updates suchen."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "When enabled, the plugin will check for updates from the license server and show notifications in the WordPress admin."
|
||||||
|
msgstr "Wenn aktiviert, prüft das Plugin auf Updates vom Lizenzserver und zeigt Benachrichtigungen im WordPress-Admin an."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Automatically Install Updates"
|
||||||
|
msgstr "Updates automatisch installieren"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Automatically install updates when available."
|
||||||
|
msgstr "Updates automatisch installieren, wenn verfügbar."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Requires a valid license)"
|
||||||
|
msgstr "(Erfordert eine gültige Lizenz)"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "When enabled, updates will be automatically installed when WordPress performs background updates."
|
||||||
|
msgstr "Wenn aktiviert, werden Updates automatisch installiert, wenn WordPress Hintergrund-Updates durchführt."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check Frequency (Hours)"
|
||||||
|
msgstr "Prüfhäufigkeit (Stunden)"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "How often to check for updates."
|
||||||
|
msgstr "Wie oft nach Updates gesucht werden soll."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Number of hours between update checks. Default is 12 hours."
|
||||||
|
msgstr "Anzahl der Stunden zwischen Update-Prüfungen. Standard ist 12 Stunden."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Status"
|
||||||
|
msgstr "Update-Status"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check for Updates"
|
||||||
|
msgstr "Nach Updates suchen"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Current Version:"
|
||||||
|
msgstr "Aktuelle Version:"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Available:"
|
||||||
|
msgstr "Update verfügbar:"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "You are running the latest version."
|
||||||
|
msgstr "Du verwendest die neueste Version."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Now"
|
||||||
|
msgstr "Jetzt aktualisieren"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
#. translators: %s: Version number
|
||||||
|
msgid "Update available: version %s"
|
||||||
|
msgstr "Update verfügbar: Version %s"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Failed to check for updates."
|
||||||
|
msgstr "Fehler beim Suchen nach Updates."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Localhost environment - license validation bypassed)"
|
||||||
|
msgstr "(Localhost-Umgebung - Lizenzvalidierung übersprungen)"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Self-licensing server - license validation bypassed)"
|
||||||
|
msgstr "(Selbstlizenzierender Server - Lizenzvalidierung übersprungen)"
|
||||||
|
|||||||
Binary file not shown.
@@ -1,12 +1,12 @@
|
|||||||
# English (US) translation for WooCommerce Tier and Package Prices
|
# English (US) translation for WooCommerce Tier and Package Prices
|
||||||
# Copyright (C) 2025 Marco Graetsch
|
# Copyright (C) 2026 Marco Graetsch
|
||||||
# This file is distributed under the GPL v2 or later.
|
# This file is distributed under the GPL v2 or later.
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: WooCommerce Tier and Package Prices 1.2.7\n"
|
"Project-Id-Version: WooCommerce Tier and Package Prices 1.4.1\n"
|
||||||
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/wc-tier-package-prices\n"
|
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/wc-tier-package-prices\n"
|
||||||
"POT-Creation-Date: 2025-12-30 00:00+0000\n"
|
"POT-Creation-Date: 2026-02-03 00:00+0000\n"
|
||||||
"PO-Revision-Date: 2025-12-30 00:00+0000\n"
|
"PO-Revision-Date: 2026-02-03 00:00+0000\n"
|
||||||
"Last-Translator: Marco Graetsch\n"
|
"Last-Translator: Marco Graetsch\n"
|
||||||
"Language-Team: English\n"
|
"Language-Team: English\n"
|
||||||
"Language: en_US\n"
|
"Language: en_US\n"
|
||||||
@@ -359,12 +359,33 @@ msgid "Permission denied."
|
|||||||
msgstr "Permission denied."
|
msgstr "Permission denied."
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "License key and server URL are required."
|
msgid "Server Secret"
|
||||||
msgstr "License key and server URL are required."
|
msgstr "Server Secret"
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "Please enter both license server URL and license key."
|
msgid "The shared secret for secure communication with the license server."
|
||||||
msgstr "Please enter both license server URL and license key."
|
msgstr "The shared secret for secure communication with the license server."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "License key, server URL, and server secret are required."
|
||||||
|
msgstr "License key, server URL, and server secret are required."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
#. translators: %d: Number of seconds to wait
|
||||||
|
msgid "Rate limit exceeded. Please try again in %d seconds."
|
||||||
|
msgstr "Rate limit exceeded. Please try again in %d seconds."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Response signature verification failed. Please check your server secret."
|
||||||
|
msgstr "Response signature verification failed. Please check your server secret."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "An unexpected error occurred. Please try again."
|
||||||
|
msgstr "An unexpected error occurred. Please try again."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Please enter license server URL, license key, and server secret."
|
||||||
|
msgstr "Please enter license server URL, license key, and server secret."
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "Validation failed."
|
msgid "Validation failed."
|
||||||
@@ -377,3 +398,98 @@ msgstr "Activation failed."
|
|||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "Request failed. Please try again."
|
msgid "Request failed. Please try again."
|
||||||
msgstr "Request failed. Please try again."
|
msgstr "Request failed. Please try again."
|
||||||
|
|
||||||
|
#. v1.4.1 - Auto-Updates and License Bypass
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Auto-Updates"
|
||||||
|
msgstr "Auto-Updates"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Auto-Update Settings"
|
||||||
|
msgstr "Auto-Update Settings"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Configure automatic plugin updates from the license server."
|
||||||
|
msgstr "Configure automatic plugin updates from the license server."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Enable Update Notifications"
|
||||||
|
msgstr "Enable Update Notifications"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check for available plugin updates."
|
||||||
|
msgstr "Check for available plugin updates."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "When enabled, the plugin will check for updates from the license server and show notifications in the WordPress admin."
|
||||||
|
msgstr "When enabled, the plugin will check for updates from the license server and show notifications in the WordPress admin."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Automatically Install Updates"
|
||||||
|
msgstr "Automatically Install Updates"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Automatically install updates when available."
|
||||||
|
msgstr "Automatically install updates when available."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Requires a valid license)"
|
||||||
|
msgstr "(Requires a valid license)"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "When enabled, updates will be automatically installed when WordPress performs background updates."
|
||||||
|
msgstr "When enabled, updates will be automatically installed when WordPress performs background updates."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check Frequency (Hours)"
|
||||||
|
msgstr "Check Frequency (Hours)"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "How often to check for updates."
|
||||||
|
msgstr "How often to check for updates."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Number of hours between update checks. Default is 12 hours."
|
||||||
|
msgstr "Number of hours between update checks. Default is 12 hours."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Status"
|
||||||
|
msgstr "Update Status"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check for Updates"
|
||||||
|
msgstr "Check for Updates"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Current Version:"
|
||||||
|
msgstr "Current Version:"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Available:"
|
||||||
|
msgstr "Update Available:"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "You are running the latest version."
|
||||||
|
msgstr "You are running the latest version."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Now"
|
||||||
|
msgstr "Update Now"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
#. translators: %s: Version number
|
||||||
|
msgid "Update available: version %s"
|
||||||
|
msgstr "Update available: version %s"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Failed to check for updates."
|
||||||
|
msgstr "Failed to check for updates."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Localhost environment - license validation bypassed)"
|
||||||
|
msgstr "(Localhost environment - license validation bypassed)"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Self-licensing server - license validation bypassed)"
|
||||||
|
msgstr "(Self-licensing server - license validation bypassed)"
|
||||||
|
|||||||
Binary file not shown.
@@ -1,12 +1,12 @@
|
|||||||
# French (Switzerland) translation for WooCommerce Tier and Package Prices
|
# French (Switzerland) translation for WooCommerce Tier and Package Prices
|
||||||
# Copyright (C) 2025 Marco Graetsch
|
# Copyright (C) 2026 Marco Graetsch
|
||||||
# This file is distributed under the GPL v2 or later.
|
# This file is distributed under the GPL v2 or later.
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: WooCommerce Tier and Package Prices 1.2.7\n"
|
"Project-Id-Version: WooCommerce Tier and Package Prices 1.4.1\n"
|
||||||
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/wc-tier-package-prices\n"
|
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/wc-tier-package-prices\n"
|
||||||
"POT-Creation-Date: 2025-12-30 00:00+0000\n"
|
"POT-Creation-Date: 2026-02-03 00:00+0000\n"
|
||||||
"PO-Revision-Date: 2025-12-30 00:00+0000\n"
|
"PO-Revision-Date: 2026-02-03 00:00+0000\n"
|
||||||
"Last-Translator: Marco Graetsch\n"
|
"Last-Translator: Marco Graetsch\n"
|
||||||
"Language-Team: French (Switzerland)\n"
|
"Language-Team: French (Switzerland)\n"
|
||||||
"Language: fr_CH\n"
|
"Language: fr_CH\n"
|
||||||
@@ -359,12 +359,33 @@ msgid "Permission denied."
|
|||||||
msgstr "Accès refusé."
|
msgstr "Accès refusé."
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "License key and server URL are required."
|
msgid "Server Secret"
|
||||||
msgstr "La clé de licence et l'URL du serveur sont requises."
|
msgstr "Secret serveur"
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "Please enter both license server URL and license key."
|
msgid "The shared secret for secure communication with the license server."
|
||||||
msgstr "Veuillez entrer l'URL du serveur de licence et la clé de licence."
|
msgstr "Le secret partagé pour la communication sécurisée avec le serveur de licence."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "License key, server URL, and server secret are required."
|
||||||
|
msgstr "La clé de licence, l'URL du serveur et le secret serveur sont requis."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
#. translators: %d: Number of seconds to wait
|
||||||
|
msgid "Rate limit exceeded. Please try again in %d seconds."
|
||||||
|
msgstr "Limite de requêtes dépassée. Veuillez réessayer dans %d secondes."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Response signature verification failed. Please check your server secret."
|
||||||
|
msgstr "La vérification de la signature a échoué. Veuillez vérifier votre secret serveur."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "An unexpected error occurred. Please try again."
|
||||||
|
msgstr "Une erreur inattendue s'est produite. Veuillez réessayer."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Please enter license server URL, license key, and server secret."
|
||||||
|
msgstr "Veuillez entrer l'URL du serveur de licence, la clé de licence et le secret serveur."
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "Validation failed."
|
msgid "Validation failed."
|
||||||
@@ -377,3 +398,98 @@ msgstr "L'activation a échoué."
|
|||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "Request failed. Please try again."
|
msgid "Request failed. Please try again."
|
||||||
msgstr "La requête a échoué. Veuillez réessayer."
|
msgstr "La requête a échoué. Veuillez réessayer."
|
||||||
|
|
||||||
|
#. v1.4.1 - Auto-Updates and License Bypass
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Auto-Updates"
|
||||||
|
msgstr "Mises à jour automatiques"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Auto-Update Settings"
|
||||||
|
msgstr "Paramètres de mise à jour automatique"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Configure automatic plugin updates from the license server."
|
||||||
|
msgstr "Configurez les mises à jour automatiques du plugin depuis le serveur de licence."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Enable Update Notifications"
|
||||||
|
msgstr "Activer les notifications de mise à jour"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check for available plugin updates."
|
||||||
|
msgstr "Rechercher les mises à jour disponibles du plugin."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "When enabled, the plugin will check for updates from the license server and show notifications in the WordPress admin."
|
||||||
|
msgstr "Lorsque cette option est activée, le plugin vérifiera les mises à jour depuis le serveur de licence et affichera des notifications dans l'administration WordPress."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Automatically Install Updates"
|
||||||
|
msgstr "Installer automatiquement les mises à jour"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Automatically install updates when available."
|
||||||
|
msgstr "Installer automatiquement les mises à jour lorsqu'elles sont disponibles."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Requires a valid license)"
|
||||||
|
msgstr "(Nécessite une licence valide)"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "When enabled, updates will be automatically installed when WordPress performs background updates."
|
||||||
|
msgstr "Lorsque cette option est activée, les mises à jour seront automatiquement installées lors des mises à jour en arrière-plan de WordPress."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check Frequency (Hours)"
|
||||||
|
msgstr "Fréquence de vérification (heures)"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "How often to check for updates."
|
||||||
|
msgstr "Fréquence de recherche des mises à jour."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Number of hours between update checks. Default is 12 hours."
|
||||||
|
msgstr "Nombre d'heures entre les vérifications de mise à jour. Par défaut: 12 heures."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Status"
|
||||||
|
msgstr "Statut de mise à jour"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check for Updates"
|
||||||
|
msgstr "Rechercher des mises à jour"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Current Version:"
|
||||||
|
msgstr "Version actuelle:"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Available:"
|
||||||
|
msgstr "Mise à jour disponible:"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "You are running the latest version."
|
||||||
|
msgstr "Vous utilisez la dernière version."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Now"
|
||||||
|
msgstr "Mettre à jour maintenant"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
#. translators: %s: Version number
|
||||||
|
msgid "Update available: version %s"
|
||||||
|
msgstr "Mise à jour disponible: version %s"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Failed to check for updates."
|
||||||
|
msgstr "Échec de la recherche de mises à jour."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Localhost environment - license validation bypassed)"
|
||||||
|
msgstr "(Environnement localhost - validation de licence ignorée)"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Self-licensing server - license validation bypassed)"
|
||||||
|
msgstr "(Serveur auto-licencié - validation de licence ignorée)"
|
||||||
|
|||||||
Binary file not shown.
@@ -1,12 +1,12 @@
|
|||||||
# Italian (Switzerland) translation for WooCommerce Tier and Package Prices
|
# Italian (Switzerland) translation for WooCommerce Tier and Package Prices
|
||||||
# Copyright (C) 2025 Marco Graetsch
|
# Copyright (C) 2026 Marco Graetsch
|
||||||
# This file is distributed under the GPL v2 or later.
|
# This file is distributed under the GPL v2 or later.
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: WooCommerce Tier and Package Prices 1.2.7\n"
|
"Project-Id-Version: WooCommerce Tier and Package Prices 1.4.1\n"
|
||||||
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/wc-tier-package-prices\n"
|
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/wc-tier-package-prices\n"
|
||||||
"POT-Creation-Date: 2025-12-30 00:00+0000\n"
|
"POT-Creation-Date: 2026-02-03 00:00+0000\n"
|
||||||
"PO-Revision-Date: 2025-12-30 00:00+0000\n"
|
"PO-Revision-Date: 2026-02-03 00:00+0000\n"
|
||||||
"Last-Translator: Marco Graetsch\n"
|
"Last-Translator: Marco Graetsch\n"
|
||||||
"Language-Team: Italian (Switzerland)\n"
|
"Language-Team: Italian (Switzerland)\n"
|
||||||
"Language: it_CH\n"
|
"Language: it_CH\n"
|
||||||
@@ -359,12 +359,33 @@ msgid "Permission denied."
|
|||||||
msgstr "Accesso negato."
|
msgstr "Accesso negato."
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "License key and server URL are required."
|
msgid "Server Secret"
|
||||||
msgstr "La chiave di licenza e l'URL del server sono obbligatori."
|
msgstr "Segreto del server"
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "Please enter both license server URL and license key."
|
msgid "The shared secret for secure communication with the license server."
|
||||||
msgstr "Inserisci sia l'URL del server di licenza che la chiave di licenza."
|
msgstr "Il segreto condiviso per la comunicazione sicura con il server di licenza."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "License key, server URL, and server secret are required."
|
||||||
|
msgstr "La chiave di licenza, l'URL del server e il segreto del server sono obbligatori."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
#. translators: %d: Number of seconds to wait
|
||||||
|
msgid "Rate limit exceeded. Please try again in %d seconds."
|
||||||
|
msgstr "Limite di richieste superato. Per favore riprova tra %d secondi."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Response signature verification failed. Please check your server secret."
|
||||||
|
msgstr "Verifica della firma della risposta fallita. Per favore controlla il tuo segreto del server."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "An unexpected error occurred. Please try again."
|
||||||
|
msgstr "Si è verificato un errore imprevisto. Per favore riprova."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Please enter license server URL, license key, and server secret."
|
||||||
|
msgstr "Inserisci l'URL del server di licenza, la chiave di licenza e il segreto del server."
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "Validation failed."
|
msgid "Validation failed."
|
||||||
@@ -377,3 +398,98 @@ msgstr "Attivazione fallita."
|
|||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "Request failed. Please try again."
|
msgid "Request failed. Please try again."
|
||||||
msgstr "Richiesta fallita. Per favore riprova."
|
msgstr "Richiesta fallita. Per favore riprova."
|
||||||
|
|
||||||
|
#. v1.4.1 - Auto-Updates and License Bypass
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Auto-Updates"
|
||||||
|
msgstr "Aggiornamenti automatici"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Auto-Update Settings"
|
||||||
|
msgstr "Impostazioni aggiornamento automatico"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Configure automatic plugin updates from the license server."
|
||||||
|
msgstr "Configura gli aggiornamenti automatici del plugin dal server di licenza."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Enable Update Notifications"
|
||||||
|
msgstr "Abilita notifiche di aggiornamento"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check for available plugin updates."
|
||||||
|
msgstr "Verifica la disponibilità di aggiornamenti del plugin."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "When enabled, the plugin will check for updates from the license server and show notifications in the WordPress admin."
|
||||||
|
msgstr "Se abilitato, il plugin verificherà la presenza di aggiornamenti dal server di licenza e mostrerà le notifiche nell'amministrazione WordPress."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Automatically Install Updates"
|
||||||
|
msgstr "Installa automaticamente gli aggiornamenti"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Automatically install updates when available."
|
||||||
|
msgstr "Installa automaticamente gli aggiornamenti quando disponibili."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Requires a valid license)"
|
||||||
|
msgstr "(Richiede una licenza valida)"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "When enabled, updates will be automatically installed when WordPress performs background updates."
|
||||||
|
msgstr "Se abilitato, gli aggiornamenti verranno installati automaticamente quando WordPress esegue gli aggiornamenti in background."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check Frequency (Hours)"
|
||||||
|
msgstr "Frequenza di controllo (ore)"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "How often to check for updates."
|
||||||
|
msgstr "Con quale frequenza controllare gli aggiornamenti."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Number of hours between update checks. Default is 12 hours."
|
||||||
|
msgstr "Numero di ore tra i controlli degli aggiornamenti. Predefinito: 12 ore."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Status"
|
||||||
|
msgstr "Stato aggiornamento"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check for Updates"
|
||||||
|
msgstr "Verifica aggiornamenti"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Current Version:"
|
||||||
|
msgstr "Versione attuale:"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Available:"
|
||||||
|
msgstr "Aggiornamento disponibile:"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "You are running the latest version."
|
||||||
|
msgstr "Stai utilizzando l'ultima versione."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Now"
|
||||||
|
msgstr "Aggiorna ora"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
#. translators: %s: Version number
|
||||||
|
msgid "Update available: version %s"
|
||||||
|
msgstr "Aggiornamento disponibile: versione %s"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Failed to check for updates."
|
||||||
|
msgstr "Impossibile verificare la presenza di aggiornamenti."
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Localhost environment - license validation bypassed)"
|
||||||
|
msgstr "(Ambiente localhost - verifica della licenza saltata)"
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Self-licensing server - license validation bypassed)"
|
||||||
|
msgstr "(Server auto-licenziato - verifica della licenza saltata)"
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
# Copyright (C) 2025 Marco Graetsch
|
# Copyright (C) 2026 Marco Graetsch
|
||||||
# This file is distributed under the GPL v2 or later.
|
# This file is distributed under the GPL v2 or later.
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: WooCommerce Tier and Package Prices 1.2.7\n"
|
"Project-Id-Version: WooCommerce Tier and Package Prices 1.4.1\n"
|
||||||
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/wc-tier-package-prices\n"
|
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/wc-tier-package-prices\n"
|
||||||
"POT-Creation-Date: 2025-12-30 00:00+0000\n"
|
"POT-Creation-Date: 2026-02-03 00:00+0000\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
@@ -332,11 +332,32 @@ msgid "Permission denied."
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "License key and server URL are required."
|
msgid "Server Secret"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "Please enter both license server URL and license key."
|
msgid "The shared secret for secure communication with the license server."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "License key, server URL, and server secret are required."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
#. translators: %d: Number of seconds to wait
|
||||||
|
msgid "Rate limit exceeded. Please try again in %d seconds."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Response signature verification failed. Please check your server secret."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "An unexpected error occurred. Please try again."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Please enter license server URL, license key, and server secret."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
@@ -350,3 +371,98 @@ msgstr ""
|
|||||||
#: includes/class-wc-tpp-settings.php
|
#: includes/class-wc-tpp-settings.php
|
||||||
msgid "Request failed. Please try again."
|
msgid "Request failed. Please try again."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. v1.4.1 - Auto-Updates and License Bypass
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Auto-Updates"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Auto-Update Settings"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Configure automatic plugin updates from the license server."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Enable Update Notifications"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check for available plugin updates."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "When enabled, the plugin will check for updates from the license server and show notifications in the WordPress admin."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Automatically Install Updates"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Automatically install updates when available."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Requires a valid license)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "When enabled, updates will be automatically installed when WordPress performs background updates."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check Frequency (Hours)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "How often to check for updates."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Number of hours between update checks. Default is 12 hours."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Status"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Check for Updates"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Current Version:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Available:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "You are running the latest version."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Update Now"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
#. translators: %s: Version number
|
||||||
|
msgid "Update available: version %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "Failed to check for updates."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Localhost environment - license validation bypassed)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-wc-tpp-settings.php
|
||||||
|
msgid "(Self-licensing server - license validation bypassed)"
|
||||||
|
msgstr ""
|
||||||
|
|||||||
1
lib/wc-licensed-product-client
Submodule
1
lib/wc-licensed-product-client
Submodule
Submodule lib/wc-licensed-product-client added at 56abe8a97c
@@ -4,7 +4,7 @@
|
|||||||
* Plugin Name: WooCommerce Tier and Package Prices
|
* Plugin Name: WooCommerce Tier and Package Prices
|
||||||
* Plugin URI: https://src.bundespruefstelle.ch/magdev/wc-tier-package-prices
|
* Plugin URI: https://src.bundespruefstelle.ch/magdev/wc-tier-package-prices
|
||||||
* Description: Add tier pricing and package prices to WooCommerce products with configurable quantities at fixed prices
|
* Description: Add tier pricing and package prices to WooCommerce products with configurable quantities at fixed prices
|
||||||
* Version: 1.3.0
|
* Version: 1.4.1
|
||||||
* Author: Marco Graetsch
|
* Author: Marco Graetsch
|
||||||
* Author URI: https://src.bundespruefstelle.ch/magdev
|
* Author URI: https://src.bundespruefstelle.ch/magdev
|
||||||
* Text Domain: wc-tier-package-prices
|
* Text Domain: wc-tier-package-prices
|
||||||
@@ -46,7 +46,7 @@ if (!function_exists('wc_tpp_php_version_notice')) {
|
|||||||
|
|
||||||
// Define plugin constants
|
// Define plugin constants
|
||||||
if (!defined('WC_TPP_VERSION')) {
|
if (!defined('WC_TPP_VERSION')) {
|
||||||
define('WC_TPP_VERSION', '1.3.0');
|
define('WC_TPP_VERSION', '1.4.1');
|
||||||
}
|
}
|
||||||
if (!defined('WC_TPP_PLUGIN_DIR')) {
|
if (!defined('WC_TPP_PLUGIN_DIR')) {
|
||||||
define('WC_TPP_PLUGIN_DIR', plugin_dir_path(__FILE__));
|
define('WC_TPP_PLUGIN_DIR', plugin_dir_path(__FILE__));
|
||||||
@@ -111,10 +111,18 @@ if (!class_exists('WC_Tier_Package_Prices')) {
|
|||||||
|
|
||||||
private function includes() {
|
private function includes() {
|
||||||
require_once WC_TPP_PLUGIN_DIR . 'includes/class-wc-tpp-template-loader.php';
|
require_once WC_TPP_PLUGIN_DIR . 'includes/class-wc-tpp-template-loader.php';
|
||||||
|
require_once WC_TPP_PLUGIN_DIR . 'includes/class-wc-tpp-license-checker.php';
|
||||||
|
require_once WC_TPP_PLUGIN_DIR . 'includes/class-wc-tpp-update-checker.php';
|
||||||
require_once WC_TPP_PLUGIN_DIR . 'includes/class-wc-tpp-admin.php';
|
require_once WC_TPP_PLUGIN_DIR . 'includes/class-wc-tpp-admin.php';
|
||||||
require_once WC_TPP_PLUGIN_DIR . 'includes/class-wc-tpp-product-meta.php';
|
require_once WC_TPP_PLUGIN_DIR . 'includes/class-wc-tpp-product-meta.php';
|
||||||
require_once WC_TPP_PLUGIN_DIR . 'includes/class-wc-tpp-frontend.php';
|
require_once WC_TPP_PLUGIN_DIR . 'includes/class-wc-tpp-frontend.php';
|
||||||
require_once WC_TPP_PLUGIN_DIR . 'includes/class-wc-tpp-cart.php';
|
require_once WC_TPP_PLUGIN_DIR . 'includes/class-wc-tpp-cart.php';
|
||||||
|
|
||||||
|
// Initialize license checker (singleton)
|
||||||
|
WC_TPP_License_Checker::get_instance();
|
||||||
|
|
||||||
|
// Initialize update checker (singleton)
|
||||||
|
WC_TPP_Update_Checker::get_instance();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function declare_hpos_compatibility() {
|
public function declare_hpos_compatibility() {
|
||||||
@@ -132,6 +140,12 @@ if (!class_exists('WC_Tier_Package_Prices')) {
|
|||||||
add_option('wc_tpp_enable_tier_pricing', 'yes');
|
add_option('wc_tpp_enable_tier_pricing', 'yes');
|
||||||
add_option('wc_tpp_enable_package_pricing', 'yes');
|
add_option('wc_tpp_enable_package_pricing', 'yes');
|
||||||
add_option('wc_tpp_display_table', 'yes');
|
add_option('wc_tpp_display_table', 'yes');
|
||||||
|
|
||||||
|
// Add default auto-update options
|
||||||
|
add_option('wc_tpp_update_notification_enabled', 'yes');
|
||||||
|
add_option('wc_tpp_auto_install_enabled', 'no');
|
||||||
|
add_option('wc_tpp_update_check_frequency', '12');
|
||||||
|
|
||||||
flush_rewrite_rules();
|
flush_rewrite_rules();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user