array( 'budget' => 8, 'chunk' => 2097152, 'rows' => 250, ), 'balanced' => array( 'budget' => 20, 'chunk' => 8388608, 'rows' => 1000, ), 'turbo' => array( 'budget' => 40, 'chunk' => 33554432, 'rows' => 3000, ), ); /** * Default values. * * @return array */ public static function defaults() { return array( 'max_import' => 0, 'max_backup' => 0, 'mode' => 'balanced', 'speed_cap' => 0, 'schedule' => 'off', 'keep' => 5, 'custom_exclude' => '', 'remove_data' => 0, ); } /** * All settings merged with defaults. * * @return array */ public static function all() { $saved = get_option( self::OPTION, array() ); return wp_parse_args( is_array( $saved ) ? $saved : array(), self::defaults() ); } /** * One setting. * * @param string $key Key. * @return mixed */ public static function get( $key ) { $all = self::all(); return isset( $all[ $key ] ) ? $all[ $key ] : null; } /** * Active performance profile, capped by the server's execution limit. * * @return array */ public static function profile() { $mode = self::get( 'mode' ); $profile = isset( self::PROFILES[ $mode ] ) ? self::PROFILES[ $mode ] : self::PROFILES['balanced']; $max = (int) ini_get( 'max_execution_time' ); if ( $max > 0 ) { $profile['budget'] = max( 3, min( $profile['budget'], $max - 5 ) ); } /** * Filters the performance profile. * * @param array $profile budget (seconds), chunk (bytes), rows (per query). */ return apply_filters( 'shiftbox_profile', $profile ); } /** * Largest upload chunk the server will accept for one request. * * @return int Bytes. */ public static function upload_chunk() { $server = (int) wp_max_upload_size(); $cap = $server > 0 ? (int) floor( $server * 0.9 ) - 65536 : 1048576; $chunk = min( self::profile()['chunk'], $cap ); return max( 262144, $chunk ); } /** * Converts a value and unit to bytes; 0 means unlimited. * * @param mixed $value Number. * @param string $unit MB or GB. * @return int */ public static function to_bytes( $value, $unit ) { $value = (float) $value; if ( $value <= 0 ) { return 0; } $mult = ( 'GB' === $unit ) ? 1073741824 : 1048576; return (int) round( $value * $mult ); } /** * Splits bytes into a value and unit for the settings form. * * @param int $bytes Bytes. * @return array value, unit. */ public static function split( $bytes ) { $bytes = (int) $bytes; if ( $bytes <= 0 ) { return array( 10, 'GB' ); } if ( 0 === $bytes % 1073741824 ) { return array( $bytes / 1073741824, 'GB' ); } return array( round( $bytes / 1048576, 2 ), 'MB' ); } /** * Human size. * * @param int $bytes Bytes. * @return string */ public static function human( $bytes ) { return $bytes > 0 ? size_format( $bytes, $bytes >= 1073741824 ? 2 : 1 ) : __( 'Unlimited', 'shiftbox' ); } /** * Sanitize callback for register_setting. * * @param array $input Raw input. * @return array */ public static function sanitize( $input ) { $input = is_array( $input ) ? $input : array(); $out = self::defaults(); foreach ( array( 'max_import', 'max_backup' ) as $key ) { // WordPress runs this callback twice on the very first save; the second pass // receives already-sanitized bytes, so keep them instead of resetting to 0. if ( ! isset( $input[ $key . '_value' ] ) && ! isset( $input[ $key . '_unlimited' ] ) && isset( $input[ $key ] ) ) { $out[ $key ] = max( 0, (int) $input[ $key ] ); continue; } $unlimited = ! empty( $input[ $key . '_unlimited' ] ); $unit = ( isset( $input[ $key . '_unit' ] ) && 'GB' === $input[ $key . '_unit' ] ) ? 'GB' : 'MB'; $num = isset( $input[ $key . '_value' ] ) ? (float) $input[ $key . '_value' ] : 0; $out[ $key ] = $unlimited ? 0 : self::to_bytes( $num, $unit ); } $out['mode'] = ( isset( $input['mode'] ) && isset( self::PROFILES[ $input['mode'] ] ) ) ? $input['mode'] : 'balanced'; $out['speed_cap'] = isset( $input['speed_cap'] ) ? max( 0, min( 10000, (float) $input['speed_cap'] ) ) : 0; $out['schedule'] = ( isset( $input['schedule'] ) && in_array( $input['schedule'], array( 'off', 'daily', 'weekly' ), true ) ) ? $input['schedule'] : 'off'; $out['keep'] = isset( $input['keep'] ) ? max( 1, min( 100, (int) $input['keep'] ) ) : 5; $lines = isset( $input['custom_exclude'] ) ? preg_split( '/\R/', (string) $input['custom_exclude'] ) : array(); $clean = array(); foreach ( $lines as $line ) { $line = trim( str_replace( '\\', '/', sanitize_text_field( $line ) ), "/ \t" ); if ( '' !== $line && false === strpos( $line, '..' ) ) { $clean[] = $line; } } $out['custom_exclude'] = implode( "\n", array_unique( $clean ) ); $out['remove_data'] = empty( $input['remove_data'] ) ? 0 : 1; Shiftbox_Scheduler::reschedule( $out['schedule'] ); return $out; } }