| @@ -34,23 +34,55 @@ | ||
| 34 | 34 | add_action('admin_footer', [$this, 'render_reload_script']); |
| 35 | 35 | } |
| 36 | 36 | } |
| 37 | 37 | |
| 38 | - static function render_reload_script() { | |
| 38 | + public static function render_reload_script() { | |
| 39 | 39 | self::custom_plugin_change_reload(); |
| 40 | 40 | } |
| 41 | 41 | |
| 42 | - static function custom_plugin_change_reload($actual_link = null) { | |
| 43 | - if (!is_null($actual_link)) { | |
| 44 | - $safe_link = esc_url_raw($actual_link); | |
| 45 | - echo "<script type='text/javascript'> | |
| 46 | - parent.location.replace('" . esc_js($safe_link) . "'); | |
| 47 | - </script>"; | |
| 42 | + /** | |
| 43 | + * Break the current page out of the Adminify UI iframe. | |
| 44 | + * | |
| 45 | + * @param string|null $actual_link Optional. URL to send the parent window to. | |
| 46 | + * When null, the parent simply reloads. | |
| 47 | + * @return void | |
| 48 | + */ | |
| 49 | + public static function custom_plugin_change_reload( $actual_link = null ) { | |
| 50 | + if ( null !== $actual_link ) { | |
| 51 | + // wp_json_encode(), not esc_js(): esc_js() turns "&" into "&", | |
| 52 | + // which a classic <script> does not decode, breaking query args. | |
| 53 | + echo '<script>parent.location.replace(' . wp_json_encode( | |
| 54 | + esc_url_raw( $actual_link ), | |
| 55 | + JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | |
| 56 | + ) . ');</script>'; | |
| 57 | + | |
| 58 | + // The reload() below would abort the replace() navigation above. | |
| 59 | + return; | |
| 48 | 60 | } |
| 49 | 61 | |
| 50 | - echo '<script type="text/javascript"> | |
| 51 | - parent.location.reload(); | |
| 52 | - </script>'; | |
| 62 | + echo '<script>parent.location.reload();</script>'; | |
| 63 | + } | |
| 64 | + | |
| 65 | + /** | |
| 66 | + * Break out of the Adminify UI iframe, decided by the browser. | |
| 67 | + * | |
| 68 | + * Same job as custom_plugin_change_reload(), for requests that could not | |
| 69 | + * be classified server-side because the environment strips Fetch Metadata | |
| 70 | + * headers (see Utils::has_fetch_metadata()). The script checks the frame | |
| 71 | + * it actually runs in, so a genuine top-level load is left alone. | |
| 72 | + * | |
| 73 | + * @param string $actual_link URL to send the parent window to. | |
| 74 | + * @return void | |
| 75 | + */ | |
| 76 | + public static function maybe_break_out_of_frame( $actual_link ) { | |
| 77 | + $url = wp_json_encode( | |
| 78 | + esc_url_raw( $actual_link ), | |
| 79 | + JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | |
| 80 | + ); | |
| 81 | + | |
| 82 | + echo '<script>(function(){var f;try{f=window.frameElement;}catch(e){return;}' | |
| 83 | + . 'if(!f||f.id!=="frame-adminify-app--iframe")return;' | |
| 84 | + . 'parent.location.replace(' . $url . ');})();</script>'; | |
| 53 | 85 | } |
| 54 | 86 | |
| 55 | 87 | public function load_scripts() |
| 56 | 88 | { |