Skip to content
24 changes: 21 additions & 3 deletions src/hooks/tests/use-import-export.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,13 @@ describe( 'useImportExport hook', () => {
{
site: selectedSite,
backupFile: '/path/to/exported-site.tar.gz',
includes: { database: true, uploads: true, plugins: true, themes: true },
includes: {
database: true,
uploads: true,
plugins: true,
themes: true,
muPlugins: true,
},
phpVersion: '8.0',
},
SITE_ID
Expand All @@ -80,7 +86,13 @@ describe( 'useImportExport hook', () => {
{
site: selectedSite,
backupFile: '/path/to/exported-site.tar.gz',
includes: { database: true, uploads: true, plugins: true, themes: true },
includes: {
database: true,
uploads: true,
plugins: true,
themes: true,
muPlugins: true,
},
phpVersion: '8.0',
},
SITE_ID
Expand All @@ -106,7 +118,13 @@ describe( 'useImportExport hook', () => {
{
site: selectedSite,
backupFile: '/path/to/exported-database.sql',
includes: { database: true, uploads: false, plugins: false, themes: false },
includes: {
database: true,
uploads: false,
plugins: false,
themes: false,
muPlugins: false,
},
phpVersion: '8.0',
},
SITE_ID
Expand Down
2 changes: 2 additions & 0 deletions src/hooks/use-import-export.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ export const ImportExportProvider = ( { children }: { children: React.ReactNode
uploads: true,
plugins: true,
themes: true,
muPlugins: true,
},
phpVersion: selectedSite.phpVersion,
};
Expand Down Expand Up @@ -341,6 +342,7 @@ export const ImportExportProvider = ( { children }: { children: React.ReactNode
uploads: false,
plugins: false,
themes: false,
muPlugins: false,
},
phpVersion: selectedSite.phpVersion,
};
Expand Down
8 changes: 7 additions & 1 deletion src/ipc-handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,13 @@ export async function exportSiteToPush( event: IpcMainInvokeEvent, id: string )
const exportOptions: ExportOptions = {
site: site.details,
backupFile: archivePath,
includes: { database: true, uploads: true, plugins: true, themes: true },
includes: {
database: true,
uploads: true,
plugins: true,
themes: true,
muPlugins: true,
},
phpVersion: site.details.phpVersion,
splitDatabaseDumpByTable: true,
};
Expand Down
49 changes: 38 additions & 11 deletions src/lib/import-export/export/exporters/default-exporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ export class DefaultExporter extends EventEmitter implements Exporter {
private backup: BackupContents;
private readonly options: ExportOptions;
private siteFiles: string[];
private readonly pathsToExclude = [
'wp-content/mu-plugins/sqlite-database-integration',
'wp-content/mu-plugins/0-32bit-integer-warnings.php',
'wp-content/mu-plugins/0-allowed-redirect-hosts.php',
'wp-content/mu-plugins/0-check-theme-availability.php',
'wp-content/mu-plugins/0-deactivate-jetpack-modules.php',
'wp-content/mu-plugins/0-dns-functions.php',
'wp-content/mu-plugins/0-permalinks.php',
'wp-content/mu-plugins/0-wp-config-constants-polyfill.php',
'wp-content/mu-plugins/0-sqlite.php',
'wp-content/mu-plugins/0-thumbnails.php',
];

constructor( options: ExportOptions ) {
super();
Expand All @@ -35,6 +47,7 @@ export class DefaultExporter extends EventEmitter implements Exporter {
uploads: [],
plugins: [],
themes: [],
muPlugins: [],
},
};
}
Expand Down Expand Up @@ -141,9 +154,9 @@ export class DefaultExporter extends EventEmitter implements Exporter {
}

private addWpContent(): void {
const categories = ( [ 'uploads', 'plugins', 'themes' ] as BackupContentsCategory[] ).filter(
( category ) => this.options.includes[ category ]
);
const categories = (
[ 'uploads', 'plugins', 'themes', 'muPlugins' ] as BackupContentsCategory[]
).filter( ( category ) => this.options.includes[ category ] );
this.emit( ExportEvents.WP_CONTENT_EXPORT_START );
for ( const category of categories ) {
for ( const file of this.backup.wpContent[ category ] ) {
Expand All @@ -156,6 +169,7 @@ export class DefaultExporter extends EventEmitter implements Exporter {
uploads: this.backup.wpContent.uploads.length,
plugins: this.backup.wpContent.plugins.length,
themes: this.backup.wpContent.themes.length,
muPlugins: this.backup.wpContent.muPlugins.length,
} );
}

Expand Down Expand Up @@ -203,8 +217,16 @@ export class DefaultExporter extends EventEmitter implements Exporter {
} );

return directoryContents.reduce< string[] >( ( files: string[], directoryContent ) => {
const filePath = path.join( directoryContent.path, directoryContent.name );
const relativePath = path.relative( this.options.site.path, filePath );
const isExcluded = this.pathsToExclude.some( ( pathToExclude ) =>
relativePath.startsWith( path.normalize( pathToExclude ) )
);
if ( isExcluded ) {
return files;
}
if ( directoryContent.isFile() ) {
files.push( path.join( directoryContent.path, directoryContent.name ) );
files.push( filePath );
}
return files;
}, [] );
Expand All @@ -219,22 +241,27 @@ export class DefaultExporter extends EventEmitter implements Exporter {
uploads: [],
plugins: [],
themes: [],
muPlugins: [],
},
};

const siteFiles = await this.getSiteFiles();
siteFiles.forEach( ( file ) => {
const relativePath = path.relative( options.site.path, file );
const relativePathItems = relativePath.split( path.sep );
const [ wpContent, category ] = relativePathItems;

const [ wpContent, wpContentDirectory ] = relativePathItems;
if ( path.basename( file ) === 'wp-config.php' ) {
backupContents.wpConfigFile = file;
} else if (
wpContent === 'wp-content' &&
( category === 'uploads' || category === 'plugins' || category === 'themes' )
) {
backupContents.wpContent[ category ].push( file );
} else if ( wpContent === 'wp-content' ) {
if (
wpContentDirectory === 'uploads' ||
wpContentDirectory === 'plugins' ||
wpContentDirectory === 'themes'
) {
backupContents.wpContent[ wpContentDirectory as BackupContentsCategory ].push( file );
} else if ( wpContentDirectory === 'mu-plugins' ) {
backupContents.wpContent.muPlugins.push( file );
}
}
} );

Expand Down
2 changes: 1 addition & 1 deletion src/lib/import-export/export/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export interface BackupContents {
wpConfigFile?: string;
}

export type BackupContentsCategory = 'uploads' | 'plugins' | 'themes';
export type BackupContentsCategory = 'uploads' | 'plugins' | 'themes' | 'muPlugins';

export interface Exporter extends Partial< EventEmitter > {
canHandle(): Promise< boolean >;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ platformTestSuite( 'DefaultExporter', ( { normalize } ) => {
isFile: () => true,
},
{
path: normalize( '/path/to/site/wp-includes/index.php' ),
path: normalize( '/path/to/site/wp-includes' ),
name: 'index.php',
isFile: () => true,
},
Expand All @@ -97,6 +97,21 @@ platformTestSuite( 'DefaultExporter', ( { normalize } ) => {
name: 'wp-load.php',
isFile: () => true,
},
{
path: normalize( '/path/to/site/wp-content/mu-plugins/sqlite-database-integration' ),
name: 'load.php',
isFile: () => true,
},
{
path: normalize( '/path/to/site/wp-content/mu-plugins' ),
name: '0-32bit-integer-warnings.php',
isFile: () => true,
},
{
path: normalize( '/path/to/site/wp-content/mu-plugins' ),
name: 'custom-mu-plugin.php',
isFile: () => true,
},
];

( fsPromises.readdir as jest.Mock ).mockResolvedValue( mockFiles );
Expand All @@ -109,6 +124,7 @@ platformTestSuite( 'DefaultExporter', ( { normalize } ) => {
uploads: [ normalize( '/path/to/wp-content/uploads/file1.jpg' ) ],
plugins: [ normalize( '/path/to/wp-content/plugins/plugin1' ) ],
themes: [ normalize( '/path/to/wp-content/themes/theme1' ) ],
muPlugins: [ normalize( '/path/to/wp-content/mu-plugins/custom-mu-plugin.php' ) ],
},
};

Expand All @@ -126,6 +142,7 @@ platformTestSuite( 'DefaultExporter', ( { normalize } ) => {
plugins: true,
themes: true,
database: true,
muPlugins: true,
},
phpVersion: '8.4',
};
Expand Down Expand Up @@ -197,6 +214,7 @@ platformTestSuite( 'DefaultExporter', ( { normalize } ) => {
plugins: false,
themes: false,
database: false,
muPlugins: false,
},
};

Expand Down Expand Up @@ -230,6 +248,7 @@ platformTestSuite( 'DefaultExporter', ( { normalize } ) => {
plugins: true,
themes: true,
database: false,
muPlugins: false,
},
};

Expand Down Expand Up @@ -258,6 +277,42 @@ platformTestSuite( 'DefaultExporter', ( { normalize } ) => {
);
} );

it( 'should add (non-excluded) mu-plugins files to the archive', async () => {
const options = {
...mockOptions,
includes: {
uploads: false,
plugins: false,
themes: false,
database: false,
muPlugins: true,
},
};

const exporter = new DefaultExporter( options );
await exporter.export();

expect( mockArchiver.file ).toHaveBeenNthCalledWith(
1,
normalize( '/path/to/site/wp-config.php' ),
{ name: 'wp-config.php' }
);
expect( mockArchiver.file ).toHaveBeenNthCalledWith(
2,
normalize( '/path/to/site/wp-content/mu-plugins/custom-mu-plugin.php' ),
{ name: normalize( 'wp-content/mu-plugins/custom-mu-plugin.php' ) }
);

expect( mockArchiver.file ).not.toHaveBeenCalledWith(
normalize( '/path/to/site/wp-content/mu-plugins/sqlite-database-integration/load.php' ),
{ name: normalize( 'wp-content/mu-plugins/sqlite-database-integration/load.php' ) }
);
expect( mockArchiver.file ).not.toHaveBeenCalledWith(
normalize( '/path/to/site/wp-content/mu-plugins/0-32bit-integer-warnings.php' ),
{ name: normalize( 'wp-content/mu-plugins/0-32bit-integer-warnings.php' ) }
);
} );

it( 'should add a database file to the archive when database is included', async () => {
const options = {
...mockOptions,
Expand All @@ -266,6 +321,7 @@ platformTestSuite( 'DefaultExporter', ( { normalize } ) => {
uploads: false,
themes: false,
database: true,
muPlugins: false,
},
};
( fsPromises.mkdtemp as jest.Mock ).mockResolvedValue( normalize( '/tmp/studio_export_123' ) );
Expand Down Expand Up @@ -293,6 +349,7 @@ platformTestSuite( 'DefaultExporter', ( { normalize } ) => {
uploads: false,
themes: false,
database: true,
muPlugins: false,
},
splitDatabaseDumpByTable: true,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ platformTestSuite( 'SqlExporter', ( { normalize } ) => {
plugins: false,
themes: false,
database: true,
muPlugins: false,
},
phpVersion: '7.4',
};
Expand Down