PluginProbe
CryptX / 4.2.1
CryptX v4.2.1
4.2.1 4.2.0 4.1.1 trunk 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.9 2.0 2.1 2.2 2.3 2.3.1 2.3.2 2.3.3 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 All 93 releases
← All changes | classes/CryptX.php +65 -1 4.2.04.2.1 View file →
@@ -2065,8 +2065,15 @@
2065 2065 * One exception: with the script placed in the head (load_java = 0) that
2066 2066 * decision cannot be deferred -- the head is sent before the content runs.
2067 2067 * In that configuration the script is enqueued unconditionally, as before.
2068 2068 *
2069 + * That head branch deliberately does not look at "java" at all, and never
2070 + * did -- this method leaves it untouched. It follows that a
2071 + * "[cryptx java=...]" shortcode override has nothing to add there: the
2072 + * script is already on every page regardless of the global setting, so
2073 + * only the footer branch below needs to read "java" or care about a
2074 + * shortcode overriding it.
2075 + *
2069 2076 * @return void
2070 2077 */
2071 2078 public function loadJavascriptFiles(): void
2072 2079 {
@@ -2078,8 +2085,32 @@
2078 2085
2079 2086 if (!$inFooter) {
2080 2087 wp_enqueue_script('cryptx-js');
2081 2088 wp_enqueue_style('cryptx-styles');
2089 + } elseif (!empty(self::$cryptXOptions['java'])) {
2090 + // Footer placement, JavaScript handler enabled: enqueue cryptx-js
2091 + // unconditionally, here, before it is known whether THIS request's
2092 + // content carries an address. wp_register_script() above already
2093 + // registered it with $inFooter = true, so this does not move the
2094 + // print location -- it still prints in wp_footer, exactly as
2095 + // before. Deferring to enqueueAssetsIfNeeded() (scriptNeeded) only
2096 + // covers a classic page load, where the address a visitor clicks
2097 + // is guaranteed to be in the same document that carried the
2098 + // script. A client-side navigation (swup.js, PJAX, Barba, Turbo)
2099 + // can land a visitor on a page with no address at all and then
2100 + // drop .cryptx-link elements in later, without ever loading a
2101 + // second script -- the delegated handler in cryptx.js was simply
2102 + // never attached. See
2103 + // docs/entscheidungen/2026-09-11-assets-bei-clientseitiger-navigation.md
2104 + // for the analysis.
2105 + //
2106 + // Known remaining gap, not closable from here: this branch only
2107 + // reads the global "java" setting. A page whose first load carries
2108 + // no [cryptx java="1"] shortcode, under a global java = 0, still
2109 + // enqueues nothing here -- so a later client-side navigation to a
2110 + // page that DOES carry that shortcode still finds no click handler
2111 + // attached. See the decision doc above for why this is left open.
2112 + wp_enqueue_script('cryptx-js');
2082 2113 }
2083 2114 }
2084 2115
2085 2116 /**
@@ -2091,14 +2122,47 @@
2091 2122 */
2092 2123 public function enqueueAssetsIfNeeded(): void
2093 2124 {
2094 2125 if (self::$scriptNeeded) {
2126 + // Still needed as a net: a shortcode can set java=1 for its own
2127 + // instance while the global setting says java=0, since "java" is
2128 + // not in NOT_SETTABLE_BY_SHORTCODE. loadJavascriptFiles() only
2129 + // sees the global setting, so this is what catches that case. A
2130 + // second wp_enqueue_script() on an already-enqueued handle is a
2131 + // no-op.
2095 2132 wp_enqueue_script('cryptx-js');
2096 2133 }
2097 2134
2098 - if (self::$styleNeeded) {
2135 + // wp_register_style() has no footer flag to lean on the way the
2136 + // script does, and enqueuing the stylesheet at wp_enqueue_scripts
2137 + // would move it from the footer to <head> -- a behaviour change for
2138 + // classic navigation, which is exactly what must not happen. So the
2139 + // same client-side-navigation gap for a configured picture variant
2140 + // (opt_linktext 2/3/5, the only settings that need img.cryptxImage
2141 + // { height: 1em }) is closed here instead, gated on the setting
2142 + // alone rather than on whether THIS request's content produced one.
2143 + if (self::$styleNeeded || self::isPictureLinktext((int) (self::$cryptXOptions['opt_linktext'] ?? 0))) {
2099 2144 wp_enqueue_style('cryptx-styles');
2100 2145 }
2146 + }
2147 +
2148 + /**
2149 + * Whether an opt_linktext setting renders links as pictures.
2150 + *
2151 + * Same known gap as the script branch in loadJavascriptFiles(), and purely
2152 + * cosmetic here: a page whose first load carries no picture-producing
2153 + * shortcode override, under a global opt_linktext that is not 2/3/5, still
2154 + * skips the stylesheet -- a later client-side navigation to a page that
2155 + * DOES render a picture link can arrive without img.cryptxImage. See
2156 + * docs/entscheidungen/2026-09-11-assets-bei-clientseitiger-navigation.md.
2157 + *
2158 + * @param int $optLinktext The opt_linktext setting value.
2159 + *
2160 + * @return bool
2161 + */
2162 + private static function isPictureLinktext(int $optLinktext): bool
2163 + {
2164 + return in_array($optLinktext, [2, 3, 5], true);
2101 2165 }
2102 2166
2103 2167 /**
2104 2168 * Updates the CryptX settings.