Skip to content

Commit f701f40

Browse files
authored
Merge pull request #5951 from BrianHenryIE/add/filecache-import-tests
2 parents 2cf9ec8 + 94d182a commit f701f40

File tree

3 files changed

+109
-5
lines changed

3 files changed

+109
-5
lines changed

php/WP_CLI/FileCache.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,16 @@ public function read( $key, $ttl = null ) {
156156
* Copy a file into the cache
157157
*
158158
* @param string $key cache key
159-
* @param string $source source filename
159+
* @param string $source source filename; tmp file filepath from HTTP response
160160
* @return bool
161161
*/
162162
public function import( $key, $source ) {
163163
$filename = $this->prepare_write( $key );
164164

165+
if ( ! is_readable( $source ) ) {
166+
return false;
167+
}
168+
165169
if ( $filename ) {
166170
return copy( $source, $filename ) && touch( $filename );
167171
}
@@ -339,7 +343,7 @@ protected function ensure_dir_exists( $dir ) {
339343
* Prepare cache write
340344
*
341345
* @param string $key cache key
342-
* @return bool|string filename or false
346+
* @return bool|string The destination filename or false when cache disabled or directory creation fails.
343347
*/
344348
protected function prepare_write( $key ) {
345349
if ( ! $this->enabled ) {
@@ -377,11 +381,11 @@ protected function validate_key( $key ) {
377381

378382
$parts = preg_replace( "#[^{$this->whitelist}]#i", '-', $parts );
379383

380-
return implode( '/', $parts );
384+
return rtrim( implode( '/', $parts ), '.' );
381385
}
382386

383387
/**
384-
* Filename from key
388+
* Destination filename from key
385389
*
386390
* @param string $key
387391
* @return string filename

php/WP_CLI/WpHttpCacheManager.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
class WpHttpCacheManager {
1313

1414
/**
15-
* @var array map whitelisted urls to keys and ttls
15+
* @var array<string, array{key:string, ttl:int}> map whitelisted urls to keys and ttls
1616
*/
1717
protected $whitelist = [];
1818

tests/FileCacheTest.php

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,4 +102,104 @@ public function test_export() {
102102
unlink( $target );
103103
rmdir( $target_dir );
104104
}
105+
106+
public function test_import() {
107+
$max_size = 32;
108+
$ttl = 60;
109+
$cache_dir = Utils\get_temp_dir() . uniqid( 'wp-cli-test-file-cache', true );
110+
$cache = new FileCache( $cache_dir, $ttl, $max_size );
111+
112+
$tmp_dir = Utils\get_temp_dir() . uniqid( 'wp-cli-test-file-cache-import', true );
113+
mkdir( $tmp_dir );
114+
115+
// "$group/$slug-$version.$ext";
116+
$key = 'plugin/my-fixture-plugin-1.0.0.zip';
117+
$fixture_filepath = $tmp_dir . '/my-downloaded-fixture-plugin-1.0.0.zip';
118+
119+
$zip = new ZipArchive();
120+
$zip->open( $fixture_filepath, ZIPARCHIVE::CREATE );
121+
$zip->addFile( __FILE__ );
122+
$zip->close();
123+
124+
$result = $cache->import( $key, $fixture_filepath );
125+
126+
// Assert file is imported.
127+
$this->assertTrue( $result );
128+
$this->assertFileExists( "{$cache_dir}/{$key}" );
129+
130+
// Clean up.
131+
$cache->clear();
132+
unlink( $fixture_filepath );
133+
rmdir( $tmp_dir );
134+
}
135+
136+
/**
137+
* @see https://github.com/wp-cli/wp-cli/pull/5947
138+
*/
139+
public function test_import_do_not_use_cache_file_cannot_be_read() {
140+
$max_size = 32;
141+
$ttl = 60;
142+
$cache_dir = Utils\get_temp_dir() . uniqid( 'wp-cli-test-file-cache', true );
143+
$cache = new FileCache( $cache_dir, $ttl, $max_size );
144+
145+
$tmp_dir = Utils\get_temp_dir() . uniqid( 'wp-cli-test-file-cache-import', true );
146+
mkdir( $tmp_dir );
147+
148+
$key = 'plugin/my-fixture-plugin-1.0.0.zip';
149+
$fixture_filepath = $tmp_dir . '/my-bad-permissions-fixture-plugin-1.0.0.zip';
150+
151+
$zip = new ZipArchive();
152+
$zip->open( $fixture_filepath, ZIPARCHIVE::CREATE );
153+
$zip->addFile( __FILE__ );
154+
$zip->close();
155+
156+
chmod( $fixture_filepath, 0000 );
157+
158+
// "Warning: copy(-.): Failed to open stream: Permission denied".
159+
$error = null;
160+
set_error_handler(
161+
function ( $errno, $errstr ) use ( &$error ) {
162+
$error = $errstr;
163+
}
164+
);
165+
166+
$result = $cache->import( $key, $fixture_filepath );
167+
168+
restore_error_handler();
169+
170+
$this->assertNull( $error );
171+
$this->assertFalse( $result );
172+
173+
// Clean up.
174+
$cache->clear();
175+
unlink( $fixture_filepath );
176+
rmdir( $tmp_dir );
177+
}
178+
179+
/**
180+
* Windows filenames cannot end in periods.
181+
*
182+
* @covers \WP_CLI\FileCache::validate_key
183+
*
184+
* @see https://github.com/wp-cli/wp-cli/pull/5947
185+
* @see https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#naming-conventions
186+
*/
187+
public function test_validate_key_ending_in_period() {
188+
$max_size = 32;
189+
$ttl = 60;
190+
$cache_dir = Utils\get_temp_dir() . uniqid( 'wp-cli-test-file-cache', true );
191+
$cache = new FileCache( $cache_dir, $ttl, $max_size );
192+
193+
$key = 'plugin/advanced-sidebar-menu-pro-9.5.7.';
194+
195+
$reflection = new ReflectionClass( $cache );
196+
197+
$method = $reflection->getMethod( 'validate_key' );
198+
$method->setAccessible( true );
199+
200+
$result = $method->invoke( $cache, $key );
201+
202+
$this->assertStringEndsNotWith( '.', $result );
203+
$this->assertSame( 'plugin/advanced-sidebar-menu-pro-9.5.7', $result );
204+
}
105205
}

0 commit comments

Comments
 (0)