Advertisement
Guest User

Untitled

a guest
Apr 21st, 2014
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.56 KB | None | 0 0
  1. <?php
  2. /*
  3. Plugin Name: Blog Copier
  4. Plugin URI: http://wordpress.org/extend/plugins/blog-copier/
  5. Description: Enables superusers to copy existing sub blogs to new sub blogs.
  6. Version: 1.0.4
  7. Author: Modern Tribe, Inc.
  8. Network: true
  9. Author URI: http://tri.be
  10.  
  11. Copyright: (C) 2012 Modern Tribe derived from (C) 2010 Ron Rennick, All rights reserved.
  12.  
  13. See http://wpebooks.com/replicator/ for original code.
  14.  
  15. This program is free software; you can redistribute it and/or modify
  16. it under the terms of the GNU General Public License as published by
  17. the Free Software Foundation; either version 2 of the License, or
  18. (at your option) any later version.
  19.  
  20. This program is distributed in the hope that it will be useful,
  21. but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. GNU General Public License for more details.
  24.  
  25. You should have received a copy of the GNU General Public License
  26. along with this program; if not, write to the Free Software
  27. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  28. */
  29.  
  30. // Block direct requests
  31. if ( !defined('ABSPATH') )
  32. die('-1');
  33.  
  34. if ( !class_exists('BlogCopier') ) {
  35.  
  36. /**
  37. * Blog Copier
  38. *
  39. * @package BlogCopier
  40. */
  41. class BlogCopier {
  42.  
  43. private $_name;
  44. private $_domain = 'blog-copier';
  45.  
  46. /**
  47. * Main constructor function
  48. */
  49. public function __construct() {
  50. add_action( 'network_admin_menu', array( $this, 'ms_add_page' ) );
  51. add_filter( 'manage_sites_action_links', array( $this, 'add_site_action' ), 10, 2 );
  52. }
  53.  
  54. /**
  55. * Add admin page to network admin menu
  56. */
  57. public function ms_add_page() {
  58. $this->setup_localization();
  59. add_submenu_page( 'sites.php', $this->_name, $this->_name, 'manage_sites', $this->_domain, array( $this, 'admin_page' ) );
  60. }
  61.  
  62. /**
  63. * Add "Copy Blog" link under each site in the sites list view.
  64. *
  65. * @param array $actions
  66. * @param int $blog_id
  67. * @return array $actions
  68. */
  69. public function add_site_action( $actions, $blog_id ) {
  70. if( !is_main_site( $blog_id ) ) {
  71. $this->setup_localization();
  72. $url = add_query_arg( array(
  73. 'page' => $this->_domain,
  74. 'blog' => $blog_id
  75. ), network_admin_url( 'sites.php' ) );
  76. $nonce_string = sprintf( '%s-%s', $this->_domain, $blog_id );
  77. $actions[$this->_domain] = '<a href="' . esc_url( wp_nonce_url( $url, $nonce_string ) ) . '">' . __( 'Copy', $this->_domain ) . '</a>';
  78. }
  79.  
  80. return $actions;
  81. }
  82.  
  83. /**
  84. * Admin page
  85. */
  86. public function admin_page() {
  87. global $wpdb, $current_site;
  88.  
  89. if( !current_user_can( 'manage_sites' ) )
  90. wp_die( __( "Sorry, you don't have permissions to use this page.", $this->_domain ) );
  91.  
  92. $from_blog = false;
  93. $copy_id = 0;
  94. $nonce_string = sprintf( '%s-%s', $this->_domain, $copy_id );
  95. if( isset($_GET['blog']) && wp_verify_nonce( $_GET['_wpnonce'], $nonce_string ) ) {
  96. $copy_id = (int)$_GET['blog'];
  97. $from_blog = get_blog_details( $copy_id );
  98. if( $from_blog->site_id != $current_site->id ) {
  99. $from_blog = false;
  100. }
  101. }
  102. $from_blog_id = ( isset( $_POST['source_blog'] ) ) ? (int) $_POST['source_blog'] : -1;
  103.  
  104. if( isset($_POST[ 'action' ]) && $_POST[ 'action' ] == $this->_domain ) {
  105. check_admin_referer( $this->_domain );
  106. $blog = $_POST['blog'];
  107. $domain = sanitize_user( str_replace( '/', '', $blog[ 'domain' ] ) );
  108. $title = $blog[ 'title' ];
  109. $copy_files = (isset($_POST['copy_files']) && $_POST['copy_files'] == '1') ? true : false;
  110. $network_domain =(isset($_POST['network_domain']) ? $_POST['network_domain'] : $current_site->domain);
  111.  
  112. if ( !$from_blog_id ) {
  113. $msg = __( 'Please select a source blog.', $this->_domain );
  114. } elseif ( empty( $domain ) ) {
  115. $msg = __( 'Please enter a "New Blog Address".', $this->_domain );
  116. } elseif ( empty( $title ) ) {
  117. $msg = __( 'Please enter a "New Blog Title".', $this->_domain );
  118. } else {
  119. $msg = $this->copy_blog( $domain, $title, $from_blog_id, $copy_files, $network_domain );
  120. }
  121. } else {
  122. $copy_files = true; // set the default for first page load
  123. } ?>
  124. <div class='wrap'><h2><?php echo $this->_name; ?></h2><?php
  125.  
  126. if( isset( $msg ) ) { ?>
  127. <div id="message" class="updated fade"><p><strong><?php echo $msg; ?>
  128. </strong></p></div><?php
  129. }
  130. if( !$from_blog ) {
  131. $query = "SELECT b.blog_id, CONCAT(b.domain, b.path) as domain_path FROM {$wpdb->blogs} b " .
  132. "WHERE b.site_id = {$current_site->id} && b.blog_id > 1 ORDER BY domain_path ASC LIMIT 10000";
  133.  
  134. $blogs = $wpdb->get_results( $query );
  135. }
  136. if( $from_blog || $blogs ) { ?>
  137. <div class="wrap">
  138. <h3><?php _e( 'Blog Copy Settings', $this->_domain ); ?></h3>
  139. <form method="POST">
  140. <input type="hidden" name="action" value="<?php echo $this->_domain; ?>" />
  141. <table class="form-table">
  142.  
  143. <?php if( $from_blog ) { ?>
  144. <tr>
  145. <th scope='row'><?php _e( 'Source Blog to Copy', $this->_domain ); ?></th>
  146. <td><strong><?php printf( '<a href="%s" target="_blank">%s</a>', $from_blog->siteurl, $from_blog->blogname ); ?></strong>
  147. <input type="hidden" name="source_blog" value="<?php echo $copy_id; ?>" />
  148. </td>
  149. </tr>
  150. <?php } else { ?>
  151. <tr class="form-required">
  152. <th scope='row'><?php _e( 'Choose Source Blog to Copy', $this->_domain ); ?></th>
  153. <td>
  154. <select name="source_blog">
  155. <?php foreach( $blogs as $blog ) { ?>
  156. <option value="<?php echo $blog->blog_id; ?>" <?php selected( $blog->blog_id, $from_blog_id ); ?>><?php echo substr($blog->domain_path, 0, -1); ?></option>
  157. <?php } ?>
  158. </select>
  159. </td>
  160. </tr>
  161. <?php } ?>
  162.  
  163. <tr class="form-required">
  164. <th scope='row'><?php _e( 'New Blog Address', $this->_domain ); ?></th>
  165. <td>
  166. <?php if( is_subdomain_install() ) {
  167. $network_domains = get_site_option( 'md_domains' );
  168. ?>
  169. <input name="blog[domain]" type="text" title="<?php _e( 'Subdomain', $this->_domain ); ?>" class="regular-text"/>.<?php
  170. if(count($network_domains) > 0)
  171. {
  172. $sorted_domains = array();
  173. foreach ($network_domains as $network_domain) {
  174. $sorted_domains[] = $network_domain['domain_name'];
  175. }
  176. asort($sorted_domains);
  177. echo "<select name='network_domain' id='network_domain'>";
  178. foreach($sorted_domains as $network_domain)
  179. {
  180. $selected = ($network_domain == $current_site->domain ? "selected" : "");
  181. echo "<option value='{$network_domain}' $selected>{$network_domain}</option>";
  182. }
  183. echo "</select>";
  184. }
  185. else
  186. {
  187. echo $current_site->domain;
  188. }
  189. ?>
  190. <?php } else {
  191. echo $current_site->domain . $current_site->path ?><input name="blog[domain]" type="text" title="<?php _e( 'Domain', $this->_domain ); ?>" class="regular-text"/>
  192. <?php } ?>
  193. </td>
  194. </tr>
  195.  
  196. <tr class="form-required">
  197. <th scope='row'><?php _e( 'New Blog Title', $this->_domain ); ?></th>
  198. <td><input name="blog[title]" type="text" title="<?php _e( 'Title', $this->_domain ); ?>" class="regular-text"/></td>
  199. </tr>
  200.  
  201. <tr class="form-required">
  202. <th scope='row'><?php _e( 'Copy Files?', $this->_domain ); ?></th>
  203. <td><input type="checkbox" name="copy_files" value="1" <?php checked( $copy_files ); ?>/></td>
  204. </tr>
  205.  
  206. </table>
  207. <?php wp_nonce_field( $this->_domain ); ?>
  208. <p class="submit"><input class='button' type='submit' value='<?php _e( 'Copy Now', $this->_domain ); ?>' /></p>
  209. </form></div>
  210. <?php } else { ?>
  211. <div class="wrap">
  212. <h3><?php _e( 'Oops!', $this->_domain ); ?></h3>
  213. <p><?php
  214. printf( __( 'This plugin only works on subblogs. To use this you\'ll need to <a href="%s">create at least one subblog</a>.', $this->_domain ), network_admin_url( 'site-new.php' ) );
  215. ?></p>
  216. </div>
  217. <?php }
  218. }
  219.  
  220. /**
  221. * Copy the blog
  222. *
  223. * @param string $domain url of the new blog
  224. * @param string $title title of the new blog
  225. * @param int $from_blog_id ID of the blog being copied from.
  226. * @param bool $copy_files true if files should be copied
  227. * @return string status message
  228. */
  229. public function copy_blog($domain, $title, $from_blog_id = 0, $copy_files = true, $network_domain = false) {
  230. global $wpdb, $current_site, $base;
  231.  
  232. $email = get_blog_option( $from_blog_id, 'admin_email' );
  233. $user_id = email_exists( sanitize_email( $email ) );
  234. if( !$user_id ) {
  235. // Use current user instead
  236. $user_id = get_current_user_id();
  237. }
  238. // The user id of the user that will become the blog admin of the new blog.
  239. $user_id = apply_filters('copy_blog_user_id', $user_id, $from_blog_id);
  240.  
  241. if( is_subdomain_install() ) {
  242. $top_doman = ($network_domain ? $network_domain : $current_site->domain);
  243. $newdomain = $domain.".".$top_doman;
  244. $path = $base;
  245. } else {
  246. $newdomain = $current_site->domain;
  247. $path = trailingslashit($base.$domain);
  248. }
  249.  
  250. // The new domain that will be created for the destination blog.
  251. $newdomain = apply_filters('copy_blog_domain', $newdomain, $domain);
  252.  
  253. // The new path that will be created for the destination blog.
  254. $path = apply_filters('copy_blog_path', $path, $domain);
  255.  
  256. $wpdb->hide_errors();
  257. $to_blog_id = wpmu_create_blog( $newdomain, $path, $title, $user_id , array( "public" => 1 ), $current_site->id );
  258. $wpdb->show_errors();
  259.  
  260. if( !is_wp_error( $to_blog_id ) ) {
  261. $dashboard_blog = get_dashboard_blog();
  262. if( !is_super_admin() && get_user_option( 'primary_blog', $user_id ) == $dashboard_blog->blog_id )
  263. update_user_option( $user_id, 'primary_blog', $to_blog_id, true );
  264.  
  265. // now copy
  266. if( $from_blog_id ) {
  267.  
  268. $this->copy_blog_data( $from_blog_id, $to_blog_id );
  269.  
  270. if ($copy_files) {
  271.  
  272. $this->copy_blog_files( $from_blog_id, $to_blog_id );
  273. $this->replace_content_urls( $from_blog_id, $to_blog_id );
  274.  
  275. }
  276. $msg = sprintf(__( 'Copied: %s in %s seconds', $this->_domain ),'<a href="http://'.$newdomain.'" target="_blank">'.$title.'</a>', number_format_i18n(timer_stop()));
  277. do_action( 'log', __( 'Copy Complete!', $this->_domain ), $this->_domain, $msg );
  278. }
  279. } else {
  280. $msg = $to_blog_id->get_error_message();
  281. }
  282. return $msg;
  283. }
  284.  
  285. /**
  286. * Copy blog data from one blog to another
  287. *
  288. * @param int $from_blog_id ID of the blog being copied from.
  289. * @param int $to_blog_id ID of the blog being copied to.
  290. */
  291. private function copy_blog_data( $from_blog_id, $to_blog_id ) {
  292. global $wpdb, $wp_version;
  293. if( $from_blog_id ) {
  294. $from_blog_prefix = $this->get_blog_prefix( $from_blog_id );
  295. $to_blog_prefix = $this->get_blog_prefix( $to_blog_id );
  296. $from_blog_prefix_length = strlen($from_blog_prefix);
  297. $to_blog_prefix_length = strlen($to_blog_prefix);
  298. $from_blog_escaped_prefix = str_replace( '_', '\_', $from_blog_prefix );
  299.  
  300. // Grab key options from new blog.
  301. $saved_options = array(
  302. 'siteurl'=>'',
  303. 'home'=>'',
  304. 'upload_path'=>'',
  305. 'fileupload_url'=>'',
  306. 'upload_url_path'=>'',
  307. 'admin_email'=>'',
  308. 'blogname'=>''
  309. );
  310. // Options that should be preserved in the new blog.
  311. $saved_options = apply_filters('copy_blog_data_saved_options', $saved_options);
  312. foreach($saved_options as $option_name => $option_value) {
  313. $saved_options[$option_name] = get_blog_option( $to_blog_id, $option_name );
  314. }
  315.  
  316. // Copy over ALL the tables.
  317. $query = $wpdb->prepare('SHOW TABLES LIKE %s',$from_blog_escaped_prefix.'%');
  318. do_action( 'log', $query, $this->_domain);
  319. $old_tables = $wpdb->get_col($query);
  320.  
  321. foreach ($old_tables as $k => $table) {
  322. $raw_table_name = substr( $table, $from_blog_prefix_length );
  323. $newtable = $to_blog_prefix . $raw_table_name;
  324.  
  325. $query = "DROP TABLE IF EXISTS {$newtable}";
  326. do_action( 'log', $query, $this->_domain);
  327. $wpdb->get_results($query);
  328.  
  329. $query = "CREATE TABLE IF NOT EXISTS {$newtable} LIKE {$table}";
  330. do_action( 'log', $query, $this->_domain);
  331. $wpdb->get_results($query);
  332.  
  333. $query = "INSERT {$newtable} SELECT * FROM {$table}";
  334. do_action( 'log', $query, $this->_domain);
  335. $wpdb->get_results($query);
  336. }
  337.  
  338. // apply key opptions from new blog.
  339. switch_to_blog( $to_blog_id );
  340. foreach( $saved_options as $option_name => $option_value ) {
  341. update_option( $option_name, $option_value );
  342. }
  343.  
  344. /// fix all options with the wrong prefix...
  345. $query = $wpdb->prepare("SELECT * FROM {$wpdb->options} WHERE option_name LIKE %s",$from_blog_escaped_prefix.'%');
  346. $options = $wpdb->get_results( $query );
  347. do_action( 'log', $query, $this->_domain, count($options).' results found.');
  348. if( $options ) {
  349. foreach( $options as $option ) {
  350. $raw_option_name = substr($option->option_name,$from_blog_prefix_length);
  351. $wpdb->update( $wpdb->options, array( 'option_name' => $to_blog_prefix . $raw_option_name ), array( 'option_id' => $option->option_id ) );
  352. }
  353. wp_cache_flush();
  354. }
  355.  
  356. // Fix GUIDs on copied posts
  357. $this->replace_guid_urls( $from_blog_id, $to_blog_id );
  358.  
  359. restore_current_blog();
  360. }
  361. }
  362.  
  363. /**
  364. * Copy files from one blog to another.
  365. *
  366. * @param int $from_blog_id ID of the blog being copied from.
  367. * @param int $to_blog_id ID of the blog being copied to.
  368. */
  369. private function copy_blog_files( $from_blog_id, $to_blog_id ) {
  370. set_time_limit( 2400 ); // 60 seconds x 10 minutes
  371. @ini_set('memory_limit','2048M');
  372.  
  373. // Path to source blog files.
  374. switch_to_blog($from_blog_id);
  375. $dir_info = wp_upload_dir();
  376. $from = str_replace(' ', "\\ ", trailingslashit($dir_info['basedir']).'*'); // * necessary with GNU cp, doesn't hurt anything with BSD cp
  377. restore_current_blog();
  378. $from = apply_filters('copy_blog_files_from', $from, $from_blog_id);
  379.  
  380. // Path to destination blog files.
  381. switch_to_blog($to_blog_id);
  382. $dir_info = wp_upload_dir();
  383. $to = str_replace(' ', "\\ ", trailingslashit($dir_info['basedir']));
  384. restore_current_blog();
  385. $to = apply_filters('copy_blog_files_to', $to, $to_blog_id);
  386.  
  387. // Shell command used to copy files.
  388. $command = apply_filters('copy_blog_files_command', sprintf("cp -Rfp %s %s", $from, $to), $from, $to );
  389. exec($command);
  390. }
  391.  
  392. /**
  393. * Replace URLs in post content
  394. *
  395. * @param int $from_blog_id ID of the blog being copied from.
  396. * @param int $to_blog_id ID of the blog being copied to.
  397. */
  398. private function replace_content_urls( $from_blog_id, $to_blog_id ) {
  399. global $wpdb;
  400. $to_blog_prefix = $this->get_blog_prefix( $to_blog_id );
  401. $from_blog_url = get_blog_option( $from_blog_id, 'siteurl' );
  402. $to_blog_url = get_blog_option( $to_blog_id, 'siteurl' );
  403. $query = $wpdb->prepare( "UPDATE {$to_blog_prefix}posts SET post_content = REPLACE(post_content, '%s', '%s')", $from_blog_url, $to_blog_url );
  404. do_action( 'log', $query, $this->_domain);
  405. $wpdb->query( $query );
  406. }
  407.  
  408. /**
  409. * Replace URLs in post GUIDs
  410. *
  411. * @param int $from_blog_id ID of the blog being copied from.
  412. * @param int $to_blog_id ID of the blog being copied to.
  413. */
  414. private function replace_guid_urls( $from_blog_id, $to_blog_id ) {
  415. global $wpdb;
  416. $to_blog_prefix = $this->get_blog_prefix( $to_blog_id );
  417. $from_blog_url = get_blog_option( $from_blog_id, 'siteurl' );
  418. $to_blog_url = get_blog_option( $to_blog_id, 'siteurl' );
  419. $query = $wpdb->prepare( "UPDATE {$to_blog_prefix}posts SET guid = REPLACE(guid, '%s', '%s')", $from_blog_url, $to_blog_url );
  420. do_action( 'log', $query, $this->_domain);
  421. $wpdb->query( $query );
  422. }
  423.  
  424. /**
  425. * Get the database prefix for a blog
  426. *
  427. * @param int $blog_id ID of the blog.
  428. * @return string prefix
  429. */
  430. private function get_blog_prefix( $blog_id ) {
  431. global $wpdb;
  432. if( is_callable( array( &$wpdb, 'get_blog_prefix' ) ) ) {
  433. $prefix = $wpdb->get_blog_prefix( $blog_id );
  434. } else {
  435. $prefix = $wpdb->base_prefix . $blog_id . '_';
  436. }
  437. return $prefix;
  438. }
  439.  
  440. /**
  441. * Load the localization file
  442. */
  443. private function setup_localization() {
  444. if ( !isset( $this->_name ) ) {
  445. load_plugin_textdomain( $this->_domain, false, trailingslashit(dirname(__FILE__)) . 'lang/');
  446. $this->_name = __( 'Blog Copier', $this->_domain );
  447. }
  448. }
  449.  
  450. }
  451.  
  452. global $BlogCopier;
  453. $BlogCopier = new BlogCopier();
  454. }
  455. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement