Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1f6e54f9d | ||
|
|
48119f2034 | ||
|
|
056be0e917 | ||
|
|
426015bb12 |
+5
-2
@@ -1,10 +1,10 @@
|
|||||||
=== WooCommerce Email Discount Manager ===
|
=== WooCommerce Email Discount Manager ===
|
||||||
Contributors: wedsmp
|
Contributors: kristianwind
|
||||||
Tags: woocommerce, discount, email, shipping, coupon
|
Tags: woocommerce, discount, email, shipping, coupon
|
||||||
Requires at least: 5.8
|
Requires at least: 5.8
|
||||||
Tested up to: 7.1
|
Tested up to: 7.1
|
||||||
Requires PHP: 7.4
|
Requires PHP: 7.4
|
||||||
Stable tag: 1.4.2
|
Stable tag: 1.4.3
|
||||||
WC requires at least: 6.0
|
WC requires at least: 6.0
|
||||||
WC tested up to: 11.1.0
|
WC tested up to: 11.1.0
|
||||||
License: GPLv2 or later
|
License: GPLv2 or later
|
||||||
@@ -96,6 +96,9 @@ The most specific match wins: exact email, then domain, then partial match.
|
|||||||
|
|
||||||
== Changelog ==
|
== Changelog ==
|
||||||
|
|
||||||
|
= 1.4.3 =
|
||||||
|
* The plugin is now credited to Kristian Wind, with a link to where its source lives. It previously carried a placeholder name.
|
||||||
|
|
||||||
= 1.4.2 =
|
= 1.4.2 =
|
||||||
* The plugin now has an icon, so it no longer shows up as a generic grey plug under Dashboard → Updates.
|
* The plugin now has an icon, so it no longer shows up as a generic grey plug under Dashboard → Updates.
|
||||||
* "Check again" on the updates screen really does check again. It previously reused a cached answer for up to six hours, which made a brand new version look like it had not been published.
|
* "Check again" on the updates screen really does check again. It previously reused a cached answer for up to six hours, which made a brand new version look like it had not been published.
|
||||||
|
|||||||
+8
-1
@@ -18,7 +18,14 @@ while IFS= read -r line; do
|
|||||||
[ -n "$line" ] && patterns+=("${line%/}")
|
[ -n "$line" ] && patterns+=("${line%/}")
|
||||||
done < .distignore
|
done < .distignore
|
||||||
|
|
||||||
git ls-files | while IFS= read -r file; do
|
# -z, not plain `git ls-files`: git QUOTES any path containing a non-ASCII
|
||||||
|
# byte, so "TESTMILJØ.md" comes out as the literal 14-character string
|
||||||
|
# "TESTMILJ\303\230.md". That form matches no pattern in .distignore, so the
|
||||||
|
# file is kept — an internal document walking straight into the release zip
|
||||||
|
# with nothing said. (-z also covers paths with spaces.) Found in a sibling
|
||||||
|
# plugin that has exactly such a filename; this repo has none today, which is
|
||||||
|
# precisely why it would have sat here until someone added one.
|
||||||
|
git ls-files -z | while IFS= read -r -d '' file; do
|
||||||
keep=1
|
keep=1
|
||||||
for p in "${patterns[@]}"; do
|
for p in "${patterns[@]}"; do
|
||||||
# A bare name excludes the file or directory wherever it appears, which is
|
# A bare name excludes the file or directory wherever it appears, which is
|
||||||
|
|||||||
@@ -46,33 +46,51 @@ ci_plugin_header() {
|
|||||||
"$(ci_repo_root)/$PLUGIN_MAIN" | head -1 | sed -E 's/[[:space:]]+$//'
|
"$(ci_repo_root)/$PLUGIN_MAIN" | head -1 | sed -E 's/[[:space:]]+$//'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Run a shell script against a checkout of this repository, inside a container.
|
||||||
|
#
|
||||||
|
# The repository goes in over a tarball and `docker cp`, never a bind mount: a
|
||||||
|
# Gitea Actions job runs inside a container talking to the HOST's docker
|
||||||
|
# daemon, so a host path here lands on an empty directory nobody created and
|
||||||
|
# the check passes by checking nothing. The symptom reads like a typo in a path.
|
||||||
|
#
|
||||||
|
# Two details are load-bearing. The script is copied in as a FILE rather than
|
||||||
|
# interpolated into `sh -c`, so it can contain $, quotes and newlines without
|
||||||
|
# being mangled — which matters the moment it is more than one command. And
|
||||||
|
# --entrypoint sh is not decoration: some images (composer:2, for one) have an
|
||||||
|
# entrypoint that swallows its arguments.
|
||||||
|
#
|
||||||
|
# Taken from the subscriptions port, which needed it for composer.
|
||||||
|
ci_in_container() { # image script-text
|
||||||
|
local image="$1" script="$2"
|
||||||
|
local dir cid code=0
|
||||||
|
|
||||||
|
dir=$(mktemp -d -t wpci-XXXXXX)
|
||||||
|
( cd "$(ci_repo_root)" && git ls-files -z | tar --null -T - -cf "$dir/src.tar" )
|
||||||
|
printf '%s\n' "$script" > "$dir/run.sh"
|
||||||
|
|
||||||
|
cid=$(docker create --entrypoint sh -w /src "$image" \
|
||||||
|
-c 'mkdir -p /src && tar -xf /tmp/src.tar -C /src && exec sh /tmp/run.sh')
|
||||||
|
docker cp "$dir/src.tar" "$cid:/tmp/src.tar" >/dev/null
|
||||||
|
docker cp "$dir/run.sh" "$cid:/tmp/run.sh" >/dev/null
|
||||||
|
docker start -a "$cid" || code=$?
|
||||||
|
docker rm -f "$cid" >/dev/null
|
||||||
|
rm -rf "$dir"
|
||||||
|
return "$code"
|
||||||
|
}
|
||||||
|
|
||||||
# Run one of this repository's PHP scripts.
|
# Run one of this repository's PHP scripts.
|
||||||
#
|
#
|
||||||
# Uses the local php when there is one — a laptop, GitHub's hosted runners —
|
# Uses the local php when there is one — a laptop, GitHub's hosted runners —
|
||||||
# and a container otherwise. The Gitea runner image has no php, and losing a
|
# and a container otherwise. The Gitea runner image has no php, and losing a
|
||||||
# build to "php: command not found" after everything else passed is a silly way
|
# build to "php: command not found" after everything else passed is a silly way
|
||||||
# to spend an afternoon. Measured: it happened on the very first Gitea run.
|
# to spend an afternoon. Measured: it happened on the very first Gitea run.
|
||||||
#
|
|
||||||
# The repository goes in over a tarball and `docker cp`, never a bind mount: a
|
|
||||||
# Gitea Actions job runs inside a container talking to the HOST's docker
|
|
||||||
# daemon, so a host path here lands on an empty directory nobody created.
|
|
||||||
ci_php() {
|
ci_php() {
|
||||||
if command -v php >/dev/null 2>&1; then
|
if command -v php >/dev/null 2>&1; then
|
||||||
php "$@"
|
php "$@"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local tarball cid code=0
|
ci_in_container "php:8.4-cli" "exec php $(printf '%q ' "$@")"
|
||||||
tarball=$(mktemp -t wpci-php-XXXXXX.tar)
|
|
||||||
( cd "$(ci_repo_root)" && git ls-files -z | tar --null -T - -cf "$tarball" )
|
|
||||||
|
|
||||||
cid=$(docker create "php:8.4-cli" sh -c \
|
|
||||||
"mkdir -p /src && tar -xf /tmp/src.tar -C /src && cd /src && exec php $(printf '%q ' "$@")")
|
|
||||||
docker cp "$tarball" "$cid:/tmp/src.tar" >/dev/null
|
|
||||||
docker start -a "$cid" || code=$?
|
|
||||||
docker rm -f "$cid" >/dev/null
|
|
||||||
rm -f "$tarball"
|
|
||||||
return "$code"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ci_step() { printf '\n\033[1m→ %s\033[0m\n' "$*"; }
|
ci_step() { printf '\n\033[1m→ %s\033[0m\n' "$*"; }
|
||||||
|
|||||||
+28
-2
@@ -76,11 +76,13 @@ before=$fails
|
|||||||
if git ls-files -z '*.php' | xargs -0 grep -nP '<\?(?!php|=|xml)' ; then
|
if git ls-files -z '*.php' | xargs -0 grep -nP '<\?(?!php|=|xml)' ; then
|
||||||
note_fail "Use <?php, not short open tags."
|
note_fail "Use <?php, not short open tags."
|
||||||
fi
|
fi
|
||||||
while read -r f; do
|
# -z: git quotes non-ASCII paths, and the quoted form is not a path that
|
||||||
|
# exists, so this loop would silently skip the file it was meant to check.
|
||||||
|
while IFS= read -r -d '' f; do
|
||||||
[ -n "$f" ] || continue
|
[ -n "$f" ] || continue
|
||||||
[ "$(tail -c 3 "$f" | tr -d '[:space:]')" = "?>" ] \
|
[ "$(tail -c 3 "$f" | tr -d '[:space:]')" = "?>" ] \
|
||||||
&& { ci_annotate error "$f" 1 "Remove the trailing ?> at the end of the file."; fails=$((fails + 1)); }
|
&& { ci_annotate error "$f" 1 "Remove the trailing ?> at the end of the file."; fails=$((fails + 1)); }
|
||||||
done <<< "$(git ls-files '*.php')"
|
done < <(git ls-files -z '*.php')
|
||||||
[ "$fails" = "$before" ] && echo " clean"
|
[ "$fails" = "$before" ] && echo " clean"
|
||||||
|
|
||||||
ci_step "text domain"
|
ci_step "text domain"
|
||||||
@@ -141,6 +143,30 @@ for readme in readme.txt README.txt; do
|
|||||||
|| note_fail "$readme has 'Stable tag: $stable' but the plugin header says $version."
|
|| note_fail "$readme has 'Stable tag: $stable' but the plugin header says $version."
|
||||||
done
|
done
|
||||||
|
|
||||||
|
ci_step "no placeholders left in the plugin header"
|
||||||
|
# The header is the plugin's business card: wp-admin shows the author and the
|
||||||
|
# links to whoever installs it, so a placeholder there survives for as long as
|
||||||
|
# nobody happens to look at that screen. This plugin shipped with
|
||||||
|
# "https://example.com/" as its Plugin URI for several releases.
|
||||||
|
#
|
||||||
|
# It catches the generic markers only. A made-up vendor name — this one went
|
||||||
|
# out as "WEDSMP" — looks exactly like a real one to any check, so an empty
|
||||||
|
# field is warned about but a wrong-but-plausible value cannot be.
|
||||||
|
before=$fails
|
||||||
|
for field in 'Plugin Name' 'Description' 'Author' 'Author URI' 'Plugin URI'; do
|
||||||
|
value=$(ci_plugin_header "$field")
|
||||||
|
if [ -z "$value" ]; then
|
||||||
|
echo "::warning::The plugin header has no '$field:'."
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
case "$value" in
|
||||||
|
*example.com*|*example.org*|*yourname*|*YOUR_*|*TODO*|*FIXME*|*changeme*|*'<'*'>'*)
|
||||||
|
note_fail "$field is still a placeholder: $value"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
[ "$fails" = "$before" ] && echo " name, description, author and links are all filled in"
|
||||||
|
|
||||||
ci_step "the compatibility headers still tell the truth"
|
ci_step "the compatibility headers still tell the truth"
|
||||||
# Advisory, never fatal. WordPress ships a new version whether or not anything
|
# Advisory, never fatal. WordPress ships a new version whether or not anything
|
||||||
# here is wrong, and a build that goes red on release day for a header nobody
|
# here is wrong, and a build that goes red on release day for a header nobody
|
||||||
|
|||||||
+26
-5
@@ -71,11 +71,14 @@ Three things in that file are load-bearing and none of them look it:
|
|||||||
WordPress 5.8. Remove the header and a .org plugin that happens to share the
|
WordPress 5.8. Remove the header and a .org plugin that happens to share the
|
||||||
slug could be pushed onto a shop running yours.
|
slug could be pushed onto a shop running yours.
|
||||||
|
|
||||||
The answer is cached for six hours, which is right for the check WordPress runs
|
🔴 **Keep the feed cache short — WordPress is already the rate limiter.** It
|
||||||
twice a day and wrong for the **Check again** link — so `forget_on_force_check()`
|
gates its own check by screen: one minute on Dashboard → Updates, one hour on
|
||||||
drops the cache on `force-check`. Without it, someone who has just published a
|
the Plugins screen, 2–12 hours in the background. This filter only runs when
|
||||||
release clicks that link, sees nothing, and concludes the whole mechanism is
|
that check runs, so any cache longer than that cadence simply hides new
|
||||||
broken.
|
releases underneath it. Ours was six hours "because WordPress checks twice a
|
||||||
|
day anyway", and the symptom was a release going out and the shop being shown
|
||||||
|
nothing. It is fifteen minutes now, and `forget_on_force_check()` drops it
|
||||||
|
entirely on the **Check again** link.
|
||||||
|
|
||||||
**6. Make the Gitea repository public**, or point `Update URI` at a separate
|
**6. Make the Gitea repository public**, or point `Update URI` at a separate
|
||||||
public releases-only repository. Every shop reads that feed without
|
public releases-only repository. Every shop reads that feed without
|
||||||
@@ -105,6 +108,24 @@ it cannot.
|
|||||||
- `ci/workflows-in-sync.sh` — fails when the two workflow roots drift, which is
|
- `ci/workflows-in-sync.sh` — fails when the two workflow roots drift, which is
|
||||||
the only way to notice that a workflow stopped running on Gitea.
|
the only way to notice that a workflow stopped running on Gitea.
|
||||||
|
|
||||||
|
## Running these locally: `git add` first
|
||||||
|
|
||||||
|
Every one of these scripts derives "what ships" from `git ls-files`, which
|
||||||
|
reads the **index**. An uncommitted file is therefore invisible to
|
||||||
|
`ci/dist-files.sh`, to the release zip, and to the copy that goes into the test
|
||||||
|
site.
|
||||||
|
|
||||||
|
That is deliberate — it is what catches a file that was written, referenced and
|
||||||
|
never committed, which is a release that is missing a file while every local
|
||||||
|
test passes because the file is sitting right there in the working tree. But it
|
||||||
|
also means running any of this before `git add` tests a release without your
|
||||||
|
newest file, and the failure is silent: the check does not complain, it just
|
||||||
|
measures something else. It cost two rounds here, once on
|
||||||
|
`includes/class-updater.php` and once on `assets/icon.svg`.
|
||||||
|
|
||||||
|
If a script reports something you just fixed as still missing, `git status`
|
||||||
|
before you debug the script.
|
||||||
|
|
||||||
## Two guards worth understanding before you move them
|
## Two guards worth understanding before you move them
|
||||||
|
|
||||||
**`.gitea/workflows/` hides `.github/workflows/` completely.** Gitea uses the
|
**`.gitea/workflows/` hides `.github/workflows/` completely.** Gitea uses the
|
||||||
|
|||||||
@@ -185,11 +185,21 @@ the real list table and asserts the flag rather than trusting the reasoning.
|
|||||||
|
|
||||||
### "Check again" really checks again
|
### "Check again" really checks again
|
||||||
|
|
||||||
The feed is cached for six hours. That is right for the check WordPress runs on
|
The feed is cached for fifteen minutes, and the cache is dropped entirely when
|
||||||
its own twice a day, and wrong for a link whose entire promise is that it looks
|
wp-admin is loaded with `force-check`.
|
||||||
*now* — so the cache is dropped when wp-admin is loaded with `force-check`.
|
|
||||||
Without that, publishing a release and then clicking **Check again** shows
|
It was six hours, on the reasoning that WordPress checks twice a day anyway.
|
||||||
nothing for up to six hours, which reads exactly like a broken updater.
|
That reasoning was wrong. WordPress gates its own check **by screen**:
|
||||||
|
|
||||||
|
| Screen | How often WordPress re-checks |
|
||||||
|
| --- | --- |
|
||||||
|
| Dashboard → Updates | every minute |
|
||||||
|
| Plugins | every hour |
|
||||||
|
| Background / cron | every 2–12 hours |
|
||||||
|
|
||||||
|
This filter only runs when that check runs, so WordPress is already the rate
|
||||||
|
limiter. A cache longer than its cadence does nothing but hide new releases
|
||||||
|
underneath it — a release published, and a shop shown nothing.
|
||||||
|
|
||||||
From the command line, `wp transient delete wc_edm_release_feed` does the same.
|
From the command line, `wp transient delete wc_edm_release_feed` does the same.
|
||||||
|
|
||||||
|
|||||||
@@ -34,10 +34,24 @@ class WC_EDM_Updater {
|
|||||||
const TRANSIENT = 'wc_edm_release_feed';
|
const TRANSIENT = 'wc_edm_release_feed';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How long that cache lives. WordPress checks for updates twice a day; a
|
* How long that cache lives.
|
||||||
* shorter window would only add requests, a longer one would delay a fix.
|
*
|
||||||
|
* Six hours, originally, on the reasoning that WordPress checks twice a
|
||||||
|
* day anyway. That reasoning was wrong, and the symptom was a shop that
|
||||||
|
* had just been told a new version existed and was shown nothing.
|
||||||
|
*
|
||||||
|
* WordPress does not check twice a day when somebody is looking. It gates
|
||||||
|
* its own check by screen — one minute on Dashboard → Updates, one hour on
|
||||||
|
* the Plugins screen, twelve hours in the background (wp_update_plugins(),
|
||||||
|
* switch on current_filter()). This filter only runs when that check runs,
|
||||||
|
* so WordPress is already the rate limiter, and a cache longer than its
|
||||||
|
* cadence does nothing but hide new releases underneath it.
|
||||||
|
*
|
||||||
|
* Fifteen minutes is left only to absorb a burst — several calls in one
|
||||||
|
* request, or other code calling wp_update_plugins() with extra stats,
|
||||||
|
* which bypasses the gate above.
|
||||||
*/
|
*/
|
||||||
const TTL = 6 * HOUR_IN_SECONDS;
|
const TTL = 15 * MINUTE_IN_SECONDS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook into the update check for our own host only.
|
* Hook into the update check for our own host only.
|
||||||
|
|||||||
+53
-7
@@ -14,7 +14,29 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
$wc_edm_failures = 0;
|
/*
|
||||||
|
* The counter lives in $GLOBALS on purpose, and the four lines below prove it
|
||||||
|
* reaches the verdict before anything relies on it.
|
||||||
|
*
|
||||||
|
* `wp eval-file` runs this file through eval() INSIDE A METHOD, so the top
|
||||||
|
* level here is function scope, not global scope. A plain `$failures = 0` at
|
||||||
|
* the top and a `global $failures` in a helper below are therefore two
|
||||||
|
* different variables: the helpers increment the real global, the verdict at
|
||||||
|
* the bottom reads the local, and the local is always zero. Every assertion
|
||||||
|
* fails, every FAIL line prints, the file ends with "All assertions passed"
|
||||||
|
* and exits 0 — and CI goes green. That is not reasoning, it is what this file
|
||||||
|
* did until it was measured.
|
||||||
|
*
|
||||||
|
* This is the one file whose entire job is to be able to go red, so it checks
|
||||||
|
* that it can.
|
||||||
|
*/
|
||||||
|
$GLOBALS['wc_edm_failures'] = 0;
|
||||||
|
( static function () { ++$GLOBALS['wc_edm_failures']; } )();
|
||||||
|
if ( 1 !== $GLOBALS['wc_edm_failures'] ) {
|
||||||
|
echo "The failure counter does not reach the verdict: this file cannot go red.\n";
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
$GLOBALS['wc_edm_failures'] = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assert a condition and keep going, so one run reports every failure.
|
* Assert a condition and keep going, so one run reports every failure.
|
||||||
@@ -24,14 +46,12 @@ $wc_edm_failures = 0;
|
|||||||
* @param string $detail Shown when it fails.
|
* @param string $detail Shown when it fails.
|
||||||
*/
|
*/
|
||||||
function wc_edm_ok( $what, $condition, $detail = '' ) {
|
function wc_edm_ok( $what, $condition, $detail = '' ) {
|
||||||
global $wc_edm_failures;
|
|
||||||
|
|
||||||
if ( $condition ) {
|
if ( $condition ) {
|
||||||
printf( " ok %s\n", $what );
|
printf( " ok %s\n", $what );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
++$wc_edm_failures;
|
++$GLOBALS['wc_edm_failures'];
|
||||||
printf( " FAIL %s%s\n", $what, '' !== $detail ? " — {$detail}" : '' );
|
printf( " FAIL %s%s\n", $what, '' !== $detail ? " — {$detail}" : '' );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,7 +365,18 @@ wc_edm_is( 'the current version is answered too, not passed over', WC_EDM_VERSIO
|
|||||||
* WordPress does with our answer, and a test that needs the internet fails for
|
* WordPress does with our answer, and a test that needs the internet fails for
|
||||||
* reasons that have nothing to do with it.
|
* reasons that have nothing to do with it.
|
||||||
*/
|
*/
|
||||||
// "Check again" must discard the six-hour cache, or the button lies: someone
|
// The cache must not outlive WordPress's own check cadence. It gates by screen
|
||||||
|
// — one minute on Dashboard → Updates, one hour on the Plugins screen — and
|
||||||
|
// this filter only runs when that check runs, so anything longer here hides a
|
||||||
|
// new release underneath a cache the shop owner cannot see. This was six hours
|
||||||
|
// and produced exactly that: a release published, and a shop shown nothing.
|
||||||
|
wc_edm_ok(
|
||||||
|
'the cache is shorter than the interval WordPress re-checks on',
|
||||||
|
WC_EDM_Updater::TTL <= 15 * MINUTE_IN_SECONDS,
|
||||||
|
'TTL is ' . WC_EDM_Updater::TTL . 's; WordPress re-checks every 60s on Dashboard → Updates'
|
||||||
|
);
|
||||||
|
|
||||||
|
// "Check again" must discard the cache, or the button lies: someone
|
||||||
// who has just published a release clicks it, sees nothing, and concludes the
|
// who has just published a release clicks it, sees nothing, and concludes the
|
||||||
// whole mechanism is broken.
|
// whole mechanism is broken.
|
||||||
set_transient( WC_EDM_Updater::TRANSIENT, array( 'version' => '1.0.0', 'package' => 'x', 'url' => 'x', 'tested' => '' ), 600 );
|
set_transient( WC_EDM_Updater::TRANSIENT, array( 'version' => '1.0.0', 'package' => 'x', 'url' => 'x', 'tested' => '' ), 600 );
|
||||||
@@ -368,6 +399,21 @@ delete_transient( WC_EDM_Updater::TRANSIENT );
|
|||||||
// strlen(null) deprecation from class-wp-plugins-list-table.php. It is
|
// strlen(null) deprecation from class-wp-plugins-list-table.php. It is
|
||||||
// WordPress's, not ours, which is why the deprecation check filters on this
|
// WordPress's, not ours, which is why the deprecation check filters on this
|
||||||
// plugin's directory rather than failing on everything it sees.
|
// plugin's directory rather than failing on everything it sees.
|
||||||
|
// Primed again deliberately. The force-check assertions above deleted it, and
|
||||||
|
// without this offer_update() makes a real HTTP request — which passes only
|
||||||
|
// because this plugin's feed repo happens to be public. That would make the
|
||||||
|
// assertion measure the environment rather than the code under test.
|
||||||
|
set_transient(
|
||||||
|
WC_EDM_Updater::TRANSIENT,
|
||||||
|
array(
|
||||||
|
'version' => WC_EDM_VERSION,
|
||||||
|
'package' => 'https://gitea.nolimit.dk/kw/demo/releases/download/v1/demo.zip',
|
||||||
|
'url' => 'https://gitea.nolimit.dk/kw/demo',
|
||||||
|
'tested' => '7.1',
|
||||||
|
),
|
||||||
|
600
|
||||||
|
);
|
||||||
|
|
||||||
delete_site_transient( 'update_plugins' );
|
delete_site_transient( 'update_plugins' );
|
||||||
wp_update_plugins();
|
wp_update_plugins();
|
||||||
$transient = get_site_transient( 'update_plugins' );
|
$transient = get_site_transient( 'update_plugins' );
|
||||||
@@ -407,8 +453,8 @@ delete_transient( WC_EDM_Updater::TRANSIENT );
|
|||||||
/* --------------------------------------------------------------- verdict -- */
|
/* --------------------------------------------------------------- verdict -- */
|
||||||
|
|
||||||
echo "\n";
|
echo "\n";
|
||||||
if ( $wc_edm_failures > 0 ) {
|
if ( $GLOBALS['wc_edm_failures'] > 0 ) {
|
||||||
printf( "%d assertion(s) failed on WordPress %s.\n", $wc_edm_failures, get_bloginfo( 'version' ) );
|
printf( "%d assertion(s) failed on WordPress %s.\n", $GLOBALS['wc_edm_failures'], get_bloginfo( 'version' ) );
|
||||||
exit( 1 );
|
exit( 1 );
|
||||||
}
|
}
|
||||||
printf(
|
printf(
|
||||||
|
|||||||
@@ -4,8 +4,9 @@
|
|||||||
* Plugin URI: https://gitea.nolimit.dk/kw/woocommerce-email-discount-manager
|
* Plugin URI: https://gitea.nolimit.dk/kw/woocommerce-email-discount-manager
|
||||||
* Update URI: https://gitea.nolimit.dk/kw/woocommerce-email-discount-manager
|
* Update URI: https://gitea.nolimit.dk/kw/woocommerce-email-discount-manager
|
||||||
* Description: Apply discounts and show/hide shipping methods based on the customer's email address (full address, domain or partial match).
|
* Description: Apply discounts and show/hide shipping methods based on the customer's email address (full address, domain or partial match).
|
||||||
* Version: 1.4.2
|
* Version: 1.4.3
|
||||||
* Author: WEDSMP
|
* Author: Kristian Wind
|
||||||
|
* Author URI: https://gitea.nolimit.dk/kw
|
||||||
* License: GPL-2.0-or-later
|
* License: GPL-2.0-or-later
|
||||||
* Text Domain: wc-email-discount
|
* Text Domain: wc-email-discount
|
||||||
* Requires at least: 5.8
|
* Requires at least: 5.8
|
||||||
@@ -27,7 +28,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
define( 'WC_EDM_VERSION', '1.4.2' );
|
define( 'WC_EDM_VERSION', '1.4.3' );
|
||||||
define( 'WC_EDM_PLUGIN_FILE', __FILE__ );
|
define( 'WC_EDM_PLUGIN_FILE', __FILE__ );
|
||||||
define( 'WC_EDM_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
|
define( 'WC_EDM_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
|
||||||
define( 'WC_EDM_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
|
define( 'WC_EDM_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
|
||||||
|
|||||||
Reference in New Issue
Block a user