array(), 'inactive' => array() ); /** * Class constructor which hooks the instance into the WordPress init action */ function __construct() { $this->update_path(); add_action( 'init', array( $this, 'init' ) ); if ( $this->_enable_rg_autoupgrade ) { require_once( 'class-gf-auto-upgrade.php' ); $is_gravityforms_supported = $this->is_gravityforms_supported( $this->_min_gravityforms_version ); new GFAutoUpgrade( $this->_slug, $this->_version, $this->_min_gravityforms_version, $this->_title, $this->_full_path, $this->get_path(), $this->_url, $is_gravityforms_supported ); } $this->pre_init(); } /** * Registers an addon so that it gets initialized appropriately * * @param string $class - The class name * @param string $overrides - Specify the class to replace/override */ public static function register( $class, $overrides = null ) { //Ignore classes that have been marked as inactive if ( in_array( $class, self::$_registered_addons['inactive'] ) ) { return; } //Mark classes as active. Override existing active classes if they are supposed to be overridden $index = array_search( $overrides, self::$_registered_addons['active'] ); if ( $index !== false ) { self::$_registered_addons['active'][ $index ] = $class; } else { self::$_registered_addons['active'][] = $class; } //Mark overridden classes as inactive. if ( ! empty( $overrides ) ) { self::$_registered_addons['inactive'][] = $overrides; } } /** * Gets all active, registered Add-Ons. * * @since Unknown * @access public * * @uses GFAddOn::$_registered_addons * * @return array Active, registered Add-Ons. */ public static function get_registered_addons() { return self::$_registered_addons['active']; } /** * Initializes all addons. */ public static function init_addons() { //Removing duplicate add-ons $active_addons = array_unique( self::$_registered_addons['active'] ); foreach ( $active_addons as $addon ) { call_user_func( array( $addon, 'get_instance' ) ); } } /** * Gets executed before all init functions. Override this function to perform initialization tasks that must be done prior to init */ public function pre_init() { if ( $this->is_gravityforms_supported() ) { //Entry meta if ( $this->method_is_overridden( 'get_entry_meta' ) ) { add_filter( 'gform_entry_meta', array( $this, 'get_entry_meta' ), 10, 2 ); } } } /** * Plugin starting point. Handles hooks and loading of language files. */ public function init() { $this->load_text_domain(); add_filter( 'gform_logging_supported', array( $this, 'set_logging_supported' ) ); add_action( 'gform_post_upgrade', array( $this, 'post_gravityforms_upgrade' ), 10, 3 ); // Get minimum requirements state. $meets_requirements = $this->meets_minimum_requirements(); if ( RG_CURRENT_PAGE == 'admin-ajax.php' ) { //If gravity forms is supported, initialize AJAX if ( $this->is_gravityforms_supported() && $meets_requirements['meets_requirements'] ) { $this->init_ajax(); } } elseif ( is_admin() ) { $this->init_admin(); } else { if ( $this->is_gravityforms_supported() && $meets_requirements['meets_requirements'] ) { $this->init_frontend(); } } } /** * Override this function to add initialization code (i.e. hooks) for the admin site (WP dashboard) */ public function init_admin() { // enqueues admin scripts add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ), 10, 0 ); // message enforcing min version of Gravity Forms if ( isset( $this->_min_gravityforms_version ) && RG_CURRENT_PAGE == 'plugins.php' ) { add_action( 'after_plugin_row_' . $this->get_path(), array( $this, 'plugin_row' ), 10, 2 ); } // STOP HERE IF GRAVITY FORMS IS NOT SUPPORTED if ( isset( $this->_min_gravityforms_version ) && ! $this->is_gravityforms_supported( $this->_min_gravityforms_version ) ) { return; } // STOP HERE IF CANNOT PASS MINIMUM REQUIREMENTS CHECK. $meets_requirements = $this->meets_minimum_requirements(); if ( ! $meets_requirements['meets_requirements'] ) { $this->failed_requirements_init(); return; } $this->setup(); // Add form settings only when there are form settings fields configured or form_settings() method is implemented if ( self::has_form_settings_page() ) { $this->form_settings_init(); } // Add plugin page when there is a plugin page configured or plugin_page() method is implemented if ( self::has_plugin_page() ) { $this->plugin_page_init(); } // Add addon settings page only when there are addon settings fields configured or settings_page() method is implemented if ( self::has_plugin_settings_page() ) { if ( $this->current_user_can_any( $this->_capabilities_settings_page ) ) { $this->plugin_settings_init(); } } // creates the top level app left menu if ( self::has_app_menu() ) { if ( $this->current_user_can_any( $this->_capabilities_app_menu ) ) { add_action( 'admin_menu', array( $this, 'create_app_menu' ) ); } } // Members plugin integration. if ( $this->has_members_plugin( ) ) { add_action( 'members_register_cap_groups', array( $this, 'members_register_cap_group' ), 11 ); add_action( 'members_register_caps', array( $this, 'members_register_caps' ), 11 ); } // User Role Editor integration. add_filter( 'ure_capabilities_groups_tree', array( $this, 'filter_ure_capabilities_groups_tree' ), 11 ); add_filter( 'ure_custom_capability_groups', array( $this, 'filter_ure_custom_capability_groups' ), 10, 2 ); // Results page if ( $this->method_is_overridden( 'get_results_page_config' ) ) { $results_page_config = $this->get_results_page_config(); $results_capabilities = rgar( $results_page_config, 'capabilities' ); if ( $results_page_config && $this->current_user_can_any( $results_capabilities ) ) { $this->results_page_init( $results_page_config ); } } // Locking if ( $this->method_is_overridden( 'get_locking_config' ) ) { require_once( GFCommon::get_base_path() . '/includes/locking/class-gf-locking.php' ); require_once( 'class-gf-addon-locking.php' ); $config = $this->get_locking_config(); new GFAddonLocking( $config, $this ); } // No conflict scripts add_filter( 'gform_noconflict_scripts', array( $this, 'register_noconflict_scripts' ) ); add_filter( 'gform_noconflict_styles', array( $this, 'register_noconflict_styles' ) ); add_action( 'gform_enqueue_scripts', array( $this, 'enqueue_scripts' ), 10, 2 ); } /** * Override this function to add initialization code (i.e. hooks) for the public (customer facing) site */ public function init_frontend() { $this->setup(); add_filter( 'gform_preview_styles', array( $this, 'enqueue_preview_styles' ), 10, 2 ); add_filter( 'gform_print_styles', array( $this, 'enqueue_print_styles' ), 10, 2 ); add_action( 'gform_enqueue_scripts', array( $this, 'enqueue_scripts' ), 10, 2 ); } /** * Override this function to add AJAX hooks or to add initialization code when an AJAX request is being performed */ public function init_ajax() { if ( rgpost( 'view' ) == 'gf_results_' . $this->_slug ) { require_once( GFCommon::get_base_path() . '/tooltips.php' ); require_once( 'class-gf-results.php' ); $gf_results = new GFResults( $this->_slug, $this->get_results_page_config() ); add_action( 'wp_ajax_gresults_get_results_gf_results_' . $this->_slug, array( $gf_results, 'ajax_get_results' ) ); add_action( 'wp_ajax_gresults_get_more_results_gf_results_' . $this->_slug, array( $gf_results, 'ajax_get_more_results' ) ); } elseif ( $this->method_is_overridden( 'get_locking_config' ) ) { require_once( GFCommon::get_base_path() . '/includes/locking/class-gf-locking.php' ); require_once( 'class-gf-addon-locking.php' ); $config = $this->get_locking_config(); new GFAddonLocking( $config, $this ); } } //-------------- Minimum Requirements Check --------------- /** * Override this function to provide a list of requirements needed to use Add-On. * * Custom requirements can be defined by adding a callback to the minimum requirements array. * A custom requirement receives and should return an array with two parameters: * bool $meets_requirements If the custom requirements check passed. * array $errors An array of error messages to present to the user. * * Following is an example of the array that is expected to be returned by this function: * @example https://gist.github.com/JeffMatson/a8d23e16e333e5116060906c6f091aa7 * * @since 2.2 * @access public * * @return array */ public function minimum_requirements() { return array(); } /** * Performs a check to see if WordPress environment meets minimum requirements need to use Add-On. * * @since 2.2 * @access public * * @uses GFAddOn::minimum_requirements() * @uses GFAddOn::get_slug() * * @return bool|array */ public function meets_minimum_requirements() { // Get minimum requirements. $requirements = $this->minimum_requirements(); // Prepare response. $meets_requirements = array( 'meets_requirements' => true, 'errors' => array() ); // If no minimum requirements are defined, return. if ( empty( $requirements ) ) { return $meets_requirements; } // Loop through requirements. foreach ( $requirements as $requirement_type => $requirement ) { // If requirement is a callback, run it. if ( is_callable( $requirement ) ) { $meets_requirements = call_user_func( $requirement, $meets_requirements ); continue; } // Set requirement type to lowercase. $requirement_type = strtolower( $requirement_type ); // Run base requirement checks. switch ( $requirement_type ) { case 'add-ons': // Initialize active Add-Ons array. $active_addons = array(); // Loop through active Add-Ons. foreach ( self::$_registered_addons['active'] as $active_addon ) { // Get Add-On instance. $active_addon = call_user_func( array( $active_addon, 'get_instance' ) ); // Add to active Add-Ons array. $active_addons[ $active_addon->get_slug() ] = array( 'slug' => $active_addon->get_slug(), 'title' => $active_addon->_title, 'version' => $active_addon->_version, ); } // Loop through Add-Ons. foreach ( $requirement as $addon_slug => $addon_requirements ) { // If Add-On requirements is not an array, set Add-On slug to requirements value. if ( ! is_array( $addon_requirements ) ) { $addon_slug = $addon_requirements; } // If Add-On is not active, set error. if ( ! isset( $active_addons[ $addon_slug ] ) ) { // Get Add-On name. $addon_name = rgar( $addon_requirements, 'name' ) ? $addon_requirements['name'] : $addon_slug; $meets_requirements['meets_requirements'] = false; $meets_requirements['errors'][] = sprintf( esc_html__( 'Required Gravity Forms Add-On is missing: %s.', 'gravityforms' ), $addon_name ); continue; } // If Add-On does not meet minimum version, set error. if ( rgar( $addon_requirements, 'version' ) && ! version_compare( $active_addons[ $addon_slug ]['version'], $addon_requirements['version'], '>=' ) ) { $meets_requirements['meets_requirements'] = false; $meets_requirements['errors'][] = sprintf( esc_html__( 'Required Gravity Forms Add-On "%s" does not meet minimum version requirement: %s.', 'gravityforms' ), $active_addons[ $addon_slug ]['title'], $addon_requirements['version'] ); continue; } } break; case 'plugins': // Loop through plugins. foreach ( $requirement as $plugin_path => $plugin_name ) { // If plugin name is not defined, set plugin path to name. if ( is_int( $plugin_path ) ) { $plugin_path = $plugin_name; } // If plugin is not active, set error. if ( ! is_plugin_active( $plugin_path ) ) { $meets_requirements['meets_requirements'] = false; $meets_requirements['errors'][] = sprintf( esc_html__( 'Required WordPress plugin is missing: %s.', 'gravityforms' ), $plugin_name ); continue; } } case 'php': // Check version. if ( rgar( $requirement, 'version' ) && ! version_compare( PHP_VERSION, $requirement['version'], '>=' ) ) { $meets_requirements['meets_requirements'] = false; $meets_requirements['errors'][] = sprintf( esc_html__( 'Current PHP version (%s) does not meet minimum PHP version requirement (%s).', 'gravityforms' ), PHP_VERSION, $requirement['version'] ); } // Check extensions. if ( rgar( $requirement, 'extensions' ) ) { // Loop through extensions. foreach ( $requirement['extensions'] as $extension => $extension_requirements ) { // If extension requirements is not an array, set extension name to requirements value. if ( ! is_array( $extension_requirements ) ) { $extension = $extension_requirements; } // If PHP extension is not loaded, set error. if ( ! extension_loaded( $extension ) ) { $meets_requirements['meets_requirements'] = false; $meets_requirements['errors'][] = sprintf( esc_html__( 'Required PHP extension missing: %s', 'gravityforms' ), $extension ); continue; } // If PHP extension does not meet minimum version, set error. if ( rgar( $extension_requirements, 'version' ) && ! version_compare( phpversion( $extension ), $extension_requirements['version'], '>=' ) ) { $meets_requirements['meets_requirements'] = false; $meets_requirements['errors'][] = sprintf( esc_html__( 'Required PHP extension "%s" does not meet minimum version requirement: %s.', 'gravityforms' ), $extension, $extension_requirements['version'] ); continue; } } } // Check functions. if ( rgar( $requirement, 'functions' ) ) { // Loop through functions. foreach ( $requirement['functions'] as $function ) { if ( ! function_exists( $function ) ) { $meets_requirements['meets_requirements'] = false; $meets_requirements['errors'][] = sprintf( esc_html__( 'Required PHP function missing: %s', 'gravityforms' ), $function ); } } } break; case 'wordpress': // Check version. if ( rgar( $requirement, 'version' ) && ! version_compare( get_bloginfo( 'version' ), $requirement['version'], '>=' ) ) { $meets_requirements['meets_requirements'] = false; $meets_requirements['errors'][] = sprintf( esc_html__( 'Current WordPress version (%s) does not meet minimum WordPress version requirement (%s).', 'gravityforms' ), get_bloginfo( 'version' ), $requirement['version'] ); } break; } } return $meets_requirements; } /** * Register failed requirements page under Gravity Forms settings. * * @since 2.2 * @access public * * @uses GFAddOn::current_user_can_any() * @uses GFAddOn::get_short_title() * @uses GFAddOn::plugin_settings_title() * @uses GFCommon::get_base_path() * @uses RGForms::add_settings_page() */ public function failed_requirements_init() { // Get failed requirements. $failed_requirements = $this->meets_minimum_requirements(); // Prepare errors list. $errors = ''; foreach ( $failed_requirements['errors'] as $error ) { $errors .= sprintf( '
  • %s
  • ', esc_html( $error ) ); } // Prepare error message. $error_message = sprintf( '%s
    %s
      %s
    ', sprintf( esc_html__( '%s is not able to run because your WordPress environment has not met the minimum requirements.', 'gravityforms' ), $this->_title ), sprintf( esc_html__( 'Please resolve the following issues to use %s:', 'gravityforms' ), $this->get_short_title() ), $errors ); // Add error message. if ( $this->is_form_list() || $this->is_entry_list() || $this->is_form_settings() || $this->is_plugin_settings() || GFForms::get_page() === 'system_status' ) { GFCommon::add_error_message( $error_message ); } } //-------------- Setup --------------- /** * Performs upgrade tasks when the version of the Add-On changes. To add additional upgrade tasks, override the upgrade() function, which will only get executed when the plugin version has changed. */ public function setup() { //Upgrading add-on $installed_version = get_option( 'gravityformsaddon_' . $this->_slug . '_version' ); //Making sure version has really changed. Gets around aggressive caching issue on some sites that cause setup to run multiple times. if ( $installed_version != $this->_version ) { $installed_version = GFForms::get_wp_option( 'gravityformsaddon_' . $this->_slug . '_version' ); } //Upgrade if version has changed if ( $installed_version != $this->_version ) { $this->upgrade( $installed_version ); update_option( 'gravityformsaddon_' . $this->_slug . '_version', $this->_version ); } } /** * Override this function to add to add database update scripts or any other code to be executed when the Add-On version changes */ public function upgrade( $previous_version ) { return; } /** * Gets called when Gravity Forms upgrade process is completed. This function is intended to be used internally, override the upgrade() function to execute database update scripts. * @param $db_version - Current Gravity Forms database version * @param $previous_db_version - Previous Gravity Forms database version * @param $force_upgrade - True if this is a request to force an upgrade. False if this is a standard upgrade (due to version change) */ public function post_gravityforms_upgrade( $db_version, $previous_db_version, $force_upgrade ){ // Forcing Upgrade if( $force_upgrade ){ $installed_version = get_option( 'gravityformsaddon_' . $this->_slug . '_version' ); $this->upgrade( $installed_version ); update_option( 'gravityformsaddon_' . $this->_slug . '_version', $this->_version ); } } //-------------- Script enqueuing --------------- /** * Override this function to provide a list of styles to be enqueued. * When overriding this function, be sure to call parent::styles() to ensure the base class scripts are enqueued. * See scripts() for an example of the format expected to be returned. */ public function styles() { $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG || isset( $_GET['gform_debug'] ) ? '' : '.min'; return array( array( 'handle' => 'gaddon_form_settings_css', 'src' => GFAddOn::get_gfaddon_base_url() . "/css/gaddon_settings{$min}.css", 'version' => GFCommon::$version, 'enqueue' => array( array( 'admin_page' => array( 'form_settings', 'plugin_settings', 'plugin_page', 'app_settings' ) ), ) ), array( 'handle' => 'gaddon_results_css', 'src' => GFAddOn::get_gfaddon_base_url() . "/css/gaddon_results{$min}.css", 'version' => GFCommon::$version, 'enqueue' => array( array( 'admin_page' => array( 'results' ) ), ) ), ); } /** * Override this function to provide a list of scripts to be enqueued. * When overriding this function, be sure to call parent::scripts() to ensure the base class scripts are enqueued. * Following is an example of the array that is expected to be returned by this function: *
    	 * 
    	 *
    	 *    array(
    	 *        array(
    	 *            'handle'    => 'maskedinput',
    	 *            'src'       => GFCommon::get_base_url() . '/js/jquery.maskedinput-1.3.min.js',
    	 *            'version'   => GFCommon::$version,
    	 *            'deps'      => array( 'jquery' ),
    	 *            'in_footer' => false,
    	 *
    	 *            // Determines where the script will be enqueued. The script will be enqueued if any of the conditions match.
    	 *            'enqueue'   => array(
    	 *                // admin_page - Specified one or more pages (known pages) where the script is supposed to be enqueued.
    	 *                // To enqueue scripts in the front end (public website), simply don't define this setting.
    	 *                array( 'admin_page' => array( 'form_settings', 'plugin_settings' ) ),
    	 *
    	 *                // tab - Specifies a form settings or plugin settings tab in which the script is supposed to be enqueued.
    	 *                // If none are specified, the script will be enqueued in any of the form settings or plugin_settings page
    	 *                array( 'tab' => 'signature'),
    	 *
    	 *                // query - Specifies a set of query string ($_GET) values.
    	 *                // If all specified query string values match the current requested page, the script will be enqueued
    	 *                array( 'query' => 'page=gf_edit_forms&view=settings&id=_notempty_' )
    	 *
    	 *                // post - Specifies a set of post ($_POST) values.
    	 *                // If all specified posted values match the current request, the script will be enqueued
    	 *                array( 'post' => 'posted_field=val' )
    	 *            )
    	 *        ),
    	 *        array(
    	 *            'handle'   => 'super_signature_script',
    	 *            'src'      => $this->get_base_url() . '/super_signature/ss.js',
    	 *            'version'  => $this->_version,
    	 *            'deps'     => array( 'jquery'),
    	 *            'callback' => array( $this, 'localize_scripts' ),
    	 *            'strings'  => array(
    	 *                // Accessible in JavaScript using the global variable "[script handle]_strings"
    	 *                'stringKey1' => __( 'The string', 'gravityforms' ),
    	 *                'stringKey2' => __( 'Another string.', 'gravityforms' )
    	 *            )
    	 *            "enqueue"  => array(
    	 *                // field_types - Specifies one or more field types that requires this script.
    	 *                // The script will only be enqueued if the current form has a field of any of the specified field types.
    	 *                // Only applies when a current form is available.
    	 *                array( 'field_types' => array( 'signature' ) )
    	 *            )
    	 *        )
    	 *    );
    	 *
    	 * 
    	 * 
    */ public function scripts() { $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG || isset( $_GET['gform_debug'] ) ? '' : '.min'; return array( array( 'handle' => 'gform_form_admin', 'enqueue' => array( array( 'admin_page' => array( 'form_settings' ) ) ) ), array( 'handle' => 'gform_gravityforms', 'enqueue' => array( array( 'admin_page' => array( 'form_settings' ) ) ) ), array( 'handle' => 'google_charts', 'src' => 'https://www.google.com/jsapi', 'version' => GFCommon::$version, 'enqueue' => array( array( 'admin_page' => array( 'results' ) ), ) ), array( 'handle' => 'gaddon_results_js', 'src' => GFAddOn::get_gfaddon_base_url() . "/js/gaddon_results{$min}.js", 'version' => GFCommon::$version, 'deps' => array( 'jquery', 'sack', 'jquery-ui-resizable', 'gform_datepicker_init', 'google_charts', 'gform_field_filter' ), 'callback' => array( 'GFResults', 'localize_results_scripts' ), 'enqueue' => array( array( 'admin_page' => array( 'results' ) ), ) ), array( 'handle' => 'gaddon_repeater', 'src' => GFAddOn::get_gfaddon_base_url() . "/js/repeater{$min}.js", 'version' => GFCommon::$version, 'deps' => array( 'jquery' ), 'enqueue' => array( array( 'admin_page' => array( 'form_settings' ), ), ), ), array( 'handle' => 'gaddon_fieldmap_js', 'src' => GFAddOn::get_gfaddon_base_url() . "/js/gaddon_fieldmap{$min}.js", 'version' => GFCommon::$version, 'deps' => array( 'jquery', 'gaddon_repeater' ), 'enqueue' => array( array( 'admin_page' => array( 'form_settings' ) ), ) ), array( 'handle' => 'gaddon_genericmap_js', 'src' => GFAddOn::get_gfaddon_base_url() . "/js/gaddon_genericmap{$min}.js", 'version' => GFCommon::$version, 'deps' => array( 'jquery', 'gaddon_repeater' ), 'enqueue' => array( array( 'admin_page' => array( 'form_settings' ) ), ) ), array( 'handle' => 'gaddon_selectcustom_js', 'src' => GFAddOn::get_gfaddon_base_url() . "/js/gaddon_selectcustom{$min}.js", 'version' => GFCommon::$version, 'deps' => array( 'jquery' ), 'enqueue' => array( array( 'admin_page' => array( 'form_settings', 'plugin_settings' ) ), ) ), ); } /** * Target of admin_enqueue_scripts and gform_enqueue_scripts hooks. * Not intended to be overridden by child classes. * In order to enqueue scripts and styles, override the scripts() and styles() functions * * @ignore */ public function enqueue_scripts( $form = '', $is_ajax = false ) { if ( empty( $form ) ) { $form = $this->get_current_form(); } //Enqueueing scripts $scripts = $this->scripts(); foreach ( $scripts as $script ) { $src = isset( $script['src'] ) ? $script['src'] : false; $deps = isset( $script['deps'] ) ? $script['deps'] : array(); $version = array_key_exists( 'version', $script ) ? $script['version'] : false; $in_footer = isset( $script['in_footer'] ) ? $script['in_footer'] : false; wp_register_script( $script['handle'], $src, $deps, $version, $in_footer ); if ( isset( $script['enqueue'] ) && $this->_can_enqueue_script( $script['enqueue'], $form, $is_ajax ) ) { $this->add_no_conflict_scripts( array( $script['handle'] ) ); wp_enqueue_script( $script['handle'] ); if ( isset( $script['strings'] ) ) { wp_localize_script( $script['handle'], $script['handle'] . '_strings', $script['strings'] ); } if ( isset( $script['callback'] ) && is_callable( $script['callback'] ) ) { $args = compact( 'form', 'is_ajax' ); call_user_func_array( $script['callback'], $args ); } } } //Enqueueing styles $styles = $this->styles(); foreach ( $styles as $style ) { $src = isset( $style['src'] ) ? $style['src'] : false; $deps = isset( $style['deps'] ) ? $style['deps'] : array(); $version = array_key_exists( 'version', $style ) ? $style['version'] : false; $media = isset( $style['media'] ) ? $style['media'] : 'all'; wp_register_style( $style['handle'], $src, $deps, $version, $media ); if ( $this->_can_enqueue_script( $style['enqueue'], $form, $is_ajax ) ) { $this->add_no_conflict_styles( array( $style['handle'] ) ); if ( $this->is_preview() ) { $this->_preview_styles[] = $style['handle']; } elseif ( $this->is_print() ) { $this->_print_styles[] = $style['handle']; } else { wp_enqueue_style( $style['handle'] ); } } } } /** * Target of gform_preview_styles. Enqueue styles to the preview page. * Not intended to be overridden by child classes * * @ignore */ public function enqueue_preview_styles( $preview_styles, $form ) { return array_merge( $preview_styles, $this->_preview_styles ); } /** * Target of gform_print_styles. Enqueue styles to the print entry page. * Not intended to be overridden by child classes * * @ignore */ public function enqueue_print_styles( $print_styles, $form ) { if ( false === $print_styles ) { $print_styles = array(); } $styles = $this->styles(); foreach ( $styles as $style ) { if ( $this->_can_enqueue_script( $style['enqueue'], $form, false ) ) { $this->add_no_conflict_styles( array( $style['handle'] ) ); $src = isset( $style['src'] ) ? $style['src'] : false; $deps = isset( $style['deps'] ) ? $style['deps'] : array(); $version = isset( $style['version'] ) ? $style['version'] : false; $media = isset( $style['media'] ) ? $style['media'] : 'all'; wp_register_style( $style['handle'], $src, $deps, $version, $media ); $print_styles[] = $style['handle']; } } return array_merge( $print_styles, $this->_print_styles ); } /** * Adds scripts to the list of white-listed no conflict scripts. * * @param $scripts */ private function add_no_conflict_scripts( $scripts ) { $this->_no_conflict_scripts = array_merge( $scripts, $this->_no_conflict_scripts ); } /** * Adds styles to the list of white-listed no conflict styles. * * @param $styles */ private function add_no_conflict_styles( $styles ) { $this->_no_conflict_styles = array_merge( $styles, $this->_no_conflict_styles ); } private function _can_enqueue_script( $enqueue_conditions, $form = array(), $is_ajax = false ) { if ( empty( $enqueue_conditions ) ) { return false; } foreach ( $enqueue_conditions as $condition ) { if ( is_callable( $condition ) ) { $callback_matches = call_user_func( $condition, $form, $is_ajax ); if ( $callback_matches ) { return true; } } else { $query_matches = isset( $condition['query'] ) ? $this->_request_condition_matches( $_GET, $condition['query'] ) : true; $post_matches = isset( $condition['post'] ) ? $this->_request_condition_matches( $_POST, $condition['post'] ) : true; $admin_page_matches = isset( $condition['admin_page'] ) ? $this->_page_condition_matches( $condition['admin_page'], rgar( $condition, 'tab' ) ) : true; $field_type_matches = isset( $condition['field_types'] ) ? $this->_field_condition_matches( $condition['field_types'], $form ) : true; if ( $query_matches && $post_matches && $admin_page_matches && $field_type_matches ) { return true; } } } return false; } private function _request_condition_matches( $request, $query ) { parse_str( $query, $query_array ); foreach ( $query_array as $key => $value ) { switch ( $value ) { case '_notempty_' : if ( rgempty( $key, $request ) ) { return false; } break; case '_empty_' : if ( ! rgempty( $key, $request ) ) { return false; } break; default : if ( rgar( $request, $key ) != $value ) { return false; } break; } } return true; } private function _page_condition_matches( $pages, $tab ) { if ( ! is_array( $pages ) ) { $pages = array( $pages ); } foreach ( $pages as $page ) { switch ( $page ) { case 'form_editor' : if ( $this->is_form_editor() ) { return true; } break; case 'form_list' : if ( $this->is_form_list() ) { return true; } break; case 'form_settings' : if ( $this->is_form_settings( $tab ) ) { return true; } break; case 'plugin_settings' : if ( $this->is_plugin_settings( $tab ) ) { return true; } break; case 'app_settings' : if ( $this->is_app_settings( $tab ) ) { return true; } break; case 'plugin_page' : if ( $this->is_plugin_page() ) { return true; } break; case 'entry_list' : if ( $this->is_entry_list() ) { return true; } break; case 'entry_view' : if ( $this->is_entry_view() ) { return true; } break; case 'entry_edit' : if ( $this->is_entry_edit() ) { return true; } break; case 'results' : if ( $this->is_results() ) { return true; } break; case 'customizer' : if ( is_customize_preview() ) { return true; } break; } } return false; } private function _field_condition_matches( $field_types, $form ) { if ( ! is_array( $field_types ) ) { $field_types = array( $field_types ); } /* @var GF_Field[] $fields */ $fields = GFAPI::get_fields_by_type( $form, $field_types ); if ( count( $fields ) > 0 ) { foreach ( $fields as $field ) { if ( $field->is_administrative() && ! $field->allowsPrepopulate && ! GFForms::get_page() ) { continue; } return true; } } return false; } /** * Target for the gform_noconflict_scripts filter. Adds scripts to the list of white-listed no conflict scripts. * * Not intended to be overridden or called directed by Add-Ons. * * @ignore * * @param array $scripts Array of scripts to be white-listed * * @return array */ public function register_noconflict_scripts( $scripts ) { //registering scripts with Gravity Forms so that they get enqueued when running in no-conflict mode return array_merge( $scripts, $this->_no_conflict_scripts ); } /** * Target for the gform_noconflict_styles filter. Adds styles to the list of white-listed no conflict scripts. * * Not intended to be overridden or called directed by Add-Ons. * * @ignore * * @param array $styles Array of styles to be white-listed * * @return array */ public function register_noconflict_styles( $styles ) { //registering styles with Gravity Forms so that they get enqueued when running in no-conflict mode return array_merge( $styles, $this->_no_conflict_styles ); } //-------------- Entry meta -------------------------------------- /** * Override this method to activate and configure entry meta. * * * @param array $entry_meta An array of entry meta already registered with the gform_entry_meta filter. * @param int $form_id The form id * * @return array The filtered entry meta array. */ public function get_entry_meta( $entry_meta, $form_id ) { return $entry_meta; } //-------------- Results page -------------------------------------- /** * Returns the configuration for the results page. By default this is not activated. * To activate the results page override this function and return an array with the configuration data. * * Example: * public function get_results_page_config() { * return array( * "title" => 'Quiz Results', * "capabilities" => array("gravityforms_quiz_results"), * "callbacks" => array( * "fields" => array($this, 'results_fields'), * "calculation" => array($this, 'results_calculation'), * "markup" => array($this, 'results_markup'), * ) * ); * } * */ public function get_results_page_config() { return false; } /** * Initializes the result page functionality. To activate result page functionality, override the get_results_page_config() function. * * @param $results_page_config - configuration returned by get_results_page_config() */ public function results_page_init( $results_page_config ) { require_once( 'class-gf-results.php' ); if ( isset( $results_page_config['callbacks']['filters'] ) ) { add_filter( 'gform_filters_pre_results', $results_page_config['callbacks']['filters'], 10, 2 ); } if ( isset( $results_page_config['callbacks']['filter_ui'] ) ) { add_filter( 'gform_filter_ui', $results_page_config['callbacks']['filter_ui'], 10, 5 ); } $gf_results = new GFResults( $this->_slug, $results_page_config ); $gf_results->init(); } //-------------- Logging integration -------------------------------------- public function set_logging_supported( $plugins ) { $plugins[ $this->_slug ] = $this->_title; return $plugins; } // # PERMISSIONS --------------------------------------------------------------------------------------------------- /** * Checks whether the Members plugin is installed and activated. * * Not intended to be overridden or called directly by Add-Ons. * * @ignore * * @return bool */ public function has_members_plugin() { return GFForms::has_members_plugin(); } /** * Register the Gravity Forms Add-Ons capabilities group with the Members plugin. * * @since 2.4 * @access public */ public function members_register_cap_group() { members_register_cap_group( 'gravityforms_addons', array( 'label' => esc_html__( 'GF Add-Ons', 'gravityforms' ), 'icon' => 'dashicons-gravityforms', 'caps' => array(), ) ); } /** * Register the Add-On capabilities and their human readable labels with the Members plugin. * * @since 2.4 * @access public * * @uses GFAddOn::get_short_title() */ public function members_register_caps() { // Get capabilities. $caps = $this->get_members_caps(); // If no capabilities were found, exit. if ( empty( $caps ) ) { return; } // Register capabilities. foreach ( $caps as $cap => $label ) { members_register_cap( $cap, array( 'label' => sprintf( '%s: %s', $this->get_short_title(), $label ), 'group' => 'gravityforms_addons', ) ); } } /** * Get Add-On capabilities and their human readable labels. * * @since 2.4 * @access public * * @return array */ public function get_members_caps() { // Initialize capabilities array. $caps = array(); // Add capabilities. if ( ! empty( $this->_capabilities_form_settings ) && is_string( $this->_capabilities_form_settings ) ) { $caps[ $this->_capabilities_form_settings ] = esc_html__( 'Form Settings', 'gravityforms' ); } if ( ! empty( $this->_capabilities_uninstall ) && is_string( $this->_capabilities_uninstall ) ) { $caps[ $this->_capabilities_uninstall ] = esc_html__( 'Uninstall', 'gravityforms' ); } if ( ! empty( $this->_capabilities_plugin_page ) && is_string( $this->_capabilities_plugin_page ) ) { $caps[ $this->_capabilities_plugin_page ] = esc_html__( 'Add-On Page', 'gravityforms' ); } if ( ! empty( $this->_capabilities_settings_page ) && is_string( $this->_capabilities_settings_page ) ) { $caps[ $this->_capabilities_settings_page ] = esc_html__( 'Add-On Settings', 'gravityforms' ); } return $caps; } /** * Register Gravity Forms Add-Ons capabilities group with User Role Editor plugin. * * @since 2.4 * * @param array $groups Existing capabilities groups. * * @return array */ public static function filter_ure_capabilities_groups_tree( $groups = array() ) { $groups['gravityforms_addons'] = array( 'caption' => esc_html__( 'Gravity Forms Add-Ons', 'gravityforms' ), 'parent' => 'gravityforms', 'level' => 3, ); return $groups; } /** * Register Gravity Forms capabilities with Gravity Forms group in User Role Editor plugin. * * @since 2.4 * * @param array $groups Current capability groups. * @param string $cap_id Capability identifier. * * @return array */ public function filter_ure_custom_capability_groups( $groups = array(), $cap_id = '' ) { // Get Add-On capabilities. $caps = $this->_capabilities; // If capability belongs to Add-On, register it to group. if ( in_array( $cap_id, $caps, true ) ) { $groups[] = 'gravityforms_addons'; } return $groups; } /** * Checks whether the current user is assigned to a capability or role. * * @since Unknown * @access public * * @param string|array $caps An string or array of capabilities to check * * @return bool Returns true if the current user is assigned to any of the capabilities. */ public function current_user_can_any( $caps ) { return GFCommon::current_user_can_any( $caps ); } //------- Settings Helper Methods (Common to all settings pages) ------------------- /*** * Renders the UI of all settings page based on the specified configuration array $sections * * @param array $sections - Configuration array containing all fields to be rendered grouped into sections */ public function render_settings( $sections ) { if ( ! $this->has_setting_field_type( 'save', $sections ) ) { $sections = $this->add_default_save_button( $sections ); } ?>
    _slug . '_save_settings', '_' . $this->_slug . '_save_settings_nonce' ) ?> settings( $sections ); ?>
    setting_dependency_met( rgar( $section, 'dependency' ) ) ) { $this->single_section( $section, $is_first ); } $is_first = false; } } /*** * Displays the UI for a field section * * @param array $section - The section to be displayed * @param bool $is_first - true for the first section in the list, false for all others */ public function single_section( $section, $is_first = false ) { extract( wp_parse_args( $section, array( 'title' => false, 'description' => false, 'id' => '', 'class' => false, 'style' => '', 'tooltip' => false, 'tooltip_class' => '' ) ) ); $classes = array( 'gaddon-section' ); if ( $is_first ) { $classes[] = 'gaddon-first-section'; } if ( $class ) $classes[] = $class; ?>

    setting_dependency_met( rgar( $field, 'dependency' ) ) ) continue; if ( is_callable( array( $this, "single_setting_row_{$field['type']}" ) ) ) { call_user_func( array( $this, "single_setting_row_{$field['type']}" ), $field ); } else { $this->single_setting_row( $field ); } } ?>
    ' . $field['description'] . '' : null; ?> > single_setting_label( $field ); ?> single_setting( $field ); echo $description; ?> maybe_get_tooltip( $field ); } if ( rgar( $field, 'required' ) ) { echo ' ' . $this->get_required_indicator( $field ); } } public function single_setting_row_save( $field ) { ?> single_setting( $field ); ?> _saved_settings = $settings; } /*** * Sets the previous settings to a class variable so that it can be accessed by lower level functions providing support for * verifying whether a value was changed before executing an action * * @param array $settings : Settings to be stored */ public function set_previous_settings( $settings ) { $this->_previous_settings = $settings; } public function get_previous_settings() { return $this->_previous_settings; } /*** * Gets settings from $_POST variable, returning a name/value collection of setting name and setting value */ public function get_posted_settings() { global $_gaddon_posted_settings; if ( isset( $_gaddon_posted_settings ) ) { return $_gaddon_posted_settings; } $_gaddon_posted_settings = array(); if ( count( $_POST ) > 0 ) { foreach ( $_POST as $key => $value ) { if ( preg_match( '|_gaddon_setting_(.*)|', $key, $matches ) ) { $_gaddon_posted_settings[ $matches[1] ] = self::maybe_decode_json( stripslashes_deep( $value ) ); } } } return $_gaddon_posted_settings; } public static function maybe_decode_json( $value ) { if ( self::is_json( $value ) ) { return json_decode( $value, ARRAY_A ); } return $value; } public static function is_json( $value ) { if ( is_string( $value ) && in_array( substr( $value, 0, 1 ), array( '{', '[' ) ) && is_array( json_decode( $value, ARRAY_A ) ) ) { return true; } return false; } /*** * Gets the "current" settings, which are settings from $_POST variables if this is a postback request, or the current saved settings for a get request. */ public function get_current_settings() { //try getting settings from post $settings = $this->get_posted_settings(); //if nothing has been posted, get current saved settings if ( empty( $settings ) ) { $settings = $this->_saved_settings; } return $settings; } /*** * Retrieves the setting for a specific field/input * * @param string $setting_name The field or input name * @param string $default_value Optional. The default value * @param bool|array $settings Optional. THe settings array * * @return string|array */ public function get_setting( $setting_name, $default_value = '', $settings = false ) { if ( ! $settings ) { $settings = $this->get_current_settings(); } if ( false === $settings ) { return $default_value; } if ( strpos( $setting_name, '[' ) !== false ) { $path_parts = explode( '[', $setting_name ); foreach ( $path_parts as $part ) { $part = trim( $part, ']' ); if ( $part != '0'){ if ( empty( $part ) ) { return $settings; } } if ( false === isset( $settings[ $part ] ) ) { return $default_value; } $settings = rgar( $settings, $part ); } $setting = $settings; } else { if ( false === isset( $settings[ $setting_name ] ) ) { return $default_value; } $setting = $settings[ $setting_name ]; } return $setting; } /*** * Determines if a dependent field has been populated. * * @param string $dependency - Field or input name of the "parent" field. * * @return bool - true if the "parent" field has been filled out and false if it has not. * */ public function setting_dependency_met( $dependency ) { // if no dependency, always return true if ( ! $dependency ) { return true; } //use a callback if one is specified in the configuration if ( is_callable( $dependency ) ) { return call_user_func( $dependency ); } if ( is_array( $dependency ) ) { //supports: 'dependency' => array("field" => 'myfield', 'values' => array("val1", 'val2')) $dependency_field = $dependency['field']; $dependency_value = $dependency['values']; } else { //supports: 'dependency' => 'myfield' $dependency_field = $dependency; $dependency_value = '_notempty_'; } if ( ! is_array( $dependency_value ) ) { $dependency_value = array( $dependency_value ); } $current_value = $this->get_setting( $dependency_field ); foreach ( $dependency_value as $val ) { if ( $current_value == $val ) { return true; } if ( $val == '_notempty_' && ! rgblank( $current_value ) ) { return true; } } return false; } public function has_setting_field_type( $type, $fields ) { if ( ! empty( $fields ) ) { foreach ( $fields as &$section ) { foreach ( $section['fields'] as $field ) { if ( rgar( $field, 'type' ) == $type ) { return true; } } } } return false; } public function add_default_save_button( $sections ) { $sections[ count( $sections ) - 1 ]['fields'][] = array( 'type' => 'save' ); return $sections; } public function get_save_success_message( $sections ) { $save_button = $this->get_save_button( $sections ); return isset( $save_button['messages']['success'] ) ? $save_button['messages']['success'] : sprintf( esc_html__( '%s settings updated.', 'gravityforms' ), $this->get_short_title() ); } public function get_save_error_message( $sections ) { $save_button = $this->get_save_button( $sections ); return isset( $save_button['messages']['error'] ) ? $save_button['messages']['error'] : esc_html__( 'There was an error while saving your settings.', 'gravityforms' ); } public function get_save_button( $sections ) { $sections = array_values( $sections ); $fields = $sections[ count( $sections ) - 1 ]['fields']; foreach ( $fields as $field ) { if ( $field['type'] == 'save' ) return $field; } return false; } //------------- Field Types ------------------------------------------------------ /*** * Renders and initializes a text field based on the $field array * * @param array $field - Field array containing the configuration options of this field * @param bool $echo = true - true to echo the output to the screen, false to simply return the contents as a string * * @return string The HTML for the field */ public function settings_text( $field, $echo = true ) { $field['type'] = 'text'; //making sure type is set to text $field['input_type'] = rgar( $field, 'input_type' ) ? rgar( $field, 'input_type' ) : 'text'; $attributes = $this->get_field_attributes( $field ); $default_value = rgar( $field, 'value' ) ? rgar( $field, 'value' ) : rgar( $field, 'default_value' ); $value = $this->get_setting( $field['name'], $default_value ); // Add autocomplete attribute for password inputs. if ( 'password' === $field['input_type'] ) { $attributes['autocomplete'] = 'autocomplete="off"'; } $html = ''; $html .= ''; $html .= rgar( $field, 'after_input' ); $feedback_callback = rgar( $field, 'feedback_callback' ); if ( is_callable( $feedback_callback ) ) { $is_valid = call_user_func_array( $feedback_callback, array( $value, $field ) ); $icon = ''; if ( $is_valid === true ) { $icon = 'icon-check fa-check gf_valid'; // check icon } elseif ( $is_valid === false ) { $icon = 'icon-remove fa-times gf_invalid'; // x icon } if ( ! empty( $icon ) ) { $html .= "  "; } } if ( $this->field_failed_validation( $field ) ) { $html .= $this->get_error_icon( $field ); } if ( $echo ) { echo $html; } return $html; } /*** * Renders and initializes a textarea field based on the $field array * * @param array $field - Field array containing the configuration options of this field * @param bool $echo = true - true to echo the output to the screen, false to simply return the contents as a string * * @return string The HTML for the field */ public function settings_textarea( $field, $echo = true ) { $field['type'] = 'textarea'; //making sure type is set to textarea $attributes = $this->get_field_attributes( $field ); $default_value = rgar( $field, 'value' ) ? rgar( $field, 'value' ) : rgar( $field, 'default_value' ); $value = $this->get_setting( $field['name'], $default_value ); $name = '' . esc_attr( $field['name'] ); $html = ''; if ( rgar( $field, 'use_editor' ) ) { $html .= ''; ob_start(); wp_editor( $value, '_gaddon_setting_'. $field['name'], array( 'autop' => false, 'editor_class' => 'merge-tag-support mt-wp_editor mt-manual_position mt-position-right' ) ); $html .= ob_get_contents(); ob_end_clean(); } else { $html .= ''; } if ( $this->field_failed_validation( $field ) ) { $html .= $this->get_error_icon( $field ); } if ( $echo ) { echo $html; } return $html; } /*** * Renders and initializes a hidden field based on the $field array * * @param array $field - Field array containing the configuration options of this field * @param bool $echo = true - true to echo the output to the screen, false to simply return the contents as a string * * @return string The HTML for the field */ public function settings_hidden( $field, $echo = true ) { $field['type'] = 'hidden'; //making sure type is set to hidden $attributes = $this->get_field_attributes( $field ); $default_value = rgar( $field, 'value' ) ? rgar( $field, 'value' ) : rgar( $field, 'default_value' ); $value = $this->get_setting( $field['name'], $default_value ); if ( is_array( $value ) ) { $value = json_encode( $value ); } $html = ''; if ( $echo ) { echo $html; } return $html; } /*** * Renders and initializes a checkbox field or a collection of checkbox fields based on the $field array * * @param array $field - Field array containing the configuration options of this field * @param bool $echo = true - true to echo the output to the screen, false to simply return the contents as a string * * @return string The HTML for the field */ public function settings_checkbox( $field, $echo = true ) { $field['type'] = 'checkbox'; //making sure type is set to checkbox $field_attributes = $this->get_field_attributes( $field, array() ); $have_icon = $this->choices_have_icon( rgar( $field, 'choices' ) ); $horizontal = rgar( $field, 'horizontal' ) || $have_icon ? ' gaddon-setting-inline' : ''; $html = ''; $default_choice_attributes = array( 'onclick' => 'jQuery(this).siblings("input[type=hidden]").val(jQuery(this).prop("checked") ? 1 : 0);', 'onkeypress' => 'jQuery(this).siblings("input[type=hidden]").val(jQuery(this).prop("checked") ? 1 : 0);' ); $is_first_choice = true; if ( is_array( $field['choices'] ) ) { foreach ( $field['choices'] as $choice ) { $choice['id'] = sanitize_title( $choice['name'] ); $choice_attributes = $this->get_choice_attributes( $choice, $field_attributes, $default_choice_attributes ); $value = $this->get_setting( $choice['name'], rgar( $choice, 'default_value' ) ); $tooltip = $this->maybe_get_tooltip( $choice ); //displaying error message after first checkbox item $error_icon = ''; if ( $is_first_choice ){ $error_icon = $this->field_failed_validation( $field ) ? $this->get_error_icon( $field ) : ''; } // Add icon to choice if choices have icon if ( $have_icon ) { $choice['icon'] = rgar( $choice, 'icon' ) ? $choice['icon'] : 'fa-cog'; } $html .= $this->checkbox_item( $choice, $horizontal, $choice_attributes, $value, $tooltip, $error_icon ); $is_first_choice = false; } } if ( $echo ) { echo $html; } return $html; } /** * Returns the markup for an individual checkbox item give the parameters * * @param $choice - Choice array with all configured properties * @param $horizontal_class - CSS class to style checkbox items horizontally * @param $attributes - String containing all the attributes for the input tag. * @param $value - Currently selection (1 if field has been checked. 0 or null otherwise) * @param $tooltip - String containing a tooltip for this checkbox item. * * @return string - The markup of an individual checkbox item */ public function checkbox_item( $choice, $horizontal_class, $attributes, $value, $tooltip, $error_icon = '' ) { $hidden_field_value = $value == '1' ? '1' : '0'; $icon_class = rgar( $choice, 'icon' ) ? ' gaddon-setting-choice-visual' : ''; $checkbox_item = '
    '; $checkbox_item .= ''; if ( is_callable( array( $this, "checkbox_input_{$choice['name']}" ) ) ) { $markup = call_user_func( array( $this, "checkbox_input_{$choice['name']}" ), $choice, $attributes, $value, $tooltip ); } else { $markup = $this->checkbox_input( $choice, $attributes, $value, $tooltip ); } $checkbox_item .= $markup . $error_icon . '
    '; return $checkbox_item; } /** * Returns the markup for an individual checkbox input and its associated label * * @param $choice - Choice array with all configured properties * @param $attributes - String containing all the attributes for the input tag. * @param $value - Currently selection (1 if field has been checked. 0 or null otherwise) * @param $tooltip - String containing a tooltip for this checkbox item. * * @return string - The markup of an individual checkbox input and its associated label */ public function checkbox_input( $choice, $attributes, $value, $tooltip ) { $icon_tag = ''; if ( rgar( $choice, 'icon' ) ) { /* Get the defined icon. */ $icon = rgar( $choice, 'icon' ) ? $choice['icon'] : 'fa-cog'; /* Set icon tag based on icon type. */ if ( filter_var( $icon, FILTER_VALIDATE_URL ) ) { $icon_tag = ''; } else { $icon_tag = ''; } $icon_tag .= '
    '; } $markup = ''; $markup .= ''; return $markup; } /*** * Renders and initializes a radio field or a collection of radio fields based on the $field array * * @param array $field - Field array containing the configuration options of this field * @param bool $echo = true - true to echo the output to the screen, false to simply return the contents as a string * * @return string Returns the markup for the radio buttons * */ public function settings_radio( $field, $echo = true ) { $field['type'] = 'radio'; //making sure type is set to radio $selected_value = $this->get_setting( $field['name'], rgar( $field, 'default_value' ) ); $field_attributes = $this->get_field_attributes( $field ); $have_icon = $this->choices_have_icon( rgar( $field, 'choices' ) ); $horizontal = rgar( $field, 'horizontal' ) || $have_icon ? ' gaddon-setting-inline' : ''; $html = ''; if ( is_array( $field['choices'] ) ) { foreach ( $field['choices'] as $i => $choice ) { if ( rgempty( 'id', $choice ) ) { $choice['id'] = $field['name'] . $i; } $choice_attributes = $this->get_choice_attributes( $choice, $field_attributes ); $tooltip = $this->maybe_get_tooltip( $choice ); $radio_value = isset( $choice['value'] ) ? $choice['value'] : $choice['label']; $checked = checked( $selected_value, $radio_value, false ); if ( $have_icon ) { /* Get the defined icon. */ $icon = rgar( $choice, 'icon' ) ? $choice['icon'] : 'fa-cog'; /* Set icon tag based on icon type. */ if ( filter_var( $icon, FILTER_VALIDATE_URL ) ) { $icon_tag = ''; } else { $icon_tag = ''; } $html .= '
    '; $html .= ''; $html .= ''; $html .= '
    '; } else { $html .= '
    '; $html .= ''; $html .= '
    '; } } } if ( $this->field_failed_validation( $field ) ) { $html .= $this->get_error_icon( $field ); } if ( $echo ) { echo $html; } return $html; } /** * Determines if any of the available settings choices have an icon. * * @access public * @param array $choices (default: array()) * @return bool */ public function choices_have_icon( $choices = array() ) { $have_icon = false; foreach ( $choices as $choice ) { if ( rgar( $choice, 'icon' ) ) { $have_icon = true; } } return $have_icon; } /*** * Renders and initializes a drop down field based on the $field array * * @param array $field - Field array containing the configuration options of this field * @param bool $echo = true - true to echo the output to the screen, false to simply return the contents as a string * * @return string The HTML for the field */ public function settings_select( $field, $echo = true ) { $field['type'] = 'select'; // making sure type is set to select $attributes = $this->get_field_attributes( $field ); $value = $this->get_setting( $field['name'], rgar( $field, 'default_value' ) ); $name = '' . esc_attr( $field['name'] ); // If no choices were provided and there is a no choices message, display it. if ( ( empty( $field['choices'] ) || ! rgar( $field, 'choices' ) ) && rgar( $field, 'no_choices' ) ) { $html = $field['no_choices']; } else { $html = sprintf( '', '_gaddon_setting_' . $name, implode( ' ', $attributes ), $this->get_select_options( $field['choices'], $value ) ); $html .= rgar( $field, 'after_select' ); } if ( $this->field_failed_validation( $field ) ) { $html .= $this->get_error_icon( $field ); } if ( $echo ) { echo $html; } return $html; } /** * Renders and initializes a drop down field with a input field for custom input based on the $field array. * * @param array $field - Field array containing the configuration options of this field * @param bool $echo = true - true to echo the output to the screen, false to simply return the contents as a string * * @return string The HTML for the field */ public function settings_select_custom( $field, $echo = true ) { /* Prepare select field */ $select_field = $field; $select_field_value = $this->get_setting( $select_field['name'], rgar( $select_field, 'default_value' ) ); $select_field['onchange'] = ''; $select_field['class'] = ( isset( $select_field['class'] ) ) ? $select_field['class'] . 'gaddon-setting-select-custom' : 'gaddon-setting-select-custom'; /* Prepare input field */ $input_field = $field; $input_field['name'] .= '_custom'; $input_field['style'] = 'width:200px;max-width:90%;'; $input_field_display = ''; /* Loop through select choices and make sure option for custom exists */ $has_gf_custom = false; foreach ( $select_field['choices'] as $choice ) { if ( rgar( $choice, 'name' ) == 'gf_custom' || rgar( $choice, 'value' ) == 'gf_custom' ) { $has_gf_custom = true; } /* If choice has choices, check inside those choices. */ if ( rgar( $choice, 'choices' ) ) { foreach ( $choice['choices'] as $subchoice ) { if ( rgar( $subchoice, 'name' ) == 'gf_custom' || rgar( $subchoice, 'value' ) == 'gf_custom' ) { $has_gf_custom = true; } } } } if ( ! $has_gf_custom ) { $select_field['choices'][] = array( 'label' => esc_html__( 'Add Custom', 'gravityforms' ) .' ' . $select_field['label'], 'value' => 'gf_custom' ); } /* If select value is "gf_custom", hide the select field and display the input field. */ if ( $select_field_value == 'gf_custom' || ( count( $select_field['choices'] ) == 1 && $select_field['choices'][0]['value'] == 'gf_custom' ) ) { $select_field['style'] = 'display:none;'; } else { $input_field_display = ' style="display:none;"'; } /* Add select field */ $html = $this->settings_select( $select_field, false ); /* Add input field */ $html .= '
    '; $html .= count( $select_field['choices'] ) > 1 ? 'Reset' : ''; $html .= $this->settings_text( $input_field, false ); $html .= '
    '; if ( $echo ) { echo $html; } return $html; } /** * Prepares an HTML string of options for a drop down field. * * @param array $choices - Array containing all the options for the drop down field * @param string $selected_value - The value currently selected for the field * * @return string The HTML for the select options */ public function get_select_options( $choices, $selected_value ) { $options = ''; foreach ( $choices as $choice ) { if ( isset( $choice['choices'] ) ) { $options .= sprintf( '%2$s', esc_attr( $choice['label'] ), $this->get_select_options( $choice['choices'], $selected_value ) ); } else { if ( ! isset( $choice['value'] ) ) { $choice['value'] = $choice['label']; } $options .= $this->get_select_option( $choice, $selected_value ); } } return $options; } /** * Prepares an HTML string for a single drop down field option. * * @access protected * @param array $choice - Array containing the settings for the drop down option * @param string $selected_value - The value currently selected for the field * * @return string The HTML for the select choice */ public function get_select_option( $choice, $selected_value ) { if ( is_array( $selected_value ) ) { $selected = in_array( $choice['value'], $selected_value ) ? "selected='selected'" : ''; } else { $selected = selected( $selected_value, $choice['value'], false ); } return sprintf( '', esc_attr( $choice['value'] ), $selected, $choice['label'] ); } //------------- Field Map Field Type -------------------------- /** * Renders and initializes a generic map field based on the $field array whose choices are populated by the fields to be mapped. * * @since 2.2 * @access public * * @uses GFAddOn::field_failed_validation() * @uses GFCommon::get_base_url() * @uses GFAddOn::get_current_forn() * @uses GFAddOn::get_error_icon() * @uses GFAddOn::get_mapping_field() * @uses GFAddOn::settings_hidden() * * @param array $field Field array containing the configuration options of this field. * @param bool $echo Determines if field contents should automatically be displayed. Defaults to true. * * @return string The HTML for the field */ public function settings_generic_map( $field, $echo = true ) { // Initialize return HTML string. $html = ''; // Shift field map choices to key property. if ( isset( $field['field_map' ] ) ) { $field['key_choices'] = $field['field_map']; } // Shift legacy title properties. foreach ( array( 'key', 'value' ) as $type ) { if ( isset( $field[ $type . '_field_title' ] ) ) { $field[ $type . '_field' ]['title'] = $field[ $type . '_field_title' ]; unset( $field[ $type . '_field_title' ] ); } } // Set merge tags state to false if not defined. if ( ! rgar( $field, 'merge_tags' ) ) { $field['merge_tags'] = false; } // Initialize field objects for child fields. $value_field = $key_field = $custom_key_field = $custom_value_field = $field; // Define custom placeholder. $custom_placeholder = 'gf_custom'; // Define key field properties. $key_field['name'] .= '_key'; $key_field['choices'] = rgar( $field, 'key_choices' ) ? $field['key_choices'] : rgars( $field, 'key_field/choices' ); $key_field['class'] = 'key key_{i}'; // Define custom key field properties. $custom_key_field['name'] .= '_custom_key_{i}'; $custom_key_field['class'] = 'custom_key custom_key_{i}'; $custom_key_field['value'] = '{custom_key}'; $custom_key_field['placeholder'] = rgars( $field, 'key_field/placeholder' ) ? $field['key_field']['placeholder'] : esc_html__( 'Custom Key', 'gravityforms' ); // Define value field properties. $value_field['name'] .= '_custom_value'; $value_field['choices'] = rgar( $field, 'value_choices' ) ? $field['value_choices'] : rgars( $field, 'value_field/choices' ); $value_field['class'] = 'value value_{i}'; // Define custom value field properties. $custom_value_field['name'] .= '_custom_value_{i}'; $custom_value_field['class'] = 'custom_value custom_value_{i}'; $custom_value_field['value'] = '{custom_value}'; $custom_value_field['placeholder'] = rgars( $field, 'value_field/placeholder' ) ? $field['value_field']['placeholder'] : esc_html__( 'Custom Value', 'gravityforms' ); // Get key/field column titles. $key_field_title = rgars( $field, 'key_field/title' ) ? $field['key_field']['title'] : esc_html__( 'Key', 'gravityforms' ); $value_field_title = rgars( $field, 'value_field/title' ) ? $field['value_field']['title'] : esc_html__( 'Value', 'gravityforms' ); // Remove unneeded field properties. $unneeded_props = array( 'field_map', 'key_choices', 'value_choices', 'placeholders', 'callback' ); foreach ( $unneeded_props as $unneeded_prop ) { unset( $field[ $unneeded_prop ] ); unset( $key_field[ $unneeded_prop ] ); unset( $value_field[ $unneeded_prop ] ); unset( $custom_key_field[ $unneeded_prop ] ); unset( $custom_value_field[ $unneeded_prop ] ); } // If field failed validation, display error icon. if ( $this->field_failed_validation( $field ) ) { $html .= $this->get_error_icon( $field ); } // Display hidden field containing dynamic field map value. $html .= $this->settings_hidden( $field, false ); // Display map table. $html .= ' ' . $this->get_mapping_field( 'key', $key_field, $custom_key_field ) . $this->get_mapping_field( 'value', $value_field, $custom_value_field ) . '
    ' . $key_field_title . ' ' . $value_field_title . '
    {buttons}
    '; // Get generic map limit. $limit = empty( $field['limit'] ) ? 0 : $field['limit']; // Initialize generic map via Javascript. $html .= " "; // If automatic display is enabled, echo field HTML. if ( $echo ) { echo $html; } return $html; } /** * Renders and initializes a field map field based on the $field array whose choices are populated by the fields to be mapped. * * @since unknown * @access public * * @uses GFAddOn::field_map_table_header() * @uses GFAddOn::get_mapped_field_name() * @uses GFAddOn::get_required_indicator() * @uses GFAddOn::maybe_get_tooltip() * @uses GFAddOn::setting_dependency_met() * @uses GFAddOn::settings_field_map_select() * * @param array $field Field array containing the configuration options of this field. * @param bool $echo Determines if field contents should automatically be displayed. Defaults to true. * * @return string The HTML for the field */ public function settings_field_map( $field, $echo = true ) { // Initialize return HTML string. $html = ''; // Get field map choices. $field_map = rgar( $field, 'field_map' ); // If no field map choices exist, return HTML. if ( empty( $field_map ) ) { return $html; } // Get current form ID. $form_id = rgget( 'id' ); // Display field map table header. $html .= '' . $this->field_map_table_header() . ''; // Loop through field map choices. foreach ( $field['field_map'] as $child_field ) { // If field map choice does not meet the dependencies required to be displayed, skip it. if ( ! $this->setting_dependency_met( rgar( $child_field, 'dependency' ) ) ) { continue; } // Get field map choice name, tooltip and required indicator. $child_field['name'] = $this->get_mapped_field_name( $field, $child_field['name'] ); $tooltip = $this->maybe_get_tooltip( $child_field ); $required = rgar( $child_field, 'required' ) ? ' ' . $this->get_required_indicator( $child_field ) : ''; // Display field map choice row. $html .= ' '; } // Close field map table. $html .= '
    ' . $this->settings_field_map_select( $child_field, $form_id ) . '
    '; // If automatic display is enabled, echo field HTML. if ( $echo ) { echo $html; } return $html; } /** * Renders and initializes a dynamic field map field based on the $field array whose choices are populated by the fields to be mapped. * * @since 1.9.5.13 * @access public * * @uses GFAddOn::field_failed_validation() * @uses GFAddOn::get_current_form() * @uses GFAddOn::get_error_icon() * @uses GFAddOn::get_mapping_field() * @uses GFAddOn::settings_field_map_select() * @uses GFAddOn::settings_hidden() * @uses GFAddOn::settings_select() * @uses GFAddOn::settings_text() * @uses GFCommon::get_base_url() * * @param array $field Field array containing the configuration options of this field. * @param bool $echo Determines if field contents should automatically be displayed. Defaults to true. * * @return string The HTML for the field */ public function settings_dynamic_field_map( $field, $echo = true ) { // Initialize return HTML string. $html = ''; // Initialize field objects for child fields. $value_field = $key_field = $custom_key_field = $field; // Get current form object. $form = $this->get_current_form(); // Change disable custom property to enable custom key property. if ( isset( $field['disabled_custom'] ) ) { $field['enable_custom_key'] = ! rgar( $field, 'disabled_custom' ); unset( $field['disabled_custom'] ); } // Define key field properties. $key_field['name'] .= '_key'; $key_field['choices'] = isset( $field['field_map'] ) ? $field['field_map'] : null; $key_field['class'] = 'key key_{i}'; $key_field['title'] = rgar( $field, 'key_field_title' ); // Define custom key field properties. $custom_key_field['name'] .= '_custom_key_{i}'; $custom_key_field['class'] = 'custom_key custom_key_{i}'; $custom_key_field['value'] = '{custom_key}'; // Define custom key value. $custom_key = 'gf_custom'; // Define value field properties. $value_field['name'] .= '_custom_value'; $value_field['class'] = 'value value_{i}'; $value_field['title'] = rgar( $field, 'value_field_title' ); // Remove unneeded field properties. unset( $field['field_map'], $value_field['field_map'], $key_field['field_map'], $custom_key_field['field_map'] ); // If field failed validation, display error icon. if ( $this->field_failed_validation( $field ) ) { $html .= $this->get_error_icon( $field ); } $header = ''; if ( ! empty( $key_field['title'] ) || ! empty ( $value_field['title'] ) ) { $header = '' . $key_field['title'] . '' .' ' . $value_field['title'] . ''; } // Display dynamic field map table. $html .= ' ' . $header . ' '. $this->get_mapping_field( 'key', $key_field, $custom_key_field ) .'
    ' . $this->settings_field_map_select( $value_field, $form['id'] ) . ' {buttons}
    '; // Display hidden field containing dynamic field map value. $html .= $this->settings_hidden( $field, false ); // Get dynamic field map limit. $limit = empty( $field['limit'] ) ? 0 : $field['limit']; // Initialize dynamic field map via Javascript. $html .= " "; // If automatic display is enabled, echo field HTML. if ( $echo ) { echo $html; } return $html; } /** * Renders a field select field for field maps. * * @since unknown * @access public * * @uses GFAddOn::get_field_map_choices() * @uses GF_Field::get_form_editor_field_title() * * @param array $field Field array containing the configuration options of this field. * @param int $form_id Form ID to retrieve fields from. * * @return string The HTML for the field */ public function settings_field_map_select( $field, $form_id ) { // Get field types to only display. $field_type = rgempty( 'field_type', $field ) ? null : $field['field_type']; // Get field types to exclude. $exclude_field_types = rgempty( 'exclude_field_types', $field ) ? null : $field['exclude_field_types']; // Get form field choices based on field type inclusions/exclusions. $field['choices'] = $this->get_field_map_choices( $form_id, $field_type, $exclude_field_types ); // If no choices were found, return error. if ( empty( $field['choices'] ) || ( count( $field['choices'] ) == 1 && rgblank( $field['choices'][0]['value'] ) ) ) { if ( ( ! is_array( $field_type ) && ! rgblank( $field_type ) ) || ( is_array( $field_type ) && count( $field_type ) == 1 ) ) { $type = is_array( $field_type ) ? $field_type[0] : $field_type; $type = ucfirst( GF_Fields::get( $type )->get_form_editor_field_title() ); return sprintf( __( 'Please add a %s field to your form.', 'gravityforms' ), $type ); } } // Set default value. $field['default_value'] = $this->get_default_field_select_field( $field ); return $this->settings_select( $field, false ); } /** * Prepares the markup for mapping field key and value fields. * * @since 2.2 * @access public * * @uses GFAddOn::get_current_form() * @uses GFAddOn::get_field_map_choices() * * @param string $type The field type being prepared; key or value. * @param array $select_field The drop down field properties. * @param array $text_field The text field properties. * * @return string */ public function get_mapping_field( $type, $select_field, $text_field ) { // If use form fields as choices flag is set, add as choices. if ( isset( $select_field['choices'] ) && ! is_array( $select_field['choices'] ) && 'form_fields' === strtolower( $select_field['choices'] ) ) { // Set choices to form fields. $select_field['choices'] = $this->get_field_map_choices( rgget( 'id' ) ); } // If field has no choices, display custom field only. if ( empty( $select_field['choices'] ) ) { // Set field value to custom key. $select_field['value'] = 'gf_custom'; // Display field row. return sprintf( '%s
    %s
    ', $this->settings_hidden( $select_field, false ), $type, $this->settings_text( $text_field, false ) ); } else { // Set initial additional classes. $additional_classes = array(); // Set has custom key flag. $has_gf_custom = false; // Loop through key field choices. foreach ( $select_field['choices'] as $choice ) { // If choice name or value is the custom key, set custom key flag to true and exit loop. if ( rgar( $choice, 'name' ) == 'gf_custom' || rgar( $choice, 'value' ) == 'gf_custom' ) { $has_gf_custom = true; break; } // If choice has sub-choices, check for custom key option. if ( rgar( $choice, 'choices' ) ) { // Loop through sub-choices. foreach ( $choice['choices'] as $subchoice ) { // If sub-choice name or value is the custom key, set custom key flag to true and exit loop. if ( rgar( $subchoice, 'name' ) == 'gf_custom' || rgar( $subchoice, 'value' ) == 'gf_custom' ) { $has_gf_custom = true; break; } } } } // If custom key option is not found and we're allowed to add it, add it. if ( ! $has_gf_custom ) { if ( $type == 'key' ) { $enable_custom = rgars( $select_field, 'key_field/custom_value' ) ? (bool) $select_field['key_field']['custom_value'] : ! (bool) rgar( $select_field, 'disable_custom' ); $enable_custom = isset( $select_field['enable_custom_key'] ) ? (bool) $select_field['enable_custom_key'] : $enable_custom; $label = esc_html__( 'Add Custom Key', 'gravityforms' ); } else { // Add merge tag class. if ( rgars( $select_field, 'value_field/merge_tags' ) ) { $additional_classes[] = 'supports-merge-tags'; } $enable_custom = rgars( $select_field, 'value_field/custom_value' ) ? (bool) $select_field['value_field']['custom_value'] : (bool) rgars( $select_field, 'enable_custom_value' ); $label = esc_html__( 'Add Custom Value', 'gravityforms' ); } if ( $enable_custom ) { $select_field['choices'][] = array( 'label' => $label, 'value' => 'gf_custom' ); } } // Display field row. return sprintf( '%s
    %s%s
    ', $this->settings_select( $select_field, false ), $type, implode( ' ', $additional_classes ), $this->settings_text( $text_field, false ), $type, esc_html__( 'Reset', 'gravityforms' ) ); } } /** * Heading row for field map table. * * @since 2.2 * @access public * * @uses GFAddOn::field_map_title() * * @return string */ public function field_map_table_header() { return ' ' . $this->field_map_title() . ' ' . esc_html__( 'Form Field', 'gravityforms' ) . ' '; } /** * Heading for field map field column. * * @since 2.2 * @access public * * @used-by GFAddOn::field_map_table_header() * * @return string */ public function field_map_title() { return esc_html__( 'Field', 'gravityforms' ); } /** * Get field map choices for specific form. * * @since unknown * @access public * * @uses GFCommon::get_label() * @uses GFFormsModel::get_entry_meta() * @uses GFFormsModel::get_form_meta() * @uses GF_Field::get_entry_inputs() * @uses GF_Field::get_form_editor_field_title() * @uses GF_Field::get_input_type() * * @param int $form_id Form ID to display fields for. * @param array|string $field_type Field types to only include as choices. Defaults to null. * @param array|string $exclude_field_types Field types to exclude from choices. Defaults to null. * * @return array */ public static function get_field_map_choices( $form_id, $field_type = null, $exclude_field_types = null ) { $form = GFFormsModel::get_form_meta( $form_id ); $fields = array(); // Setup first choice if ( rgblank( $field_type ) || ( is_array( $field_type ) && count( $field_type ) > 1 ) ) { $first_choice_label = __( 'Select a Field', 'gravityforms' ); } else { $type = is_array( $field_type ) ? $field_type[0] : $field_type; $type = ucfirst( GF_Fields::get( $type )->get_form_editor_field_title() ); $first_choice_label = sprintf( __( 'Select a %s Field', 'gravityforms' ), $type ); } $fields[] = array( 'value' => '', 'label' => $first_choice_label ); // if field types not restricted add the default fields and entry meta if ( is_null( $field_type ) ) { $fields[] = array( 'value' => 'id', 'label' => esc_html__( 'Entry ID', 'gravityforms' ) ); $fields[] = array( 'value' => 'date_created', 'label' => esc_html__( 'Entry Date', 'gravityforms' ) ); $fields[] = array( 'value' => 'ip', 'label' => esc_html__( 'User IP', 'gravityforms' ) ); $fields[] = array( 'value' => 'source_url', 'label' => esc_html__( 'Source Url', 'gravityforms' ) ); $fields[] = array( 'value' => 'form_title', 'label' => esc_html__( 'Form Title', 'gravityforms' ) ); $entry_meta = GFFormsModel::get_entry_meta( $form['id'] ); foreach ( $entry_meta as $meta_key => $meta ) { $fields[] = array( 'value' => $meta_key, 'label' => rgars( $entry_meta, "{$meta_key}/label" ) ); } } // Populate form fields if ( is_array( $form['fields'] ) ) { foreach ( $form['fields'] as $field ) { $input_type = $field->get_input_type(); $inputs = $field->get_entry_inputs(); $field_is_valid_type = ( empty( $field_type ) || ( is_array( $field_type ) && in_array( $input_type, $field_type ) ) || ( ! empty( $field_type ) && $input_type == $field_type ) ); if ( is_null( $exclude_field_types ) ) { $exclude_field = false; } elseif ( is_array( $exclude_field_types ) ) { if ( in_array( $input_type, $exclude_field_types ) ) { $exclude_field = true; } else { $exclude_field = false; } } else { //not array, so should be single string if ( $input_type == $exclude_field_types ) { $exclude_field = true; } else { $exclude_field = false; } } if ( is_array( $inputs ) && $field_is_valid_type && ! $exclude_field ) { //If this is an address field, add full name to the list if ( $input_type == 'address' ) { $fields[] = array( 'value' => $field->id, 'label' => strip_tags( GFCommon::get_label( $field ) . ' (' . esc_html__( 'Full', 'gravityforms' ) . ')' ) ); } //If this is a name field, add full name to the list if ( $input_type == 'name' ) { $fields[] = array( 'value' => $field->id, 'label' => strip_tags( GFCommon::get_label( $field ) . ' (' . esc_html__( 'Full', 'gravityforms' ) . ')' ) ); } //If this is a checkbox field, add to the list if ( $input_type == 'checkbox' ) { $fields[] = array( 'value' => $field->id, 'label' => strip_tags( GFCommon::get_label( $field ) . ' (' . esc_html__( 'Selected', 'gravityforms' ) . ')' ) ); } foreach ( $inputs as $input ) { $fields[] = array( 'value' => $input['id'], 'label' => strip_tags( GFCommon::get_label( $field, $input['id'] ) ) ); } } elseif ( $input_type == 'list' && $field->enableColumns && $field_is_valid_type && ! $exclude_field ) { $fields[] = array( 'value' => $field->id, 'label' => strip_tags( GFCommon::get_label( $field ) . ' (' . esc_html__( 'Full', 'gravityforms' ) . ')' ) ); $col_index = 0; foreach ( $field->choices as $column ) { $fields[] = array( 'value' => $field->id . '.' . $col_index, 'label' => strip_tags( GFCommon::get_label( $field ) . ' (' . esc_html( rgar( $column, 'text' ) ) . ')' ), ); $col_index ++; } } elseif ( ! $field->displayOnly && $field_is_valid_type && ! $exclude_field ) { $fields[] = array( 'value' => $field->id, 'label' => strip_tags( GFCommon::get_label( $field ) ) ); } } } /** * Filter the choices available in the field map drop down. * * @since 2.0.7.11 * * @param array $fields The value and label properties for each choice. * @param int $form_id The ID of the form currently being configured. * @param null|array $field_type Null or the field types to be included in the drop down. * @param null|array|string $exclude_field_types Null or the field type(s) to be excluded from the drop down. */ $fields = apply_filters( 'gform_addon_field_map_choices', $fields, $form_id, $field_type, $exclude_field_types ); if ( function_exists( 'get_called_class' ) ) { $callable = array( get_called_class(), 'get_instance' ); if ( is_callable( $callable ) ) { $add_on = call_user_func( $callable ); $slug = $add_on->get_slug(); $fields = apply_filters( "gform_{$slug}_field_map_choices", $fields, $form_id, $field_type, $exclude_field_types ); } } return $fields; } /** * Get input name for field map field. * * @since unknown * @access public * * @used-by GFAddOn::settings_field_map() * @used-by GFAddOn::validate_field_map_settings() * * @param array $parent_field Field map field. * @param string $field_name Child field. * * @return string */ public function get_mapped_field_name( $parent_field, $field_name ) { return "{$parent_field['name']}_{$field_name}"; } /** * Get mapped key/value pairs for standard field map. * * @since unknown * @access public * * @param array $feed Feed object. * @param string $field_name Field map field name. * * @return array */ public static function get_field_map_fields( $feed, $field_name ) { // Initialize return fields array. $fields = array(); // Get prefix for mapped field map keys. $prefix = "{$field_name}_"; // Loop through feed meta. foreach ( $feed['meta'] as $name => $value ) { // If field name matches prefix, add value to return array. if ( strpos( $name, $prefix ) === 0 ) { $name = str_replace( $prefix, '', $name ); $fields[ $name ] = $value; } } return $fields; } /** * Get mapped key/value pairs for dynamic field map. * * @since 1.9.9.9 * @access public * * @param array $feed Feed object. * @param string $field_name Dynamic field map field name. * * @return array */ public static function get_dynamic_field_map_fields( $feed, $field_name ) { // Initialize return fields array. $fields = array(); // Get dynamic field map field. $dynamic_fields = rgars( $feed, 'meta/' . $field_name ); // If dynamic field map field is found, loop through mapped fields and add to array. if ( ! empty( $dynamic_fields ) ) { // Loop through mapped fields. foreach ( $dynamic_fields as $dynamic_field ) { // Get mapped key or replace with custom value. $field_key = 'gf_custom' === $dynamic_field['key'] ? $dynamic_field['custom_key'] : $dynamic_field['key']; // Add mapped field to return array. $fields[ $field_key ] = $dynamic_field['value']; } } return $fields; } /** * Get mapped key/value pairs for generic map. * * @since 2.2 * @access public * * @param array $feed Feed object or settings array. * @param string $field_name Generic map field name. * @param array $form Form object. Defaults to empty array. * @param array $entry Entry object. Defaults to empty array. * * @uses GFCommon::replace_variables() * * @return array */ public function get_generic_map_fields( $feed, $field_name, $form = array(), $entry = array() ) { // Initialize return fields array. $fields = array(); // Get generic map field. $generic_fields = rgar( $feed, 'meta' ) ? rgars( $feed, 'meta/' . $field_name ) : rgar( $feed, $field_name ); // If generic map field is found, loop through mapped fields and add to array. if ( ! empty( $generic_fields ) ) { // Loop through mapped fields. foreach ( $generic_fields as $generic_field ) { // Get mapped key or replace with custom value. $field_key = 'gf_custom' === $generic_field['key'] ? $generic_field['custom_key'] : $generic_field['key']; // Get mapped field choice or replace with custom value. if ( 'gf_custom' === $generic_field['value'] ) { // If form isn't set, use custom value. Otherwise, replace merge tags. $field_value = empty( $form ) ? $generic_field['custom_value'] : GFCommon::replace_variables( $generic_field['custom_value'], $form, $entry, false, false, false, 'text' ); } else { // If form isn't set, use value. Otherwise, get field value. $field_value = empty( $form ) ? $generic_field['value'] : $this->get_field_value( $form, $entry, $generic_field['value'] ); } // Add mapped field to return array. $fields[ $field_key ] = $field_value; } } return $fields; } //------------ Field Select Field Type ------------------------ /** * Renders and initializes a drop down field based on the $field array whose choices are populated by the form's fields. * * @param array $field - Field array containing the configuration options of this field * @param bool $echo = true - true to echo the output to the screen, false to simply return the contents as a string * * @return string The HTML for the field */ public function settings_field_select( $field, $echo = true ) { $field = $this->prepare_field_select_field( $field ); $html = $this->settings_select( $field, false ); if ( $echo ) { echo $html; } return $html; } public function prepare_field_select_field( $field ) { $args = is_array( rgar( $field, 'args' ) ) ? rgar( $field, 'args' ) : array( rgar( $field, 'args' ) ); $args = wp_parse_args( $args, array( 'append_choices' => array(), 'disable_first_choice' => false, ) ); $field['choices'] = array(); if ( ! $args['disable_first_choice'] ) { // Setup first choice if ( empty( $args['input_types'] ) || ( is_array( $args['input_types'] ) && count( $args['input_types'] ) > 1 ) ) { $first_choice_label = __( 'Select a Field', 'gravityforms' ); } else { $type = is_array( $args['input_types'] ) ? $args['input_types'][0] : $args['input_types']; $type = ucfirst( GF_Fields::get( $type )->get_form_editor_field_title() ); $first_choice_label = sprintf( __( 'Select a %s Field', 'gravityforms' ), $type ); } $field['choices'][] = array( 'value' => '', 'label' => $first_choice_label ); } $field['choices'] = array_merge( $field['choices'], $this->get_form_fields_as_choices( $this->get_current_form(), $args ) ); if ( ! empty( $args['append_choices'] ) ) { $field['choices'] = array_merge( $field['choices'], $args['append_choices'] ); } // Set default value. $field['default_value'] = $this->get_default_field_select_field( $field ); return $field; } /** * Returns the field to be selected by default for field select fields based on matching labels. * * @access public * @param array $field - Field array containing the configuration options of this field * * @return string|null */ public function get_default_field_select_field( $field ) { // Prepare field name. $field_name = str_replace( '.', '_', $field['name'] ); // If field's value is already set, return it. if ( $this->get_setting( $field_name ) ) { return $this->get_setting( $field_name ); } // If field's default value is not an array and not empty, return it. if ( ! rgempty( 'default_value', $field ) && ! is_array( $field['default_value'] ) ) { return $field['default_value']; } // Set default value if auto populate is not disabled. if ( rgar( $field, 'auto_mapping' ) !== false ) { $field_label = rgar( $field, 'label' ); // Initialize array to store auto-population choices. $default_value_choices = array( $field_label ); // Define global aliases to help with the common case mappings. $global_aliases = array( __('First Name', 'gravityforms') => array( __( 'Name (First)', 'gravityforms' ) ), __('Last Name', 'gravityforms') => array( __( 'Name (Last)', 'gravityforms' ) ), __('Address', 'gravityforms') => array( __( 'Address (Street Address)', 'gravityforms' ) ), __('Address 2', 'gravityforms') => array( __( 'Address (Address Line 2)', 'gravityforms' ) ), __('City', 'gravityforms') => array( __( 'Address (City)', 'gravityforms' ) ), __('State', 'gravityforms') => array( __( 'Address (State / Province)', 'gravityforms' ) ), __('Zip', 'gravityforms') => array( __( 'Address (Zip / Postal Code)', 'gravityforms' ) ), __('Country', 'gravityforms') => array( __( 'Address (Country)', 'gravityforms' ) ), ); // If one or more global aliases are defined for this particular field label, merge them into auto-population choices. if ( isset( $global_aliases[ $field_label ] ) ){ $default_value_choices = array_merge( $default_value_choices, $global_aliases[ $field_label ] ); } // If field aliases are defined, merge them into auto-population choices. if ( rgars( $field, 'default_value/aliases' ) ) { $default_value_choices = array_merge( $default_value_choices, $field['default_value']['aliases'] ); } // Convert all auto-population choices to lowercase. $default_value_choices = array_map( 'strtolower', $default_value_choices ); // Loop through fields. foreach ( $field['choices'] as $choice ) { // If choice value is empty, skip it. if ( rgblank( $choice['value'] ) ) { continue; } // If lowercase field label matches a default value choice, set it to the default value. if ( in_array( strtolower( $choice['label'] ), $default_value_choices ) ) { return $choice['value']; } } } return null; } /** * Retrieve an array of form fields formatted for select, radio and checkbox settings fields. * * @access public * @param array $form - The form object * @param array $args - Additional settings to check for (field and input types to include, callback for applicable input type) * * @return array The array of formatted form fields */ public function get_form_fields_as_choices( $form, $args = array() ) { $fields = array(); if ( ! is_array( $form['fields'] ) ) { return $fields; } $args = wp_parse_args( $args, array( 'field_types' => array(), 'input_types' => array(), 'callback' => false ) ); foreach ( $form['fields'] as $field ) { if ( ! empty( $args['field_types'] ) && ! in_array( $field->type, $args['field_types'] ) ) { continue; } $input_type = GFFormsModel::get_input_type( $field ); $is_applicable_input_type = empty( $args['input_types'] ) || in_array( $input_type, $args['input_types'] ); if ( is_callable( $args['callback'] ) ) { $is_applicable_input_type = call_user_func( $args['callback'], $is_applicable_input_type, $field, $form ); } if ( ! $is_applicable_input_type ) { continue; } if ( ! empty( $args['property'] ) && ( ! isset( $field->{$args['property']} ) || $field->{$args['property']} != $args['property_value'] ) ) { continue; } $inputs = $field->get_entry_inputs(); if ( is_array( $inputs ) ) { // if this is an address field, add full name to the list if ( $input_type == 'address' ) { $fields[] = array( 'value' => $field->id, 'label' => GFCommon::get_label( $field ) . ' (' . esc_html__( 'Full', 'gravityforms' ) . ')' ); } // if this is a name field, add full name to the list if ( $input_type == 'name' ) { $fields[] = array( 'value' => $field->id, 'label' => GFCommon::get_label( $field ) . ' (' . esc_html__( 'Full', 'gravityforms' ) . ')' ); } // if this is a checkbox field, add to the list if ( $input_type == 'checkbox' ) { $fields[] = array( 'value' => $field->id, 'label' => GFCommon::get_label( $field ) . ' (' . esc_html__( 'Selected', 'gravityforms' ) . ')' ); } foreach ( $inputs as $input ) { $fields[] = array( 'value' => $input['id'], 'label' => GFCommon::get_label( $field, $input['id'] ) ); } } elseif ( $input_type == 'list' && $field->enableColumns ) { $fields[] = array( 'value' => $field->id, 'label' => GFCommon::get_label( $field ) . ' (' . esc_html__( 'Full', 'gravityforms' ) . ')' ); $col_index = 0; foreach ( $field->choices as $column ) { $fields[] = array( 'value' => $field->id . '.' . $col_index, 'label' => GFCommon::get_label( $field ) . ' (' . rgar( $column, 'text' ) . ')', ); $col_index ++; } } elseif ( ! $field->displayOnly ) { $fields[] = array( 'value' => $field->id, 'label' => GFCommon::get_label( $field ) ); } else { $fields[] = array( 'value' => $field->id, 'label' => GFCommon::get_label( $field ) ); } } return $fields; } /** * Renders and initializes a checkbox field that displays a select field when checked based on the $field array. * * @access public * @param array $field - Field array containing the configuration options of this field * @param bool $echo = true - true to echo the output to the screen, false to simply return the contents as a string * * @return string The HTML for the field */ public function settings_checkbox_and_select( $field, $echo = true ) { $field = $this->prepare_settings_checkbox_and_select( $field ); $checkbox_field = $field['checkbox']; $select_field = $field['select']; $is_enabled = $this->get_setting( $checkbox_field['name'] ); // get markup $html = sprintf( '%s %s %s', $this->settings_checkbox( $checkbox_field, false ), $select_field['name'] . 'Span', $is_enabled ? '' : 'gf_invisible', $this->settings_select( $select_field, false ), $this->maybe_get_tooltip( $select_field ) ); if ( $echo ) { echo $html; } return $html; } public function prepare_settings_checkbox_and_select( $field ) { // prepare checkbox $checkbox_input = rgars( $field, 'checkbox' ); $checkbox_field = array( 'type' => 'checkbox', 'name' => $field['name'] . 'Enable', 'label' => esc_html__( 'Enable', 'gravityforms' ), 'horizontal' => true, 'value' => '1', 'choices' => false, 'tooltip' => false ); $checkbox_field = wp_parse_args( $checkbox_input, $checkbox_field ); // prepare select $select_input = rgars( $field, 'select' ); $select_field = array( 'name' => $field['name'] . 'Value', 'type' => 'select', 'class' => '', 'tooltip' => false ); $select_field['class'] .= ' ' . $select_field['name']; $select_field = wp_parse_args( $select_input, $select_field ); // a little more with the checkbox if( empty( $checkbox_field['choices'] ) ) { $checkbox_field['choices'] = array( array( 'name' => $checkbox_field['name'], 'label' => $checkbox_field['label'], 'onchange' => sprintf( "( function( $, elem ) { $( elem ).parents( 'td' ).css( 'position', 'relative' ); if( $( elem ).prop( 'checked' ) ) { $( '%1\$s' ).css( 'visibility', 'visible' ); $( '%1\$s' ).fadeTo( 400, 1 ); } else { $( '%1\$s' ).fadeTo( 400, 0, function(){ $( '%1\$s' ).css( 'visibility', 'hidden' ); } ); } } )( jQuery, this );", "#{$select_field['name']}Span" ) ) ); } $field['select'] = $select_field; $field['checkbox'] = $checkbox_field; return $field; } /*** * Renders the save button for settings pages * * @param array $field - Field array containing the configuration options of this field * @param bool $echo = true - true to echo the output to the screen, false to simply return the contents as a string * * @return string The HTML */ public function settings_save( $field, $echo = true ) { $field['type'] = 'submit'; $field['name'] = 'gform-settings-save'; $field['class'] = 'button-primary gfbutton'; if ( ! rgar( $field, 'value' ) ) { $field['value'] = esc_html__( 'Update Settings', 'gravityforms' ); } $attributes = $this->get_field_attributes( $field ); $html = ''; if ( $echo ) { echo $html; } return $html; } /** * Parses the properties of the $field meta array and returns a set of HTML attributes to be added to the HTML element. * * @param array $field - current field meta to be parsed. * @param array $default - default set of properties. Will be appended to the properties specified in the $field array * * @return array - resulting HTML attributes ready to be included in the HTML element. */ public function get_field_attributes( $field, $default = array() ) { /** * Each nonstandard property will be extracted from the $props array so it is not auto-output in the field HTML * * @param array $field The current field meta to be parsed */ $no_output_props = apply_filters( 'gaddon_no_output_field_properties', array( 'default_value', 'label', 'choices', 'feedback_callback', 'checked', 'checkbox_label', 'value', 'type', 'validation_callback', 'required', 'hidden', 'tooltip', 'dependency', 'messages', 'name', 'args', 'exclude_field_types', 'field_type', 'after_input', 'input_type', 'icon', 'save_callback', 'enable_custom_value', 'enable_custom_key', 'merge_tags', 'key_field', 'value_field', 'callback', ), $field ); $default_props = array( 'class' => '', // will default to gaddon-setting 'default_value' => '', // default value that should be selected or entered for the field ); // Property switch case switch ( $field['type'] ) { case 'select': $default_props['choices'] = array(); break; case 'checkbox': $default_props['checked'] = false; $default_props['checkbox_label'] = ''; $default_props['choices'] = array(); break; case 'text': default: break; } $props = wp_parse_args( $field, $default_props ); $props['id'] = rgempty( 'id', $props ) ? rgar( $props, 'name' ) : rgar( $props, 'id' ); $props['class'] = trim( "{$props['class']} gaddon-setting gaddon-{$props['type']}" ); // extract no-output properties from $props array so they are not auto-output in the field HTML foreach ( $no_output_props as $prop ) { if ( isset( $props[ $prop ] ) ) { ${$prop} = $props[ $prop ]; unset( $props[ $prop ] ); } } //adding default attributes foreach ( $default as $key => $value ) { if ( isset( $props[ $key ] ) ) { $props[ $key ] = $value . $props[ $key ]; } else { $props[ $key ] = $value; } } // get an array of property strings, example: name='myFieldName' $prop_strings = array(); foreach ( $props as $prop => $value ) { $prop_strings[ $prop ] = "{$prop}='" . esc_attr( $value ) . "'"; } return $prop_strings; } /** * Parses the properties of the $choice meta array and returns a set of HTML attributes to be added to the HTML element. * * @param array $choice - current choice meta to be parsed. * @param array $field_attributes - current field's attributes. * * @return array - resulting HTML attributes ready to be included in the HTML element. */ public function get_choice_attributes( $choice, $field_attributes, $default_choice_attributes = array() ) { $choice_attributes = $field_attributes; foreach ( $choice as $prop => $val ) { $no_output_choice_attributes = array( 'default_value', 'label', 'checked', 'value', 'type', 'validation_callback', 'required', 'tooltip', ); if ( in_array( $prop, $no_output_choice_attributes ) || is_array( $val ) ) { unset( $choice_attributes[ $prop ] ); } else { $choice_attributes[ $prop ] = "{$prop}='" . esc_attr( $val ) . "'"; } } //Adding default attributes. Either creating a new attribute or pre-pending to an existing one. foreach ( $default_choice_attributes as $default_attr_name => $default_attr_value ) { if ( isset( $choice_attributes[ $default_attr_name ] ) ) { $choice_attributes[ $default_attr_name ] = $this->prepend_attribute( $default_attr_name, $default_attr_value, $choice_attributes[ $default_attr_name ] ); } else { $choice_attributes[ $default_attr_name ] = "{$default_attr_name}='" . esc_attr( $default_attr_value ) . "'"; } } return $choice_attributes; } /*** * @param $name - The name of the attribute to be added * @param $attribute - The attribute value to be added * @param $current_attribute - The full string containing the current attribute value * @return mixed - The new attribute string with the new value added to the beginning of the list */ public function prepend_attribute( $name, $attribute, $current_attribute ) { return str_replace( "{$name}='", "{$name}='{$attribute}", $current_attribute ); } /** * Validates settings fields. * Validates that all fields are valid. Fields can be invalid when they are blank and marked as required or if it fails a custom validation check. * To specify a custom validation, use the 'validation_callback' field meta property and implement the validation function with the custom logic. * * @param $fields - A list of all fields from the field meta configuration * @param $settings - A list of submitted settings values * * @return bool - Returns true if all fields have passed validation, and false otherwise. */ public function validate_settings( $fields, $settings ) { foreach ( $fields as $section ) { if ( ! $this->setting_dependency_met( rgar( $section, 'dependency' ) ) ) { continue; } foreach ( $section['fields'] as $field ) { if ( ! $this->setting_dependency_met( rgar( $field, 'dependency' ) ) ) { continue; } $field_setting = rgar( $settings, rgar( $field, 'name' ) ); if ( is_callable( rgar( $field, 'validation_callback' ) ) ) { call_user_func( rgar( $field, 'validation_callback' ), $field, $field_setting ); continue; } if ( is_callable( array( $this, 'validate_' . $field['type'] . '_settings' ) ) ) { call_user_func( array( $this, 'validate_' . $field['type'] . '_settings' ), $field, $settings ); continue; } if ( rgar( $field, 'required' ) && rgblank( $field_setting ) ) { $this->set_field_error( $field, rgar( $field, 'error_message' ) ); } } } $field_errors = $this->get_field_errors(); $is_valid = empty( $field_errors ); return $is_valid; } public function validate_text_settings( $field, $settings ) { $field_setting = rgar( $settings, rgar( $field, 'name' ) ); if ( rgar( $field, 'required' ) && rgblank( $field_setting ) ) { $this->set_field_error( $field, rgar( $field, 'error_message' ) ); } $field_setting_safe = sanitize_text_field( $field_setting ); if ( $field_setting !== $field_setting_safe ) { $message = esc_html__( 'The text you have entered is not valid. For security reasons, some characters are not allowed. ', 'gravityforms' ); $script = sprintf( 'jQuery("input[name=\"_gaddon_setting_%s\"]").val(jQuery(this).data("safe"));', $field['name'] ); $double_encoded_safe_value = htmlspecialchars( htmlspecialchars( $field_setting_safe, ENT_QUOTES ), ENT_QUOTES ); $message .= sprintf( " %s", htmlspecialchars( $script, ENT_QUOTES ), $double_encoded_safe_value, esc_html__('Fix it', 'gravityforms' ) ); $this->set_field_error( $field, $message ); } } public function validate_textarea_settings( $field, $settings ) { $field_setting = rgar( $settings, rgar( $field, 'name' ) ); if ( rgar( $field, 'required' ) && rgblank( $field_setting ) ) { $this->set_field_error( $field, rgar( $field, 'error_message' ) ); } $field_setting_safe = $this->maybe_wp_kses( $field_setting ); if ( $field_setting !== $field_setting_safe ) { $message = esc_html__( 'The text you have entered is not valid. For security reasons, some characters are not allowed. ', 'gravityforms' ); $script = sprintf( 'jQuery("textarea[name=\"_gaddon_setting_%s\"]").val(jQuery(this).data("safe"));', $field['name'] ); $double_encoded_safe_value = htmlspecialchars( htmlspecialchars( $field_setting_safe, ENT_QUOTES ), ENT_QUOTES ); $message .= sprintf( " %s", htmlspecialchars( $script, ENT_QUOTES ), $double_encoded_safe_value, esc_html__('Fix it', 'gravityforms' ) ); $this->set_field_error( $field, $message ); } } public function validate_radio_settings( $field, $settings ) { $field_setting = rgar( $settings, rgar( $field, 'name' ) ); if ( rgar( $field, 'required' ) && rgblank( $field_setting ) ) { $this->set_field_error( $field, rgar( $field, 'error_message' ) ); return; } if ( rgblank( $field_setting ) ){ return; //Nothing is selected. Let it pass validation } foreach( $field['choices'] as $choice ) { if ( $this->is_choice_valid( $choice, $field_setting ) ) { return; // Choice is valid } } $this->set_field_error( $field, esc_html__( 'Invalid value', 'gravityforms' ) ); } public function validate_select_settings( $field, $settings ) { $field_name = str_replace( '[]', '', $field['name'] ); $field_setting = rgar( $settings, $field_name ); $multiple = rgar( $field, 'multiple' ) == 'multiple'; $required = rgar( $field, 'required' ); if ( ! $multiple && $required && rgblank( $field_setting ) ) { $this->set_field_error( $field, rgar( $field, 'error_message' ) ); return; } if ( rgblank( $field_setting ) ) { return; } if ( $multiple ) { $selected = 0; foreach( $field['choices'] as $choice ) { if ( isset( $choice['choices'] ) ) { foreach( $choice['choices'] as $optgroup_choice ) { if ( $this->is_choice_valid( $optgroup_choice, $field_setting ) ) { $selected++; } } } else { if ( $this->is_choice_valid( $choice, $field_setting ) ) { $selected++; } } } if ( $required && $selected == 0 ) { $this->set_field_error( $field, rgar( $field, 'error_message' ) ); return; } if ( ! $required && $selected !== count( $field_setting ) ) { $this->set_field_error( $field, esc_html__( 'Invalid value', 'gravityforms' ) ); } } else { foreach( $field['choices'] as $choice ) { if ( isset( $choice['choices'] ) ) { foreach( $choice['choices'] as $optgroup_choice ) { if ( $this->is_choice_valid( $optgroup_choice, $field_setting ) ) { return; } } } else { if ( $this->is_choice_valid( $choice, $field_setting ) ) { return; // Choice is valid } } } $this->set_field_error( $field, esc_html__( 'Invalid value', 'gravityforms' ) ); } } public function validate_checkbox_settings( $field, $settings ) { if ( ! is_array( rgar( $field, 'choices' ) ) ) { return; } $selected = 0; foreach ( $field['choices'] as $choice ) { $value = $this->get_setting( $choice['name'], '', $settings ); if ( ! in_array( $value, array( '1', '0' ) ) ) { $this->set_field_error( $field, esc_html__( 'Invalid value', 'gravityforms' ) ); return; } if ( $value === '1' ) { $selected++; } } if ( rgar( $field, 'required' ) && $selected < 1 ) { $this->set_field_error( $field, rgar( $field, 'error_message' ) ); } } public function validate_select_custom_settings( $field, $settings ) { if ( ! is_array( rgar( $field, 'choices' ) ) ) { return; } $select_value = rgar( $settings, $field['name'] ); $custom_value = rgar( $settings, $field['name'] . '_custom' ); if ( rgar( $field, 'required' ) && rgblank( $select_value ) ) { $this->set_field_error( $field ); return; } if ( rgar( $field, 'required' ) && $select_value == 'gf_custom' && rgblank( $custom_value ) ) { $custom_field = $field; $custom_field['name'] .= '_custom'; $this->set_field_error( $custom_field ); return; } if ( $select_value != 'gf_custom' ) { foreach( $field['choices'] as $choice ) { if ( isset( $choice['choices'] ) ) { foreach ( $choice['choices'] as $optgroup_choice ) { if ( $this->is_choice_valid( $optgroup_choice, $select_value ) ) { return; } } } else { if ( $this->is_choice_valid( $choice, $select_value ) ) { return; } } } $this->set_field_error( $field, esc_html__( 'Invalid value', 'gravityforms' ) ); } } public function validate_field_select_settings( $field, $settings ) { $field = $this->prepare_field_select_field( $field ); $this->validate_select_settings( $field, $settings ); } public function validate_field_map_settings( $field, $settings ) { $field_map = rgar( $field, 'field_map' ); if ( empty( $field_map ) ) { return; } foreach ( $field_map as $child_field ) { if ( ! $this->setting_dependency_met( rgar( $child_field, 'dependency' ) ) ) { continue; } $child_field['name'] = $this->get_mapped_field_name( $field, $child_field['name'] ); $setting_value = rgar( $settings, $child_field['name'] ); if ( rgar( $child_field, 'required' ) && rgblank( $setting_value ) ) { $this->set_field_error( $child_field ); } elseif ( rgar( $child_field, 'validation_callback' ) && is_callable( rgar( $child_field, 'validation_callback' ) ) ) { call_user_func( rgar( $child_field, 'validation_callback' ), $child_field, $field ); } } } public function validate_checkbox_and_select_settings( $field, $settings ) { $field = $this->prepare_settings_checkbox_and_select( $field ); $checkbox_field = $field['checkbox']; $select_field = $field['select']; $this->validate_checkbox_settings( $checkbox_field, $settings ); $this->validate_select_settings( $select_field, $settings ); } /** * Helper to determine if the current choice is a match for the submitted field value. * * @param array $choice The choice properties. * @param string|array $value The submitted field value. * * @return bool */ public function is_choice_valid( $choice, $value ) { $choice_value = isset( $choice['value'] ) ? $choice['value'] : $choice['label']; return is_array( $value ) ? in_array( $choice_value, $value ) : $choice_value == $value; } /** * Sets the validation error message * Sets the error message to be displayed when a field fails validation. * When implementing a custom validation callback function, use this function to specify the error message to be displayed. * * @param array $field - The current field meta * @param string $error_message - The error message to be displayed */ public function set_field_error( $field, $error_message = '' ) { // set default error message if none passed if ( ! $error_message ) { $error_message = esc_html__( 'This field is required.', 'gravityforms' ); } $this->_setting_field_errors[ $field['name'] ] = $error_message; } /** * Gets the validation errors for a field. * Returns validation errors associated with the specified field or a list of all validation messages (if a field isn't specified) * * @param array|boolean $field - Optional. The field meta. When specified, errors for this field will be returned * * @return mixed - If a field is specified, a string containing the error message will be returned. Otherwise, an array of all errors will be returned */ public function get_field_errors( $field = false ) { if ( ! $field ) { return $this->_setting_field_errors; } return isset( $this->_setting_field_errors[ $field['name'] ] ) ? $this->_setting_field_errors[ $field['name'] ] : array(); } /** * Gets the invalid field icon * Returns the markup for an alert icon to indicate and highlight invalid fields. * * @param array $field - The field meta. * * @return string - The full markup for the icon */ public function get_error_icon( $field ) { $error = $this->get_field_errors( $field ); return ' '; } /** * Returns the tooltip markup if a tooltip is configured for the supplied item (field/child field/choice). * * @param array $item The item properties. * * @return string */ public function maybe_get_tooltip( $item ) { $html = ''; if ( isset( $item['tooltip'] ) ) { $html = ' ' . gform_tooltip( $item['tooltip'], rgar( $item, 'tooltip_class' ), true ); } return $html; } /** * Gets the required indicator * Gets the markup of the required indicator symbol to highlight fields that are required * * @param $field - The field meta. * * @return string - Returns markup of the required indicator symbol */ public function get_required_indicator( $field ) { return '*'; } /** * Checks if the specified field failed validation * * @param $field - The field meta to be checked * * @return bool|mixed - Returns a validation error string if the field has failed validation. Otherwise returns false */ public function field_failed_validation( $field ) { $field_error = $this->get_field_errors( $field ); return ! empty( $field_error ) ? $field_error : false; } /** * Filter settings fields. * Runs through each field and applies the 'save_callback', if set, before saving the settings. * To specify a custom save filter, use the 'save_callback' field meta property and implement the save filter function with the custom logic. * * @param $fields - A list of all fields from the field meta configuration * @param $settings - A list of submitted settings values * * @return $settings - The updated settings values. */ public function filter_settings( $fields, $settings ) { foreach ( $fields as $section ) { if ( ! $this->setting_dependency_met( rgar( $section, 'dependency' ) ) ) { continue; } foreach ( $section['fields'] as $field ) { if ( ! $this->setting_dependency_met( rgar( $field, 'dependency' ) ) ) { continue; } $field_setting = rgar( $settings, rgar( $field, 'name' ) ); if ( is_callable( rgar( $field, 'save_callback' ) ) ) { $settings[ $field['name'] ] = call_user_func( rgar( $field, 'save_callback' ), $field, $field_setting ); continue; } } } return $settings; } public function add_field_before( $name, $fields, $settings ) { return $this->add_field( $name, $fields, $settings, 'before' ); } public function add_field_after( $name, $fields, $settings ) { return $this->add_field( $name, $fields, $settings, 'after' ); } public function add_field( $name, $fields, $settings, $pos ) { if ( rgar( $fields, 'name' ) ) { $fields = array( $fields ); } $pos_mod = $pos == 'before' ? 0 : 1; foreach ( $settings as &$section ) { for ( $i = 0; $i < count( $section['fields'] ); $i ++ ) { if ( $section['fields'][ $i ]['name'] == $name ) { array_splice( $section['fields'], $i + $pos_mod, 0, $fields ); break 2; } } } return $settings; } public function remove_field( $name, $settings ) { foreach ( $settings as &$section ) { for ( $i = 0; $i < count( $section['fields'] ); $i ++ ) { if ( $section['fields'][ $i ]['name'] == $name ) { array_splice( $section['fields'], $i, 1 ); break 2; } } } return $settings; } public function replace_field( $name, $fields, $settings ) { if ( rgar( $fields, 'name' ) ) { $fields = array( $fields ); } foreach ( $settings as &$section ) { for ( $i = 0; $i < count( $section['fields'] ); $i ++ ) { if ( $section['fields'][ $i ]['name'] == $name ) { array_splice( $section['fields'], $i, 1, $fields ); break 2; } } } return $settings; } public function get_field( $name, $settings ) { foreach ( $settings as $section ) { for ( $i = 0; $i < count( $section['fields'] ); $i ++ ) { if ( rgar( $section['fields'][ $i ], 'name' ) == $name ) { return $section['fields'][ $i ]; } } } return false; } public function build_choices( $key_value_pairs ) { $choices = array(); if ( ! is_array( $key_value_pairs ) ) { return $choices; } $first_key = key( $key_value_pairs ); $is_numeric = is_int( $first_key ) && $first_key === 0; foreach ( $key_value_pairs as $value => $label ) { if ( $is_numeric ) { $value = $label; } $choices[] = array( 'value' => $value, 'label' => $label ); } return $choices; } //-------------- Simple Condition ------------------------------------------------ /** * Helper to create a simple conditional logic set of fields. It creates one row of conditional logic with Field/Operator/Value inputs. * * @param mixed $setting_name_root - The root name to be used for inputs. It will be used as a prefix to the inputs that make up the conditional logic fields. * * @return string The HTML */ public function simple_condition( $setting_name_root ) { $conditional_fields = $this->get_conditional_logic_fields(); $value_input = esc_js( '_gaddon_setting_' . esc_attr( $setting_name_root ) . '_value' ); $object_type = esc_js( "simple_condition_{$setting_name_root}" ); $str = $this->settings_select( array( 'name' => "{$setting_name_root}_field_id", 'type' => 'select', 'choices' => $conditional_fields, 'class' => 'optin_select', 'onchange' => "jQuery('#" . esc_js( $setting_name_root ) . "_container').html(GetRuleValues('{$object_type}', 0, jQuery(this).val(), '', '{$value_input}'));" ), false ); $str .= $this->settings_select( array( 'name' => "{$setting_name_root}_operator", 'type' => 'select', 'onchange' => "SetRuleProperty('{$object_type}', 0, 'operator', jQuery(this).val()); jQuery('#" . esc_js( $setting_name_root ) . "_container').html(GetRuleValues('{$object_type}', 0, jQuery('#{$setting_name_root}_field_id').val(), '', '{$value_input}'));", 'choices' => array( array( 'value' => 'is', 'label' => esc_html__( 'is', 'gravityforms' ), ), array( 'value' => 'isnot', 'label' => esc_html__( 'is not', 'gravityforms' ), ), array( 'value' => '>', 'label' => esc_html__( 'greater than', 'gravityforms' ), ), array( 'value' => '<', 'label' => esc_html__( 'less than', 'gravityforms' ), ), array( 'value' => 'contains', 'label' => esc_html__( 'contains', 'gravityforms' ), ), array( 'value' => 'starts_with', 'label' => esc_html__( 'starts with', 'gravityforms' ), ), array( 'value' => 'ends_with', 'label' => esc_html__( 'ends with', 'gravityforms' ), ), ), ), false ); $str .= sprintf( "", esc_attr( $setting_name_root ) ); $field_id = $this->get_setting( "{$setting_name_root}_field_id" ); $value = $this->get_setting( "{$setting_name_root}_value" ); $operator = $this->get_setting( "{$setting_name_root}_operator" ); if ( empty( $operator ) ) { $operator = 'is'; } $field_id_attribute = ! empty( $field_id ) ? $field_id : 'jQuery("#' . esc_attr( $setting_name_root ) . '_field_id").val()'; $str .= ""; return $str; } /** * Override this to define the array of choices which should be used to populate the Simple Condition fields drop down. * * Each choice should have 'label' and 'value' properties. * * @return array */ public function get_conditional_logic_fields() { return array(); } /** * Evaluate the rules defined for the Simple Condition field. * * @param string $setting_name_root The root name used as the prefix to the inputs that make up the Simple Condition field. * @param array $form The form currently being processed. * @param array $entry The entry currently being processed. * @param array $feed The feed currently being processed or an empty array when the field is stored in the form settings. * * @return bool */ public function is_simple_condition_met( $setting_name_root, $form, $entry, $feed = array() ) { $settings = empty( $feed ) ? $this->get_form_settings( $form ) : rgar( $feed, 'meta', array() ); $is_enabled = rgar( $settings, $setting_name_root . '_enabled' ); if ( ! $is_enabled ) { // The setting is not enabled so we handle it as if the rules are met. return true; } // Build the logic array to be used by Gravity Forms when evaluating the rules. $logic = array( 'logicType' => 'all', 'rules' => array( array( 'fieldId' => rgar( $settings, $setting_name_root . '_field_id' ), 'operator' => rgar( $settings, $setting_name_root . '_operator' ), 'value' => rgar( $settings, $setting_name_root . '_value' ), ), ) ); return GFCommon::evaluate_conditional_logic( $logic, $form, $entry ); } //-------------- Form settings --------------------------------------------------- /** * Initializes form settings page * Hooks up the required scripts and actions for the Form Settings page */ public function form_settings_init() { $view = rgget( 'view' ); $subview = rgget( 'subview' ); add_filter( 'gform_form_settings_menu', array( $this, 'add_form_settings_menu' ), 10, 2 ); if ( rgget( 'page' ) == 'gf_edit_forms' && $view == 'settings' && $subview == $this->_slug && $this->current_user_can_any( $this->_capabilities_form_settings ) ) { require_once( GFCommon::get_base_path() . '/tooltips.php' ); add_action( 'gform_form_settings_page_' . $this->_slug, array( $this, 'form_settings_page' ) ); } } /** * Initializes plugin settings page * Hooks up the required scripts and actions for the Plugin Settings page */ public function plugin_page_init() { if ( $this->current_user_can_any( $this->_capabilities_plugin_page ) ) { //creates the subnav left menu add_filter( 'gform_addon_navigation', array( $this, 'create_plugin_page_menu' ) ); } } /** * Creates plugin page menu item * Target of gform_addon_navigation filter. Creates a menu item in the left nav, linking to the plugin page * * @param $menus - Current list of menu items * * @return array - Returns a new list of menu items */ public function create_plugin_page_menu( $menus ) { $menus[] = array( 'name' => $this->_slug, 'label' => $this->get_short_title(), 'callback' => array( $this, 'plugin_page_container' ), 'permission' => $this->_capabilities_plugin_page ); return $menus; } /** * Renders the form settings page. * * Not intended to be overridden or called directly by Add-Ons. * Sets up the form settings page. * * @ignore */ public function form_settings_page() { GFFormSettings::page_header( $this->_title ); ?>
    get_current_form(); $form_id = $form['id']; $form = gf_apply_filters( array( 'gform_admin_pre_render', $form_id ), $form ); if ( $this->method_is_overridden( 'form_settings' ) ) { //enables plugins to override settings page by implementing a form_settings() function $this->form_settings( $form ); } else { //saves form settings if save button was pressed $this->maybe_save_form_settings( $form ); //reads current form settings $settings = $this->get_form_settings( $form ); $this->set_settings( $settings ); //reading addon fields $sections = $this->form_settings_fields( $form ); GFCommon::display_admin_message(); $page_title = $this->form_settings_page_title(); if ( empty( $page_title ) ) { $page_title = rgar( $sections[0], 'title' ); //using first section title as page title, so disable section title $sections[0]['title'] = false; } $icon = $this->form_settings_icon(); if ( empty( $icon ) ) { $icon = ''; } ?>

    render_settings( $sections ); } ?>
    is_save_postback() ) { check_admin_referer( $this->_slug . '_save_settings', '_' . $this->_slug . '_save_settings_nonce' ); if ( ! $this->current_user_can_any( $this->_capabilities_form_settings ) ) { GFCommon::add_error_message( esc_html__( "You don't have sufficient permissions to update the form settings.", 'gravityforms' ) ); return false; } // store a copy of the previous settings for cases where action would only happen if value has changed $this->set_previous_settings( $this->get_form_settings( $form ) ); $settings = $this->get_posted_settings(); $sections = $this->form_settings_fields( $form ); $is_valid = $this->validate_settings( $sections, $settings ); $result = false; if ( $is_valid ) { $settings = $this->filter_settings( $sections, $settings ); $result = $this->save_form_settings( $form, $settings ); } if ( $result ) { GFCommon::add_message( $this->get_save_success_message( $sections ) ); } else { GFCommon::add_error_message( $this->get_save_error_message( $sections ) ); } return $result; } } /*** * Saves form settings to form object * * @param array $form * @param array $settings * * @return true|false True on success or false on error */ public function save_form_settings( $form, $settings ) { $form[ $this->_slug ] = $settings; $result = GFFormsModel::update_form_meta( $form['id'], $form ); return ! ( false === $result ); } /** * Checks whether the current Add-On has a form settings page. * * @return bool */ private function has_form_settings_page() { return $this->method_is_overridden( 'form_settings_fields' ) || $this->method_is_overridden( 'form_settings' ); } /** * Custom form settings page * Override this function to implement a complete custom form settings page. * Before overriding this function, consider using the form_settings_fields() and specifying your field meta. */ public function form_settings( $form ) { } /** * Custom form settings title * Override this function to display a custom title on the Form Settings Page. * By default, the first section in the configuration done in form_settings_fields() will be used as the page title. * Use this function to override that behavior and add a custom page title. */ public function form_settings_page_title() { return ''; } /** * Override this function to customize the form settings icon */ public function form_settings_icon() { return ''; } /** * Checks whether the current Add-On has a plugin page. * * @return bool */ private function has_plugin_page() { return $this->method_is_overridden( 'plugin_page' ); } /** * Override this function to create a custom plugin page */ public function plugin_page() { } /** * Override this function to customize the plugin page icon */ public function plugin_page_icon() { return ''; } /** * Override this function to customize the plugin page title */ public function plugin_page_title() { return $this->_title; } /** * Plugin page container * Target of the plugin menu left nav icon. Displays the outer plugin page markup and calls plugin_page() to render the actual page. * Override plugin_page() in order to provide a custom plugin page */ public function plugin_page_container() { ?>
    plugin_page_icon(); if ( ! empty( $icon ) ) { ?> <?php echo $this->get_short_title() ?>

    plugin_page_title() ?>

    plugin_page(); ?>
    has_app_settings() || $this->method_is_overridden( 'get_app_menu_items' ); } /** * Creates a top level app menu. Adds the app settings page automatically if it's configured. * Target of the WordPress admin_menu action. * Not intended to be overridden or called directly by add-ons. */ public function create_app_menu() { $has_full_access = current_user_can( 'gform_full_access' ); $min_cap = GFCommon::current_user_can_which( $this->_capabilities_app_menu ); if ( empty( $min_cap ) ) { $min_cap = 'gform_full_access'; } $menu_items = $this->get_app_menu_items(); $addon_menus = array(); /** * Filters through addon menus (filter by addon slugs) * * @param array $addon_menus A modifiable array of admin addon menus */ $addon_menus = apply_filters( 'gform_addon_app_navigation_' . $this->_slug, $addon_menus ); $parent_menu = self::get_parent_menu( $menu_items, $addon_menus ); if ( empty( $parent_menu ) ) { return; } // Add a top-level left nav $callback = isset( $parent_menu['callback'] ) ? $parent_menu['callback'] : array( $this, 'app_tab_page' ); global $menu; $number = 10; $menu_position = '16.' . $number; while ( isset( $menu[$menu_position] ) ) { $number += 10; $menu_position = '16.' . $number; } /** * Modify the menu position of an add-on menu * * @param int $menu_position The Menu position of the add-on menu */ $menu_position = apply_filters( 'gform_app_menu_position_' . $this->_slug, $menu_position ); $this->app_hook_suffix = add_menu_page( $this->get_short_title(), $this->get_short_title(), $has_full_access ? 'gform_full_access' : $min_cap, $parent_menu['name'], $callback, $this->get_app_menu_icon(), $menu_position ); if ( method_exists( $this, 'load_screen_options' ) ) { add_action( "load-$this->app_hook_suffix", array( $this, 'load_screen_options' ) ); } // Adding submenu pages foreach ( $menu_items as $menu_item ) { $callback = isset( $menu_item['callback'] ) ? $menu_item['callback'] : array( $this, 'app_tab_page' ); add_submenu_page( $parent_menu['name'], $menu_item['label'], $menu_item['label'], $has_full_access || empty( $menu_item['permission'] ) ? 'gform_full_access' : $menu_item['permission'], $menu_item['name'], $callback ); } if ( is_array( $addon_menus ) ) { foreach ( $addon_menus as $addon_menu ) { add_submenu_page( $parent_menu['name'], $addon_menu['label'], $addon_menu['label'], $has_full_access ? 'gform_full_access' : $addon_menu['permission'], $addon_menu['name'], $addon_menu['callback'] ); } } if ( $this->has_app_settings() ) { add_submenu_page( $parent_menu['name'], esc_html__( 'Settings', 'gravityforms' ), esc_html__( 'Settings', 'gravityforms' ), $has_full_access ? 'gform_full_access' : $this->_capabilities_app_settings, $this->_slug . '_settings', array( $this, 'app_tab_page' ) ); } } /** * Returns the parent menu item * * @param $menu_items * @param $addon_menus * * @return array|bool The parent menu araray or false if none */ private function get_parent_menu( $menu_items, $addon_menus ) { $parent = false; if ( GFCommon::current_user_can_any( $this->_capabilities_app_menu ) ) { foreach ( $menu_items as $menu_item ) { if ( $this->current_user_can_any( $menu_item['permission'] ) ) { $parent = $menu_item; break; } } } elseif ( is_array( $addon_menus ) && sizeof( $addon_menus ) > 0 ) { foreach ( $addon_menus as $addon_menu ) { if ( $this->current_user_can_any( $addon_menu['permission'] ) ) { $parent = array( 'name' => $addon_menu['name'], 'callback' => $addon_menu['callback'] ); break; } } } elseif ( $this->has_app_settings() && $this->current_user_can_any( $this->_capabilities_app_settings ) ) { $parent = array( 'name' => $this->_slug . '_settings', 'callback' => array( $this, 'app_settings' ) ); } return $parent; } /** * Override this function to create a top level app menu. * * e.g. * $menu_item['name'] = 'gravitycontacts'; * $menu_item['label'] = __("Contacts", 'gravitycontacts'); * $menu_item['permission'] = 'gravitycontacts_view_contacts'; * $menu_item['callback'] = array($this, 'app_menu'); * * @return array The array of menu items */ public function get_app_menu_items() { return array(); } /** * Override this function to specify a custom icon for the top level app menu. * Accepts a dashicon class or a URL. * * @return string */ public function get_app_menu_icon() { return ''; } /** * Override this function to load custom screen options. * * e.g. * $screen = get_current_screen(); * if(!is_object($screen) || $screen->id != $this->app_hook_suffix) * return; * * if($this->is_contact_list_page()){ * $args = array( * 'label' => __('Contacts per page', 'gravitycontacts'), * 'default' => 20, * 'option' => 'gcontacts_per_page' * ); * add_screen_option( 'per_page', $args ); */ public function load_screen_options() { } /** * Handles the rendering of app menu items that implement the tabs UI. * * Not intended to be overridden or called directly by add-ons. */ public function app_tab_page() { $page = sanitize_text_field( rgget( 'page' ) ); $current_tab = sanitize_text_field( rgget( 'view' ) ); if ( $page == $this->_slug . '_settings' ) { $tabs = $this->get_app_settings_tabs(); } else { $menu_items = $this->get_app_menu_items(); $current_menu_item = false; foreach ( $menu_items as $menu_item ) { if ( $menu_item['name'] == $page ) { $current_menu_item = $menu_item; break; } } if ( empty( $current_menu_item ) ) { return; } if ( empty( $current_menu_item['tabs'] ) ) { return; } $tabs = $current_menu_item['tabs']; } if ( empty( $current_tab ) ) { foreach ( $tabs as $tab ) { if ( ! isset( $tab['permission'] ) || $this->current_user_can_any( $tab['permission'] ) ) { $current_tab = $tab['name']; break; } } } if ( empty( $current_tab ) ) { wp_die( esc_html__( "You don't have adequate permission to view this page", 'gravityforms' ) ); } foreach ( $tabs as $tab ) { if ( $tab['name'] == $current_tab && isset( $tab['callback'] ) && is_callable( $tab['callback'] ) ) { if ( isset( $tab['permission'] ) && ! $this->current_user_can_any( $tab['permission'] ) ) { wp_die( esc_html__( "You don't have adequate permission to view this page", 'gravityforms' ) ); } $title = rgar( $tab,'title' ); if ( empty( $title ) ) { $title = isset( $tab['label'] ) ? $tab['label'] : $tab['name']; } $this->app_tab_page_header( $tabs, $current_tab, $title, '' ); call_user_func( $tab['callback'] ); $this->app_tab_page_footer(); return; } } $this->app_tab_page_header( $tabs, $current_tab, $current_tab, '' ); /** * Fires when an addon page and tab is accessed. * * Typically used to render settings tab content. */ $action_hook = 'gform_addon_app_' . $page . '_' . str_replace( ' ', '_', $current_tab ); do_action( $action_hook ); $this->app_tab_page_footer(); } /** * Returns the form settings for the Add-On * * @param $form * * @return array */ public function get_form_settings( $form ) { return rgar( $form, $this->_slug ); } /** * Add the form settings tab. * * Override this function to add the tab conditionally. * * * @param $tabs * @param $form_id * * @return array */ public function add_form_settings_menu( $tabs, $form_id ) { $tabs[] = array( 'name' => $this->_slug, 'label' => $this->get_short_title(), 'query' => array( 'fid' => null ), 'capabilities' => $this->_capabilities_form_settings ); return $tabs; } /** * Override this function to specify the settings fields to be rendered on the form settings page */ public function form_settings_fields( $form ) { // should return an array of sections, each section contains a title, description and an array of fields return array(); } //-------------- Plugin Settings --------------------------------------------------- public function plugin_settings_init() { $subview = rgget( 'subview' ); RGForms::add_settings_page( array( 'name' => $this->_slug, 'tab_label' => $this->get_short_title(), 'title' => $this->plugin_settings_title(), 'handler' => array( $this, 'plugin_settings_page' ), ) ); if ( rgget( 'page' ) == 'gf_settings' && $subview == $this->_slug && $this->current_user_can_any( $this->_capabilities_settings_page ) ) { require_once( GFCommon::get_base_path() . '/tooltips.php' ); } add_filter( 'plugin_action_links', array( $this, 'plugin_settings_link' ), 10, 2 ); } public function plugin_settings_link( $links, $file ) { if ( $file != $this->get_path() ) { return $links; } array_unshift( $links, '' . esc_html__( 'Settings', 'gravityforms' ) . '' ); return $links; } /** * Plugin settings page */ public function plugin_settings_page() { $icon = $this->plugin_settings_icon(); if ( empty( $icon ) ) { $icon = ''; } ?>

    plugin_settings_title() ?>

    has_deprecated_elements() ) : ?>
    method_is_overridden( 'plugin_settings' ) ) { //enables plugins to override settings page by implementing a plugin_settings() function $this->plugin_settings(); } elseif ( $this->maybe_uninstall() ) { ?>
    _title, "", '' ); ?>
    maybe_save_plugin_settings(); //reads main addon settings $settings = $this->get_plugin_settings(); $this->set_settings( $settings ); //reading addon fields $sections = $this->plugin_settings_fields(); GFCommon::display_admin_message(); //rendering settings based on fields and current settings $this->render_settings( $sections, $settings ); //renders uninstall section $this->render_uninstall(); } } public function plugin_settings_title() { return sprintf( esc_html__( "%s Settings", "gravityforms" ), $this->get_short_title() ); } public function plugin_settings_icon() { return ''; } /** * Override this function to add a custom settings page. */ public function plugin_settings() { } /** * Checks whether the current Add-On has a settings page. * * @return bool */ public function has_plugin_settings_page() { return $this->method_is_overridden( 'plugin_settings_fields' ) || $this->method_is_overridden( 'plugin_settings_page' ) || $this->method_is_overridden( 'plugin_settings' ); } /** * Returns the currently saved plugin settings * @return mixed */ public function get_plugin_settings() { return get_option( 'gravityformsaddon_' . $this->_slug . '_settings' ); } /** * Get plugin setting * Returns the plugin setting specified by the $setting_name parameter * * @param string $setting_name - Plugin setting to be returned * * @return mixed - Returns the specified plugin setting or null if the setting doesn't exist */ public function get_plugin_setting( $setting_name ) { $settings = $this->get_plugin_settings(); return isset( $settings[ $setting_name ] ) ? $settings[ $setting_name ] : null; } /** * Updates plugin settings with the provided settings * * @param array $settings - Plugin settings to be saved */ public function update_plugin_settings( $settings ) { update_option( 'gravityformsaddon_' . $this->_slug . '_settings', $settings ); } /** * Saves the plugin settings if the submit button was pressed * */ public function maybe_save_plugin_settings() { if ( $this->is_save_postback() ) { check_admin_referer( $this->_slug . '_save_settings', '_' . $this->_slug . '_save_settings_nonce' ); if ( ! $this->current_user_can_any( $this->_capabilities_settings_page ) ) { GFCommon::add_error_message( esc_html__( "You don't have sufficient permissions to update the settings.", 'gravityforms' ) ); return false; } // store a copy of the previous settings for cases where action would only happen if value has changed $this->set_previous_settings( $this->get_plugin_settings() ); $settings = $this->get_posted_settings(); $sections = $this->plugin_settings_fields(); $is_valid = $this->validate_settings( $sections, $settings ); if ( $is_valid ) { $settings = $this->filter_settings( $sections, $settings ); $this->update_plugin_settings( $settings ); GFCommon::add_message( $this->get_save_success_message( $sections ) ); } else { GFCommon::add_error_message( $this->get_save_error_message( $sections ) ); } } } /** * Override this function to specify the settings fields to be rendered on the plugin settings page * @return array */ public function plugin_settings_fields() { // should return an array of sections, each section contains a title, description and an array of fields return array(); } //-------------- App Settings --------------------------------------------------- /** * Returns the tabs for the settings app menu item * * Not intended to be overridden or called directly by add-ons. * * @return array|mixed|void */ public function get_app_settings_tabs() { // Build left side options, always have app Settings first and Uninstall last, put add-ons in the middle $setting_tabs = array( array( 'name' => 'settings', 'label' => esc_html__( 'Settings', 'gravityforms' ), 'callback' => array( $this, 'app_settings_tab' ) ) ); /** * Filters the tabs within the settings menu. * * This filter is appended by the page slug. Ex: gform_addon_app_settings_menu_SLUG * * @param array $setting_tabs Contains the information on the settings tabs. */ $setting_tabs = apply_filters( 'gform_addon_app_settings_menu_' . $this->_slug, $setting_tabs ); if ( $this->current_user_can_uninstall() ) { $setting_tabs[] = array( 'name' => 'uninstall', 'label' => esc_html__( 'Uninstall', 'gravityforms' ), 'callback' => array( $this, 'app_settings_uninstall_tab' ) ); } ksort( $setting_tabs, SORT_NUMERIC ); return $setting_tabs; } /** * Renders the app settings uninstall tab. * * Not intended to be overridden or called directly by add-ons. */ public function app_settings_uninstall_tab() { if ( $this->maybe_uninstall() ) { ?>
    _title ), "", '' ); ?>
    current_user_can_uninstall() ) { ?>

    get_short_title() ); ?>

    uninstall_warning_message() ?>
    get_short_title() ) . '" class="button" onclick="return confirm(\'' . esc_js( $this->uninstall_confirm_message() ) . '\');" onkeypress="return confirm(\'' . esc_js( $this->uninstall_confirm_message() ) . '\');"/>'; echo $uninstall_button; ?>


    app_settings_icon(); if ( empty( $icon ) ) { $icon = ''; } ?>

    app_settings_title() ?>

    method_is_overridden( 'app_settings' ) ) { //enables plugins to override settings page by implementing a plugin_settings() function $this->app_settings(); } elseif ( $this->maybe_uninstall() ) { ?>
    _title ), "", '' ); ?>
    maybe_save_app_settings(); //reads main addon settings $settings = $this->get_app_settings(); $this->set_settings( $settings ); //reading addon fields $sections = $this->app_settings_fields(); GFCommon::display_admin_message(); //rendering settings based on fields and current settings $this->render_settings( $sections, $settings ); } } /** * Override this function to specific a custom app settings title * * @return string */ public function app_settings_title() { return sprintf( esc_html__( '%s Settings', 'gravityforms' ), $this->get_short_title() ); } /** * Override this function to specific a custom app settings icon * * @return string */ public function app_settings_icon() { return ''; } /** * Checks whether the current Add-On has a settings page. * * @return bool */ public function has_app_settings() { return $this->method_is_overridden( 'app_settings_fields' ) || $this->method_is_overridden( 'app_settings' ); } /** * Override this function to add a custom app settings page. */ public function app_settings() { } /** * Returns the currently saved plugin settings * @return mixed */ public function get_app_settings() { return get_option( 'gravityformsaddon_' . $this->_slug . '_app_settings' ); } /** * Get app setting * Returns the app setting specified by the $setting_name parameter * * @param string $setting_name - Plugin setting to be returned * * @return mixed - Returns the specified plugin setting or null if the setting doesn't exist */ public function get_app_setting( $setting_name ) { $settings = $this->get_app_settings(); return isset( $settings[ $setting_name ] ) ? $settings[ $setting_name ] : null; } /** * Updates app settings with the provided settings * * @param array $settings - App settings to be saved */ public function update_app_settings( $settings ) { update_option( 'gravityformsaddon_' . $this->_slug . '_app_settings', $settings ); } /** * Saves the plugin settings if the submit button was pressed * */ public function maybe_save_app_settings() { if ( $this->is_save_postback() ) { check_admin_referer( $this->_slug . '_save_settings', '_' . $this->_slug . '_save_settings_nonce' ); if ( ! $this->current_user_can_any( $this->_capabilities_app_settings ) ) { GFCommon::add_error_message( esc_html__( "You don't have sufficient permissions to update the settings.", 'gravityforms' ) ); return false; } // store a copy of the previous settings for cases where action would only happen if value has changed $this->set_previous_settings( $this->get_app_settings() ); $settings = $this->get_posted_settings(); $sections = $this->app_settings_fields(); $is_valid = $this->validate_settings( $sections, $settings ); if ( $is_valid ) { $settings = $this->filter_settings( $sections, $settings ); $this->update_app_settings( $settings ); GFCommon::add_message( $this->get_save_success_message( $sections ) ); } else { GFCommon::add_error_message( $this->get_save_error_message( $sections ) ); } } } /** * Override this function to specify the settings fields to be rendered on the plugin settings page * @return array */ public function app_settings_fields() { // should return an array of sections, each section contains a title, description and an array of fields return array(); } /** * Returns an flattened array of field settings for the specified settings type ignoring sections. * * @param string $settings_type The settings type. e.g. 'plugin' * * @return array */ public function settings_fields_only( $settings_type = 'plugin' ) { $fields = array(); if ( ! is_callable( array( $this, "{$settings_type}_settings_fields" ) ) ) { return $fields; } $sections = call_user_func( array( $this, "{$settings_type}_settings_fields" ) ); foreach ( $sections as $section ) { foreach ( $section['fields'] as $field ) { $fields[] = $field; } } return $fields; } //-------------- Uninstall --------------- /** * Override this function to customize the markup for the uninstall section on the plugin settings page */ public function render_uninstall() { ?>
    current_user_can_uninstall() ) { ?>

    get_short_title() ) ?>

    uninstall_warning_message() ?>
    ', esc_html( $this->get_short_title() ), '' ); } public function uninstall_confirm_message() { return sprintf( __( "Warning! ALL %s settings will be deleted. This cannot be undone. 'OK' to delete, 'Cancel' to stop", 'gravityforms' ), __( $this->get_short_title() ) ); } /** * Not intended to be overridden or called directly by Add-Ons. * * @ignore */ public function maybe_uninstall() { if ( rgpost( 'uninstall' ) ) { check_admin_referer( 'uninstall', 'gf_addon_uninstall' ); return $this->uninstall_addon(); } return false; } /** * Removes all settings and deactivates the Add-On. * * Not intended to be overridden or called directly by Add-Ons. * * @ignore */ public function uninstall_addon() { if ( ! $this->current_user_can_uninstall() ) { die( esc_html__( "You don't have adequate permission to uninstall this add-on: " . $this->_title, 'gravityforms' ) ); } $continue = $this->uninstall(); if ( false === $continue ) { return false; } global $wpdb; $forms = GFFormsModel::get_forms(); $all_form_ids = array(); // remove entry meta $meta_table = version_compare( GFFormsModel::get_database_version(), '2.3-dev-1', '<' ) ? GFFormsModel::get_lead_meta_table_name() : GFFormsModel::get_entry_meta_table_name(); remove_filter( 'query', array( 'GFForms', 'filter_query' ) ); foreach ( $forms as $form ) { $all_form_ids[] = $form->id; $entry_meta = $this->get_entry_meta( array(), $form->id ); if ( is_array( $entry_meta ) ) { foreach ( array_keys( $entry_meta ) as $meta_key ) { $sql = $wpdb->prepare( "DELETE from $meta_table WHERE meta_key=%s", $meta_key ); $wpdb->query( $sql ); } } } add_filter( 'query', array( 'GFForms', 'filter_query' ) ); //remove form settings if ( ! empty( $all_form_ids ) ) { $form_metas = GFFormsModel::get_form_meta_by_id( $all_form_ids ); require_once( GFCommon::get_base_path() . '/form_detail.php' ); foreach ( $form_metas as $form_meta ) { if ( isset( $form_meta[ $this->_slug ] ) ) { unset( $form_meta[ $this->_slug ] ); $form_json = json_encode( $form_meta ); GFFormDetail::save_form_info( $form_meta['id'], addslashes( $form_json ) ); } } } //removing options delete_option( 'gravityformsaddon_' . $this->_slug . '_settings' ); delete_option( 'gravityformsaddon_' . $this->_slug . '_app_settings' ); delete_option( 'gravityformsaddon_' . $this->_slug . '_version' ); //Deactivating plugin deactivate_plugins( $this->get_path() ); update_option( 'recently_activated', array( $this->get_path() => time() ) + (array) get_option( 'recently_activated' ) ); return true; } /** * Called when the user chooses to uninstall the Add-On - after permissions have been checked and before removing * all Add-On settings and Form settings. * * Override this method to perform additional functions such as dropping database tables. * * * Return false to cancel the uninstall request. */ public function uninstall() { return true; } //-------------- Enforce minimum GF version --------------------------------------------------- /** * 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. * * Not intended to be overridden or called directly by Add-Ons. * * @since Unknown * @since 2.4.15 Update to improve multisite updates. * * @param string $plugin_name The plugin filename. Immediately overwritten. * @param array $plugin_data An array of plugin data. */ public function plugin_row( $plugin_name, $plugin_data ) { if ( false === $this->_enable_rg_autoupgrade && ! self::is_gravityforms_supported( $this->_min_gravityforms_version ) ) { $message = $this->plugin_message(); self::display_plugin_message( $message, true ); } GFForms::maybe_display_update_notification( $plugin_name, $plugin_data, $this->get_slug(), $this->_version ); } /** * Returns the message that will be displayed if the current version of Gravity Forms is not supported. * * Override this method to display a custom message. */ public function plugin_message() { $message = sprintf( esc_html__( 'Gravity Forms %s is required. Activate it now or %spurchase it today!%s', 'gravityforms' ), $this->_min_gravityforms_version, "", '' ); return $message; } /** * Formats and outs a message for the plugin row. * * Not intended to be overridden or called directly by Add-Ons. * * @ignore * * @param $message * @param bool $is_error */ public static function display_plugin_message( $message, $is_error = false ) { $style = $is_error ? 'style="background-color: #ffebe8;"' : ''; echo '
    ' . $message . '
    '; } //--------------- Logging ------------------------------------------------------------- /** * Writes an error message to the Gravity Forms log. Requires the Gravity Forms logging Add-On. * * Not intended to be overridden by Add-Ons. * * @ignore */ public function log_error( $message ) { if ( class_exists( 'GFLogging' ) ) { GFLogging::include_logger(); GFLogging::log_message( $this->_slug, $message, KLogger::ERROR ); } } /** * Writes an error message to the Gravity Forms log. Requires the Gravity Forms logging Add-On. * * Not intended to be overridden by Add-Ons. * * @ignore */ public function log_debug( $message ) { if ( class_exists( 'GFLogging' ) ) { GFLogging::include_logger(); GFLogging::log_message( $this->_slug, $message, KLogger::DEBUG ); } } //--------------- Locking ------------------------------------------------------------ /** * Returns the configuration for locking * * e.g. * * array( * "object_type" => 'contact', * "capabilities" => array("gravityforms_contacts_edit_contacts"), * "redirect_url" => admin_url("admin.php?page=gf_contacts"), * "edit_url" => admin_url(sprintf("admin.php?page=gf_contacts&id=%d", $contact_id)), * "strings" => $strings * ); * * Override this method to implement locking */ public function get_locking_config() { return array(); } /** * Returns TRUE if the current page is the edit page. Otherwise, returns FALSE * * Override this method to implement locking on the edit page. */ public function is_locking_edit_page() { return false; } /** * Returns TRUE if the current page is the list page. Otherwise, returns FALSE * * Override this method to display locking info on the list page. */ public function is_locking_list_page() { return false; } /** * Returns TRUE if the current page is the view page. Otherwise, returns FALSE * * Override this method to display locking info on the view page. */ public function is_locking_view_page() { return false; } /** * Returns the ID of the object to be locked. E.g. Form ID * * Override this method to implement locking */ public function get_locking_object_id() { return 0; } /** * Outputs information about the user currently editing the specified object * * @param int $object_id The Object ID * @param bool $echo Whether to echo * * @return string The markup for the lock info */ public function lock_info( $object_id, $echo = true ) { $gf_locking = new GFAddonLocking( $this->get_locking_config(), $this ); $lock_info = $gf_locking->lock_info( $object_id, false ); if ( $echo ) { echo $lock_info; } return $lock_info; } /** * Outputs class for the row for the specified Object ID on the list page. * * @param int $object_id The object ID * @param bool $echo Whether to echo * * @return string The markup for the class */ public function list_row_class( $object_id, $echo = true ) { $gf_locking = new GFAddonLocking( $this->get_locking_config(), $this ); $class = $gf_locking->list_row_class( $object_id, false ); if ( $echo ) { echo $class; } return $class; } /** * Checked whether an object is locked * * @param int|mixed $object_id The object ID * * @return bool */ public function is_object_locked( $object_id ) { $gf_locking = new GFAddonLocking( $this->get_locking_config(), $this ); return $gf_locking->is_locked( $object_id ); } //------------- Field Value Retrieval ------------------------------------------------- /** * Returns the value of the mapped field. * * @param string $setting_name * @param array $form * @param array $entry * @param mixed $settings * * @return string */ public function get_mapped_field_value( $setting_name, $form, $entry, $settings = false ) { $field_id = $this->get_setting( $setting_name, '', $settings ); return $this->get_field_value( $form, $entry, $field_id ); } /** * Returns the value of the selected field. * * @access private * * @param array $form * @param array $entry * @param string $field_id * * @return string field value */ public function get_field_value( $form, $entry, $field_id ) { $field_value = ''; switch ( strtolower( $field_id ) ) { case 'form_title': $field_value = rgar( $form, 'title' ); break; case 'date_created': $date_created = rgar( $entry, strtolower( $field_id ) ); if ( empty( $date_created ) ) { //the date created may not yet be populated if this function is called during the validation phase and the entry is not yet created $field_value = gmdate( 'Y-m-d H:i:s' ); } else { $field_value = $date_created; } break; case 'ip': case 'source_url': case 'id': $field_value = rgar( $entry, strtolower( $field_id ) ); break; default: $field = GFFormsModel::get_field( $form, $field_id ); if ( is_object( $field ) ) { $is_integer = $field_id == intval( $field_id ); $input_type = $field->get_input_type(); if ( $is_integer && $input_type == 'address' ) { $field_value = $this->get_full_address( $entry, $field_id ); } elseif ( $is_integer && $input_type == 'name' ) { $field_value = $this->get_full_name( $entry, $field_id ); } elseif ( is_callable( array( $this, "get_{$input_type}_field_value" ) ) ) { $field_value = call_user_func( array( $this, "get_{$input_type}_field_value" ), $entry, $field_id, $field ); } else { $field_value = $field->get_value_export( $entry, $field_id ); } } else { $field_value = rgar( $entry, $field_id ); } } /** * A generic filter allowing the field value to be overridden. Form and field id modifiers supported. * * @param string $field_value The value to be overridden. * @param array $form The Form currently being processed. * @param array $entry The Entry currently being processed. * @param string $field_id The ID of the Field currently being processed. * @param string $slug The add-on slug e.g. gravityformsactivecampaign. * * @since 1.9.15.12 * * @return string */ $field_value = gf_apply_filters( array( 'gform_addon_field_value', $form['id'], $field_id ), $field_value, $form, $entry, $field_id, $this->_slug ); return $this->maybe_override_field_value( $field_value, $form, $entry, $field_id ); } /** * Enables use of the gform_SLUG_field_value filter to override the field value. Override this function to prevent the filter being used or to implement a custom filter. * * @param string $field_value * @param array $form * @param array $entry * @param string $field_id * * @return string */ public function maybe_override_field_value( $field_value, $form, $entry, $field_id ) { /* Get Add-On slug */ $slug = str_replace( 'gravityforms', '', $this->_slug ); return gf_apply_filters( array( "gform_{$slug}_field_value", $form['id'], $field_id ), $field_value, $form, $entry, $field_id ); } /** * Returns the combined value of the specified Address field. * * @param array $entry * @param string $field_id * * @return string */ public function get_full_address( $entry, $field_id ) { return GF_Fields::get( 'address' )->get_value_export( $entry, $field_id ); } /** * Returns the combined value of the specified Name field. * * @param array $entry * @param string $field_id * * @return string */ public function get_full_name( $entry, $field_id ) { return GF_Fields::get( 'name' )->get_value_export( $entry, $field_id ); } /** * Returns the value of the specified List field. * * @param array $entry * @param string $field_id * @param GF_Field_List $field * * @return string */ public function get_list_field_value( $entry, $field_id, $field ) { return $field->get_value_export( $entry, $field_id ); } /** * Returns the field ID of the first field of the desired type. * * @access public * @param string $field_type * @param int $subfield_id (default: null) * @param int $form_id (default: null) * @return string */ public function get_first_field_by_type( $field_type, $subfield_id = null, $form_id = null, $return_first_only = true ) { /* Get the current form ID. */ if ( rgblank( $form_id ) ) { $form_id = rgget( 'id' ); } /* Get the form. */ $form = GFAPI::get_form( $form_id ); /* Get the request field type for the form. */ $fields = GFAPI::get_fields_by_type( $form, array( $field_type ) ); if ( count( $fields ) == 0 || ( count( $fields ) > 1 && $return_first_only ) ) { return null; } else { if ( rgblank( $subfield_id ) ) { return $fields[0]->id; } else { return $fields[0]->id . '.' . $subfield_id; } } } //--------------- Notes ------------------ /** * Override this function to specify a custom avatar (i.e. the payment gateway logo) for entry notes created by the Add-On * @return string - A fully qualified URL for the avatar */ public function note_avatar() { return false; } public function notes_avatar( $avatar, $note ) { if ( $note->user_name == $this->_short_title && empty( $note->user_id ) && $this->method_is_overridden( 'note_avatar', 'GFAddOn' ) ) { $new_avatar = $this->note_avatar(); } return empty( $new_avatar ) ? $avatar : "{$this->_short_title}"; } public function add_note( $entry_id, $note, $note_type = null ) { $user_id = 0; $user_name = $this->_short_title; GFFormsModel::add_note( $entry_id, $user_id, $user_name, $note, $note_type ); } //-------------- Helper functions --------------------------------------------------- protected final function method_is_overridden( $method_name, $base_class = 'GFAddOn' ) { $reflector = new ReflectionMethod( $this, $method_name ); $name = $reflector->getDeclaringClass()->getName(); return $name !== $base_class; } /** * Returns the url of the root folder of the current Add-On. * * @param string $full_path Optional. The full path the the plugin file. * * @return string */ public function get_base_url( $full_path = '' ) { if ( empty( $full_path ) ) { $full_path = $this->_full_path; } return plugins_url( null, $full_path ); } /** * Returns the url of the Add-On Framework root folder. * * @return string */ final public static function get_gfaddon_base_url() { return plugins_url( null, __FILE__ ); } /** * Returns the physical path of the Add-On Framework root folder. * * @return string */ final public static function get_gfaddon_base_path() { return self::_get_base_path(); } /** * Returns the physical path of the plugins root folder. * * @param string $full_path * * @return string */ public function get_base_path( $full_path = '' ) { if ( empty( $full_path ) ) { $full_path = $this->_full_path; } $folder = basename( dirname( $full_path ) ); return WP_PLUGIN_DIR . '/' . $folder; } /** * Returns the physical path of the Add-On Framework root folder * * @return string */ private static function _get_base_path() { $folder = basename( dirname( __FILE__ ) ); return GFCommon::get_base_path() . '/includes/' . $folder; } /** * Returns the URL of the Add-On Framework root folder * * @return string */ private static function _get_base_url() { $folder = basename( dirname( __FILE__ ) ); return GFCommon::get_base_url() . '/includes/' . $folder; } /** * Checks whether the Gravity Forms is installed. * * @return bool */ public function is_gravityforms_installed() { return class_exists( 'GFForms' ); } public function table_exists( $table_name ) { return GFCommon::table_exists( $table_name ); } /** * Checks whether the current version of Gravity Forms is supported * * @param $min_gravityforms_version * * @return bool|mixed */ public function is_gravityforms_supported( $min_gravityforms_version = '' ) { if ( isset( $this->_min_gravityforms_version ) && empty( $min_gravityforms_version ) ) { $min_gravityforms_version = $this->_min_gravityforms_version; } if ( empty( $min_gravityforms_version ) ) { return true; } if ( class_exists( 'GFCommon' ) ) { $is_correct_version = version_compare( GFCommon::$version, $min_gravityforms_version, '>=' ); return $is_correct_version; } else { return false; } } /** * Returns this plugin's short title. Used to display the plugin title in small areas such as tabs */ public function get_short_title() { return isset( $this->_short_title ) ? $this->_short_title : $this->_title; } /** * Return this plugin's version. * * @since 2.0 * @access public * * @return string */ public function get_version() { return $this->_version; } /** * Returns the unescaped URL for the plugin settings tab associated with this plugin * */ public function get_plugin_settings_url() { return add_query_arg( array( 'page' => 'gf_settings', 'subview' => $this->_slug ), admin_url( 'admin.php' ) ); } /** * Returns the current form object based on the id query var. Otherwise returns false */ public function get_current_form() { return rgempty( 'id', $_GET ) ? false : GFFormsModel::get_form_meta( rgget( 'id' ) ); } /** * Returns TRUE if the current request is a postback, otherwise returns FALSE */ public function is_postback() { return is_array( $_POST ) && count( $_POST ) > 0; } /** * Returns TRUE if the settings "Save" button was pressed */ public function is_save_postback() { return ! rgempty( 'gform-settings-save' ); } /** * Returns TRUE if the current page is the form editor page. Otherwise, returns FALSE */ public function is_form_editor() { if ( rgget( 'page' ) == 'gf_edit_forms' && ! rgempty( 'id', $_GET ) && rgempty( 'view', $_GET ) ) { return true; } return false; } /** * Returns TRUE if the current page is the form list page. Otherwise, returns FALSE */ public function is_form_list() { if ( rgget( 'page' ) == 'gf_edit_forms' && rgempty( 'id', $_GET ) && rgempty( 'view', $_GET ) ) { return true; } return false; } /** * Returns TRUE if the current page is the form settings page, or a specific form settings tab (specified by the $tab parameter). Otherwise returns FALSE * * @param string $tab - Specifies a specific form setting page/tab * * @return bool */ public function is_form_settings( $tab = null ) { $is_form_settings = rgget( 'page' ) == 'gf_edit_forms' && rgget( 'view' ) == 'settings'; $is_tab = $this->_tab_matches( $tab ); if ( $is_form_settings && $is_tab ) { return true; } else { return false; } } private function _tab_matches( $tabs ) { if ( $tabs == null ) { return true; } if ( ! is_array( $tabs ) ) { $tabs = array( $tabs ); } $current_tab = rgempty( 'subview', $_GET ) ? 'settings' : rgget( 'subview' ); foreach ( $tabs as $tab ) { if ( strtolower( $tab ) == strtolower( $current_tab ) ) { return true; } } } /** * Returns TRUE if the current page is the plugin settings main page, or a specific plugin settings tab (specified by the $tab parameter). Otherwise returns FALSE * * @param string $tab - Specifies a specific plugin setting page/tab. * * @return bool */ public function is_plugin_settings( $tab = '' ) { $is_plugin_settings = rgget( 'page' ) == 'gf_settings'; $is_tab = $this->_tab_matches( $tab ); if ( $is_plugin_settings && $is_tab ) { return true; } else { return false; } } /** * Returns TRUE if the current page is the app settings main page, or a specific apps settings tab (specified by the $tab parameter). Otherwise returns FALSE * * @param string $tab - Specifies a specific app setting page/tab. * * @return bool */ public function is_app_settings( $tab = '' ) { $is_app_settings = rgget( 'page' ) == $this->_slug . '_settings'; $is_tab = $this->_tab_matches( $tab ); if ( $is_app_settings && $is_tab ) { return true; } else { return false; } } /** * Returns TRUE if the current page is the plugin page. Otherwise returns FALSE * @return bool */ public function is_plugin_page() { return strtolower( rgget( 'page' ) ) == strtolower( $this->_slug ); } /** * Returns TRUE if the current page is the entry view page. Otherwise, returns FALSE * @return bool */ public function is_entry_view() { if ( rgget( 'page' ) == 'gf_entries' && rgget( 'view' ) == 'entry' && ( ! isset( $_POST['screen_mode'] ) || rgpost( 'screen_mode' ) == 'view' ) ) { return true; } return false; } /** * Returns TRUE if the current page is the entry edit page. Otherwise, returns FALSE * @return bool */ public function is_entry_edit() { if ( rgget( 'page' ) == 'gf_entries' && rgget( 'view' ) == 'entry' && rgpost( 'screen_mode' ) == 'edit' ) { return true; } return false; } public function is_entry_list() { if ( rgget( 'page' ) == 'gf_entries' && ( rgget( 'view' ) == 'entries' || rgempty( 'view', $_GET ) ) ) { return true; } return false; } /** * Returns TRUE if the current page is the results page. Otherwise, returns FALSE */ public function is_results() { if ( rgget( 'page' ) == 'gf_entries' && rgget( 'view' ) == 'gf_results_' . $this->_slug ) { return true; } return false; } /** * Returns TRUE if the current page is the print page. Otherwise, returns FALSE */ public function is_print() { if ( rgget( 'gf_page' ) == 'print-entry' ) { return true; } return false; } /** * Returns TRUE if the current page is the preview page. Otherwise, returns FALSE */ public function is_preview() { if ( rgget( 'gf_page' ) == 'preview' ) { return true; } return false; } public function has_deprecated_elements() { $deprecated = GFAddOn::get_all_deprecated_protected_methods( get_class( $this ) ); if ( ! empty( $deprecated ) ) { return true; } return false; } public static function get_all_deprecated_protected_methods($add_on_class_name = ''){ $deprecated = array(); $deprecated = array_merge( $deprecated, self::get_deprecated_protected_methods_for_base_class( 'GFAddOn', $add_on_class_name )) ; $deprecated = array_merge( $deprecated, self::get_deprecated_protected_methods_for_base_class( 'GFFeedAddOn', $add_on_class_name ) ) ; $deprecated = array_merge( $deprecated, self::get_deprecated_protected_methods_for_base_class( 'GFPaymentAddOn', $add_on_class_name ) ) ; return $deprecated; } public static function get_deprecated_protected_methods_for_base_class( $base_class_name, $add_on_class_name = '' ) { $deprecated = array(); if ( ! class_exists( $base_class_name ) ) { return $deprecated; } $base_class_names = array( 'GFAddOn', 'GFFeedAddOn', 'GFPaymentAddOn' ); $base_class = new ReflectionClass( $base_class_name ); $classes = empty($add_on_class_name) ? get_declared_classes() : array( $add_on_class_name ); foreach ( $classes as $class ) { if ( ! is_subclass_of( $class, $base_class_name ) || in_array( $class, $base_class_names ) ) { continue; } $add_on_class = new ReflectionClass( $class ); $add_on_methods = $add_on_class->getMethods( ReflectionMethod::IS_PROTECTED ); foreach ( $add_on_methods as $method ) { $method_name = $method->getName(); $base_has_method = $base_class->hasMethod( $method_name ); $is_declared_by_base_class = $base_has_method && $base_class->getMethod( $method_name )->getDeclaringClass()->getName() == $base_class_name; $is_overridden = $method->getDeclaringClass()->getName() == $class; if ( $is_declared_by_base_class && $is_overridden ) { $deprecated[] = $class . '::' . $method_name; } } } return $deprecated; } public function maybe_wp_kses( $html, $allowed_html = 'post', $allowed_protocols = array() ) { return GFCommon::maybe_wp_kses( $html, $allowed_html, $allowed_protocols ); } /** * Returns the slug for the add-on. * * @since 2.0 */ public function get_slug() { return $this->_slug; } /** * Returns the path for the add-on. * * @since 2.2 */ public function get_path() { return $this->_path; } /** * Fixes the add-on _path property value, if the directory has been renamed. * * @since 2.4.17 */ public function update_path() { $path_dirname = dirname( $this->_path ); if ( $path_dirname !== '.' ) { $full_path_dirname = basename( dirname( $this->_full_path ) ); if ( $path_dirname !== $full_path_dirname ) { $this->_path = trailingslashit( $full_path_dirname ) . basename( $this->_path ); } } } /** * Get all or a specific capability for Add-On. * * @since 2.2.5.27 * @access public * * @param string $capability Capability to return. * * @return string|array */ public function get_capabilities( $capability = '' ) { if ( rgblank( $capability ) ) { return $this->_capabilities; } return isset( $this->{'_capabilities_' . $capability} ) ? $this->{'_capabilities_' . $capability} : array(); } /** * Initializing translations. * * @since 2.0.7 */ public function load_text_domain() { GFCommon::load_gf_text_domain( $this->_slug, plugin_basename( dirname( $this->_full_path ) ) ); } /*** * Determines if the current user has the proper cabalities to uninstall this add-on * Add-ons that have been network activated can only be uninstalled by a network admin. * * @since 2.3.1.12 * @access public * * @return bool True if current user can uninstall this add-on. False otherwise */ public function current_user_can_uninstall(){ return GFCommon::current_user_can_uninstall( $this->_capabilities_uninstall, $this->get_path() ); } }