Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
- detect dead jobs and mark as failed @john-shaffer
- mark duplicated waiting jobs as skipped on jobs page @john-shaffer
- add an option to process the queue immediately #794 @john-shaffer
- add ability to rewrite hosts specified on a new advanced options page @john-shaffer
- as part of this, changed the host replacement function to use strtr instead of str_replace to avoid replacing things that we just replaced
- add advanced option to skip URL rewriting @john-shaffer

## WP2Static 7.1.7

Expand Down
2 changes: 1 addition & 1 deletion phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ parameters:
count: 6
- message: '#^In method "WP2Static\\\S+::\S+", you should not use the \$_(GET|POST) superglobal#'
path: src/CoreOptions.php
count: 20
count: 22
- message: '#^In method "WP2Static\\\S+::\S+", you should not use the \$_(GET|POST) superglobal#'
path: src/ViewRenderer.php
count: 32
Expand Down
12 changes: 12 additions & 0 deletions src/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ public static function registerOptionsPage() : void {
'diagnostics' => [ ViewRenderer::class, 'renderDiagnosticsPage' ],
'logs' => [ ViewRenderer::class, 'renderLogsPage' ],
'addons' => [ ViewRenderer::class, 'renderAddonsPage' ],
'advanced' => [ ViewRenderer::class, 'renderAdvancedOptionsPage' ],
];

foreach ( $submenu_pages as $slug => $method ) {
Expand Down Expand Up @@ -471,6 +472,17 @@ public static function wp2staticTrashedPostHandler() : void {
}
}

public static function wp2staticUISaveAdvancedOptions() : void {
CoreOptions::savePosted( 'advanced' );

do_action( 'wp2static_addon_ui_save_advanced_options' );

check_admin_referer( 'wp2static-ui-advanced-options' );

wp_safe_redirect( admin_url( 'admin.php?page=wp2static-advanced' ) );
exit;
}

public static function wp2staticEnqueueJobs() : void {
// check each of these in order we want to enqueue
$job_types = [
Expand Down
87 changes: 86 additions & 1 deletion src/CoreOptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public static function createTable() : void {
id mediumint(9) NOT NULL AUTO_INCREMENT,
name VARCHAR(191) NOT NULL,
value VARCHAR(249) NOT NULL,
blob_value BLOB,
label VARCHAR(249) NULL,
description VARCHAR(249) NULL,
PRIMARY KEY (id)
Expand Down Expand Up @@ -59,6 +60,10 @@ public static function seedOptions() : void {
"INSERT IGNORE INTO $table_name (name, value, label, description)
VALUES (%s, %s, %s, %s);";

$blob_query_string =
"INSERT IGNORE INTO $table_name (name, value, label, description, blob_value)
VALUES (%s, %s, %s, %s, %s);";

$queries[] = $wpdb->prepare(
$query_string,
'detectCustomPostTypes',
Expand Down Expand Up @@ -211,6 +216,26 @@ public static function seedOptions() : void {
'How to send completion webhook payload (GET|POST).'
);

// Advanced options

$queries[] = $wpdb->prepare(
$query_string,
'skipURLRewrite',
'0',
'Skip URL Rewrite',
'Don\'t rewrite any URLs. This may give a slight speed-up when the'
. ' deployment URL is the same as WordPress\'s URL.'
);

$queries[] = $wpdb->prepare(
$blob_query_string,
'hostsToRewrite',
'1',
'Hosts to Rewrite',
'Hosts to rewrite to the deployment URL.',
'localhost'
);

foreach ( $queries as $query ) {
$wpdb->query( $query );
}
Expand Down Expand Up @@ -254,6 +279,47 @@ public static function getValue( string $name ) : string {
return $option_value;
}

/**
* Get option BLOB value
*
* @throws WP2StaticException
* @return string option BLOB value
*/
public static function getBlobValue( string $name ) : string {
global $wpdb;

$table_name = $wpdb->prefix . self::$table_name;

$sql = $wpdb->prepare(
"SELECT blob_value FROM $table_name WHERE" . ' name = %s LIMIT 1',
$name
);

$option_value = $wpdb->get_var( $sql );

if ( ! is_string( $option_value ) ) {
return '';
}

return $option_value;
}

/**
* @return array<string>
*/
public static function getLineDelimitedBlobValue( string $name ) : array {
$vals = preg_split(
'/\r\n|\r|\n/',
self::getBlobValue( $name )
);

if ( ! $vals ) {
return [];
}

return $vals;
}

/**
* Get option (value, description, label, etc)
*
Expand All @@ -265,7 +331,8 @@ public static function get( string $name ) {
$table_name = $wpdb->prefix . self::$table_name;

$sql = $wpdb->prepare(
"SELECT name, value, label, description FROM $table_name WHERE" . ' name = %s LIMIT 1',
"SELECT name, value, label, description, blob_value
FROM $table_name WHERE" . ' name = %s LIMIT 1',
$name
);

Expand Down Expand Up @@ -492,6 +559,24 @@ public static function savePosted( string $screen = 'core' ) : void {
[ 'name' => 'autoJobQueueDeployment' ]
);

break;
case 'advanced':
$wpdb->update(
$table_name,
[ 'value' => isset( $_POST['skipURLRewrite'] ) ? 1 : 0 ],
[ 'name' => 'skipURLRewrite' ]
);

$hosts_to_rewrite = preg_replace(
'/^\s+|\s+$/m',
'',
$_POST['hostsToRewrite']
);
$wpdb->update(
$table_name,
[ 'blob_value' => $hosts_to_rewrite ],
[ 'name' => 'hostsToRewrite' ]
);
break;
}
}
Expand Down
41 changes: 28 additions & 13 deletions src/SimpleRewriter.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ public static function rewriteFileContents( string $file_contents ) : string
return '';
}

if ( (int) CoreOptions::getValue( 'skipURLRewrite' ) === 1 ) {
return $file_contents;
}

$destination_url = apply_filters(
'wp2static_set_destination_url',
CoreOptions::getValue( 'deploymentURL' )
Expand All @@ -53,22 +57,33 @@ public static function rewriteFileContents( string $file_contents ) : string

$wordpress_site_url = untrailingslashit( $wordpress_site_url );
$destination_url = untrailingslashit( $destination_url );
$destination_url_rel = URLHelper::getProtocolRelativeURL( $destination_url );
$destination_url_rel_c = addcslashes( $destination_url_rel, '/' );

$search_patterns = [
$wordpress_site_url,
URLHelper::getProtocolRelativeURL( $wordpress_site_url ),
addcslashes( URLHelper::getProtocolRelativeURL( $wordpress_site_url ), '/' ),
];
$replace_patterns = [
$destination_url,
URLHelper::getProtocolRelativeURL( $destination_url ),
addcslashes( URLHelper::getProtocolRelativeURL( $destination_url ), '/' ),
$replacement_patterns = [
$wordpress_site_url => $destination_url,
URLHelper::getProtocolRelativeURL( $wordpress_site_url ) =>
URLHelper::getProtocolRelativeURL( $destination_url ),
addcslashes( URLHelper::getProtocolRelativeURL( $wordpress_site_url ), '/' ) =>
addcslashes( URLHelper::getProtocolRelativeURL( $destination_url ), '/' ),
];

$rewritten_contents = str_replace(
$search_patterns,
$replace_patterns,
$file_contents
$hosts = CoreOptions::getLineDelimitedBlobValue( 'hostsToRewrite' );

foreach ( $hosts as $host ) {
if ( $host ) {
$host_rel = URLHelper::getProtocolRelativeURL( 'http://' . $host );

$replacement_patterns[ 'http:' . $host_rel ] = $destination_url;
$replacement_patterns[ 'https:' . $host_rel ] = $destination_url;
$replacement_patterns[ $host_rel ] = $destination_url_rel;
$replacement_patterns[ addcslashes( $host_rel, '/' ) ] = $destination_url_rel_c;
}
}

$rewritten_contents = strtr(
$file_contents,
$replacement_patterns
);

return $rewritten_contents;
Expand Down
14 changes: 14 additions & 0 deletions src/ViewRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,20 @@ public static function renderOptionsPage() : void {
require_once WP2STATIC_PATH . 'views/options-page.php';
}

public static function renderAdvancedOptionsPage() : void {
CoreOptions::init();

$view = [];
$view['nonce_action'] = 'wp2static-ui-advanced-options';

$view['coreOptions'] = [
'hostsToRewrite' => CoreOptions::get( 'hostsToRewrite' ),
'skipURLRewrite' => CoreOptions::get( 'skipURLRewrite' ),
];

require_once WP2STATIC_PATH . 'views/advanced-options-page.php';
}

public static function renderDiagnosticsPage() : void {
$view = [];
$view['memoryLimit'] = ini_get( 'memory_limit' );
Expand Down
7 changes: 7 additions & 0 deletions src/WordPressAdmin.php
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,13 @@ public static function registerHooks( string $bootstrap_file ) : void {
0
);

add_action(
'admin_post_wp2static_ui_save_advanced_options',
[ Controller::class, 'wp2staticUISaveAdvancedOptions' ],
10,
0
);

add_action(
'admin_post_wp2static_manually_enqueue_jobs',
[ Controller::class, 'wp2staticManuallyEnqueueJobs' ],
Expand Down
63 changes: 57 additions & 6 deletions tests/unit/SimpleRewriterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ public function tearDown() : void
Mockery::close();
}

public static function coreOptionsMock() : \Mockery\CompositeExpectation {
return Mockery::mock( 'overload:\WP2Static\CoreOptions' )
->shouldReceive( 'getValue' )
->withArgs( [ 'skipURLRewrite' ] )
->andReturn( '0' )
->shouldreceive( 'getLineDelimitedBlobValue' )
->withArgs( [ 'hostsToRewrite' ] )
->andReturn( [ 'localhost' ] );
}

/**
* Test deleteDirWithFiles method
*
Expand All @@ -38,7 +48,7 @@ public function tearDown() : void
*/
public function testRewrite() {
// Mock the methods and functions used by SimpleRewriter
Mockery::mock( 'overload:\WP2Static\CoreOptions' )
self::coreOptionsMock()
->shouldreceive( 'getValue' )
->withArgs( [ 'deploymentURL' ] )
->andReturn( 'https://bar.com' );
Expand Down Expand Up @@ -101,7 +111,7 @@ public function rewriteFileContentsProvider() {
*/
public function testRewriteFileContents( $raw_html, $expected ) {
// Mock the methods and functions used by SimpleRewriter
Mockery::mock( 'overload:\WP2Static\CoreOptions' )
self::coreOptionsMock()
->shouldreceive( 'getValue' )
->withArgs( [ 'deploymentURL' ] )
->andReturn( 'https://bar.com' );
Expand All @@ -120,7 +130,7 @@ public function testRewriteFileContents( $raw_html, $expected ) {

public function testRewriteFileContentsHttpToHttps() {
// Mock the methods and functions used by SimpleRewriter
Mockery::mock( 'overload:\WP2Static\CoreOptions' )
self::coreOptionsMock()
->shouldreceive( 'getValue' )
->withArgs( [ 'deploymentURL' ] )
->andReturn( 'https://bar.com' )
Expand All @@ -139,7 +149,7 @@ public function testRewriteFileContentsHttpToHttps() {

public function testRewriteFileContentsHttpsToHttp() {
// Mock the methods and functions used by SimpleRewriter
Mockery::mock( 'overload:\WP2Static\CoreOptions' )
self::coreOptionsMock()
->shouldreceive( 'getValue' )
->withArgs( [ 'deploymentURL' ] )
->andReturn( 'http://bar.com' )
Expand All @@ -156,12 +166,53 @@ public function testRewriteFileContentsHttpsToHttp() {
$this->assertEquals( $expected, $actual );
}

public function testRewriteFileContentsSkipURLRewrite() {
// Mock the methods and functions used by SimpleRewriter
Mockery::mock( 'overload:\WP2Static\CoreOptions' )
->shouldReceive( 'getValue' )
->withArgs( [ 'skipURLRewrite' ] )
->andReturn( '1' )
->shouldreceive( 'getLineDelimitedBlobValue' )
->withArgs( [ 'hostsToRewrite' ] )
->andReturn( [ 'localhost' ] )
->shouldreceive( 'getValue' )
->withArgs( [ 'deploymentURL' ] )
->andReturn( 'http://bar.com' );
Mockery::mock( 'overload:\WP2Static\SiteInfo' )
->shouldreceive( 'getUrl' )
->withArgs( [ 'site' ] )
->andReturn( 'https://foo.com/' );

$expected = 'https://foo.com/somepath';
$actual = SimpleRewriter::rewriteFileContents( $expected );
$this->assertEquals( $expected, $actual );
}

public function testRewriteFileContentsHostsToRewrite() {
// Mock the methods and functions used by SimpleRewriter
self::coreOptionsMock()
->shouldreceive( 'getValue' )
->withArgs( [ 'deploymentURL' ] )
->andReturn( 'http://bar.com' )
->getMock();
Mockery::mock( 'overload:\WP2Static\SiteInfo' )
->shouldreceive( 'getUrl' )
->withArgs( [ 'site' ] )
->andReturn( 'https://foo.com/' )
->getMock();

// localhost -> bar.com
$expected = 'http://bar.com/somepath';
$actual = SimpleRewriter::rewriteFileContents( 'https://localhost/somepath' );
$this->assertEquals( $expected, $actual );
}

/**
* @dataProvider rewriteFileContentsProvider
*/
public function testRewriteFileContentsDestinationUrlFilter( $raw_html, $expected ) {
// Mock the methods and functions used by SimpleRewriter
Mockery::mock( 'overload:\WP2Static\CoreOptions' )
self::coreOptionsMock()
->shouldreceive( 'getValue' )
->withArgs( [ 'deploymentURL' ] )
->andReturn( 'https://bar.com' );
Expand Down Expand Up @@ -190,7 +241,7 @@ public function testRewriteFileContentsDestinationUrlFilter( $raw_html, $expecte
*/
public function testRewriteFileContentsSiteUrlFilter( $raw_html, $expected ) {
// Mock the methods and functions used by SimpleRewriter
Mockery::mock( 'overload:\WP2Static\CoreOptions' )
self::coreOptionsMock()
->shouldreceive( 'getValue' )
->withArgs( [ 'deploymentURL' ] )
->andReturn( 'https://bar.com' );
Expand Down
Loading