Skip to content

Commit

Permalink
Merge pull request #809 from john-shaffer/hosts-to-rewrite-option
Browse files Browse the repository at this point in the history
Add hostsToRewrite option and advanced-options page.
  • Loading branch information
leonstafford authored Sep 21, 2021
2 parents 68d6bd0 + 65b6e5d commit d915d37
Show file tree
Hide file tree
Showing 9 changed files with 275 additions and 21 deletions.
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

0 comments on commit d915d37

Please sign in to comment.