/wp-content/plugins/search-and-replace/inc/Page/SearchReplace.php

https://gitlab.com/iamgraeme/royalmile · PHP · 300 lines · 154 code · 62 blank · 84 comment · 23 complexity · 0f838edef6b75c068ae638d7652e9918 MD5 · raw file

  1. <?php
  2. namespace Inpsyde\SearchReplace\Page;
  3. use Inpsyde\SearchReplace\Database,
  4. Inpsyde\SearchReplace\Service;
  5. use Inpsyde\SearchReplace\FileDownloader;
  6. /**
  7. * Class SearchReplace
  8. *
  9. * @package Inpsyde\SearchReplace\Page
  10. */
  11. class SearchReplace extends AbstractPage implements PageInterface {
  12. /**
  13. * @var Manager
  14. */
  15. private $dbm;
  16. /**
  17. * @var $replace
  18. */
  19. private $replace;
  20. /**
  21. * @var $dbe
  22. */
  23. private $dbe;
  24. /**
  25. * @var FileDownloader
  26. */
  27. private $downloader;
  28. /**
  29. * BackupDatabase constructor.
  30. *
  31. * @param Database\Manager $dbm
  32. * @param Database\Replace $replace
  33. * @param Database\Exporter $dbe
  34. * @param FileDownloader $downloader
  35. */
  36. public function __construct( Database\Manager $dbm, Database\Replace $replace, Database\Exporter $dbe, FileDownloader $downloader ) {
  37. $this->dbm = $dbm;
  38. $this->replace = $replace;
  39. $this->dbe = $dbe;
  40. $this->downloader = $downloader;
  41. }
  42. /**
  43. * shows the page contents
  44. */
  45. public function render() {
  46. require_once( __DIR__ . '/../templates/search_replace.php' );
  47. }
  48. /**
  49. * @return string
  50. */
  51. public function get_page_title() {
  52. return esc_html__( 'Search & Replace', 'search-and-replace' );
  53. }
  54. /**
  55. * Return the static slug string.
  56. *
  57. * @return string
  58. */
  59. public function get_slug() {
  60. return 'search-replace';
  61. }
  62. /**
  63. *prints a select with all the tables and their sizes
  64. *
  65. * @return void
  66. */
  67. protected function show_table_list() {
  68. $tables = $this->dbm->get_tables();
  69. $sizes = $this->dbm->get_sizes();
  70. $table_count = count( $tables );
  71. //adjust height of select according to table count, but max 20 rows
  72. $select_rows = $table_count < 20 ? $table_count : 20;
  73. //if we come from a dry run, we select the tables to the dry run again
  74. /** @var bool | string $selected_tables */
  75. $selected_tables = FALSE;
  76. if ( isset( $_POST[ 'select_tables' ] ) ) {
  77. $selected_tables = $_POST[ 'select_tables' ];
  78. }
  79. echo '<select id="select_tables" name="select_tables[]" multiple="multiple" size = "' . $select_rows . '">';
  80. foreach ( $tables as $table ) {
  81. $table_size = isset ( $sizes[ $table ] ) ? $sizes[ $table ] : '';
  82. //check if dry run. if dry run && current table is in "selected" array add selected attribute
  83. if ( isset( $_POST[ 'dry_run' ] )
  84. && $selected_tables
  85. && in_array( $table, $selected_tables, FALSE )
  86. ) {
  87. echo "<option value='$table' selected='selected'>$table . $table_size </option>";
  88. //if current table had not been selected echo option without "selected" attribute
  89. } else {
  90. echo '<option value="' . $table . '">' . $table . $table_size . '</option>';
  91. }
  92. }
  93. echo( '</select>' );
  94. }
  95. /**
  96. * @return bool
  97. */
  98. public function save() {
  99. //check for errors in form
  100. if ( ! $this->is_request_valid() ) {
  101. return FALSE;
  102. }
  103. $tables = isset( $_POST[ 'select_tables' ] ) ? $_POST[ 'select_tables' ] : '';
  104. $dry_run = isset( $_POST[ 'dry_run' ] ) ? TRUE : FALSE;
  105. //remove wp_magic_quotes
  106. $search = stripslashes( filter_input( INPUT_POST, 'search' ) );
  107. $replace = stripslashes( filter_input( INPUT_POST, 'replace' ) );
  108. //if dry run is checked we run the replace function with dry run and return
  109. if ( TRUE === $dry_run ) {
  110. $this->run_replace( $search, $replace, $tables, $dry_run );
  111. return FALSE;
  112. }
  113. $export_or_save = filter_input( INPUT_POST, 'export_or_save' );
  114. if ( 'export' === $export_or_save ) {
  115. //'export'-button was checked
  116. $report = $this->dbe->db_backup( $search, $replace, $tables );
  117. $this->downloader->show_modal( $report );
  118. } else {
  119. //"Save changes to database" was checked
  120. $this->run_replace( $search, $replace, $tables, $dry_run );
  121. }
  122. return TRUE;
  123. }
  124. /**
  125. * @return string
  126. */
  127. protected function get_submit_button_title() {
  128. return esc_html__( 'Do Search & Replace', 'search-and-replace' );
  129. }
  130. /**
  131. * calls run_replace_table() on each table provided in array $tables
  132. *
  133. * @param $search
  134. * @param $replace
  135. * @param $tables array of tables we want to search
  136. * @param $dry_run True if dry run (no changes are written to db)
  137. *
  138. * @return null
  139. */
  140. protected function run_replace( $search, $replace, $tables, $dry_run ) {
  141. echo '<div class="updated notice is-dismissible">';
  142. if ( $dry_run ) {
  143. echo '<p><strong>'
  144. . esc_html__(
  145. 'Dry run is selected. No changes were made to the database and no SQL file was written .',
  146. 'search-and-replace'
  147. )
  148. . '</strong></p>';
  149. } else {
  150. echo '<p><strong>'
  151. . esc_html__(
  152. 'The following changes were made to the database: ',
  153. 'search-and-replace'
  154. )
  155. . '</strong></p>';
  156. }
  157. $this->replace->set_dry_run( $dry_run );
  158. $report = $this->replace->run_search_replace( $search, $replace, $tables );
  159. if ( is_wp_error( $report ) ) {
  160. $this->add_error( __( $report->get_error_message(), 'search-and-replace' ) );
  161. $this->display_errors();
  162. } else {
  163. if ( count( $report[ 'changes' ] ) > 0 ) {
  164. $this->downloader->show_changes( $report );
  165. }
  166. //if no changes found report that
  167. if ( 0 === count( $report [ 'changes' ] ) ) {
  168. echo '<p>' . esc_html__( 'Search pattern not found.', 'search-and-replace' ) . '</p>';
  169. }
  170. }
  171. echo '</div>';
  172. }
  173. /**
  174. * checks the input form and writes possible errors to a WP_Error object
  175. *
  176. * @return bool true|false
  177. */
  178. protected function is_request_valid() {
  179. $select_tables = filter_input( INPUT_POST, 'select_tables' );
  180. if ( '' === $select_tables ) {
  181. $this->add_error( __( 'No Tables were selected.', 'search-and-replace' ) );
  182. return FALSE;
  183. }
  184. $search = filter_input( INPUT_POST, 'search' );
  185. $replace = filter_input( INPUT_POST, 'replace' );
  186. //if search field is empty and replace field is not empty quit. If both fields are empty, go on (useful for backup of single tables without changing)
  187. if ( '' === $search && '' === $replace ) {
  188. $this->add_error( esc_attr__( 'Search field is empty.', 'search-and-replace' ) );
  189. return FALSE;
  190. }
  191. $export_or_save = filter_input( INPUT_POST, 'export_or_save' );
  192. //check if the user tries to replace domain name into the database
  193. if ( '' === $export_or_save || 'save_to_db' === $export_or_save ) {
  194. $contains_site_url = strpos( $search, $this->get_stripped_site_url() );
  195. if ( FALSE !== $contains_site_url ) {
  196. $this->add_error(
  197. esc_html__(
  198. 'Your search contains your current site url. Replacing your site url will most likely cause your site to break. If you want to change the URL (and you know what you doing), please use the export function and make sure you backup your database before reimporting the changed SQL.',
  199. 'search-and-replace'
  200. )
  201. );
  202. return FALSE;
  203. }
  204. }
  205. return TRUE;
  206. }
  207. /**
  208. * Returns the site url, strips http:// or https://
  209. */
  210. private function get_stripped_site_url() {
  211. $url = get_site_url();
  212. return substr( $url, strpos( $url, '/' ) + 2 );
  213. }
  214. /**
  215. * shows the search value in template.
  216. */
  217. private function get_search_value() {
  218. $search = isset( $_POST[ 'search' ] ) ? $_POST[ 'search' ] : '';
  219. $dry_run = isset( $_POST[ 'dry_run' ] ) ? TRUE : FALSE;
  220. if ( $dry_run ) {
  221. $search = stripslashes( $search );
  222. $search = htmlentities( $search );
  223. echo $search;
  224. }
  225. }
  226. /**
  227. * shows the replace value in template
  228. */
  229. private function get_replace_value() {
  230. $replace = isset( $_POST[ 'replace' ] ) ? $_POST[ 'replace' ] : '';
  231. $dry_run = isset( $_POST[ 'dry_run' ] ) ? TRUE : FALSE;
  232. if ( $dry_run ) {
  233. $replace = stripslashes( $replace );
  234. $replace = htmlentities( $replace );
  235. echo $replace;
  236. }
  237. }
  238. }