SHARE
TWEET

class-import-export.php

a guest May 13th, 2019 82 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <?php
  2. /**
  3.  * The Import Export Class
  4.  *
  5.  * @since      0.9.0
  6.  * @package    RankMath
  7.  * @subpackage RankMath\Admin
  8.  * @author     Rank Math <support@rankmath.com>
  9.  */
  10.  
  11. namespace RankMath\Admin;
  12.  
  13. use RankMath\Runner;
  14. use RankMath\Traits\Ajax;
  15. use RankMath\Traits\Hooker;
  16. use RankMath\Helper as GlobalHelper;
  17. use RankMath\Admin\Importers\Detector;
  18. use MyThemeShop\Admin\Page;
  19. use MyThemeShop\Helpers\WordPress;
  20.  
  21. defined( 'ABSPATH' ) || exit;
  22.  
  23. /**
  24.  * Import_Export class.
  25.  */
  26. class Import_Export implements Runner {
  27.  
  28.     use Hooker, Ajax;
  29.  
  30.     /**
  31.      * Register hooks.
  32.      */
  33.     public function hooks() {
  34.         $this->action( 'init', 'register_page', 1 );
  35.         $this->action( 'rank_math/importers/settings/pre_import', 'run_backup', 10, 0 );
  36.  
  37.         $this->ajax( 'create_backup', 'create_backup' );
  38.         $this->ajax( 'delete_backup', 'delete_backup' );
  39.         $this->ajax( 'restore_backup', 'restore_backup' );
  40.         $this->ajax( 'clean_plugin', 'clean_plugin' );
  41.         $this->ajax( 'import_plugin', 'import_plugin' );
  42.     }
  43.  
  44.     /**
  45.      * Register admin pages for plugin.
  46.      */
  47.     public function register_page() {
  48.         $uri = rank_math()->plugin_url() . 'assets/admin/';
  49.         new Page( 'rank-math-import-export', esc_html__( 'Import &amp; Export', 'rank-math' ), [
  50.             'position' => 99,
  51.             'parent'   => 'rank-math',
  52.             'render'   => Admin_Helper::get_view( 'import-export/main' ),
  53.             'onsave'   => [ $this, 'handler' ],
  54.             'classes'  => [ 'rank-math-page' ],
  55.             'assets'   => [
  56.                 'styles'  => [
  57.                     'cmb2-styles'      => '',
  58.                     'rank-math-common' => '',
  59.                     'rank-math-cmb2'   => '',
  60.                 ],
  61.                 'scripts' => [ 'rank-math-import-export' => $uri . 'js/import-export.js' ],
  62.             ],
  63.         ]);
  64.  
  65.         GlobalHelper::add_json( 'importConfirm', esc_html__( 'Are you sure you want to import settings into Rank Math? Don\'t worry, your current configuration will be saved as a backup.', 'rank-math' ) );
  66.         GlobalHelper::add_json( 'restoreConfirm', esc_html__( 'Are you sure you want to restore this backup? Your current configuration will be overwritten.', 'rank-math' ) );
  67.         GlobalHelper::add_json( 'deleteBackupConfirm', esc_html__( 'Are you sure you want to delete this backup?', 'rank-math' ) );
  68.         GlobalHelper::add_json( 'cleanPluginConfirm', esc_html__( 'Are you sure you want erase traces of plugin?', 'rank-math' ) );
  69.     }
  70.  
  71.     /**
  72.      * Handle import or export.
  73.      */
  74.     public function handler() {
  75.  
  76.         if ( ! isset( $_POST['object_id'] ) ) {
  77.             return;
  78.         }
  79.  
  80.         if ( 'export-plz' === $_POST['object_id'] && check_admin_referer( 'rank-math-export-settings' ) ) {
  81.             $this->export();
  82.         }
  83.  
  84.         if ( isset( $_FILES['import-me'] ) && 'import-plz' === $_POST['object_id'] && check_admin_referer( 'rank-math-import-settings' ) ) {
  85.             $this->import();
  86.         }
  87.     }
  88.  
  89.     /**
  90.      * Handles AJAX plugin run clean.
  91.      */
  92.     public function clean_plugin() {
  93.  
  94.         $this->verify_nonce( 'rank-math-ajax-nonce' );
  95.  
  96.         $result = Detector::run_by_slug( $_POST['pluginSlug'], 'cleanup' );
  97.  
  98.         if ( $result['status'] ) {
  99.             /* translators: Plugin name */
  100.             $this->success( sprintf( esc_html__( 'Cleanup of %s data successfully done.', 'rank-math' ), $result['importer']->get_plugin_name() ) );
  101.         }
  102.  
  103.         /* translators: Plugin name */
  104.         $this->error( sprintf( esc_html__( 'Cleanup of %s data failed.', 'rank-math' ), $result['importer']->get_plugin_name() ) );
  105.     }
  106.  
  107.     /**
  108.      * Handles AJAX plugin run import.
  109.      */
  110.     public function import_plugin() {
  111.  
  112.         $this->verify_nonce( 'rank-math-ajax-nonce' );
  113.  
  114.         $this->has_cap_ajax( 'general' );
  115.  
  116.         $perform = isset( $_POST['perform'] ) ? filter_input( INPUT_POST, 'perform' ) : false;
  117.         if ( ! $perform || ! in_array( $perform, [ 'settings', 'postmeta', 'termmeta', 'usermeta', 'redirections', 'deactivate' ] ) ) {
  118.             $this->error( esc_html__( 'Action not allowed.', 'rank-math' ) );
  119.         }
  120.  
  121.         try {
  122.             $result = Detector::run_by_slug( $_POST['pluginSlug'], 'import', $perform );
  123.             $this->success( $result );
  124.         } catch ( \Exception $e ) {
  125.             $this->error( $e->getMessage() );
  126.         }
  127.  
  128.     }
  129.  
  130.     /**
  131.      * Handles AJAX create backup.
  132.      */
  133.     public function create_backup() {
  134.  
  135.         $this->verify_nonce( 'rank-math-ajax-nonce' );
  136.  
  137.         $key = $this->run_backup();
  138.         if ( is_null( $key ) ) {
  139.             $this->error( esc_html__( 'Unable to create backup this time.', 'rank-math' ) );
  140.         }
  141.  
  142.         $this->success([
  143.             'key'     => $key,
  144.             /* translators: Backup formatted date */
  145.             'backup'  => sprintf( esc_html__( 'Backup: %s', 'rank-math' ), date( 'M jS Y, H:i a', $key ) ),
  146.             'message' => esc_html__( 'Backup created successfully.', 'rank-math' ),
  147.         ]);
  148.     }
  149.  
  150.     /**
  151.      * Handles AJAX delete backup.
  152.      */
  153.     public function delete_backup() {
  154.  
  155.         $this->verify_nonce( 'rank-math-ajax-nonce' );
  156.  
  157.         $key = isset( $_POST['key'] ) ? $_POST['key'] : false;
  158.         if ( ! $key ) {
  159.             $this->error( esc_html__( 'No backup key found to delete.', 'rank-math' ) );
  160.         }
  161.  
  162.         $this->run_backup( 'delete', $key );
  163.         $this->success( esc_html__( 'Backup successfully deleted.', 'rank-math' ) );
  164.     }
  165.  
  166.     /**
  167.      * Handles AJAX restore backup.
  168.      */
  169.     public function restore_backup() {
  170.  
  171.         $this->verify_nonce( 'rank-math-ajax-nonce' );
  172.  
  173.         $key = isset( $_POST['key'] ) ? $_POST['key'] : false;
  174.         if ( ! $key ) {
  175.             $this->error( esc_html__( 'No backup key found to restore.', 'rank-math' ) );
  176.         }
  177.  
  178.         if ( ! $this->run_backup( 'restore', $key ) ) {
  179.             $this->error( esc_html__( 'Backup does not exist.', 'rank-math' ) );
  180.         }
  181.  
  182.         $this->success( esc_html__( 'Backup restored successfully.', 'rank-math' ) );
  183.     }
  184.  
  185.     /**
  186.      * Run backup actions
  187.      *
  188.      * @param  string $action Action to perform.
  189.      * @param  array  $key    Key to backup.
  190.      * @return mixed
  191.      */
  192.     public function run_backup( $action = 'add', $key = null ) {
  193.         $backups = get_option( 'rank_math_backups', [] );
  194.  
  195.         // Restore.
  196.         if ( 'restore' === $action ) {
  197.             if ( ! isset( $backups[ $key ] ) ) {
  198.                 return false;
  199.             }
  200.  
  201.             $this->do_import_data( $backups[ $key ], true );
  202.  
  203.             return true;
  204.         }
  205.  
  206.         // Add.
  207.         if ( 'add' === $action ) {
  208.             $key     = current_time( 'U' );
  209.             $backups = [ $key => $this->get_export_data() ] + $backups;
  210.         }
  211.  
  212.         // Delete.
  213.         if ( 'delete' === $action && isset( $backups[ $key ] ) ) {
  214.             unset( $backups[ $key ] );
  215.         }
  216.  
  217.         update_option( 'rank_math_backups', $backups );
  218.  
  219.         return $key;
  220.     }
  221.  
  222.     /**
  223.      * Handle export.
  224.      */
  225.     private function export() {
  226.         $panels   = $_POST['panels'];
  227.         $data     = $this->get_export_data( $panels );
  228.         $filename = 'rank-math-settings-' . date( 'Y-m-d-H-i-s' ) . '.txt';
  229.  
  230.         header( 'Content-Type: application/txt' );
  231.         header( 'Content-Disposition: attachment; filename=' . $filename );
  232.         header( 'Cache-Control: no-cache, no-store, must-revalidate' );
  233.         header( 'Pragma: no-cache' );
  234.         header( 'Expires: 0' );
  235.  
  236.         echo wp_json_encode( $data );
  237.         exit;
  238.     }
  239.  
  240.     /**
  241.      * Handle import.
  242.      */
  243.     private function import() {
  244.  
  245.         // Handle file upload.
  246.         $file = wp_handle_upload( $_FILES['import-me'] );
  247.         if ( is_wp_error( $file ) ) {
  248.             GlobalHelper::add_notification( esc_html__( 'Settings could not be imported:', 'rank-math' ) . ' ' . $file->get_error_message(), [ 'type' => 'error' ] );
  249.             return false;
  250.         }
  251.  
  252.         if ( is_array( $file ) && isset( $file['error'] ) ) {
  253.             GlobalHelper::add_notification( esc_html__( 'Settings could not be imported:', 'rank-math' ) . ' ' . $file['error'], [ 'type' => 'error' ] );
  254.             return false;
  255.         }
  256.  
  257.         if ( ! isset( $file['file'] ) ) {
  258.             GlobalHelper::add_notification( esc_html__( 'Settings could not be imported:', 'rank-math' ) . ' ' . esc_html__( 'Upload failed.', 'rank-math' ), [ 'type' => 'error' ] );
  259.             return false;
  260.         }
  261.  
  262.         // Parse Options.
  263.         $wp_filesystem = WordPress::get_filesystem();
  264.         $settings      = $wp_filesystem->get_contents( $file['file'] );
  265.         $settings      = json_decode( $settings, true );
  266.  
  267.         \unlink( $file['file'] );
  268.  
  269.         if ( $this->do_import_data( $settings ) ) {
  270.             GlobalHelper::add_notification( esc_html__( 'Settings successfully imported. Your old configuration has been saved as a backup.', 'rank-math' ), 'success' );
  271.             return;
  272.         }
  273.  
  274.         GlobalHelper::add_notification( esc_html__( 'No settings found to be imported.', 'rank-math' ), [ 'type' => 'info' ] );
  275.     }
  276.  
  277.     /**
  278.      * Does import data.
  279.      *
  280.      * @param  array $data           Import data.
  281.      * @param  bool  $suppress_hooks Suppress hooks or not.
  282.      * @return bool
  283.      */
  284.     private function do_import_data( array $data, $suppress_hooks = false ) {
  285.  
  286.         $this->run_import_hooks( 'pre_import', $data, $suppress_hooks );
  287.  
  288.         // Import options.
  289.         $down = $this->set_options( $data );
  290.  
  291.         // Import capabilities.
  292.         if ( isset( $data['role-manager'] ) && ! empty( $data['role-manager'] ) ) {
  293.             $down = true;
  294.             GlobalHelper::set_capabilities( $data['role-manager'] );
  295.         }
  296.  
  297.         // Import redirections.
  298.         if ( isset( $data['redirections'] ) && ! empty( $data['redirections'] ) ) {
  299.             $down = true;
  300.             $this->set_redirections( $data['redirections'] );
  301.         }
  302.  
  303.         $this->run_import_hooks( 'after_import', $data, $suppress_hooks );
  304.  
  305.         return $down;
  306.     }
  307.  
  308.     /**
  309.      * Set options from data.
  310.      *
  311.      * @param array $data An array of data.
  312.      */
  313.     private function set_options( $data ) {
  314.         $set  = false;
  315.         $hash = [
  316.             'modules' => 'rank_math_modules',
  317.             'general' => 'rank-math-options-general',
  318.             'titles'  => 'rank-math-options-titles',
  319.             'sitemap' => 'rank-math-options-sitemap',
  320.         ];
  321.  
  322.         foreach ( $hash as $key => $option_key ) {
  323.             if ( ! empty( $data[ $key ] ) ) {
  324.                 $set = true;
  325.                 update_option( $option_key, $data[ $key ] );
  326.             }
  327.         }
  328.  
  329.         return $set;
  330.     }
  331.  
  332.     /**
  333.      * Set redirections.
  334.      *
  335.      * @param array $redirections An array of redirections to import.
  336.      */
  337.     private function set_redirections( $redirections ) {
  338.         foreach ( $redirections as $key => $redirection ) {
  339.             $matched = \RankMath\Redirections\DB::match_redirections_source( $redirection['sources'] );
  340.             if ( ! empty( $matched ) ) {
  341.                 continue;
  342.             }
  343.  
  344.             \RankMath\Redirections\DB::add(
  345.                 [
  346.                     'url_to'      => $redirection['url_to'],
  347.                     'sources'     => unserialize( $redirection['sources'] ),
  348.                     'header_code' => $redirection['header_code'],
  349.                     'hits'        => $redirection['hits'],
  350.                     'created'     => $redirection['created'],
  351.                     'updated'     => $redirection['updated'],
  352.                 ]
  353.             );
  354.         }
  355.     }
  356.  
  357.     /**
  358.      * Run import hooks
  359.      *
  360.      * @param string $hook     Hook to fire.
  361.      * @param array  $data     Import data.
  362.      * @param bool   $suppress Suppress hooks or not.
  363.      */
  364.     private function run_import_hooks( $hook, $data, $suppress ) {
  365.         if ( ! $suppress ) {
  366.             /**
  367.              * Fires while importing settings.
  368.              *
  369.              * @since 0.9.0
  370.              *
  371.              * @param array $data Import data.
  372.              */
  373.             $this->do_action( 'importers/settings/' . $hook, $data );
  374.         }
  375.     }
  376.  
  377.     /**
  378.      * Gets export data.
  379.      *
  380.      * @param array $panels Which panels do you want to export. It will export all panels if this param is empty.
  381.      * @return array
  382.      */
  383.     private function get_export_data( array $panels = [] ) {
  384.         if ( ! $panels ) {
  385.             $panels = [ 'general', 'titles', 'sitemap', 'role-manager', 'redirections' ];
  386.         }
  387.  
  388.         $settings = rank_math()->settings->all_raw();
  389.  
  390.         foreach ( $panels as $panel ) {
  391.             if ( isset( $settings[ $panel ] ) ) {
  392.                 $data[ $panel ] = $settings[ $panel ];
  393.             }
  394.         }
  395.  
  396.         if ( \in_array( 'role-manager', $panels ) ) {
  397.             $data['role-manager'] = GlobalHelper::get_roles_capabilities();
  398.         }
  399.  
  400.         $data['modules'] = rank_math()->manager->get_active_modules();
  401.  
  402.         if ( \in_array( 'redirections', $panels ) ) {
  403.             $items = \RankMath\Redirections\DB::get_redirections( [ 'limit' => 1000 ] );
  404.  
  405.             $data['redirections'] = $items['redirections'];
  406.         }
  407.  
  408.         return $data;
  409.     }
  410. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top