include_taxonomy = $include_taxonomy;
$this->dir = wp_upload_dir();
$this->export_settings();
}
/**
* Returns true when the property error has a value.
*
* @return bool
*/
public function has_error() {
return ( $this->error !== '' );
}
/**
* Sets the error hook, to display the error to the user.
*/
public function set_error_hook() {
$class = 'notice notice-error';
$message = sprintf( __( 'Error creating %1$s export: ', 'wordpress-seo' ), 'Yoast SEO' ) . $this->error;
printf( '
', $class, $message );
}
/**
* Exports the current site's WP SEO settings.
*/
private function export_settings() {
$this->export_header();
foreach ( WPSEO_Options::get_option_names() as $opt_group ) {
$this->write_opt_group( $opt_group );
}
$this->taxonomy_metadata();
if ( ! $this->write_settings_file() ) {
$this->error = __( 'Could not write settings to file.', 'wordpress-seo' );
return;
}
if ( $this->zip_file() ) {
// Just exit, because there is a download being served.
exit;
}
}
/**
* Writes the header of the export file.
*/
private function export_header() {
/* translators: %1$s expands to Yoast SEO */
$this->write_line( '; ' . sprintf( __( 'This is a settings export file for the %1$s plugin by Yoast.com', 'wordpress-seo' ), 'Yoast SEO' ) . ' - https://yoast.com/wordpress/plugins/seo/' );
if ( $this->include_taxonomy ) {
$this->write_line( '; ' . __( 'This export includes taxonomy metadata', 'wordpress-seo' ) );
}
}
/**
* Writes a line to the export
*
* @param string $line Line string.
* @param boolean $newline_first Boolean flag whether to prepend with new line.
*/
private function write_line( $line, $newline_first = false ) {
if ( $newline_first ) {
$this->export .= PHP_EOL;
}
$this->export .= $line . PHP_EOL;
}
/**
* Writes an entire option group to the export
*
* @param string $opt_group Option group name.
*/
private function write_opt_group( $opt_group ) {
$this->write_line( '[' . $opt_group . ']', true );
$options = get_option( $opt_group );
if ( ! is_array( $options ) ) {
return;
}
foreach ( $options as $key => $elem ) {
if ( is_array( $elem ) ) {
for ( $i = 0; $i < count( $elem ); $i ++ ) {
$this->write_setting( $key . '[]', $elem[ $i ] );
}
}
else {
$this->write_setting( $key, $elem );
}
}
}
/**
* Writes a settings line to the export
*
* @param string $key Key string.
* @param string $val Value string.
*/
private function write_setting( $key, $val ) {
if ( is_string( $val ) ) {
$val = '"' . $val . '"';
}
$this->write_line( $key . ' = ' . $val );
}
/**
* Adds the taxonomy meta data if there is any
*/
private function taxonomy_metadata() {
if ( $this->include_taxonomy ) {
$taxonomy_meta = get_option( 'wpseo_taxonomy_meta' );
if ( is_array( $taxonomy_meta ) ) {
$this->write_line( '[wpseo_taxonomy_meta]', true );
$this->write_setting( 'wpseo_taxonomy_meta', urlencode( wp_json_encode( $taxonomy_meta ) ) );
}
else {
$this->write_line( '; ' . __( 'No taxonomy metadata found', 'wordpress-seo' ), true );
}
}
}
/**
* Writes the settings to our temporary settings.ini file
*
* @return boolean unsigned
*/
private function write_settings_file() {
$handle = fopen( $this->dir['path'] . '/' . self::INI_FILENAME, 'w' );
if ( ! $handle ) {
return false;
}
$res = fwrite( $handle, $this->export );
if ( ! $res ) {
return false;
}
fclose( $handle );
return true;
}
/**
* Zips the settings ini file
*
* @return bool|null
*/
private function zip_file() {
$is_zip_created = $this->create_zip();
// The settings.ini isn't needed, because it's in the zipfile.
$this->remove_settings_ini();
if ( ! $is_zip_created ) {
$this->error = __( 'Could not zip settings-file.', 'wordpress-seo' );
return false;
}
$this->serve_settings_export();
$this->remove_zip();
return true;
}
/**
* Creates the zipfile and returns true if it created successful.
*
* @return bool
*/
private function create_zip() {
chdir( $this->dir['path'] );
$zip = new PclZip( './' . self::ZIP_FILENAME );
if ( 0 === $zip->create( './' . self::INI_FILENAME ) ) {
return false;
}
return file_exists( self::ZIP_FILENAME );
}
/**
* Downloads the zip file.
*/
private function serve_settings_export() {
// Clean any content that has been already output. For example by other plugins or faulty PHP files.
if ( ob_get_contents() ) {
ob_clean();
}
header( 'Content-Type: application/octet-stream; charset=utf-8' );
header( 'Content-Transfer-Encoding: Binary' );
header( 'Content-Disposition: attachment; filename=' . self::ZIP_FILENAME );
header( 'Content-Length: ' . filesize( self::ZIP_FILENAME ) );
readfile( self::ZIP_FILENAME );
}
/**
* Removes the settings ini file.
*/
private function remove_settings_ini() {
unlink( './' . self::INI_FILENAME );
}
/**
* Removes the files because they are already downloaded.
*/
private function remove_zip() {
unlink( './' . self::ZIP_FILENAME );
}
}