Search
Search
Search
Search
Information
Information
Light
Dark
Open actions menu
Basic upload method
Bypass upload method
Tips!
If you encounter an error (by firewall) while uploading using both methods,
try changing extension of the file before uploading it and rename it right after.
This uploader supports multiple file upload.
Submit
~
var
www
nea-2020.wpress.dk
httpdocs
wp-content
plugins
image-hopper
src
File Content:
bootstrap.php
<?php namespace ImageHopper\ImageHopper; use ImageHopper\ImageHopper\API\ImageManager; use ImageHopper\ImageHopper\Fields\ImageHopperField; use ImageHopper\ImageHopper\Fields\ImageHopperPostField; use ImageHopper\ImageHopper\Fields\SlimField; use ImageHopper\ImageHopper\Fields\SlimPostField; use ImageHopper\ImageHopper\Fields\FieldConversion; use ImageHopper\ImageHopper\FirstParty\AdvancedPostCreation; use ImageHopper\ImageHopper\FirstParty\Capabilities; use ImageHopper\ImageHopper\FirstParty\Dropbox; use ImageHopper\ImageHopper\FirstParty\RenameUploads; use ImageHopper\ImageHopper\FirstParty\TrackEntryInField; use ImageHopper\ImageHopper\FirstParty\UserRegistration; use ImageHopper\ImageHopper\FirstParty\Webhook; use ImageHopper\ImageHopper\FirstParty\Zapier; use ImageHopper\ImageHopper\Helpers\ArrayHelper; use ImageHopper\ImageHopper\Helpers\FileHelper; use ImageHopper\ImageHopper\Licensing\LicensingChecks; use ImageHopper\ImageHopper\ThirdParty\Avatars\BasicUserAvatars; use ImageHopper\ImageHopper\ThirdParty\Avatars\SimpleLocalAvatars; use ImageHopper\ImageHopper\ThirdParty\Avatars\WpUserAvatars; use ImageHopper\ImageHopper\ThirdParty\GravityView\AdvancedFilter; use ImageHopper\ImageHopper\ThirdParty\GravityView\EditEntry; use ImageHopper\ImageHopper\ThirdParty\GravityView\Fields\ImageHopper; use ImageHopper\ImageHopper\ThirdParty\GravityView\Fields\ImageHopperPost; use ImageHopper\ImageHopper\ThirdParty\GravityFlow\FormConnector; use ImageHopper\ImageHopper\ThirdParty\GravityView\MergeTags; use ImageHopper\ImageHopper\ThirdParty\WooCommerce\GravityForms; /** * @package Image Hopper * @copyright Copyright (c) 2025, Image Hopper * @license https://opensource.org/licenses/gpl-3.0.php GNU Public License */ /* Exit if accessed directly */ if ( ! defined( 'ABSPATH' ) ) { exit; } /** * Class ImageHopperAddOn * * @package ImageHopper\ImageHopper * * @since 1.0 */ class ImageHopperAddOn extends \GFAddOn { use LicensingChecks; protected $_version = IMAGE_HOPPER_ADDON_VERSION; protected $_min_gravityforms_version = '2.4'; protected $_slug = 'image-hopper'; protected $_path = IMAGE_HOPPER_ADDON_PATH; protected $_full_path = IMAGE_HOPPER_ADDON_FILE; protected $_title = 'Image Hopper for Gravity Forms'; protected $_short_title = 'Image Hopper'; protected $_store_url = 'https://imagehopper.tech/?api=1'; protected $_capabilities = [ 'image-hopper_edit_settings', 'image-hopper_uninstall' ]; protected $_capabilities_settings_page = 'image-hopper_edit_settings'; protected $_capabilities_uninstall = 'image-hopper_uninstall'; /** * @var ImageHopperAddOn $_instance If available, contains an instance of this class. * * @since 1.0.0 */ protected static $_instance = null; /** * Returns an instance of this class, and stores it in the $_instance property. * * @return self $_instance An instance of this class. * * @since 1.0.0 */ public static function get_instance() { if ( self::$_instance === null ) { self::$_instance = new self(); } return self::$_instance; } /** * Include the field early so it is available when entry exports are being performed * * @since 1.0.0 */ public function pre_init() { parent::pre_init(); if ( $this->is_gravityforms_supported() && class_exists( 'GF_Field' ) ) { try { \GF_Fields::register( new ImageHopperField() ); \GF_Fields::register( new ImageHopperPostField() ); /* Add backwards compatibility for Slim Image Cropper users if they've removed the plugin */ if ( ! class_exists( 'GFSlimAddOn' ) ) { \GF_Fields::register( new SlimField() ); \GF_Fields::register( new SlimPostField() ); } } catch ( \Exception $e ) { /* do nothing, as it is highly likely the fields are already registered */ } } add_action( 'gfpdf_fully_loaded', function () { ( \ImageHopper\ImageHopper\ThirdParty\GravityPdf\Fields::get_instance() )->init(); } ); $this->fix_weglot_autoredirect_upload_bug(); } /** * Runs on the WordPress "init" hook * * @since 1.0.0 */ public function init() { global $wp_version; parent::init(); $this->setup_plugin_updater(); /* First party support */ add_filter( 'gform_notification', [ $this, 'attach_images_to_notification' ], 10, 3 ); add_filter( 'gform_field_types_delete_files', [ $this, 'register_field_types_for_file_deletion' ] ); add_filter( 'gform_custom_merge_tags', [ $this, 'ui_register_count_merge_tag' ], 10, 3 ); add_filter( 'gform_merge_tag_value_pre_calculation', [ $this, 'add_count_merge_tag_calculation_support' ], 10, 6 ); add_filter( 'gform_is_valid_url', [ $this, 'validate_url' ], 10, 2 ); ( RenameUploads::get_instance() )->init(); ( TrackEntryInField::get_instance() )->init(); if ( class_exists( 'GF_Advanced_Post_Creation' ) ) { ( new AdvancedPostCreation() )->init(); } /* User Registration */ if ( function_exists( 'gf_user_registration' ) ) { $ur = UserRegistration::get_instance(); $ur->init(); } /* Zapier */ if ( class_exists( 'GF_Zapier' ) ) { ( new Zapier() )->init(); } /* Webhook */ if ( class_exists( 'GF_Webhooks' ) ) { ( new Webhook() )->init(); } /* Add webp support to multisite */ if ( is_multisite() && version_compare( $wp_version, '5.8', '>=' ) ) { add_filter( 'upload_mimes', [ $this, 'add_webp_support_to_multisite' ], 20 ); } if ( class_exists( 'GF_Dropbox' ) ) { ( Dropbox::get_instance() )->init(); } /* Third party plugin support: Gravity Flow, GravityView, Nested Forms, WooCommerce Gravity Forms */ add_filter( 'gform_get_form_filter', [ $this, 'maybe_inject_hidden_uploaded_files_field' ], 10, 2 ); add_filter( 'gravityflow_post_process_workflow', [ $this, 'reset_temporary_upload_info' ] ); add_action( 'gform_post_process', [ $this, 'reset_local_upload_info' ] ); ( new FormConnector() )->init(); /* Add support for Hide My WP Ghost Plugin https://hidemywpghost.com/ */ if ( class_exists( 'HMWP_Classes_Tools' ) ) { ( new \ImageHopper\ImageHopper\ThirdParty\HideMyWpGhost\FilePath() )->init(); } /* Add support for Hide My WP Plugin https://codecanyon.net/item/hide-my-wp-amazing-security-plugin-for-wordpress/4177158 */ if ( defined( 'HMW_VERSION' ) && class_exists( '\HideMyWP' ) ) { ( new \ImageHopper\ImageHopper\ThirdParty\HideMyWp\FilePath() )->init(); } /* Add support for the WP Data Tables Gravity Forms plugin */ if ( class_exists( '\WDTGravityIntegration\Plugin' ) ) { ( new \ImageHopper\ImageHopper\ThirdParty\WpDataTables\GravityForms() )->init(); } /* GP Media Library support */ add_filter( 'gpml_supported_field_types', [ $this, 'gp_media_library_supported_fields' ] ); /* Woo GF support if Woo is > 2.7 */ if ( method_exists( 'WC_GFPA_Compatibility', 'is_wc_version_gte_2_7' ) && \WC_GFPA_Compatibility::is_wc_version_gte_2_7() ) { $woogf = GravityForms::get_instance(); $woogf->init(); } /* Only load if GravityView is available */ if ( class_exists( 'GravityView_Plugin' ) ) { new ImageHopper(); new ImageHopperPost(); $edit_entry = new EditEntry(); $edit_entry->init(); ( new AdvancedFilter() )->init(); ( new MergeTags() )->init(); add_filter( 'gravityview/edit_entry/after_update', [ $this, 'reset_temporary_upload_info' ] ); add_filter( 'gravityview/template/fields_get_template_part', [ $this, 'use_gv_render_templates' ], 100 ); } /* User Registration and Avatar Support */ if ( class_exists( 'GF_User_Registration_Bootstrap' ) && apply_filters( 'image_hopper_auto_process_local_avatar_plugins', true ) ) { if ( class_exists( 'Simple_Local_Avatars' ) ) { ( new SimpleLocalAvatars() )->init(); } if ( function_exists( 'wp_user_avatars_get_plugin_url' ) ) { ( new WpUserAvatars() )->init(); } if ( class_exists( 'basic_user_avatars' ) ) { ( new BasicUserAvatars() )->init(); } } ( \ImageHopper\ImageHopper\ThirdParty\Siteground\SpeedOptimizer::get_instance() )->init(); ( \ImageHopper\ImageHopper\ThirdParty\GravityPerks\PageTransitions::get_instance() )->init(); ( \ImageHopper\ImageHopper\ThirdParty\GravityPerks\EntryBlocks::get_instance() )->init(); ( \ImageHopper\ImageHopper\ThirdParty\GravityKit\GravityImport::get_instance() )->init(); } /** * Runs on the WordPress "init_admin" hook * * @since 1.0.0 */ public function init_admin() { parent::init_admin(); add_filter( 'gform_tooltips', [ $this, 'add_tooltips' ] ); /* Register new Field editor settings for Image Hopper */ add_action( 'gform_field_standard_settings', [ $this, 'field_max_image_sizes_settings' ], 10, 2 ); add_action( 'gform_field_standard_settings', [ $this, 'field_max_number_files_settings' ], 10, 2 ); add_action( 'gform_field_standard_settings', [ $this, 'field_output_quality_settings' ], 10, 2 ); add_action( 'gform_field_advanced_settings', [ $this, 'field_minimum_image_size_settings' ], 10, 2 ); add_action( 'gform_field_advanced_settings', [ $this, 'field_minimum_image_size_warning_settings' ], 10, 2 ); /* Include crop image setting if not already available in the editor add-on */ if ( ! defined( 'IMAGE_HOPPER_EDITOR_ADDON_VERSION' ) || version_compare( IMAGE_HOPPER_EDITOR_ADDON_VERSION, '1.1.0', '>=' ) ) { add_action( 'image_hopper_field_max_image_sizes_post_display', [ $this, 'add_crop_field_setting' ] ); add_action( 'gform_field_advanced_settings', [ $this, 'add_upscale_field_setting' ], 10, 2 ); } /* Handle Notification attachments */ add_filter( 'gform_notification_ui_settings', [ $this, 'add_notification_ui_settings' ], 10, 3 ); /* Pre GF2.5 */ add_filter( 'gform_notification_settings_fields', [ $this, 'adjust_notification_ui_dependency' ], 10, 3 ); /* GF2.5+ */ ( FieldConversion::get_instance() )->init(); } /** * Runs on the WordPress "init" hook only for frontend requests * * @since 1.0.0 */ public function init_frontend() { parent::init_frontend(); /* Our endpoint for handling restore/revert/delete operations */ add_action( 'wp', [ $this, 'process_exterior_page' ], 5 ); } /** * @param $previous_version * * @return void */ public function upgrade( $previous_version ) { /* Add new capabilities to administrator user */ if ( version_compare( $previous_version, '2.16.0', '<' ) ) { ( Capabilities::get_instance() )->add_capabilities_to_users(); } } /** * Ensure Image Hopper settings are fully cleaned up on uninstall * * @return bool * * @since 1.4.0 */ public function uninstall() { delete_option( $this->license_key_status_option_name ); ( Capabilities::get_instance() )->remove_capabilities_from_users(); return true; } /** * Target for the after_plugin_row action hook. Checks whether the current version of Gravity Forms * is supported and outputs a message just below the plugin info on the plugins page. * * Include a license registration message if the plugin is not activated * * @param string $plugin_name The plugin filename. Immediately overwritten. * @param array $plugin_data An array of plugin data. * * @since 1.3.0 */ public function plugin_row( $plugin_name, $plugin_data ) { if ( ! $this->is_gravityforms_supported( $this->_min_gravityforms_version ) ) { $message = $this->plugin_message(); self::display_plugin_message( $message, true ); } if ( ! $this->is_license_valid( $this->get_plugin_setting( 'license_key' ) ) ) { $this->display_plugin_row_message( sprintf( /* translators: %$1s and %2$s are opening <a> tags. %$3s is a closing anchor tag */ __( '%1$sRegister%3$s your copy of Image Hopper to receive access to automatic upgrades and support. Need a license key? %2$sPurchase one now.%3$s', 'image-hopper' ), '<a href="' . esc_url( admin_url( 'admin.php?page=gf_settings&subview=' . $this->_slug ) ) . '">', '<a href="https://imagehopper.tech/#buy" target="_blank">', '</a>' ) ); } } /** * Output a message on the plugin row in the admin area * * @param string $message * * @since 1.3.0 */ public function display_plugin_row_message( $message ) { global $wp_version; $colspan = version_compare( $wp_version, '5.5', '>=' ) ? 4 : 3; $is_active = is_network_admin() ? is_plugin_active_for_network( $this->_path ) : is_plugin_active( $this->_path ); ?> <tr class="plugin-update-tr <?php echo $is_active ? 'active' : 'inactive'; ?>"> <td colspan="<?php echo esc_attr( $colspan ); ?>" class="colspanchange" style="padding: 0"> <div class="update-message notice inline notice-error notice-alt"> <p><?php echo wp_kses_post( $message ); ?></p> </div> </td> </tr> <?php } /** * Returns the message that will be displayed if the current version of Gravity Forms is not supported. * * @since 1.3.0 */ public function plugin_message() { /* translators: %$1s is a software version number. %2$s and %3$s are opening and closing HTML anchor tags */ return sprintf( esc_html__( 'Gravity Forms %1$s is required. Activate it now or %2$spurchase it today!%3$s', 'image-hopper' ), $this->_min_gravityforms_version, "<a href='https://rocketgenius.pxf.io/c/1211356/445235/7938'>", '</a>' ); } /** * Return the plugin's icon for the plugin/form settings menu. * * @since 1.4 * * @return string */ public function get_menu_icon() { return 'dashicons-format-image'; } /** * Mimics Gravity Forms process_exterior_page() method and processes actions for Image HOpper * * @since 1.0.0 */ public function process_exterior_page() { /* phpcs:ignore WordPress.Security.NonceVerification.Recommended */ if ( rgempty( 'gf_page', $_GET ) && rgempty( 'ih_page', $_GET ) ) { return; } $is_upload_page = $_SERVER['REQUEST_METHOD'] === 'POST' && rgget( 'gf_page' ) === \GFCommon::get_upload_page_slug(); if ( $is_upload_page ) { $tmp_image_manager = new ImageManager(); switch ( rgget( 'ih_page' ) ) { case 'restore': $tmp_image_manager->restore(); break; case 'revert': $tmp_image_manager->revert(); break; default: $tmp_image_manager->preflight(); } } } /** * Register our field JavaScript * * @return array * * @since 1.0.0 */ public function scripts() { $filepond_plugin_to_load = ! defined( 'IMAGE_HOPPER_EDITOR_ADDON_VERSION' ) || version_compare( '2.0.0', IMAGE_HOPPER_EDITOR_ADDON_VERSION, '>' ) ? 'V1' : 'V2'; $scripts = [ [ 'handle' => 'image_hopper_js', 'src' => $this->get_base_url( IMAGE_HOPPER_ADDON_FILE ) . '/dist/filepond' . $filepond_plugin_to_load . '.build.js', 'version' => defined( 'WP_DEBUG' ) && WP_DEBUG === true ? time() : $this->_version, 'deps' => [ 'gform_gravityforms' ], 'enqueue' => [ [ 'field_types' => [ 'image_hopper', 'image_hopper_post', ], ], ], 'strings' => $this->get_strings(), ], [ 'handle' => 'image_hopper_js_modern', 'src' => $this->get_base_url( IMAGE_HOPPER_ADDON_FILE ) . '/dist/image-hopper.js', 'version' => defined( 'WP_DEBUG' ) && WP_DEBUG === true ? time() : $this->_version, 'deps' => [ 'image_hopper_js' ], 'enqueue' => [ [ 'field_types' => [ 'image_hopper', 'image_hopper_post', ], ], ], ], ]; $scripts = apply_filters( 'image_hopper_scripts', $scripts, $this ); return array_merge( parent::scripts(), $scripts ); } /** * Set the module tags to load modern JS * * @param string $tag The generated script tag * @param string $handle The JS registered ID * * @return string * * @since 2.0 * * @deprecated 2.4.6. Including as a module breaks CDNs due to CORS */ public function register_javascript_module( $tag, $handle ) { switch ( $handle ) { case 'image_hopper_js_modern': $tag = str_replace( '<script ', '<script type="module" ', $tag ); break; } return $tag; } /** * @return array * * @since 2.0 */ protected function get_strings() { global $wp_version; return [ 'wpVersion' => $wp_version, 'gfVersion' => \GFForms::$version, 'process_endpoint' => trailingslashit( site_url() ) . '?gf_page=' . \GFCommon::get_upload_page_slug(), 'pluginUrl' => plugin_dir_url( IMAGE_HOPPER_ADDON_FILE ), 'l10n' => [ 'labelFormSubmitWaitForUpload' => esc_html__( 'Please wait for the uploading to complete', 'image-hopper' ), 'labelDeleteFileConfirm' => str_replace( ''', "'", esc_html__( "Would you like to delete this file? 'Cancel' to stop. 'OK' to delete", 'image-hopper' ) ), 'labelIdleIntro' => esc_html__( 'Drop files here or', 'image-hopper' ), 'labelIdleButton' => esc_html__( 'Select files', 'image-hopper' ), 'labelInvalidField' => esc_html__( 'Field contains invalid files', 'image-hopper' ), 'labelFileWaitingForSize' => esc_html__( 'Waiting for size', 'image-hopper' ), 'labelFileSizeNotAvailable' => esc_html__( 'Size not available', 'image-hopper' ), 'labelFileLoading' => esc_html__( 'Loading', 'image-hopper' ), 'labelFileLoadError' => esc_html__( 'Error during load', 'image-hopper' ), 'labelFileProcessing' => esc_html__( 'Uploading', 'image-hopper' ), 'labelFileProcessingComplete' => esc_html__( 'Upload complete', 'image-hopper' ), 'labelFileProcessingAborted' => esc_html__( 'Upload cancelled', 'image-hopper' ), 'labelFileProcessingError' => esc_html__( 'Error during upload', 'image-hopper' ), 'labelFileProcessingRevertError' => esc_html__( 'Error during revert', 'image-hopper' ), 'labelFileRemoveError' => esc_html__( 'Error during remove', 'image-hopper' ), 'labelTapToCancel' => esc_html__( 'tap to cancel', 'image-hopper' ), 'labelTapToRetry' => esc_html__( 'tap to retry', 'image-hopper' ), 'labelTapToUndo' => esc_html__( 'tap to undo', 'image-hopper' ), 'labelButtonRemoveItem' => esc_html__( 'Remove', 'image-hopper' ), 'labelButtonAbortItemLoad' => esc_html__( 'Abort', 'image-hopper' ), 'labelButtonRetryItemLoad' => esc_html__( 'Retry', 'image-hopper' ), 'labelButtonAbortItemProcessing' => esc_html__( 'Cancel', 'image-hopper' ), 'labelButtonUndoItemProcessing' => esc_html__( 'Undo', 'image-hopper' ), 'labelButtonRetryItemProcessing' => esc_html__( 'Retry', 'image-hopper' ), 'labelButtonProcessItem' => esc_html__( 'Upload', 'image-hopper' ), 'labelMaxFileSizeExceeded' => esc_html__( 'File is too large', 'image-hopper' ), /* translators: %s is replaced with a number in MB eg. 10MB */ 'labelMaxFileSize' => sprintf( esc_html__( 'Maximum file size is %s', 'image-hopper' ), '{filesize}' ), 'labelMaxTotalFileSizeExceeded' => esc_html__( 'File exceeds size limit', 'image-hopper' ), /* translators: %s is replaced with a number in MB eg. 10MB */ 'labelMaxTotalFileSize' => sprintf( esc_html__( 'Maximum total file size is %s', 'image-hopper' ), '{filesize}' ), 'labelFileTypeNotAllowed' => esc_html__( 'This type of file is not allowed.', 'image-hopper' ), /* translators: %1$s is replaced with a comma-separated list of supported file types (all except the very last item in the list), and %2$s is the very last item in the supported file types list */ 'fileValidateTypeLabelExpectedTypes' => sprintf( esc_html__( 'Expects %1$s or %2$s', 'image-hopper' ), '{allButLastType}', '{lastType}' ), 'imageValidateSizeLabelFormatError' => esc_html__( 'Image type not supported', 'image-hopper' ), 'imageValidateSizeLabelImageSizeTooSmall' => esc_html__( 'Image is too small', 'image-hopper' ), 'imageValidateSizeLabelImageSizeTooBig' => esc_html__( 'Image is too big', 'image-hopper' ), /* translators: %1$s is the width of the image in pixels and %2$s is the height */ 'imageValidateSizeLabelExpectedMinSize' => sprintf( esc_html__( 'Minimum size is %1$s × %2$spx', 'image-hopper' ), '{minWidth}', '{minHeight}' ), /* translators: %1$s is the width of the image in pixels and %2$s is the height */ 'imageValidateSizeLabelExpectedMaxSize' => sprintf( esc_html__( 'Maximum size is %1$s × %2$spx', 'image-hopper' ), '{maxWidth}', '{maxHeight}' ), 'imageValidateSizeLabelImageResolutionTooLow' => esc_html__( 'Resolution is too low', 'image-hopper' ), 'imageValidateSizeLabelImageResolutionTooHigh' => esc_html__( 'Resolution is too high', 'image-hopper' ), /* translators: %s is a number in pixels */ 'imageValidateSizeLabelExpectedMinResolution' => sprintf( esc_html__( 'Minimum resolution is %s', 'image-hopper' ), '{minResolution}' ), /* translators: %s is a number in pixels */ 'imageValidateSizeLabelExpectedMaxResolution' => sprintf( esc_html__( 'Maximum resolution is %s', 'image-hopper' ), '{maxResolution}' ), /* translators: %s is a number */ 'imageValidationMaxFilesReached' => esc_html__( 'Maximum number of files (%s) exceeded.', 'image-hopper' ), /* translators: %1$s is the name of the image, and %2$s and %3$s is the image width and height in pixels */ 'imageValidationMinimumImageSizeWarning' => esc_html__( 'The image "%1$s" is less than %2$s × %3$spx. Consider uploading a higher resolution image.', 'image-hopper' ), /* translators: %1$s is the name of the image, and %2$s is the image width in pixels */ 'imageValidationMinimumImageSizeWidthWarning' => esc_html__( 'The image "%1$s" is less than %2$spx wide. Consider uploading a higher resolution image.', 'image-hopper' ), /* translators: %1$s is the name of the image, and %2$s is the image height in pixels */ 'imageValidationMinimumImageSizeHeightWarning' => esc_html__( 'The image "%1$s" is less than %2$spx high. Consider uploading a higher resolution image.', 'image-hopper' ), 'imageReorderInstructions' => esc_html__( 'To reorder the image use the keyboard arrows, "j" or "k" characters, or drag and drop an image.', 'image-hopper' ), /* translators: %1$s is the position of the image in the list, and %2$s is the total number of images in the list */ 'imageReorderActiveFeedback' => esc_html__( 'Current position in list: %1$s of %2$s', 'image-hopper' ), ], ]; } /** * Register our field CSS * * @return array * * @since 1.0.0 */ public function styles() { $styles = [ [ 'handle' => 'image_hopper_css', 'src' => $this->get_base_url( IMAGE_HOPPER_ADDON_FILE ) . '/dist/uploader.style.build.css', 'version' => defined( 'WP_DEBUG' ) && WP_DEBUG === true ? time() : $this->_version, 'enqueue' => [ 'field_types' => [ 'image_hopper', 'image_hopper_post', ], ], ], ]; $styles = apply_filters( 'image_hopper_styles', $styles, $this ); return array_merge( parent::styles(), $styles ); } /** * Add field settings tooltip(s) * * @param array $tooltips * * @return array * * @since 1.1.0 */ public function add_tooltips( $tooltips ) { /* translators: %1$s is replaced with a <br> tag */ $tooltips['ih_downscale_images'] = '<h6>' . esc_html__( 'Downscale Images', 'image-hopper' ) . '</h6>' . sprintf( esc_html__( 'For when you don\'t need that huge 10MB image clogging up your server. If you would like images set to a specific aspect ratio, use the following as a guide:%1$s 1:1 = 1000 x 1000%1$s 16:9 = 1280 x 720%1$s 4:3 = 1024 x 768%1$s 3:2 = 1080 x 720.', 'image-hopper' ), '<br>' ); $tooltips['ih_crop_to_dimensions'] = '<h6>' . esc_html__( 'Crop to Dimensions', 'image-hopper' ) . '</h6>' . esc_html__( 'When enabled, the image will be cropped to the width and height specified (unless the image is already smaller, in which case it will be constrained to the aspect ratio).', 'image-hopper' ); if ( defined( 'IMAGE_HOPPER_EDITOR_ADDON_VERSION' ) ) { $tooltips['ih_crop_to_dimensions'] .= ' ' . esc_html__( 'If you enable the Image Editor, the crop box will be locked to the same aspect ratio.', 'image-hopper' ); } $tooltips['ih_upscale_image'] = '<h6>' . esc_html__( 'Upscale Image', 'image-hopper' ) . '</h6>' . esc_html__( 'When enabled, images smaller than the crop size dimensions will automatically upscale to match. This ensures uniformity for all images, but does effect the overall image quality when upscaling occurs.', 'image-hopper' ); $tooltips['ih_minimum_image_size'] = '<h6>' . esc_html__( 'Minimum Image Size', 'image-hopper' ) . '</h6>' . esc_html__( 'Prevent images being uploaded if they are below the minimum threshold you have set.', 'image-hopper' ); $tooltips['ih_minimum_image_size_warning'] = '<h6>' . esc_html__( 'Downscale Images', 'image-hopper' ) . '</h6>' . esc_html__( 'Show a warning if images are below the minimum threshold you have set. This setting does not stop the image from being uploaded.', 'image-hopper' ); return $tooltips; } /** * Output the mark-up for the Max Image Size Field setting * * @param int $position The position the settings should be located at. * @param int $form_id The ID of the form currently being edited. * * @since 1.0.0 */ public function field_max_image_sizes_settings( $position, $form_id ) { if ( $position === 25 ) { ?> <li class="image_hopper_max_image_sizes field_setting"> <label for="input_maximum_dimensions" style="display:block;" class="section_label"> <?php esc_html_e( 'Downscale Images', 'image-hopper' ); ?> <?php gform_tooltip( 'ih_downscale_images' ); ?> </label> <small><?php esc_html_e( 'Automatically resizes images to fit within the dimensions set (in pixels).', 'image-hopper' ); ?></small> <div id="input_maximum_dimensions"> <?php esc_html_e( 'Width', 'image-hopper' ); ?> <input id="input_maximum_width" type="number" style="max-width:5rem" class="fieldwidth-1" onkeyup="SetFieldProperty('inputWidth', this.value);" onchange="SetFieldProperty('inputWidth', this.value);" /> <span style="padding-left: 0.25rem"><?php esc_html_e( 'Height', 'image-hopper' ); ?></span> <input id="input_maximum_height" style="max-width:5rem" type="number" class="fieldwidth-1" onkeyup="SetFieldProperty('inputHeight', this.value);" onchange="SetFieldProperty('inputHeight', this.value);" /> <?php do_action( 'image_hopper_field_max_image_sizes_post_display', $form_id ); ?> </div> </li> <?php } } /** * Output the mark-up for the Max Number of Files Field setting * * @param int $position The position the settings should be located at. * @param int $form_id The ID of the form currently being edited. * * @since 1.0.0 */ public function field_max_number_files_settings( $position, $form_id ) { if ( $position === 25 ) { ?> <li class="image_hopper_max_number_files field_setting"> <label for="input_maximum_files_uploaded" style="display:block;" class="section_label"> <?php esc_html_e( 'Maximum Number of Files', 'image-hopper' ); ?> <?php gform_tooltip( 'form_field_max_files' ); ?> </label> <input id="input_maximum_files_uploaded" style="width:5rem" type="number" min="1" onkeyup="SetFieldProperty('maxFiles', this.value);" onchange="SetFieldProperty('maxFiles', this.value);" /> </li> <?php } } /** * Output the mark-up for the Output Quality Field setting * * @param int $position The position the settings should be located at. * @param int $form_id The ID of the form currently being edited. * * @since 1.0.0 */ public function field_output_quality_settings( $position, $form_id ) { if ( $position === 25 ) { ?> <li class="image_hopper_output_quality field_setting"> <label for="input_output_quality" style="display:block;" class="section_label"> <?php esc_html_e( 'Output Quality', 'image-hopper' ); ?> </label> <input id="input_output_quality" style="width:5rem" type="number" min="1" max="100" placeholder="90" onkeyup="SetFieldProperty('outputQuality', this.value);" onchange="SetFieldProperty('outputQuality', this.value);" /> <div> <small><?php esc_html_e( 'A value between 0 and 100, where 100 is the best quality and 0 the worst.', 'image-hopper' ); ?></small> </div> </li> <?php } } /** * Include crop setting next to the Downsize Image setting * * @since 1.5 */ public function add_crop_field_setting() { ob_start(); ?> <input type="checkbox" id="input_enable_crop_to_size" onclick="SetFieldProperty('cropToSize', this.checked); ToggleUpscaleImage(this.checked)" onkeypress="SetFieldProperty('cropToSize', this.checked);ToggleUpscaleImage(this.checked)" /> <label for="input_enable_crop_to_size" class="inline"> <?php esc_html_e( 'Crop to dimensions', 'image-hopper' ); ?> <?php gform_tooltip( 'ih_crop_to_dimensions' ); ?> </label> <?php /* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped */ echo ob_get_clean(); } /** * Output the mark-up for the Upscale field setting * * @param int $position The position the settings should be located at. * @param int $form_id The ID of the form currently being edited. * * @since 1.5.0 */ public function add_upscale_field_setting( $position, $form_id ) { if ( $position === 450 ) { ?> <li class="image_hopper_upscale_field field_setting"> <input type="checkbox" id="editor_enable_upscale_image" onclick="SetFieldProperty('upscaleImageToCropSize', this.checked)" onkeypress="SetFieldProperty('upscaleImageToCropSize', this.checked);" /> <label for="editor_enable_upscale_image" class="inline"> <?php esc_html_e( 'Upscale to crop dimensions if image too small', 'image-hopper' ); ?> <?php gform_tooltip( 'ih_upscale_image' ); ?> </label> </li> <?php } } /** * Output the mark-up for the Minimum Image Size Field setting * * @param int $position The position the settings should be located at. * @param int $form_id The ID of the form currently being edited. * * @since 1.5.0 */ public function field_minimum_image_size_settings( $position, $form_id ) { if ( $position === 450 ) { ?> <li class="image_hopper_minimum_image_size field_setting"> <input type="checkbox" id="input_minimum_image_size" onclick="SetFieldProperty('inputMinImageSize', this.checked); ToggleMinimumImageSize(this.checked)" onkeypress="SetFieldProperty('inputMinImageSize', this.checked);ToggleMinimumImageSize(this.checked)" /> <label for="input_minimum_image_size" class="inline"> <?= esc_html__( 'Enable Minimum Image Size', 'image-hopper' ); ?><?php gform_tooltip( 'ih_minimum_image_size' ); ?> </label> <div id="input_minimum_dimensions" style="display:none"> <label for="input_minimum_width"><?php esc_html_e( 'Width', 'image-hopper' ); ?></label> <input id="input_minimum_width" type="number" style="max-width:5rem" class="fieldwidth-1" onkeyup="SetFieldProperty('inputMinImageSizeWidth', this.value);" onchange="SetFieldProperty('inputMinImageSizeWidth', this.value);" /> <label for="input_minimum_height" style="padding-left: 0.25rem"><?php esc_html_e( 'Height', 'image-hopper' ); ?></label> <input id="input_minimum_height" style="max-width:5rem" type="number" class="fieldwidth-1" onkeyup="SetFieldProperty('inputMinImageSizeHeight', this.value);" onchange="SetFieldProperty('inputMinImageSizeHeight', this.value);" /> </div> </li> <?php } } /** * Output the mark-up for the Minimum Image Size Warning Field setting * * @param int $position The position the settings should be located at. * @param int $form_id The ID of the form currently being edited. * * @since 1.5.0 */ public function field_minimum_image_size_warning_settings( $position, $form_id ) { if ( $position === 450 ) { ?> <li class="image_hopper_minimum_image_size_warning field_setting"> <input type="checkbox" id="input_minimum_image_size_warning" onclick="SetFieldProperty('inputMinImageSizeWarning', this.checked); ToggleMinimumImageSizeWarning(this.checked)" onkeypress="SetFieldProperty('inputMinImageSizeWarning', this.checked);ToggleMinimumImageSizeWarning(this.checked)" /> <label for="input_minimum_image_size_warning" class="inline"> <?= esc_html__( 'Enable Minimum Image Size Warning', 'image-hopper' ); ?><?php gform_tooltip( 'ih_minimum_image_size_warning' ); ?> </label> <div id="input_minimum_warning_dimensions" style="display:none"> <label for="input_minimum_warning_width"><?php esc_html_e( 'Width', 'image-hopper' ); ?></label> <input id="input_minimum_warning_width" type="number" style="max-width:5rem" class="fieldwidth-1" onkeyup="SetFieldProperty('inputMinImageSizeWarningWidth', this.value);" onchange="SetFieldProperty('inputMinImageSizeWarningWidth', this.value);" /> <label for="input_minimum_warning_height" style="padding-left: 0.25rem"><?php esc_html_e( 'Height', 'image-hopper' ); ?></label> <input id="input_minimum_warning_height" style="max-width:5rem" type="number" class="fieldwidth-1" onkeyup="SetFieldProperty('inputMinImageSizeWarningHeight', this.value);" onchange="SetFieldProperty('inputMinImageSizeWarningHeight', this.value);" /> </div> </li> <?php } } /** * Configures the settings which should be rendered on the add-on settings tab. * * @return array * * @since 1.0.0 */ public function plugin_settings_fields() { $is_gf25_or_greater = version_compare( \GFCommon::$version, '2.5-beta1', '>=' ); return [ [ 'title' => esc_html__( 'Image Hopper Add-On Settings', 'image-hopper' ), 'fields' => apply_filters( 'image_hopper_global_setting_fields', [ [ 'name' => 'license_key', 'label' => esc_html__( 'License Key', 'image-hopper' ), 'type' => 'text', 'input_type' => 'password', 'class' => 'large gform-admin-input', 'validation_callback' => [ $this, 'license_validation' ], 'after_input' => $is_gf25_or_greater ? [ $this, 'license_display_license_status_gf25' ] : $this->license_display_license_status_pre_gf25(), 'feedback_callback' => $is_gf25_or_greater ? [ $this, 'is_license_valid' ] : '', ], ], $this ), ], ]; } /** * If there's an Image Hopper field on the form but no multi-file upload field, insert the required hidden field * into the form. * * @param string $html * @param array $form * * @return string * * @since 1.0.0 */ public function maybe_inject_hidden_uploaded_files_field( $html, $form ) { if ( count( \GFAPI::get_fields_by_type( $form, [ 'image_hopper', 'image_hopper_post' ] ) ) === 0 || strpos( $html, 'gform_uploaded_files' ) !== false ) { return $html; } $input = "<input type='hidden' name='gform_uploaded_files' id='gform_uploaded_files_" . $form['id'] . "' value='' />"; return str_replace( '</form>', $input . '</form>', $html ); } /** * Reset Gravity Forms tmp uploaded files store * * @param array $form * * @since 1.0.0 */ public function reset_temporary_upload_info( $form ) { if ( isset( \GFFormsModel::$uploaded_files[ $form['id'] ] ) ) { unset( \GFFormsModel::$uploaded_files[ $form['id'] ] ); } /* * Reset the IH entry data once GravityView edit is completed * This resolves an issue with Gravity Perk Media Library which updates the entry object post save * but IH was returning the entry before the GP update */ if ( class_exists( 'GravityView_Plugin' ) && rgpost( 'is_gv_edit_entry' ) ) { /** @var \GravityView_Edit_Entry_Render $render_edit_entry_view */ $render_edit_entry_view = \GravityView_Edit_Entry::getInstance()->instances['render']; $entry = $render_edit_entry_view->get_entry(); $ih_fields = \GFAPI::get_fields_by_type( $form, 'image_hopper' ); foreach ( $ih_fields as $field ) { $_POST[ 'input_' . $field->id ] = $entry[ $field->id ]; } } } /** * Ensure the file references are correct when dealing with images already uploaded and new images * * @param array $form * * @since 1.0.0 */ public function reset_local_upload_info( $form ) { if ( is_wp_error( $form ) ) { return; } $fields = \GFAPI::get_fields_by_type( $form, [ 'image_hopper' ] ); $uploads = json_decode( stripslashes( \GFForms::post( 'gform_uploaded_files' ) ), true ); if ( ! is_array( $uploads ) || count( $uploads ) === 0 ) { return; } foreach ( $fields as $field ) { $input = 'input_' . $field->id; $files = isset( $uploads[ $input ] ) ? $uploads[ $input ] : []; foreach ( $files as &$file ) { if ( empty( $file['temp_filename'] ) ) { continue; } if ( isset( $file['temp_filename'] ) ) { $file['temp_filename'] = sanitize_file_name( wp_basename( $file['temp_filename'] ) ); } if ( isset( $file['uploaded_filename'] ) ) { $file['uploaded_filename'] = sanitize_file_name( wp_basename( $file['uploaded_filename'] ) ); } } \GFFormsModel::$uploaded_files[ $form['id'] ][ $input ] = $files; } } /** * If the Enable Attachments GF feature is on, include Image Hopper images as attachments * * @param array $notification * @param array $form * @param array $entry * * @return array * * @since 1.0.0 */ public function attach_images_to_notification( $notification, $form, $entry ) { if ( rgar( $notification, 'enableAttachments', false ) ) { $notification['attachments'] = isset( $notification['attachments'] ) ? $notification['attachments'] : []; // Get file upload fields and upload root. $upload_fields = \GFCommon::get_fields_by_type( $form, [ 'image_hopper' ] ); foreach ( $upload_fields as $upload_field ) { $attachment_urls = rgar( $entry, $upload_field->id ); $attachment_urls = json_decode( $attachment_urls, true ); if ( $attachment_urls === null ) { continue; } foreach ( $attachment_urls as $attachment_url ) { try { $attachment_url = FileHelper::url_to_path( $attachment_url ); $notification['attachments'][] = $attachment_url; } catch ( \Exception $e ) { //do nothing } } } } return $notification; } /** * Inject Notification Attachment option settings if IH field in form and settings aren't already present * * @param array $ui_settings * @param array $notification * @param array $form * * @return array * * @since 1.1.0 */ public function add_notification_ui_settings( $ui_settings, $notification, $form ) { if ( count( $ui_settings ) === 0 || isset( $ui_settings['notification_attachments'] ) || ! \GFCommon::get_fields_by_type( $form, [ 'image_hopper' ] ) ) { return $ui_settings; } ?> <tr valign="top"> <th scope="row"> <label for="gform_notification_attachments"> <?php esc_html_e( 'Attachments', 'image-hopper' ); ?> <?php gform_tooltip( 'notification_attachments' ); ?> </label> </th> <td> <input type="checkbox" name="gform_notification_attachments" id="gform_notification_attachments" value="1" <?php checked( '1', rgar( $notification, 'enableAttachments' ) ); ?>/> <label for="gform_notification_attachments" class="inline"> <?php esc_html_e( 'Attach uploaded files to notification', 'image-hopper' ); ?> </label> </td> </tr> <!-- / attachments --> <?php return ArrayHelper::insert_after( $ui_settings, 'notification_message', [ 'notification_attachments', ob_get_clean() ] ); } /** * Modify the dependency of the enableAttachments Gravity Forms 2.5 setting so that it includes IH * * @param array $fields * @param array $notification * @param array $form * * @return array * * @since 1.4.1 */ public function adjust_notification_ui_dependency( $fields, $notification, $form ) { if ( ! empty( $fields[0]['fields'] ) ) { foreach ( $fields[0]['fields'] as $key => $field ) { if ( isset( $field['name'] ) && $field['name'] === 'enableAttachments' ) { $fields[0]['fields'][ $key ]['dependency'] = function () use ( $form ) { $upload_fields = \GFCommon::get_fields_by_type( $form, [ 'fileupload', 'image_hopper' ] ); return ! empty( $upload_fields ); }; } } } return $fields; } /** * Add Image Hopper to the APC Upload field settings * * @param array $choices List of upload fields * @param array $form Current Gravity Form * @param boolean $single_file Whether to return upload fields that only allow a single file upload * * @return array * * @since 1.2.0 * * @deprecated 2.3 */ public function add_apc_support( $choices, $form, $single_file ) { _doing_it_wrong( __METHOD__, 'Use \ImageHopper\ImageHopper\FirstParty\AdvancedPostCreation::add_apc_support()', '2.3' ); $apc = AdvancedPostCreation::get_instance(); return $apc->add_apc_support( $choices, $form ); } /** * Look for Image Hopper mergetags in the Post Content setting and, if found, auto-add them to the Add to Media Library setting. * * @param integer $feed_id Feed Id * @param integer $form_id Form Id * @param array $settings Feed Settings * @param object $apc_class instance of GF_Advanced_Post_Creation * * @since 1.2.0 * * @deprecated 2.3 */ public function process_ih_mergetag_in_post_content( $feed_id, $form_id, $settings, $apc_class ) { if ( ! $apc_class instanceof \GF_Advanced_Post_Creation ) { return; } _doing_it_wrong( __METHOD__, 'Use \ImageHopper\ImageHopper\FirstParty\AdvancedPostCreation::process_ih_mergetag_in_post_content()', '2.3' ); $apc = AdvancedPostCreation::get_instance(); $apc->process_ih_mergetag_in_post_content( $feed_id, $form_id, $settings, $apc_class ); } /** * Add support for GF Media Library plugin to IH field * * @param array $field_types Supported fields for the GF Media Library * * @return array * * @since 1.3.0 */ public function gp_media_library_supported_fields( $field_types ) { $field_types[] = 'image_hopper'; return $field_types; } /** * Ensure Gravity Forms will remove uploaded files when an entry is deleted * * @param array $types * * @return array * * @since 1.4.0 */ public function register_field_types_for_file_deletion( $types ) { $types[] = 'image_hopper'; $types[] = 'image_hopper_post'; return $types; } /** * Allow GravityView to handle the output of IH fields in the view * * @param array $templates * * @return array * * @since 1.5.0 */ public function use_gv_render_templates( $templates ) { /* If not currently looking for image hopper templates, then ignore */ $ih_field = false; foreach ( $templates as $template ) { if ( strpos( $template, 'image_hopper' ) !== false ) { $ih_field = true; break; } } if ( ! $ih_field ) { return $templates; } /* Convert all IH types to File Upload or Post Image types */ array_walk( $templates, function ( &$name ) { $name = str_replace( [ 'image_hopper_post', 'image_hopper' ], [ 'post_image', 'fileupload' ], $name ); } ); return $templates; } /** * Convert Image Hopper Dropbox URLs to their raw form for use as embedded images * * @param string $value The saved field value * @param array $entry * @param ImageHopperField $field * * @return mixed * * @since 2.1 */ public function fix_dropbox_urls_on_save( $value, $entry, $field ) { if ( $field->type === 'image_hopper' && ! empty( $value ) ) { $files = json_decode( $value, true ); if ( is_array( $files ) ) { $files = array_map( function ( $file ) { if ( strpos( $file, 'www.dropbox.com' ) === false || strpos( $file, 'raw=1' ) !== false ) { return $file; } return add_query_arg( [ 'raw' => '1' ], $file ); }, $files ); $value = wp_json_encode( $files ); } } return $value; } /** * Decode the Image Hopper fields and pass along the content in a more readily accessible format. * * @param array $body * @param array $feed * @param array $entry * @param array $form * * @return array * * @since 2.1 * * @depreacted 2.12 */ public function add_expanded_zapier_support( $body, $feed, $entry, $form ) { _doing_it_wrong( __METHOD__, 'Use \ImageHopper\ImageHopper\FirstParty\Zapier::enhance_zapier_data()', '2.12' ); $zapier = Zapier::get_instance(); return $zapier->enhance_zapier_data( $body, $feed, $entry, $form ); } /** * @param array $mime * * @return array * * @since 2.1 */ public function add_webp_support_to_multisite( $mime ) { $mime['webp'] = 'image/webp'; return $mime; } /** * Fix to prevent Weglot auto-redirecting this request and causing an error * * @link https://wordpress.org/support/topic/auto-redirection-can-break-gravity-forms-file-upload-feature/ * * @return void * * @since 2.8.2 */ protected function fix_weglot_autoredirect_upload_bug() { /* phpcs:ignore WordPress.Security.NonceVerification.Recommended */ if ( rgempty( 'gf_page', $_GET ) && rgempty( 'ih_page', $_GET ) ) { return; } $page = rgget( 'gf_page' ); $is_upload_page = $_SERVER['REQUEST_METHOD'] === 'POST' && $page === \GFCommon::get_upload_page_slug(); if ( ! $is_upload_page ) { return; } add_filter( 'weglot_autoredirect_skip', '__return_true' ); } /** * @param $cart_item_meta * @param $product_id * * @return array * * @since 1.2.1 * * @deprecated 2.2.2 */ public function add_woo_gf_support_checkout( $cart_item_meta, $product_id ) { _doing_it_wrong( __METHOD__, 'Use \ImageHopper\ImageHopper\ThirdParty\WooCommerce\GravityForms::post_submission_cleanup()', '2.2.1' ); $woogf = GravityForms::get_instance(); return $woogf->post_submission_cleanup( $cart_item_meta, $product_id ); } /** * @param $text * @param $value * @param $field * * @return string * * @since 1.2.1 * * @deprecated 2.2.2 */ public function woocommerce_cart_image_format( $text, $value, $field ) { _doing_it_wrong( __METHOD__, 'Use \ImageHopper\ImageHopper\ThirdParty\WooCommerce\GravityForms::cart_image_format()', '2.2.1' ); $woogf = GravityForms::get_instance(); return $woogf->cart_image_format( $text, $value, $field ); } /** * Register the Image Hopper counter merge tag for use with calculations * * @param array $merge_tags * @param int $form_id * @param array $fields * * @return array * * @since 2.3 */ public function ui_register_count_merge_tag( $merge_tags, $form_id, $fields ) { foreach ( $fields as $field ) { if ( $field->type === 'image_hopper' ) { $merge_tags[] = [ /* translators: %s is the user-defined field label */ 'label' => sprintf( __( '%s Count', 'image-hopper' ), $field->label ), 'tag' => sprintf( '{%s:%d:count}', str_replace( [ '{', '}' ], '', $field->label ), $field->id ), ]; } } return $merge_tags; } /** * Process Image Hopper "count" merge tag for use in calculations * * @param $value * @param $input_id * @param $modifier * @param $field * @param $form * @param $entry * * @return mixed * * @since 2.3 */ public function add_count_merge_tag_calculation_support( $value, $input_id, $modifier, $field, $form, $entry ) { if ( $modifier !== 'count' ) { return $value; } $target_field = \GFFormsModel::get_field( $form, $input_id ); if ( $target_field === null || $target_field->type !== 'image_hopper' ) { return $value; } return \GFCommon::replace_variables( sprintf( '{:%d:%s}', $input_id, $modifier ), $form, $entry ); } /** * @since 2.3.1 * * @depecated Use \ImageHopper\ImageHopper\ThirdParty\GravityPdf\Fields::init() */ public function add_pdf_support() {} /** * If the URL didn't pass GF standard validation, have WP sanitize the URL and see if it matches * the original value. If so, it can be considered valid. * * @internal filter_var( $url, FILTER_VALIDATE_URL ) has a number of problems, and cannot handle unencoded unicode characters. * * @param bool $is_valid * @param string $url * * @return bool * * @since 2.10 */ public function validate_url( $is_valid, $url ) { if ( $is_valid ) { return $is_valid; } return $url === esc_url_raw( $url, [ 'http', 'https' ] ); } }
Edit
Download
Unzip
Chmod
Delete