public static function notification_edit_page($form_id, $notification_id)
    {
        if (!rgempty("gform_notification_id")) {
            $notification_id = rgpost("gform_notification_id");
        }
        $form = RGFormsModel::get_form_meta($form_id);
        $form = apply_filters("gform_form_notification_page_{$form_id}", apply_filters("gform_form_notification_page", $form, $notification_id), $notification_id);
        $notification = !$notification_id ? array() : self::get_notification($form, $notification_id);
        // added second condition to account for new notifications with errors as notification ID will
        // be available in $_POST but the notification has not actually been saved yet
        $is_new_notification = empty($notification_id) || empty($notification);
        $is_valid = true;
        $is_update = false;
        if (rgpost("save")) {
            check_admin_referer('gforms_save_notification', 'gforms_save_notification');
            //clear out notification because it could have legacy data populated
            $notification = array('isActive' => isset($notification['isActive']) ? rgar($notification, 'isActive') : true);
            $is_update = true;
            if ($is_new_notification) {
                $notification_id = uniqid();
                $notification["id"] = $notification_id;
            } else {
                $notification["id"] = $notification_id;
            }
            $notification["name"] = rgpost("gform_notification_name");
            $notification["event"] = rgpost("gform_notification_event");
            $notification["to"] = rgpost("gform_notification_to_type") == "field" ? rgpost("gform_notification_to_field") : rgpost("gform_notification_to_email");
            $notification["toType"] = rgpost("gform_notification_to_type");
            $notification["bcc"] = rgpost("gform_notification_bcc");
            $notification["subject"] = rgpost("gform_notification_subject");
            $notification["message"] = rgpost("gform_notification_message");
            $notification["from"] = rgpost("gform_notification_from");
            $notification["fromName"] = rgpost("gform_notification_from_name");
            $notification["replyTo"] = rgpost("gform_notification_reply_to");
            $notification["routing"] = !rgempty("gform_routing_meta") ? GFCommon::json_decode(rgpost("gform_routing_meta"), true) : null;
            $notification["conditionalLogic"] = !rgempty("gform_conditional_logic_meta") ? GFCommon::json_decode(rgpost("gform_conditional_logic_meta"), true) : null;
            $notification["disableAutoformat"] = rgpost("gform_notification_disable_autoformat");
            $notification = apply_filters('gform_pre_notification_save', apply_filters("gform_pre_notification_save{$form['id']}", $notification, $form), $form);
            //validating input...
            $is_valid = self::validate_notification();
            if ($is_valid) {
                //input valid, updating...
                //emptying notification email if it is supposed to be disabled
                if ($_POST["gform_notification_to_type"] == "routing") {
                    $notification["to"] = "";
                } else {
                    $notification["routing"] = null;
                }
                // trim values
                $notification = GFFormsModel::trim_conditional_logic_values_from_element($notification, $form);
                $form["notifications"][$notification_id] = $notification;
                RGFormsModel::save_form_notifications($form_id, $form['notifications']);
            }
        }
        if ($is_update && $is_valid) {
            GFCommon::add_message(sprintf(__('Notification saved successfully. %sBack to notifications.%s', 'gravityforms'), '<a href="' . remove_query_arg('nid') . '">', '</a>'));
        } else {
            if ($is_update && !$is_valid) {
                GFCommon::add_error_message(__('Notification could not be updated. Please enter all required information below.', 'gravityforms'));
            }
        }
        // moved page header loading here so the admin messages can be set upon saving and available for the header to print out
        GFFormSettings::page_header(__('Notifications', 'gravityforms'));
        $notification_ui_settings = self::get_notification_ui_settings($notification);
        ?>
        <link rel="stylesheet" href="<?php 
        echo GFCommon::get_base_url();
        ?>
/css/admin.css?ver=<?php 
        echo GFCommon::$version;
        ?>
" />

        <script type="text/javascript">

        var gform_has_unsaved_changes = false;
        jQuery(document).ready(function(){

            jQuery("#entry_form input, #entry_form textarea, #entry_form select").change(function(){
                gform_has_unsaved_changes = true;
            });

            window.onbeforeunload = function(){
                if (gform_has_unsaved_changes){
                    return "You have unsaved changes.";
                }
            }

            ToggleConditionalLogic(true, 'notification');

            jQuery(document).on('change', '.gfield_routing_value_dropdown', function(){
                SetRoutingValueDropDown(jQuery(this));
            });

        });

        <?php 
        if (empty($form["notifications"])) {
            $form["notifications"] = array();
        }
        $entry_meta = GFFormsModel::get_entry_meta($form_id);
        $entry_meta = apply_filters("gform_entry_meta_conditional_logic_notifications", $entry_meta, $form, $notification_id);
        ?>

        var form = <?php 
        echo GFCommon::json_encode($form);
        ?>
;
        var current_notification = <?php 
        echo GFCommon::json_encode($notification);
        ?>
;
        var entry_meta = <?php 
        echo GFCommon::json_encode($entry_meta);
        ?>
;

        function SetRoutingValueDropDown(element){
            //parsing ID to get routing Index
            var index = element.attr("id").replace("routing_value_", "");
            SetRouting(index);
        }

        function CreateRouting(routings){
            var str = "";
            for(var i=0; i< routings.length; i++){

                var isSelected = routings[i].operator == "is" ? "selected='selected'" :"";
                var isNotSelected = routings[i].operator == "isnot" ? "selected='selected'" :"";
                var greaterThanSelected = routings[i].operator == ">" ? "selected='selected'" :"";
                var lessThanSelected = routings[i].operator == "<" ? "selected='selected'" :"";
                var containsSelected = routings[i].operator == "contains" ? "selected='selected'" :"";
                var startsWithSelected = routings[i].operator == "starts_with" ? "selected='selected'" :"";
                var endsWithSelected = routings[i].operator == "ends_with" ? "selected='selected'" :"";
                var email = routings[i]["email"] ? routings[i]["email"] : '';

                str += "<div style='width:99%'><?php 
        _e("Send to", "gravityforms");
        ?>
 <input type='text' id='routing_email_" + i +"' value='" + email + "' onkeyup='SetRouting(" + i + ");'/>";
                str += " <?php 
        _e("if", "gravityforms");
        ?>
 " + GetRoutingFields(i, routings[i].fieldId);
                str += "<select id='routing_operator_" + i + "' onchange='SetRouting(" + i + ");' class='gform_routing_operator'>";
                str += "<option value='is' " + isSelected + "><?php 
        _e("is", "gravityforms");
        ?>
</option>";
                str += "<option value='isnot' " + isNotSelected + "><?php 
        _e("is not", "gravityforms");
        ?>
</option>";
                str += "<option value='>' " + greaterThanSelected + "><?php 
        _e("greater than", "gravityforms");
        ?>
</option>";
                str += "<option value='<' " + lessThanSelected + "><?php 
        _e("less than", "gravityforms");
        ?>
</option>";
                str += "<option value='contains' " + containsSelected + "><?php 
        _e("contains", "gravityforms");
        ?>
</option>";
                str += "<option value='starts_with' " + startsWithSelected + "><?php 
        _e("starts with", "gravityforms");
        ?>
</option>";
                str += "<option value='ends_with' " + endsWithSelected + "><?php 
        _e("ends with", "gravityforms");
        ?>
</option>";
                str += "</select>";
                str += GetRoutingValues(i, routings[i].fieldId, routings[i].value);
                str += "<a class='gf_insert_field_choice' title='add another rule' onclick=\"InsertRouting(" + (i+1) + ");\"><i class='fa fa-plus-square'></i></a>";
                if(routings.length > 1 )
                    str += "<a class='gf_delete_field_choice' title='remove this rule' onclick=\"DeleteRouting(" + i + ");\"><i class='fa fa-minus-square'></i></a>";

                str += "</div>";
            }

            jQuery("#gform_notification_to_routing_rules").html(str);
        }

        function GetRoutingValues(index, fieldId, selectedValue){
            str = GetFieldValues(index, fieldId, selectedValue, 16);

            return str;
        }

        function GetRoutingFields(index, selectedItem){
            var str = "<select id='routing_field_id_" + index + "' class='gfield_routing_select' onchange='jQuery(\"#routing_value_" + index + "\").replaceWith(GetRoutingValues(" + index + ", jQuery(this).val())); SetRouting(" + index + "); '>";
            str += GetSelectableFields(selectedItem, 16);
            str += "</select>";

            return str;
        }

        //---------------------- generic ---------------
        function GetSelectableFields(selectedFieldId, labelMaxCharacters){
            var str = "";
            var inputType;
            for(var i=0; i<form.fields.length; i++){
                inputType = form.fields[i].inputType ? form.fields[i].inputType : form.fields[i].type;
                //see if this field type can be used for conditionals
                if (IsNotificationConditionalLogicField(form.fields[i])) {
                    var selected = form.fields[i].id == selectedFieldId ? "selected='selected'" : "";
                    str += "<option value='" + form.fields[i].id + "' " + selected + ">" + form.fields[i].label + "</option>";
                }
            }
            return str;
        }

        function IsNotificationConditionalLogicField(field){
        	//this function is a duplicate of IsConditionalLogicField from form_editor.js
		    inputType = field.inputType ? field.inputType : field.type;
		    var supported_fields = ["checkbox", "radio", "select", "text", "website", "textarea", "email", "hidden", "number", "phone", "multiselect", "post_title",
		                            "post_tags", "post_custom_field", "post_content", "post_excerpt"];

		    var index = jQuery.inArray(inputType, supported_fields);

		    return index >= 0;
		}

        function GetFirstSelectableField(){
            var inputType;
            for(var i=0; i<form.fields.length; i++){
                inputType = form.fields[i].inputType ? form.fields[i].inputType : form.fields[i].type;
                if (IsNotificationConditionalLogicField(form.fields[i])){
                    return form.fields[i].id;
				}
            }

            return 0;
        }

        function TruncateMiddle(text, maxCharacters){
            if(!text)
                return "";

            if(text.length <= maxCharacters)
                return text;
            var middle = parseInt(maxCharacters / 2);
            return text.substr(0, middle) + "..." + text.substr(text.length - middle, middle);

        }

        function GetFieldValues(index, fieldId, selectedValue, labelMaxCharacters){
            if(!fieldId)
                fieldId = GetFirstSelectableField();

            if(!fieldId)
                return "";

            var str = "";
            var field = GetFieldById(fieldId);
            var isAnySelected = false;

            if(!field)
        		return "";

            if(field["type"] == "post_category" && field["displayAllCategories"]){
            	var dropdown_id = "routing_value_" + index;
		        var dropdown = jQuery('#' + dropdown_id + ".gfield_category_dropdown");

		        //don't load category drop down if it already exists (to avoid unecessary ajax requests)
		        if(dropdown.length > 0){

		            var options = dropdown.html();
		            options = options.replace("value=\"" + selectedValue + "\"", "value=\"" + selectedValue + "\" selected=\"selected\"");
		            str = "<select id='" + dropdown_id + "' class='gfield_routing_select gfield_category_dropdown gfield_routing_value_dropdown'>" + options + "</select>";
		        }
		        else{
		            //loading categories via AJAX
		            jQuery.post(ajaxurl,{   action:"gf_get_notification_post_categories",
		                                    ruleIndex: index,
		                                    selectedValue: selectedValue},
		                                function(dropdown_string){
		                                    if(dropdown_string){
		                                        jQuery('#gfield_ajax_placeholder_' + index).replaceWith(dropdown_string.trim());
		                                    }
		                                }
		                        );

		            //will be replaced by real drop down during the ajax callback
		            str = "<select id='gfield_ajax_placeholder_" + index + "' class='gfield_routing_select'><option><?php 
        _e("Loading...", "gravityforms");
        ?>
</option></select>";
		        }
			}
            else if(field.choices){
            	//create a drop down for fields that have choices (i.e. drop down, radio, checkboxes, etc...)
	            str = "<select class='gfield_routing_select gfield_routing_value_dropdown' id='routing_value_" + index + "'>";
	            for(var i=0; i<field.choices.length; i++){
	                var choiceValue = field.choices[i].value ? field.choices[i].value : field.choices[i].text;
	                var isSelected = choiceValue == selectedValue;
	                var selected = isSelected ? "selected='selected'" : "";
	                if(isSelected)
	                    isAnySelected = true;

	                str += "<option value='" + choiceValue.replace(/'/g, "&#039;") + "' " + selected + ">" + field.choices[i].text + "</option>";
	            }

	            if(!isAnySelected && selectedValue){
	                str += "<option value='" + selectedValue.replace(/'/g, "&#039;") + "' selected='selected'>" + selectedValue + "</option>";
	            }
	            str += "</select>";
			}
			else
			{
			    selectedValue = selectedValue ? selectedValue.replace(/'/g, "&#039;") : "";
			    //create a text field for fields that don't have choices (i.e text, textarea, number, email, etc...)
			    str = "<input type='text' placeholder='<?php 
        _e("Enter value", "gravityforms");
        ?>
' class='gfield_routing_select' id='routing_value_" + index + "' value='" + selectedValue.replace(/'/g, "&#039;") + "' onchange='SetRouting(" + index + ");' onkeyup='SetRouting(" + index + ");'>";
			}
            return str;
        }

        function GetFieldById(fieldId){
            for(var i=0; i<form.fields.length; i++){
                if(form.fields[i].id == fieldId)
                    return form.fields[i];
            }
            return null;
        }
        //---------------------------------------------------------------------------------

        function InsertRouting(index){
            var routings = current_notification.routing;
            routings.splice(index, 0, new ConditionalRule());

            CreateRouting(routings);
            SetRouting(index);
        }

        function SetRouting(ruleIndex){
            if(!current_notification.routing && ruleIndex == 0)
                current_notification.routing = [new ConditionalRule()];

            current_notification.routing[ruleIndex]["email"] = jQuery("#routing_email_" + ruleIndex).val();
            current_notification.routing[ruleIndex]["fieldId"] = jQuery("#routing_field_id_" + ruleIndex).val();
            current_notification.routing[ruleIndex]["operator"] = jQuery("#routing_operator_" + ruleIndex).val();
            current_notification.routing[ruleIndex]["value"] =jQuery("#routing_value_" + ruleIndex).val();

            var json = jQuery.toJSON(current_notification.routing);
            jQuery('#gform_routing_meta').val(json);
        }

        function DeleteRouting(ruleIndex){
            current_notification.routing.splice(ruleIndex, 1);
            CreateRouting(current_notification.routing);
        }

        function SetConditionalLogic(isChecked){
            current_notification.conditionalLogic = isChecked ? new ConditionalLogic() : null;
        }

        function SaveJSMeta(){
            jQuery('#gform_routing_meta').val(jQuery.toJSON(current_notification.routing));
            jQuery('#gform_conditional_logic_meta').val(jQuery.toJSON(current_notification.conditionalLogic));
        }

        </script>

        <form method="post" id="gform_notification_form" onsubmit="gform_has_unsaved_changes = false; SaveJSMeta();">

            <?php 
        wp_nonce_field('gforms_save_notification', 'gforms_save_notification');
        ?>
            <input type="hidden" id="gform_routing_meta" name="gform_routing_meta" />
            <input type="hidden" id="gform_conditional_logic_meta" name="gform_conditional_logic_meta" />
            <input type="hidden" id="gform_notification_id" name="gform_notification_id" value="<?php 
        echo $notification_id;
        ?>
" />

            <table class="form-table gform_nofification_edit">
                <?php 
        array_map(array('GFFormSettings', 'output'), $notification_ui_settings);
        ?>
            </table>

            <p class="submit">
                <?php 
        $button_label = $is_new_notification ? __("Save Notification", "gravityforms") : __("Update Notification", "gravityforms");
        $notification_button = '<input class="button-primary" type="submit" value="' . $button_label . '" name="save"/>';
        echo apply_filters("gform_save_notification_button", $notification_button);
        ?>
            </p>
        </form>

        <?php 
        GFFormSettings::page_footer();
    }
 protected function settings_feed_condition($field, $echo = true)
 {
     $checkbox_label = isset($field['checkbox_label']) ? $field['checkbox_label'] : __('Enable Condition', 'gravityforms');
     $checkbox_field = array('name' => 'feed_condition_conditional_logic', 'type' => 'checkbox', 'choices' => array(array('label' => $checkbox_label, 'name' => 'feed_condition_conditional_logic')), 'onclick' => 'ToggleConditionalLogic( false, "feed_condition" );');
     $conditional_logic_object = $this->get_setting('feed_condition_conditional_logic_object');
     if ($conditional_logic_object) {
         $form_id = rgget('id');
         $form = GFFormsModel::get_form_meta($form_id);
         $conditional_logic = json_encode(GFFormsModel::trim_conditional_logic_values_from_element($conditional_logic_object, $form));
     } else {
         $conditional_logic = '{}';
     }
     $hidden_field = array('name' => 'feed_condition_conditional_logic_object', 'value' => $conditional_logic);
     $instructions = isset($field['instructions']) ? $field['instructions'] : __('Process this feed if', 'gravityforms');
     $html = $this->settings_checkbox($checkbox_field, '', false);
     $html .= $this->settings_hidden($hidden_field, '', false);
     $html .= '<div id="feed_condition_conditional_logic_container"><!-- dynamically populated --></div>';
     $html .= '<script type="text/javascript"> var feedCondition = new FeedConditionObj({' . 'strings: { objectDescription: "' . esc_attr($instructions) . '" },' . 'logicObject: ' . $conditional_logic . '}); </script>';
     if ($echo) {
         echo $html;
     }
     return $html;
 }
 public function get_feed_condition_conditional_logic()
 {
     $conditional_logic_object = $this->get_setting('feed_condition_conditional_logic_object');
     if ($conditional_logic_object) {
         $form_id = rgget('id');
         $form = GFFormsModel::get_form_meta($form_id);
         $conditional_logic = json_encode(GFFormsModel::trim_conditional_logic_values_from_element($conditional_logic_object, $form));
     } else {
         $conditional_logic = '{}';
     }
     return $conditional_logic;
 }
 public static function handle_confirmation_edit_submission($confirmation, $form)
 {
     if (empty($_POST) || !check_admin_referer('gform_confirmation_edit', 'gform_confirmation_edit')) {
         return $confirmation;
     }
     $is_new_confirmation = !$confirmation;
     if ($is_new_confirmation) {
         $confirmation['id'] = uniqid();
     }
     $name = sanitize_text_field(rgpost('form_confirmation_name'));
     $confirmation['name'] = $name;
     $type = rgpost('form_confirmation');
     if (!in_array($type, array('message', 'page', 'redirect'))) {
         $type = 'message';
     }
     $confirmation['type'] = $type;
     $confirmation['message'] = rgpost('form_confirmation_message');
     $confirmation['disableAutoformat'] = (bool) rgpost('form_disable_autoformatting');
     $confirmation['pageId'] = absint(rgpost('form_confirmation_page'));
     $confirmation['url'] = rgpost('form_confirmation_url');
     $query_string = '' != rgpost('form_redirect_querystring') ? rgpost('form_redirect_querystring') : rgpost('form_page_querystring');
     $confirmation['queryString'] = wp_strip_all_tags($query_string);
     $confirmation['isDefault'] = (bool) rgpost('is_default');
     // if is default confirmation, override any submitted conditional logic with empty array
     $confirmation['conditionalLogic'] = $confirmation['isDefault'] ? array() : json_decode(rgpost('conditional_logic'), ARRAY_A);
     $confirmation['conditionalLogic'] = GFFormsModel::sanitize_conditional_logic($confirmation['conditionalLogic']);
     $failed_validation = false;
     if (!$confirmation['name']) {
         $failed_validation = true;
         GFCommon::add_error_message(__('You must specify a Confirmation Name.', 'gravityforms'));
     }
     switch ($type) {
         case 'page':
             if (empty($confirmation['pageId'])) {
                 $failed_validation = true;
                 GFCommon::add_error_message(__('You must select a Confirmation Page.', 'gravityforms'));
             }
             break;
         case 'redirect':
             if ((empty($confirmation['url']) || !GFCommon::is_valid_url($confirmation['url'])) && !GFCommon::has_merge_tag($confirmation['url'])) {
                 $failed_validation = true;
                 GFCommon::add_error_message(__('You must specify a valid Redirect URL.', 'gravityforms'));
             }
             break;
     }
     if ($failed_validation) {
         return $confirmation;
     }
     // allow user to filter confirmation before save
     $confirmation = gf_apply_filters('gform_pre_confirmation_save', $form['id'], $confirmation, $form, $is_new_confirmation);
     // trim values
     $confirmation = GFFormsModel::trim_conditional_logic_values_from_element($confirmation, $form);
     // add current confirmation to confirmations array
     $form['confirmations'][$confirmation['id']] = $confirmation;
     // save updated confirmations array
     $result = GFFormsModel::save_form_confirmations($form['id'], $form['confirmations']);
     if ($result !== false) {
         $url = remove_query_arg(array('cid', 'duplicatedcid'));
         GFCommon::add_message(sprintf(__('Confirmation saved successfully. %sBack to confirmations.%s', 'gravityforms'), '<a href="' . esc_url($url) . '">', '</a>'));
     } else {
         GFCommon::add_error_message(__('There was an issue saving this confirmation.', 'gravityforms'));
     }
     return $confirmation;
 }
Exemple #5
0
    /**
     * Builds the Notification Edit page.
     *
     * Called from GFNotification::notification_page
     *
     * @access public
     * @static
     * @see RGFormsModel::get_form_meta
     * @see GFNotification::get_notification
     * @see GFNotification::validate_notification
     * @see GFNotification::get_notification_ui_settings
     * @see GFFormsModel::sanitize_conditional_logic
     *
     * @param int $form_id         The ID of the form that the notification belongs to
     * @param int $notification_id The ID of the notification being edited
     */
    public static function notification_edit_page($form_id, $notification_id)
    {
        if (!rgempty('gform_notification_id')) {
            $notification_id = rgpost('gform_notification_id');
        }
        $form = RGFormsModel::get_form_meta($form_id);
        /**
         * Filters the form to be used in the notification page
         *
         * @since 1.8.6
         *
         * @param array $form            The Form Object
         * @param int   $notification_id The notification ID
         */
        $form = gf_apply_filters(array('gform_form_notification_page', $form_id), $form, $notification_id);
        $notification = !$notification_id ? array() : self::get_notification($form, $notification_id);
        // added second condition to account for new notifications with errors as notification ID will
        // be available in $_POST but the notification has not actually been saved yet
        $is_new_notification = empty($notification_id) || empty($notification);
        $is_valid = true;
        $is_update = false;
        if (rgpost('save')) {
            check_admin_referer('gforms_save_notification', 'gforms_save_notification');
            //clear out notification because it could have legacy data populated
            $notification = array('isActive' => isset($notification['isActive']) ? rgar($notification, 'isActive') : true);
            $is_update = true;
            if ($is_new_notification) {
                $notification_id = uniqid();
                $notification['id'] = $notification_id;
            } else {
                $notification['id'] = $notification_id;
            }
            $notification['name'] = sanitize_text_field(rgpost('gform_notification_name'));
            $notification['service'] = sanitize_text_field(rgpost('gform_notification_service'));
            $notification['event'] = sanitize_text_field(rgpost('gform_notification_event'));
            $notification['to'] = rgpost('gform_notification_to_type') == 'field' ? rgpost('gform_notification_to_field') : rgpost('gform_notification_to_email');
            $to_type = rgpost('gform_notification_to_type');
            if (!in_array($to_type, array('email', 'field', 'routing', 'hidden'))) {
                $to_type = 'email';
            }
            $notification['toType'] = $to_type;
            $notification['bcc'] = rgpost('gform_notification_bcc');
            $notification['subject'] = sanitize_text_field(rgpost('gform_notification_subject'));
            $notification['message'] = rgpost('gform_notification_message');
            $notification['from'] = sanitize_text_field(rgpost('gform_notification_from'));
            $notification['fromName'] = sanitize_text_field(rgpost('gform_notification_from_name'));
            $notification['replyTo'] = rgpost('gform_notification_reply_to');
            $routing = !rgempty('gform_routing_meta') ? GFCommon::json_decode(rgpost('gform_routing_meta'), true) : null;
            if (!empty($routing)) {
                $routing_logic = array('rules' => $routing);
                $routing_logic = GFFormsModel::sanitize_conditional_logic($routing_logic);
                $notification['routing'] = $routing_logic['rules'];
            }
            $notification['routing'] = $routing;
            $conditional_logic = !rgempty('gform_conditional_logic_meta') ? GFCommon::json_decode(rgpost('gform_conditional_logic_meta'), true) : null;
            $notification['conditionalLogic'] = GFFormsModel::sanitize_conditional_logic($conditional_logic);
            $notification['disableAutoformat'] = (bool) rgpost('gform_notification_disable_autoformat');
            if (rgpost('gform_is_default')) {
                $notification['isDefault'] = true;
            }
            /**
             * Filters the notification before it is saved
             *
             * @since 1.7
             *
             * @param array $notification        The Notification Object
             * @param array $form                The Form Object
             * @param bool  $is_new_notification True if it is a new notification.  False otherwise.
             */
            $notification = gf_apply_filters(array('gform_pre_notification_save', $form_id), $notification, $form, $is_new_notification);
            //validating input...
            $is_valid = self::validate_notification();
            /**
             * Allows overriding of if the notification passes validation
             *
             * @since 1.9.16
             *
             * @param bool $is_valid      True if it is valid.  False otherwise.
             * @param array $notification The Notification Object
             * @param array $form         The Form Object
             */
            $is_valid = gf_apply_filters(array('gform_notification_validation', $form_id), $is_valid, $notification, $form);
            if ($is_valid) {
                //input valid, updating...
                //emptying notification email if it is supposed to be disabled
                if ($_POST['gform_notification_to_type'] == 'routing') {
                    $notification['to'] = '';
                } else {
                    $notification['routing'] = null;
                }
                // trim values
                $notification = GFFormsModel::trim_conditional_logic_values_from_element($notification, $form);
                $form['notifications'][$notification_id] = $notification;
                RGFormsModel::save_form_notifications($form_id, $form['notifications']);
            }
        }
        if ($is_update && $is_valid) {
            $url = remove_query_arg('nid');
            GFCommon::add_message(sprintf(esc_html__('Notification saved successfully. %sBack to notifications.%s', 'gravityforms'), '<a href="' . esc_url($url) . '">', '</a>'));
            /**
             * Fires an action after a notification has been saved
             *
             * @since 1.9.16
             *
             * @param array $notification        The Notification Object
             * @param array $form                The Form Object
             * @param bool  $is_new_notification True if this is a new notification.  False otherwise.
             */
            gf_do_action(array('gform_post_notification_save', $form_id), $notification, $form, $is_new_notification);
        } else {
            if ($is_update && !$is_valid) {
                GFCommon::add_error_message(esc_html__('Notification could not be updated. Please enter all required information below.', 'gravityforms'));
            }
        }
        // moved page header loading here so the admin messages can be set upon saving and available for the header to print out
        GFFormSettings::page_header(esc_html__('Notifications', 'gravityforms'));
        $notification_ui_settings = self::get_notification_ui_settings($notification, $is_valid);
        $min = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG || isset($_GET['gform_debug']) ? '' : '.min';
        ?>
		<link rel="stylesheet" href="<?php 
        echo GFCommon::get_base_url();
        ?>
/css/admin<?php 
        echo $min;
        ?>
.css?ver=<?php 
        echo GFCommon::$version;
        ?>
" />

		<script type="text/javascript">

		var gform_has_unsaved_changes = false;
		jQuery(document).ready(function () {

			jQuery("#entry_form input, #entry_form textarea, #entry_form select").change(function () {
				gform_has_unsaved_changes = true;
			});

			window.onbeforeunload = function () {
				if (gform_has_unsaved_changes) {
					return "You have unsaved changes.";
				}
			};

			ToggleConditionalLogic(true, 'notification');

			jQuery(document).on('change', '.gfield_routing_value_dropdown', function () {
				SetRoutingValueDropDown(jQuery(this));
			});

		});

		gform.addFilter("gform_merge_tags", "MaybeAddSaveLinkMergeTag");
		function MaybeAddSaveLinkMergeTag(mergeTags, elementId, hideAllFields, excludeFieldTypes, isPrepop, option){
			var event = document.getElementById('gform_notification_event').value;
			if ( event == 'form_saved' || event == 'form_save_email_requested' ) {
				mergeTags["other"].tags.push({ tag: '{save_link}', label: <?php 
        echo json_encode(esc_html__('Save & Continue Link', 'gravityforms'));
        ?>
 });
				mergeTags["other"].tags.push({ tag: '{save_token}', label: <?php 
        echo json_encode(esc_html__('Save & Continue Token', 'gravityforms'));
        ?>
 });
			}

			return mergeTags;
		}

		<?php 
        if (empty($form['notifications'])) {
            $form['notifications'] = array();
        }
        $entry_meta = GFFormsModel::get_entry_meta($form_id);
        /**
         * Filters the entry meta when notification conditional logic is being edited
         *
         * @since 1.7.6
         *
         * @param array $entry_meta      The Entry meta
         * @param array $form            The Form Object
         * @param int   $notification_id The notification ID
         */
        $entry_meta = apply_filters('gform_entry_meta_conditional_logic_notifications', $entry_meta, $form, $notification_id);
        ?>

		var form = <?php 
        echo json_encode($form);
        ?>
;
		var current_notification = <?php 
        echo GFCommon::json_encode($notification);
        ?>
;
		var entry_meta = <?php 
        echo GFCommon::json_encode($entry_meta);
        ?>
;


		function SetRoutingValueDropDown(element) {
			//parsing ID to get routing Index
			var index = element.attr("id").replace("routing_value_", '');
			SetRouting(index);
		}

		function CreateRouting(routings) {
			var str = '';
			for (var i = 0; i < routings.length; i++) {

				var isSelected = routings[i].operator == 'is' ? "selected='selected'" : '';
				var isNotSelected = routings[i].operator == 'isnot' ? "selected='selected'" : '';
				var greaterThanSelected = routings[i].operator == '>' ? "selected='selected'" : '';
				var lessThanSelected = routings[i].operator == '<' ? "selected='selected'" : '';
				var containsSelected = routings[i].operator == 'contains' ? "selected='selected'" : '';
				var startsWithSelected = routings[i].operator == 'starts_with' ? "selected='selected'" : '';
				var endsWithSelected = routings[i].operator == 'ends_with' ? "selected='selected'" : '';
				var email = routings[i]["email"] ? routings[i]["email"] : '';

				str += "<div style='width:99%'>" + <?php 
        echo json_encode(esc_html__('Send to', 'gravityforms'));
        ?>
 + " <input type='text' id='routing_email_" + i + "' value='" + email + "' onkeyup='SetRouting(" + i + ");'/>";
				str += " " + <?php 
        echo json_encode(esc_html__('if', 'gravityforms'));
        ?>
 + " " + GetRoutingFields(i, routings[i].fieldId);
				str += "<select id='routing_operator_" + i + "' onchange='SetRouting(" + i + ");' class='gform_routing_operator'>";
				str += "<option value='is' " + isSelected + ">" + <?php 
        echo json_encode(esc_html__('is', 'gravityforms'));
        ?>
 + "</option>";
				str += "<option value='isnot' " + isNotSelected + ">" + <?php 
        echo json_encode(esc_html__('is not', 'gravityforms'));
        ?>
 + "</option>";
				str += "<option value='>' " + greaterThanSelected + ">" + <?php 
        echo json_encode(esc_html__('greater than', 'gravityforms'));
        ?>
 + "</option>";
				str += "<option value='<' " + lessThanSelected + ">" + <?php 
        echo json_encode(esc_html__('less than', 'gravityforms'));
        ?>
 + "</option>";
				str += "<option value='contains' " + containsSelected + ">" + <?php 
        echo json_encode(esc_html__('contains', 'gravityforms'));
        ?>
 + "</option>";
				str += "<option value='starts_with' " + startsWithSelected + ">" + <?php 
        echo json_encode(esc_html__('starts with', 'gravityforms'));
        ?>
 + "</option>";
				str += "<option value='ends_with' " + endsWithSelected + ">" + <?php 
        echo json_encode(esc_html__('ends with', 'gravityforms'));
        ?>
 + "</option>";
				str += "</select>";
				str += GetRoutingValues(i, routings[i].fieldId, routings[i].value);
				str += "<a class='gf_insert_field_choice' title='add another rule' onclick=\"InsertRouting(" + (i + 1) + ");\" onkeypress=\"InsertRouting(" + (i + 1) + ");\"><i class='gficon-add'></i></a>";
				if (routings.length > 1)
					str += "<a class='gf_delete_field_choice' title='remove this rule' onclick=\"DeleteRouting(" + i + ");\" onkeypress=\"DeleteRouting(" + i + ");\"><i class='gficon-subtract'></i></a>";

				str += "</div>";
			}

			jQuery("#gform_notification_to_routing_rules").html(str);
		}

		function GetRoutingValues(index, fieldId, selectedValue) {
			var str = GetFieldValues(index, fieldId, selectedValue, 16);

			return str;
		}

		function GetRoutingFields(index, selectedItem) {
			var str = "<select id='routing_field_id_" + index + "' class='gfield_routing_select' onchange='jQuery(\"#routing_value_" + index + "\").replaceWith(GetRoutingValues(" + index + ", jQuery(this).val())); SetRouting(" + index + "); '>";
			str += GetSelectableFields(selectedItem, 16);
			str += "</select>";

			return str;
		}

		//---------------------- generic ---------------
		function GetSelectableFields(selectedFieldId, labelMaxCharacters) {
			var str = "";
			var inputType;
			for (var i = 0; i < form.fields.length; i++) {
				inputType = form.fields[i].inputType ? form.fields[i].inputType : form.fields[i].type;
				//see if this field type can be used for conditionals
				if (IsNotificationConditionalLogicField(form.fields[i])) {
					var selected = form.fields[i].id == selectedFieldId ? "selected='selected'" : "";
					str += "<option value='" + form.fields[i].id + "' " + selected + ">" + form.fields[i].label + "</option>";
				}
			}
			return str;
		}

		function IsNotificationConditionalLogicField(field) {
			//this function is a duplicate of IsConditionalLogicField from form_editor.js
			inputType = field.inputType ? field.inputType : field.type;
			var supported_fields = ['checkbox', 'radio', 'select', 'text', 'website', 'textarea', 'email', 'hidden', 'number', 'phone', 'multiselect', 'post_title',
				'post_tags', 'post_custom_field', 'post_content', 'post_excerpt'];

			var index = jQuery.inArray(inputType, supported_fields);

			return index >= 0;
		}

		function GetFirstSelectableField() {
			var inputType;
			for (var i = 0; i < form.fields.length; i++) {
				inputType = form.fields[i].inputType ? form.fields[i].inputType : form.fields[i].type;
				if (IsNotificationConditionalLogicField(form.fields[i])) {
					return form.fields[i].id;
				}
			}

			return 0;
		}

		function TruncateMiddle(text, maxCharacters) {
			if (!text)
				return "";

			if (text.length <= maxCharacters)
				return text;
			var middle = parseInt(maxCharacters / 2);
			return text.substr(0, middle) + "..." + text.substr(text.length - middle, middle);

		}

		function GetFieldValues(index, fieldId, selectedValue, labelMaxCharacters) {
			if (!fieldId)
				fieldId = GetFirstSelectableField();

			if (!fieldId)
				return "";

			var str = '';
			var field = GetFieldById(fieldId);
			var isAnySelected = false;

			if (!field)
				return "";

			if (field["type"] == 'post_category' && field["displayAllCategories"]) {
				var dropdown_id = 'routing_value_' + index;
				var dropdown = jQuery('#' + dropdown_id + ".gfield_category_dropdown");

				//don't load category drop down if it already exists (to avoid unecessary ajax requests)
				if (dropdown.length > 0) {

					var options = dropdown.html();
					options = options.replace("value=\"" + selectedValue + "\"", "value=\"" + selectedValue + "\" selected=\"selected\"");
					str = "<select id='" + dropdown_id + "' class='gfield_routing_select gfield_category_dropdown gfield_routing_value_dropdown'>" + options + "</select>";
				}
				else {
					//loading categories via AJAX
					jQuery.post(ajaxurl, {   action: "gf_get_notification_post_categories",
							ruleIndex              : index,
							selectedValue          : selectedValue},
						function (dropdown_string) {
							if (dropdown_string) {
								jQuery('#gfield_ajax_placeholder_' + index).replaceWith(dropdown_string.trim());
							}
						}
					);

					//will be replaced by real drop down during the ajax callback
					str = "<select id='gfield_ajax_placeholder_" + index + "' class='gfield_routing_select'><option>" + <?php 
        json_encode(esc_html__('Loading...', 'gravityforms'));
        ?>
 + "</option></select>";
				}
			}
			else if (field.choices) {
				//create a drop down for fields that have choices (i.e. drop down, radio, checkboxes, etc...)
				str = "<select class='gfield_routing_select gfield_routing_value_dropdown' id='routing_value_" + index + "'>";
				for (var i = 0; i < field.choices.length; i++) {
					var choiceValue = field.choices[i].value ? field.choices[i].value : field.choices[i].text;
					var isSelected = choiceValue == selectedValue;
					var selected = isSelected ? "selected='selected'" : '';
					if (isSelected)
						isAnySelected = true;

					str += "<option value='" + choiceValue.replace(/'/g, "&#039;") + "' " + selected + ">" + field.choices[i].text + "</option>";
				}

				if (!isAnySelected && selectedValue) {
					str += "<option value='" + selectedValue.replace(/'/g, "&#039;") + "' selected='selected'>" + selectedValue + "</option>";
				}
				str += "</select>";
			}
			else {
				selectedValue = selectedValue ? selectedValue.replace(/'/g, "&#039;") : "";
				//create a text field for fields that don't have choices (i.e text, textarea, number, email, etc...)
				str = "<input type='text' placeholder='" + <?php 
        echo json_encode(esc_html__('Enter value', 'gravityforms'));
        ?>
 +"' class='gfield_routing_select' id='routing_value_" + index + "' value='" + selectedValue.replace(/'/g, "&#039;") + "' onchange='SetRouting(" + index + ");' onkeyup='SetRouting(" + index + ");'>";
			}
			return str;
		}

		//---------------------------------------------------------------------------------

		function InsertRouting(index) {
			var routings = current_notification.routing;
			routings.splice(index, 0, new ConditionalRule());

			CreateRouting(routings);
			SetRouting(index);
		}

		function SetRouting(ruleIndex) {
			if (!current_notification.routing && ruleIndex == 0)
				current_notification.routing = [new ConditionalRule()];

			current_notification.routing[ruleIndex]["email"] = jQuery("#routing_email_" + ruleIndex).val();
			current_notification.routing[ruleIndex]["fieldId"] = jQuery("#routing_field_id_" + ruleIndex).val();
			current_notification.routing[ruleIndex]["operator"] = jQuery("#routing_operator_" + ruleIndex).val();
			current_notification.routing[ruleIndex]["value"] = jQuery("#routing_value_" + ruleIndex).val();

			var json = jQuery.toJSON(current_notification.routing);
			jQuery('#gform_routing_meta').val(json);
		}

		function DeleteRouting(ruleIndex) {
			current_notification.routing.splice(ruleIndex, 1);
			CreateRouting(current_notification.routing);
		}

		function SetConditionalLogic(isChecked) {
			current_notification.conditionalLogic = isChecked ? new ConditionalLogic() : null;
		}

		function SaveJSMeta() {
			jQuery('#gform_routing_meta').val(jQuery.toJSON(current_notification.routing));
			jQuery('#gform_conditional_logic_meta').val(jQuery.toJSON(current_notification.conditionalLogic));
		}

		<?php 
        GFFormSettings::output_field_scripts();
        ?>

		</script>

		<form method="post" id="gform_notification_form" onsubmit="gform_has_unsaved_changes = false; SaveJSMeta();">

			<?php 
        wp_nonce_field('gforms_save_notification', 'gforms_save_notification');
        ?>
			<?php 
        if (rgar($notification, 'isDefault')) {
            echo '<input type="hidden" id="gform_is_default" name="gform_is_default" value="1"/>';
        }
        ?>
			<input type="hidden" id="gform_routing_meta" name="gform_routing_meta" />
			<input type="hidden" id="gform_conditional_logic_meta" name="gform_conditional_logic_meta" />
			<input type="hidden" id="gform_notification_id" name="gform_notification_id" value="<?php 
        echo esc_attr($notification_id);
        ?>
" />

			<table class="form-table gform_nofification_edit">
				<?php 
        array_map(array('GFFormSettings', 'output'), $notification_ui_settings);
        ?>
			</table>

			<p class="submit">
				<?php 
        $button_label = $is_new_notification ? __('Save Notification', 'gravityforms') : __('Update Notification', 'gravityforms');
        $notification_button = '<input class="button-primary" type="submit" value="' . esc_attr($button_label) . '" name="save"/>';
        /**
         * Filters the "Save Notification" button
         *
         * @param string $notification_button The notification button HTML
         */
        echo apply_filters('gform_save_notification_button', $notification_button);
        ?>
			</p>
		</form>

		<?php 
        GFFormSettings::page_footer();
    }