mirror of
https://ghproxy.net/https://github.com/elementor/wp2static.git
synced 2026-07-21 11:47:28 +08:00
367 lines
13 KiB
PHP
367 lines
13 KiB
PHP
<?php
|
|
|
|
namespace WP2Static;
|
|
|
|
use Mockery;
|
|
use org\bovigo\vfs\vfsStream;
|
|
use WP_Mock;
|
|
use WP_Mock\Tools\TestCase;
|
|
|
|
/**
|
|
* @runTestsInSeparateProcesses
|
|
* @preserveGlobalState disabled
|
|
*/
|
|
final class FileHelperTest extends TestCase {
|
|
|
|
public function setUp() : void
|
|
{
|
|
WP_Mock::setUp();
|
|
}
|
|
|
|
public function tearDown() : void
|
|
{
|
|
WP_Mock::tearDown();
|
|
Mockery::close();
|
|
}
|
|
|
|
/**
|
|
* Test deleteDirWithFiles method
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testDeleteDirWithFiles() {
|
|
// Set up a virual folder structure
|
|
$structure = [
|
|
// Latin characters
|
|
'top_level_latin_folder' => [
|
|
'no_file_extension' => 'no_file_extension',
|
|
// phpcs:ignore Generic.Files.LineLength
|
|
'example_of_an_extremely_long_latin_file_name_with_some_numbers_at_the_end_0123456789.fileextension' => 'example_of_an_extremely_long_latin_file_name_with_some_numbers_at_the_end_0123456789.fileextension',
|
|
],
|
|
// UTF-8 characters
|
|
'top_level_ùnicodë_folder' => [
|
|
'unicodÉ-file.jpg' => 'unicodÉ-file.jpg',
|
|
'sêcond_level_fÒlder' => [
|
|
'ÚÑÌÇÕÐË.pdf' => 'ÚÑÌÇÕÐË.pdf',
|
|
'second-unicøde-file.sql' => 'second-unicøde-file.sql',
|
|
|
|
],
|
|
],
|
|
// Spaces
|
|
'top level folder with spaces' => [
|
|
'only a subfolder' => [
|
|
'example file.php' => 'example file.php',
|
|
],
|
|
],
|
|
];
|
|
$vfs = vfsStream::setup( 'root' );
|
|
vfsStream::create( $structure, $vfs );
|
|
|
|
// Check vfsStream set up the top level directories correctly.
|
|
// We don't *really* need to do this as it should be covered in
|
|
// vfsStream's tests but it gives peace of mind and will confirm
|
|
// our below tests are actually doing something.
|
|
foreach ( array_keys( $structure ) as $folder ) {
|
|
$filepath = vfsStream::url( "root/$folder" );
|
|
$expected = true;
|
|
$actual = is_dir( $filepath );
|
|
$this->assertEquals( $expected, $actual );
|
|
}
|
|
|
|
// Delete the unicode subfolder
|
|
$filepath = vfsStream::url( 'root/top_level_ùnicodë_folder/sêcond_level_fÒlder' );
|
|
FilesHelper::deleteDirWithFiles( $filepath );
|
|
// Confirm it's gone
|
|
$expected = false;
|
|
$actual = is_dir( $filepath );
|
|
$this->assertEquals( $expected, $actual );
|
|
// And confirm its parent still exists
|
|
$filepath = vfsStream::url( 'root/top_level_ùnicodë_folder' );
|
|
$expected = true;
|
|
$actual = is_dir( $filepath );
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
// Delete a subfolder with spaces in the filename
|
|
$filepath = vfsStream::url( 'root/top level folder with spaces/only a subfolder' );
|
|
FilesHelper::deleteDirWithFiles( $filepath );
|
|
// Confirm it's gone
|
|
$expected = false;
|
|
$actual = is_dir( $filepath );
|
|
$this->assertEquals( $expected, $actual );
|
|
// And confirm its parent still exists
|
|
$filepath = vfsStream::url( 'root/top level folder with spaces' );
|
|
$expected = true;
|
|
$actual = is_dir( $filepath );
|
|
$this->assertEquals( $expected, $actual );
|
|
}
|
|
|
|
/**
|
|
* Test getListOfLocalFilesByDir method
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testGetListOfLocalFilesByDir() {
|
|
$filenames_to_ignore = CoreOptions::getDefaultLineDelimitedBlobValue(
|
|
'filenamesToIgnore'
|
|
);
|
|
$file_extensions_to_ignore = CoreOptions::getDefaultLineDelimitedBlobValue(
|
|
'fileExtensionsToIgnore'
|
|
);
|
|
|
|
// Set up a virtual folder structure
|
|
$structure = [
|
|
// Latin characters
|
|
'top_level_latin_folder' => [
|
|
'no_file_extension' => 'no_file_extension',
|
|
// phpcs:ignore Generic.Files.LineLength
|
|
'example_of_an_extremely_long_latin_file_name_with_some_numbers_at_the_end_0123456789.fileextension' => 'example_of_an_extremely_long_latin_file_name_with_some_numbers_at_the_end_0123456789.fileextension',
|
|
],
|
|
// UTF-8 characters
|
|
'top_level_ùnicodë_folder' => [
|
|
'unicodÉ-file.jpg' => 'unicodÉ-file.jpg',
|
|
'sêcond_level_fÒlder' => [
|
|
'ÚÑÌÇÕÐË.pdf' => 'ÚÑÌÇÕÐË.pdf',
|
|
'second-unicøde-file.php' => 'second-unicøde-file.php',
|
|
|
|
],
|
|
],
|
|
// Spaces
|
|
'top level folder with spaces' => [
|
|
'only a subfolder' => [
|
|
'example file.pdf' => 'example file.pdf',
|
|
],
|
|
],
|
|
];
|
|
$vfs = vfsStream::setup( 'root' );
|
|
vfsStream::create( $structure, $vfs );
|
|
// Set virtual WP root directory to /root/ for this test
|
|
$mock = Mockery::mock( 'overload:\WP2Static\SiteInfo' );
|
|
$mock->shouldreceive( 'getPath' )->andReturn( vfsStream::url( 'root' ) . '/' );
|
|
|
|
// Top level folder
|
|
$filepath = vfsStream::url( 'root/top_level_latin_folder' );
|
|
$expected = [
|
|
'/top_level_latin_folder/no_file_extension',
|
|
// phpcs:ignore Generic.Files.LineLength
|
|
'/top_level_latin_folder/example_of_an_extremely_long_latin_file_name_with_some_numbers_at_the_end_0123456789.fileextension',
|
|
];
|
|
$actual = FilesHelper::getListOfLocalFilesByDir(
|
|
$filepath,
|
|
$filenames_to_ignore,
|
|
$file_extensions_to_ignore
|
|
);
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
// Nested folder
|
|
// This is actually two tests in one. One of the files in this folder
|
|
// has a 'php' extension which is disallowed and shouldn't be returned.
|
|
$filepath = vfsStream::url( 'root/top_level_ùnicodë_folder/sêcond_level_fÒlder' );
|
|
$expected = [
|
|
'/top_level_%C3%B9nicod%C3%AB_folder/s%C3%AAcond_level_f%C3%92lder/ÚÑÌÇÕÐË.pdf',
|
|
];
|
|
$actual = FilesHelper::getListOfLocalFilesByDir(
|
|
$filepath,
|
|
$filenames_to_ignore,
|
|
$file_extensions_to_ignore
|
|
);
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
// Folder with subfolder
|
|
$filepath = vfsStream::url( 'root/top level folder with spaces' );
|
|
$expected = [
|
|
'/top%20level%20folder%20with%20spaces/only a subfolder/example file.pdf',
|
|
];
|
|
$actual = FilesHelper::getListOfLocalFilesByDir(
|
|
$filepath,
|
|
$filenames_to_ignore,
|
|
$file_extensions_to_ignore
|
|
);
|
|
|
|
$this->assertEquals( $expected, $actual );
|
|
}
|
|
|
|
/**
|
|
* Test pathLooksCrawlable method
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testPathLooksCrawlable() {
|
|
$filenames_to_ignore = CoreOptions::getDefaultLineDelimitedBlobValue(
|
|
'filenamesToIgnore'
|
|
);
|
|
$file_extensions_to_ignore = CoreOptions::getDefaultLineDelimitedBlobValue(
|
|
'fileExtensionsToIgnore'
|
|
);
|
|
|
|
$looks_crawlable = function( $file_name ) use (
|
|
&$filenames_to_ignore,
|
|
&$file_extensions_to_ignore
|
|
) {
|
|
return FilesHelper::pathLooksCrawlable(
|
|
$file_name,
|
|
$filenames_to_ignore,
|
|
$file_extensions_to_ignore
|
|
);
|
|
};
|
|
// Default accepted extension
|
|
$expected = true;
|
|
$actual = $looks_crawlable( '/path/to/foo.jpg' );
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
// Default disallowed extension
|
|
$expected = false;
|
|
$actual = $looks_crawlable( '/path/to/foo.txt' );
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
// Default disallowed extension uppercase
|
|
$expected = false;
|
|
$actual = $looks_crawlable( '/path/to/FOO.TXT' );
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
// Default disallowed extension with . replaced with any other character
|
|
// This is to test bad regex
|
|
$expected = true;
|
|
$actual = $looks_crawlable( '/path/to/foohtxt' );
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
// Default disallowed filename
|
|
$expected = false;
|
|
$actual = $looks_crawlable( '/path/to/thumbs.db' );
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
// Try a disallowed URL - .git filepaths
|
|
$expected = false;
|
|
$actual = $looks_crawlable(
|
|
// @phpcs:ignore Generic.Files.LineLength.TooLong
|
|
'http://foo.com/wp-content/plugins/my-plugin/.git/objects/0b/f00ad2a21d59fc587a605008d3c3a83bb81e51'
|
|
);
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
// Try a disallowed URL - .git filepaths uppercase
|
|
$expected = false;
|
|
$actual = $looks_crawlable(
|
|
// @phpcs:ignore Generic.Files.LineLength.TooLong
|
|
'http://foo.com/wp-content/plugins/my-plugin/.GIT/objects/0b/f00ad2a21d59fc587a605008d3c3a83bb81e51'
|
|
);
|
|
$this->assertEquals( $expected, $actual );
|
|
}
|
|
|
|
/**
|
|
* Test pathLooksCrawlable method's $file_extensions_to_ignore argument
|
|
* filter.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testPathLooksCrawlableExtension() {
|
|
$looks_crawlable = function( $file_name ) {
|
|
return FilesHelper::pathLooksCrawlable(
|
|
$file_name,
|
|
[],
|
|
[ '.unknown' ]
|
|
);
|
|
};
|
|
|
|
// We've disallowed .unknown - test it
|
|
$expected = false;
|
|
$actual = $looks_crawlable( '/path/to/foo.unknown' );
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
// txt extensions should now be allowed - test it
|
|
$expected = true;
|
|
$actual = $looks_crawlable( '/path/to/foo.txt' );
|
|
$this->assertEquals( $expected, $actual );
|
|
}
|
|
|
|
/**
|
|
* Test pathLooksCrawlable method's $filenames_to_ignore argument
|
|
* filter.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testPathLooksCrawlableFilenames() {
|
|
$looks_crawlable = function( $file_name ) {
|
|
return FilesHelper::pathLooksCrawlable(
|
|
$file_name,
|
|
[ 'yarn.lock' ],
|
|
[]
|
|
);
|
|
};
|
|
|
|
// We've disallowed yarn.lock - test it
|
|
$expected = false;
|
|
$actual = $looks_crawlable( '/path/to/yarn.lock' );
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
// thumbs.db filenames should now be allowed - test it
|
|
$expected = true;
|
|
$actual = $looks_crawlable( '/path/to/thumbs.db' );
|
|
$this->assertEquals( $expected, $actual );
|
|
}
|
|
|
|
public function testCleanDetectedURLs() {
|
|
// Mock the WP functions used by FilesHelper::cleanDetectedURLs()
|
|
$mock = \Mockery::mock( 'alias:WP2Static\SiteInfo' )
|
|
->shouldReceive( 'getUrl' )
|
|
->andReturn( 'https://foo.com/' );
|
|
|
|
// No trailing slash
|
|
$expected = [ '/foo' ];
|
|
$actual = FilesHelper::cleanDetectedURLs( [ 'https://foo.com/foo' ] );
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
// Trailing slash
|
|
$expected = [ '/foo/' ];
|
|
$actual = FilesHelper::cleanDetectedURLs( [ 'https://foo.com/foo/' ] );
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
// Double trailing slash
|
|
$expected = [ '/foo/' ];
|
|
$actual = FilesHelper::cleanDetectedURLs( [ 'https://foo.com/foo//' ] );
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
// Double middle slash
|
|
$expected = [ '/foo/' ];
|
|
$actual = FilesHelper::cleanDetectedURLs( [ 'https://foo.com//foo/' ] );
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
// Single URL param - no trailing slash
|
|
$expected = [ 'foo' ];
|
|
$actual = FilesHelper::cleanDetectedURLs( [ 'foo' ] );
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
// Single URL param - trailing slash
|
|
$expected = [ 'foo/' ];
|
|
$actual = FilesHelper::cleanDetectedURLs( [ 'foo/' ] );
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
// Single URL param - starting + trailing slash
|
|
$expected = [ '/foo/' ];
|
|
$actual = FilesHelper::cleanDetectedURLs( [ '/foo/' ] );
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
// Single URL param - double trailing slash
|
|
$expected = [ 'foo/' ];
|
|
$actual = FilesHelper::cleanDetectedURLs( [ 'foo//' ] );
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
// Single URL param - double starting slash
|
|
$expected = [ '/foo' ];
|
|
$actual = FilesHelper::cleanDetectedURLs( [ '//foo' ] );
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
// Single URL param - double starting + trailing slash
|
|
$expected = [ '/foo/' ];
|
|
$actual = FilesHelper::cleanDetectedURLs( [ '//foo//' ] );
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
// Two URL params, Trailing slash
|
|
$expected = [ '/foo/bar/' ];
|
|
$actual = FilesHelper::cleanDetectedURLs( [ 'https://foo.com/foo/bar/' ] );
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
// Two URL params, Double middle slash
|
|
$expected = [ '/foo/bar/' ];
|
|
$actual = FilesHelper::cleanDetectedURLs( [ 'https://foo.com/foo//bar/' ] );
|
|
$this->assertEquals( $expected, $actual );
|
|
}
|
|
}
|