PluginProbe
Elementor Website Builder – more than just a page builder / 4.3.1
Elementor Website Builder – more than just a page builder v4.3.1
4.3.1 4.3.0 4.3.0-beta3 4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 All 454 releases
← All changes | modules/atomic-widgets/styles/css-files-manager.php +26 -11 4.3.0-beta1 → 4.3.1 View file →
@@ -119,12 +119,10 @@
119 119 $filesystem->delete( $path );
120 120 }
121 121
122 122 /**
123 - * Write to a temp file first and then move it into place. The move step is atomic on
124 - * POSIX filesystems, so the public URL cannot serve a partial or zero-byte asset while a
125 - * concurrent render is in progress. If the atomic move is not supported by the current
126 - * filesystem adapter, fall back to a direct write.
123 + * Write to a temp file first and then replace the destination with it, so a concurrent
124 + * render can never see a partial, zero-byte or absent asset on the public URL.
127 125 */
128 126 private function write_atomically( string $filesystem_path, string $css ): bool {
129 127 $filesystem = $this->get_filesystem();
130 128
@@ -139,19 +137,36 @@
139 137 if ( false === $is_written ) {
140 138 return false;
141 139 }
142 140
143 - if ( ! method_exists( $filesystem, 'move' ) || ! $filesystem->move( $tmp_path, $filesystem_path, true ) ) {
144 - $fallback = $filesystem->put_contents( $filesystem_path, $css, self::PERMISSIONS );
141 + if ( $this->replace_file( $tmp_path, $filesystem_path ) ) {
142 + return true;
143 + }
145 144
146 - if ( $filesystem->exists( $tmp_path ) ) {
147 - $filesystem->delete( $tmp_path );
148 - }
145 + $fallback = $filesystem->put_contents( $filesystem_path, $css, self::PERMISSIONS );
149 146
150 - return false !== $fallback;
147 + if ( $filesystem->exists( $tmp_path ) ) {
148 + $filesystem->delete( $tmp_path );
151 149 }
152 150
153 - return true;
151 + return false !== $fallback;
152 + }
153 +
154 + /**
155 + * `WP_Filesystem_Direct::move()` unlinks the destination before renaming, leaving a window
156 + * in which the already-enqueued URL 404s. A bare `rename()` replaces the file in place with
157 + * no such window - atomically on POSIX, and via `MoveFileEx` on Windows - so it is preferred
158 + * whenever the adapter is local. Remote adapters keep the `move()` path.
159 + */
160 + private function replace_file( string $tmp_path, string $destination ): bool {
161 + $filesystem = $this->get_filesystem();
162 +
163 + if ( $filesystem instanceof \WP_Filesystem_Direct ) {
164 + // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.rename_rename
165 + return @rename( $tmp_path, $destination );
166 + }
167 +
168 + return method_exists( $filesystem, 'move' ) && $filesystem->move( $tmp_path, $destination, true );
154 169 }
155 170
156 171 private function ensure_directory_exists( string $directory ): bool {
157 172 $filesystem = $this->get_filesystem();