Page Permalinks

Add permalinks for each page of your multi-page forms.

Code

Filename: gpmpn-page-permalinks.php

<?php
/**
 * Gravity Perks // Multi-page Navigation // Page Permalinks
 * https://gravitywiz.com/documentation/gravity-forms-multi-page-navigation/
 *
 * Add permalinks for each page of your multi-page forms.
 *
 * Plugin Name:  GP Multi-page Navigation — Page Permalinks
 * Plugin URI:   https://gravitywiz.com/documentation/gravity-forms-multi-page-navigation/
 * Description:  Add permalinks for each page of your multi-page forms.
 * Author:       Gravity Wiz
 * Version:      0.2
 * Author URI:   https://gravitywiz.com
 */
class GPMPN_Page_Permalinks {

	private $_args = array();

	public function __construct( $args = array() ) {

		// set our default arguments, parse against the provided arguments, and store for use throughout the class
		$this->_args = wp_parse_args( $args, array(
			'form_id'    => false,
			'permalinks' => array(),
		) );

		// do version check in the init to make sure if GF is going to be loaded, it is already loaded
		add_action( 'init', array( $this, 'init' ) );

	}

	public function init() {

		// @todo For some reason after this runs for newly added page permalinks, all post permalinks are broken
		add_filter( 'option_rewrite_rules', array( $this, 'hotload_rewrite_rules' ) );
		add_action( 'gpmpn_default_page', array( $this, 'set_default_form_page' ) );

		add_filter( 'gform_pre_render', array( $this, 'load_form_script' ), 10, 2 );
		add_filter( 'gform_register_init_scripts', array( $this, 'add_init_script' ), 10, 2 );

		$this->add_query_var();
		$this->add_rewrite_rules();

	}

	public function add_query_var() {
		global $wp;
		$wp->add_query_var( 'gpmpn_page' );
	}

	public function add_rewrite_rules() {
		foreach ( $this->_args['permalinks'] as $page => $permalink ) {
			add_rewrite_rule( "^{$this->_args['pagename']}/{$permalink}?", "index.php?pagename={$this->_args['pagename']}&gpmpn_page={$page}", 'top' );
		}
	}

	public function hotload_rewrite_rules( $rules ) {
		static $did_rewrite_rules;

		if ( ! is_array( $rules ) ) {
			$rules = array();
		}

		$needs_flush = false;

		foreach ( $this->_args['permalinks'] as $page => $permalink ) {
			if ( ! array_key_exists( "^{$this->_args['pagename']}/{$permalink}?", $rules ) ) {
				$rules       = array( "^{$this->_args['pagename']}/{$permalink}?" => "index.php?pagename={$this->_args['pagename']}&gpmpn_page={$page}" ) + $rules;
				$needs_flush = true;
			}
		}

		//      if ( $needs_flush ) {
		//          if ( ! $did_rewrite_rules ) {
		//              $did_rewrite_rules = true;
		//              $this->flush_rewrite_rules();
		//          }
		//      }

		return $rules;
	}

	public function flush_rewrite_rules() {
		global $wp_rewrite;
		$wp_rewrite->flush_rules();
	}

	public function set_default_form_page( $page ) {
		return get_query_var( 'gpmpn_page' );
	}

	public function load_form_script( $form, $is_ajax_enabled ) {

		if ( $this->is_applicable_form( $form ) && ! has_action( 'wp_footer', array( $this, 'output_script' ) ) ) {
			add_action( 'wp_footer', array( $this, 'output_script' ) );
			add_action( 'gform_preview_footer', array( $this, 'output_script' ) );
		}

		return $form;
	}

	public function output_script() {
		?>

		<script type="text/javascript">

			( function( $ ) {

				window.GPMPNPagePermalinks = function( args ) {

					var self = this;

					self.history = [];

					// copy all args to current object: (list expected props)
					for( var prop in args ) {
						if( args.hasOwnProperty( prop ) ) {
							self[ prop ] = args[ prop ];
						}
					}

					self.init = function() {

						if ( typeof window[ 'GPMPNPagePermalinks_{0}'.gformFormat( self.formId ) ] !== 'undefined' ) {
							return;
						}

						window[ 'GPMPNPagePermalinks_{0}'.gformFormat( self.formId ) ] = self;

						self.history.push( { gpmpnPage: self.defaultPage } );

						console.log( 'init', self.history );

						$( document ).on( 'gform_page_loaded', function( event, formId, currentPage ) {
							if ( formId == self.formId ) {
								self.setPageState( currentPage );
							}
						} );

						$( document ).on( 'gform_confirmation_loaded', function( event, formId ) {
							if ( formId == self.formId ) {
								self.setPageState( 0 );
							}
						} );

						window.addEventListener( 'popstate', function ( event ) {
							// @todo Update to navigate the form to correct page based on the path.
							// var currentPage  = self.history.slice( -1 )[0].gpmpnPage;
							// var previousPage = self.history.slice( -2 )[0].gpmpnPage;
							// if ( previousPage < currentPage  ) {
							// 	$( '.gform_previous_button:visible' ).click();
							// }
							// Temporary solution: reload first page when user uses browser's back/next buttons.
							window.location = window.location.origin + '/{0}/{1}/'.gformFormat( self.pagename, self.permalinks[1] );
						} );

						self.isInit = true;

					};

					self.setPageState = function( currentPage ) {

						self.currentPage = parseInt( currentPage );

						var state = { gpmpnPage: self.currentPage };

						self.history.push( state );
						window.history.pushState( state, null, '/{0}/{1}/'.gformFormat( self.pagename, self.permalinks[ currentPage ] ) );

					}

					self.init();

				}

			} )( jQuery );

		</script>

		<?php
	}

	public function add_init_script( $form ) {

		if ( ! $this->is_applicable_form( $form ) ) {
			return;
		}

		$args = array(
			'formId'      => $this->_args['form_id'],
			'pagename'    => $this->_args['pagename'],
			'permalinks'  => $this->_args['permalinks'],
			'defaultPage' => get_query_var( 'gpmpn_page' ),
		);

		$script = 'if ( typeof window.GPMPNPagePermalinks !== \'undefined\' ) { new GPMPNPagePermalinks( ' . json_encode( $args ) . ' ); }';
		$slug   = implode( '_', array( 'gpmpn_page_permalinks', $this->_args['form_id'] ) );

		GFFormDisplay::add_init_script( $this->_args['form_id'], $slug, GFFormDisplay::ON_PAGE_RENDER, $script );

	}

	public function is_applicable_form( $form ) {

		$form_id = isset( $form['id'] ) ? $form['id'] : $form;

		return empty( $this->_args['form_id'] ) || (int) $form_id == (int) $this->_args['form_id'];
	}

}

# Configuration

new GPMPN_Page_Permalinks( array(
	'form_id'    => 889,
	'pagename'   => 'permalinks-for-form-pages',
	'permalinks' => array(
		1 => 'page-one',
		2 => 'page-two',
		3 => 'page-three',
		0 => 'confirmation',
	),
) );

Leave a Reply

Your email address will not be published. Required fields are marked *

  • Trouble installing this snippet? See our troubleshooting tips.
  • Need to include code? Create a gist and link to it in your comment.
  • Reporting a bug? Provide a URL where this issue can be recreated.

By commenting, I understand that I may receive emails related to Gravity Wiz and can unsubscribe at any time.