Sindbad~EG File Manager
<?php
namespace Inpsyde\SearchReplace;
use Inpsyde\SearchReplace\Database\Exporter;
use Inpsyde\SearchReplace\Service\MaxExecutionTime;
/**
* Class FileDownloader
*
* @package Inpsyde\SearchReplace
*/
class FileDownloader {
/**
* @var string
*/
private $nonce_action = 'download_sql';
/**
* @var string
*/
private $nonce_name = 'insr_nonce_download';
/**
* @var Exporter
*/
private $dbe;
/**
* @var MaxExecutionTime
*/
private $max_execution;
/**
* Admin constructor.
*
* @param Exporter $dbe
* @param MaxExecutionTime $max_execution
*/
public function __construct( Exporter $dbe, MaxExecutionTime $max_execution ) {
$this->dbe = $dbe;
$this->max_execution = $max_execution;
}
/**
* Renders to download modal.
*
* @param array $report
*/
public function show_modal( $report ) {
// Set compress status.
// @codingStandardsIgnoreLine
$compress = ( isset( $_POST['compress'] ) && 'on' === $_POST['compress'] );
if ( array_key_exists( 'changes', $report ) && ! empty( $report['changes'] ) ) :
?>
<div class="updated notice is-dismissible">
<?php
// Show changes if there are any.
if ( count( $report['changes'] ) > 0 ) {
$this->show_changes( $report );
}
// If no changes found report that.
if ( 0 === count( $report ['changes'] ) ) {
echo '<p>' . esc_html__( 'Search pattern not found.', 'search-and-replace' ) . '</p>';
}
?>
</div>
<?php
endif;
?>
<div class="updated notice is-dismissible insr_sql_button_wrap">
<p><?php esc_html_e( 'Your SQL file was created!', 'search-and-replace' ); ?> </p>
<form action method="post">
<?php wp_nonce_field( $this->nonce_action, $this->nonce_name ); ?>
<input type="hidden" name="action" value="download_file"/>
<input type="hidden" name="sql_file" value="<?php echo esc_attr( $report['filename'] ); ?>">
<input type="hidden" name="compress" value="<?php echo esc_attr( $compress ); ?>">
<input id="insr_submit" type="submit" value="<?php esc_attr_e(
'Download SQL File', 'search-and-replace'
) ?>" class="button"/>
</form>
</div>
<?php
}
/**
* Displays the changes made to the db
* echoes the changes in formatted html.
*
* @param array $report WP-Error Object if Errors
*
* 'tables' : Number of tables processed
* 'changes_count' : Number of changes made
* 'changes' : Array with at least these elements:
* 'table_name'=> $[name of current table],
* 'changes' => array('row' => [row that has been changed ],
* 'column' => [column that has been changed],
* 'from' => ( old value ),
* 'to' => ( $new value ),
* .
*/
public function show_changes( $report ) {
// Get search & replace values in order to highlight them in the results.
// @codingStandardsIgnoreStart
$search = isset( $_POST['search'] ) ?
esc_html( filter_var( $_POST ['search'], FILTER_SANITIZE_STRING ) ) :
'';
$replace = isset( $_POST['replace'] ) ?
esc_html( filter_var( $_POST ['replace'], FILTER_SANITIZE_STRING ) ) :
'';
// @codingStandardsIgnoreEnd
$search_highlight = '<span class="search-replace-search-value">' . $search . '</span>';
$replace_highlight = '<span class ="search-replace-replace-value">' . $replace . '</span>';
$delimiter = [ ' ...', '...<br>' ];
$this->show_message_by_report( $report );
?>
<p><a href="#" id="changes-modal-button"><?php esc_html_e( 'View details', 'search-and-replace' ); ?></a></p>
<div id="changes-modal-background" class="search-replace-modal-background" style="display: none;"></div>
<div id="changes-modal" class="search-replace-modal " style="display: none;">
<div class="search-replace-modal-header">
<button type="button" id="changes-modal-close" class="search-replace-modal-close-button"></button>
</div>
<div class="search-replace-changes-modal-content">
<?php
foreach ( $report['changes'] as $table_report ) :
$changes = $table_report['changes'];
$changes_made = count( $changes );
if ( $changes_made < 1 ) {
continue;
}
$table = $table_report['table_name'];
?>
<h2 class="search-replace-modal-table-headline">
<strong><?php esc_html_e( 'Table:', 'search-and-replace' ); ?></strong>
<?php echo esc_html( $table ); ?>
<strong><?php esc_html_e( 'Columns Changes:', 'search-and-replace' ); ?></strong>
<?php echo esc_html( $changes_made ); ?>
</h2>
<table class="search-replace-modal-table">
<thead>
<tr>
<th class="search-replace-row search-replace-narrow">
<?php esc_html_e( 'Row', 'search-and-replace' ); ?>
</th>
<th class="search-replace-column">
<?php esc_html_e( 'Column', 'search-and-replace' ); ?>
</th>
<th class="search-replace-old-value">
<?php esc_html_e( 'Old value', 'search-and-replace' ); ?>
</th>
<th class="search-replace-new-value">
<?php esc_html_e( 'New value', 'search-and-replace' ); ?>
</th>
</tr>
</thead>
<tbody>
<?php
foreach ( $changes as $change ) :
// Trim results and wrap with highlight class.
$old_value = esc_html( $change ['from'] );
$old_value = $this->trim_search_results( $search, $old_value, $delimiter );
$old_value = str_replace( $search, $search_highlight, $old_value );
$new_value = esc_html( $change['to'] );
$new_value = $this->trim_search_results( $replace, $new_value, $delimiter );
$new_value = str_replace( $replace, $replace_highlight, $new_value );
if ( $old_value && $new_value ) :
?>
<tr>
<td class="search-replace-row search-replace-narrow">
<?php echo esc_html( $change ['row'] ); ?>
</td>
<td class="search-replace-column">
<?php echo esc_html( $change ['column'] ); ?>
</td>
<td class="search-replace-old-value">
<?php echo wp_kses( $old_value, [ 'span' => [ 'class' => [] ] ] ); ?>
</td>
<td class="search-replace-new-value">
<?php echo wp_kses( $new_value, [ 'span' => [ 'class' => [] ] ] ); ?>
</td>
</tr>
<?php
endif;
endforeach;
?>
</tbody>
</table>
<?php endforeach; ?>
</div>
</div>
<?php
}
/**
* Show Message by Report
*
* @param array $report The list of all the changes made.
*
* @return void
*/
private function show_message_by_report( $report ) {
$msg = sprintf(
// translators: %s is the count of tables.
_n(
'%s table was processed. ',
'%s tables were processed. ',
$report['tables'],
'search-and-replace'
),
(int) $report['tables']
);
$msg .= sprintf(
// translators: %s is the count of selected cells after search in tables.
_n(
'%s cell needs to be updated.',
'%s cells need to be updated.',
$report['changes_count'],
'search-and-replace'
),
(int) $report['changes_count']
);
echo '<p>' . esc_html( $msg ) . '</p>';
}
/**
* Trims a given string to 50 chars before and after the search string, if the string is longer than 199 chars.
*
* @param string $needle
* @param string $haystack
* @param array $delimiter $delimiter[0]=start delimiter, $delimiter[1] = end delimiter.
*
* @return string The trimmed $haystack
*/
public function trim_search_results( $needle, $haystack, $delimiter ) {
// Ff result has <100 characters we return the whole string.
if ( strlen( $haystack ) < 100 ) {
return $haystack;
}
$trimmed_results = null;
// Get all occurrences of $needle with up to 50 chars front & back.
$matches = preg_match_all( '@.{0,50}' . $needle . '.{0,50}@', $haystack, $trimmed_results );
$return_value = '';
// Don't need to perform any action if no matches.
if ( ! $matches ) {
return $return_value;
}
for ( $i = 0; $i < $matches; $i ++ ) {
// Reset delimiter, might have been changed.
$local_delimiter = $delimiter;
// Check if the first trimmed result is the beginning of $haystack. if so remove leading delimiter.
if ( $i === 0 ) {
$pos = strpos( $haystack, $trimmed_results[0][ $i ] );
if ( $pos === 0 ) {
$local_delimiter[0] = '';
}
}
// Check if the last trimmed result is the end of $haystack. if so, remove trailing delimiter.
$last_index = $matches - 1;
if ( $i === $last_index ) {
$trimmed_result_length = strlen( $trimmed_results[0][ $i ] );
$substring = substr( $haystack, - $trimmed_result_length );
if ( $substring === $trimmed_results[0][ $i ] ) {
$local_delimiter[1] = '';
}
}
$return_value .= $local_delimiter[0] . $trimmed_results[0][ $i ] . $local_delimiter[1];
}
return $return_value;
}
/**
* Calls the file delivery in Class DatabaseExporter.
*
* @wp-hook init
*
* @return bool
*/
public function deliver_backup_file() {
// Retrieve the nonce value.
// @codingStandardsIgnoreStart
$nonce = isset( $_POST[ $this->nonce_name ] ) ?
filter_var( $_POST[ $this->nonce_name ], FILTER_SANITIZE_STRING )
: '';
// @codingStandardsIgnoreEnd
// If nonce has not been send, just return nothing else to do here.
// The method may be hooked to a wp action, so it's executed on every page request.
if ( ! $nonce ) {
return false;
}
// Die in case the nonce has been passed but not a valid one.
// @codingStandardsIgnoreLine
if ( ! wp_verify_nonce( $_POST[ $this->nonce_name ], $this->nonce_action ) ) {
wp_die( 'Cheating Uh?' );
}
$this->max_execution->set();
// Get the action to perform.
// @codingStandardsIgnoreLine
$action = isset( $_POST['action'] ) ? filter_var( $_POST['action'], FILTER_SANITIZE_STRING ) : '';
if ( 'download_file' !== $action ) {
return false;
}
$sql_file = '';
$compress = false;
// @codingStandardsIgnoreLine
if ( isset( $_POST['sql_file'] ) ) {
// @codingStandardsIgnoreLine
$sql_file = sanitize_file_name( $_POST['sql_file'] );
}
if ( ! $sql_file ) {
wp_die( esc_html__( 'The file you are looking for doesn\'t exists.', 'search-and-replace' ) );
}
// If file name contains path or does not end with '.sql' exit.
// @ToDo create a function to prevent traversal path.
$ext = strrchr( $sql_file, '.' );
if ( false !== strpos( $sql_file, '/' ) || '.sql' !== $ext ) {
wp_die( 'Cheating Uh?' );
}
// @codingStandardsIgnoreLine
if ( isset( $_POST['compress'] ) ) {
// @codingStandardsIgnoreLine
$compress = (bool) filter_var( $_POST['compress'], FILTER_VALIDATE_BOOLEAN );
}
// Download the file.
$this->dbe->deliver_backup( $sql_file, $compress );
$this->max_execution->restore();
return true;
}
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists