HEX
Server: Apache
System: Linux WWW 6.1.0-40-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.153-1 (2025-09-20) x86_64
User: web11 (1011)
PHP: 8.2.29
Disabled: NONE
Upload Files
File: /var/www/lcc.kaunokolegija.lt/wp-content/plugins/gravity-forms-pdf-extended/src/View/View_PDF.php
<?php

namespace GFPDF\View;

use Exception;
use GF_Field;
use GFCommon;
use GFPDF\Helper\Fields\Field_Products;
use GFPDF\Helper\Helper_Abstract_Fields;
use GFPDF\Helper\Helper_Abstract_Form;
use GFPDF\Helper\Helper_Abstract_Model;
use GFPDF\Helper\Helper_Abstract_Options;
use GFPDF\Helper\Helper_Abstract_View;
use GFPDF\Helper\Helper_Data;
use GFPDF\Helper\Helper_Field_Container;
use GFPDF\Helper\Helper_Field_Container_Gf25;
use GFPDF\Helper\Helper_Field_Container_Void;
use GFPDF\Helper\Helper_Form;
use GFPDF\Helper\Helper_Misc;
use GFPDF\Helper\Helper_PDF;
use GFPDF\Helper\Helper_Templates;
use GFPDF\Statics\Kses;
use GFPDFEntryDetail;
use GWConditionalLogicDateFields;
use Psr\Log\LoggerInterface;
use WP_Error;

/**
 * @package     Gravity PDF
 * @copyright   Copyright (c) 2025, Blue Liquid Designs
 * @license     http://opensource.org/licenses/gpl-2.0.php GNU Public License
 */

/* Exit if accessed directly */
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * View_PDF
 *
 * A general class for PDF display
 *
 * @since 4.0
 */
class View_PDF extends Helper_Abstract_View {

	/**
	 * Set the view's name
	 *
	 * @var string
	 *
	 * @since 4.0
	 */
	protected $view_type = 'PDF';

	/**
	 * Holds the abstracted Gravity Forms API specific to Gravity PDF
	 *
	 * @var Helper_Form
	 *
	 * @since 4.0
	 */
	protected $gform;

	/**
	 * Holds our log class
	 *
	 * @var LoggerInterface
	 *
	 * @since 4.0
	 */
	protected $log;

	/**
	 * Holds our Helper_Abstract_Options / Helper_Options_Fields object
	 * Makes it easy to access global PDF settings and individual form PDF settings
	 *
	 * @var Helper_Abstract_Options
	 * @since 4.0
	 */
	protected $options;

	/**
	 * Holds our Helper_Data object
	 * which we can autoload with any data needed
	 *
	 * @var Helper_Data
	 *
	 * @since 4.0
	 */
	protected $data;

	/**
	 * Holds our Helper_Misc object
	 * Makes it easy to access common methods throughout the plugin
	 *
	 * @var Helper_Misc
	 *
	 * @since 4.0
	 */
	protected $misc;

	/**
	 * Holds our Helper_Templates object
	 * used to ease access to our PDF templates
	 *
	 * @var Helper_Templates
	 *
	 * @since 4.0
	 */
	protected $templates;

	/**
	 * Setup our class by injecting all our dependencies
	 *
	 * @param array                            $data_cache An array of data to pass to the view
	 * @param Helper_Form|Helper_Abstract_Form $gform      Our abstracted Gravity Forms helper functions
	 * @param LoggerInterface                  $log        Our logger class
	 * @param Helper_Abstract_Options          $options    Our options class which allows us to access any settings
	 * @param Helper_Data                      $data       Our plugin data store
	 * @param Helper_Misc                      $misc       Our miscellaneous methods
	 * @param Helper_Templates                 $templates
	 *
	 * @since 4.0
	 */
	public function __construct( array $data_cache, Helper_Abstract_Form $gform, LoggerInterface $log, Helper_Abstract_Options $options, Helper_Data $data, Helper_Misc $misc, Helper_Templates $templates ) {

		/* Call our parent constructor */
		parent::__construct( $data_cache );

		/* Assign our internal variables */
		$this->gform     = $gform;
		$this->log       = $log;
		$this->options   = $options;
		$this->data      = $data;
		$this->misc      = $misc;
		$this->templates = $templates;
	}

	/**
	 * Our PDF Generator
	 *
	 * @param array $entry    The Gravity Forms Entry to process
	 * @param array $settings The Gravity Form PDF Settings
	 *
	 * @return void
	 *
	 * @since 4.0
	 */
	public function generate_pdf( $entry, $settings ) {

		$controller = $this->getController();
		$model      = $controller->model;
		$form       = apply_filters( 'gfpdf_current_form_object', $this->gform->get_form( $entry['form_id'] ), $entry, __FUNCTION__ );
		$form       = $this->add_gravity_perk_conditional_logic_date_support( $form );

		/**
		 * Set out our PDF abstraction class
		 */
		$pdf = new Helper_PDF( $entry, $settings, $this->gform, $this->data, $this->misc, $this->templates, $this->log );
		$pdf->set_filename( $model->get_pdf_name( $settings, $entry ) );

		$this->fix_wp_external_links_plugin_conflict();

		do_action( 'gfpdf_pre_pdf_generation', $form, $entry, $settings, $pdf );

		/**
		 * Load our arguments that should be accessed by our PDF template
		 *
		 * @var array
		 */
		$args = $this->templates->get_template_arguments(
			$form,
			$this->misc->get_fields_sorted_by_id( $form['id'] ),
			$entry,
			$model->get_form_data( $entry ),
			$settings,
			$this->templates->get_config_class( $settings['template'] ),
			$this->misc->get_legacy_ids( $entry['id'], $settings )
		);

		/* Show $form_data array if requested */
		$this->maybe_view_form_data( $args['form_data'] ?? [] );

		/* Enable Multicurrency support */
		$this->misc->maybe_add_multicurrency_support();

		try {

			/* Initialise our PDF helper class */
			$pdf->init();
			$pdf->set_template();

			/* Set display type and allow user to override the behaviour */
			$settings['pdf_action'] = apply_filters( 'gfpdfe_pdf_output_type', $settings['pdf_action'] ); /* Backwards compat */
			if ( $settings['pdf_action'] === 'download' ) {
				$pdf->set_output_type( 'download' );
			}

			/* Add Backwards compatibility support for our v3 Tier 2 Add-on */
			if ( isset( $settings['advanced_template'] ) && strtolower( $settings['advanced_template'] ) === 'yes' ) {

				/* Check if we should process this document using our legacy system */
				if ( $model->handle_legacy_tier_2_processing( $pdf, $entry, $settings, $args ) ) {
					return;
				}
			}

			/* Determine if we should show the print dialog box */
			/* phpcs:ignore WordPress.Security.NonceVerification.Recommended */
			if ( isset( $_GET['print'] ) ) {
				$pdf->set_print_dialog();
			}

			/* Render the PDF template HTML */
			$pdf->render_html( $args );

			/* Generate PDF */
			$pdf->generate();

		} catch ( Exception $e ) {

			$this->log->error(
				'PDF Generation Error',
				[
					'entry'     => $entry,
					'settings'  => $settings,
					'exception' => $e->getMessage(),
				]
			);

			if ( $this->gform->has_capability( 'gravityforms_view_entries' ) ) {
				$message = sprintf(
					'%s in %s on line %s',
					$e->getMessage(),
					$e->getFile(),
					$e->getLine()
				);

				wp_die( esc_html( $message ) );
			}

			wp_die( esc_html__( 'There was a problem generating your PDF', 'gravity-forms-pdf-extended' ) );
		}
	}

	/**
	 * The WP External Links plugin conflicts with Gravity PDF when trying to display the PDF
	 * This method disables the \WPEL_Front::scan() method which was causes the problem
	 *
	 * See https://github.com/GravityPDF/gravity-pdf/issues/386
	 *
	 * @since 4.1
	 */
	private function fix_wp_external_links_plugin_conflict() {
		if ( function_exists( 'wpel_init' ) ) {
			add_filter(
				'wpel_apply_settings',
				function () {
					return false;
				}
			);
		}
	}

	/**
	 * Add Gravity Perk Conditional Logic Date Field support, if required
	 *
	 * @Internal Fixed an intermittent issue with the Product table not functioning correctly
	 *
	 * @param array $form
	 *
	 * @return array
	 * @since    4.5
	 */
	private function add_gravity_perk_conditional_logic_date_support( $form ) {
		if ( method_exists( 'GWConditionalLogicDateFields', 'convert_conditional_logic_date_field_values' ) ) {
			$form = GWConditionalLogicDateFields::convert_conditional_logic_date_field_values( $form );
		}

		return $form;
	}

	/**
	 * Ensure a PHP extension is added to the end of the template name
	 *
	 * @param string $name The PHP template
	 *
	 * @return string
	 *
	 * @since  4.0
	 */
	public function get_template_filename( $name ) {
		if ( substr( $name, -4 ) !== '.php' ) {
			$name = $name . '.php';
		}

		return $name;
	}

	/**
	 * Start the PDF HTML Generation Process
	 *
	 * @param array                 $entry  The Gravity Forms Entry Array
	 * @param Helper_Abstract_Model $model
	 * @param array                 $config Any configuration data passed in
	 *
	 * @return string The generated HTML
	 *
	 * @throws Exception
	 * @since 4.0
	 */
	public function process_html_structure( $entry, Helper_Abstract_Model $model, $config = [] ) {
		/* Determine whether we should output or return the results */
		$config['meta'] = ( isset( $config['meta'] ) ) ? $config['meta'] : [];
		$echo           = ( isset( $config['meta']['echo'] ) ) ? $config['meta']['echo'] : true; /* whether to output or return the generated markup. Default is echo */

		if ( ! $echo ) {
			ob_start();
		}

		/* Generate the markup */
		?>

		<div id="container">
			<?php
			/*
			 * See https://docs.gravitypdf.com/v6/developers/actions/gfpdf_pre_html_fields for more details about this action
			 * @since 4.1
			 */
			do_action( 'gfpdf_pre_html_fields', $entry, $config );
			?>

			<?php $this->generate_html_structure( $entry, $model, $config ); ?>

			<?php
			/*
			 * See https://docs.gravitypdf.com/v6/developers/actions/gfpdf_post_html_fields for more details about this action
			 * @since 4.1
			 */
			do_action( 'gfpdf_post_html_fields', $entry, $config );
			?>
		</div>

		<?php

		if ( ! $echo ) {
			return ob_get_clean();
		}

		return null;
	}

	/**
	 * Build our HTML structure
	 *
	 * @param array                 $entry  The Gravity Forms Entry Array
	 * @param Helper_Abstract_Model $model
	 * @param array                 $config Any configuration data passed in
	 *
	 * @throws Exception
	 * @since 4.0
	 */
	public function generate_html_structure( $entry, Helper_Abstract_Model $model, $config = [] ) {

		/* Set up required variables */
		$form        = apply_filters( 'gfpdf_current_form_object', $this->gform->get_form( $entry['form_id'] ), $entry, __FUNCTION__ );
		$products    = new Field_Products( new GF_Field(), $entry, $this->gform, $this->misc );
		$page_number = 0;

		$enable_columns = ! isset( $config['meta']['enable_css_ready_classes'] ) || $config['meta']['enable_css_ready_classes'];
		if ( $enable_columns ) {
			$container = ! GFCommon::is_legacy_markup_enabled( $form['id'] ) ? new Helper_Field_Container_Gf25() : new Helper_Field_Container();
		} else {
			$container = new Helper_Field_Container_Void();
		}

		$container = apply_filters( 'gfpdf_field_container_class', $container, $form, $entry, $config );

		/* Allow the config to be changed through a filter */
		$config['meta'] = ( isset( $config['meta'] ) ) ? $config['meta'] : [];

		/**
		 * See https://docs.gravitypdf.com/v6/developers/filters/gfpdf_current_pdf_configuration/ for usage
		 *
		 * @since 4.2
		 */
		$config = apply_filters( 'gfpdf_current_pdf_configuration', $config, $entry, $form );

		/* Get the user configuration values */
		$show_title                     = ( isset( $config['meta']['show_title'] ) ) ? $config['meta']['show_title'] : false; /* whether we should show the form title. Default to true */
		$show_page_names                = ( isset( $config['meta']['page_names'] ) ) ? $config['meta']['page_names'] : false; /* whether we should show the form's page names. Default to false */
		$show_individual_product_fields = ( isset( $config['meta']['individual_products'] ) ) ? $config['meta']['individual_products'] : false; /* Whether to show individual fields in the entry. Default to false - they are grouped together at the end of the form */

		/* Skip over any of the following blacklisted fields */
		$blacklisted = apply_filters( 'gfpdf_blacklisted_fields', [ 'captcha', 'password' ] );

		/* Display the form title, if needed */
		$this->show_form_title( $show_title, $form );

		/* Loop through the fields and output or skip if needed */
		foreach ( $form['fields'] as $key => $field ) {
			/*
			 * Middleware filter to check if the field should be skipped.
			 *
			 * If $middleware is true the field will not be displayed in the PDF
			 *
			 * See https://docs.gravitypdf.com/v6/developers/filters/gfpdf_field_middleware/ for usage
			 *
			 * @since 4.2
			 */
			$middleware = apply_filters( 'gfpdf_field_middleware', false, $field, $entry, $form, $config, $products, $blacklisted );

			if ( $middleware ) {
				$container->maybe_display_faux_column( $field );
				continue;
			}

			/* Let's output our field */
			$this->process_field( $field, $entry, $form, $config, $products, $container, $model );
		}

		/* correctly close / cleanup the HTML container if needed */
		$container->close();

		/*
		 * Filter to prevent the product table showing
		 *
		 * See https://docs.gravitypdf.com/v6/developers/filters/gfpdf_disable_product_table/
		 *
		 * @since 5.1
		 */
		$should_disable_product_table = apply_filters( 'gfpdf_disable_product_table', false, $entry, $form, $config, $products );
		if ( ! $should_disable_product_table && $show_individual_product_fields === false && ! $products->is_empty() ) {
			$products->enable_output();
			$products->html();
		}
	}

	/**
	 * Handle our field loader and display the generated HTML
	 *
	 * @param GF_Field               $field    The field to process
	 * @param array                  $entry    The Gravity Form Entry
	 * @param array                  $form     The Gravity Form Field
	 * @param array                  $config   The user-passed configuration data
	 * @param Field_Products         $products A Field_Products Object
	 * @param Helper_Field_Container $container
	 * @param Helper_Abstract_Model  $model
	 *
	 * @since 4.0
	 */
	public function process_field( GF_Field $field, $entry, $form, $config, Field_Products $products, Helper_Field_Container $container, Helper_Abstract_Model $model ) {

		/*
		* Set up our configuration variables
		*/
		$config['meta']           = $config['meta'] ?? []; /* ensure we have a meta key */
		$show_empty_fields        = $config['meta']['empty'] ?? false; /* whether to show empty fields or not. Default is false */
		$load_legacy_css          = $config['meta']['legacy_css'] ?? false; /* whether we should add our legacy field class names (v3.x.x) to our fields. Default to false */
		$show_section_description = $config['meta']['section_content'] ?? false; /* whether we should include a section breaks content. Default to false */

		/** @var \GFPDF\Helper\Helper_Abstract_Fields $class */
		$class = $model->get_field_class( $field, $form, $entry, $products, $config );

		/* Try and display our HTML */
		try {

			/* Only load our HTML if the field is NOT empty, or the $empty config option is true */
			if ( $show_empty_fields === true || ! $class->is_empty() ) {
				/* Load our legacy CSS class names */
				if ( $load_legacy_css === true ) {
					GFPDFEntryDetail::load_legacy_css( $field );
				}

				/**
				 * Add CSS Ready Class Float Support to mPDF
				 * Open a HTML container if needed
				 */
				$container->generate( $field );

				$class->enable_output();
				$field->type !== 'section' ? $class->html() : $class->html( $show_section_description );
			} else {
				/* To prevent display issues we will output the column markup needed */
				$container->maybe_display_faux_column( $field );
			}
		} catch ( Exception $e ) {
			$this->log->error(
				'PDF Generation Error',
				[
					'field'     => $field,
					'entry'     => $entry,
					'config'    => $config,
					'form_id'   => $form['id'],
					'exception' => $e->getMessage(),
				]
			);
		}
	}

	/**
	 * If enabled, we'll show the Gravity Form Title in the document
	 *
	 * @param boolean $show_title Whether or not to show the title
	 * @param array   $form       The Gravity Form array
	 *
	 * @return void
	 *
	 * @since 4.0
	 */
	public function show_form_title( $show_title, $form ) {
		/* Show the form title, if needed */
		if ( $show_title !== false ) {

			/* Load our HTML */
			$html = $this->load( 'form_title', [ 'form' => $form ], false );

			/* Run it through a filter and output */
			Kses::output( apply_filters( 'gfpdf_pdf_form_title_html', $html, $form ) );
		}
	}

	/**
	 * Output the current page name HTML
	 *
	 * @param integer                $page The current page number
	 * @param array                  $form The form array
	 * @param Helper_Field_Container $container
	 *
	 * @since    4.0
	 *
	 * @deprecated 6.10.1 Page fields are handled like all other fields, with markup generated using a dedicated Field_Page class
	 */
	public function display_page_name( $page, $form, Helper_Field_Container $container ) {

		/* Only display the current page name if it exists */
		if ( isset( $form['pagination']['pages'][ $page ] ) && strlen( trim( $form['pagination']['pages'][ $page ] ) ) > 0 ) {

			/* correctly close / cleanup the HTML container if needed */
			$container->close();

			/* Find any CSS assigned to the page */
			$classes = '';
			foreach ( $form['fields'] as $field ) {
				if ( $field->type === 'page' && $field->pageNumber === ( $page + 1 ) ) {
					$classes = $field->cssClass;
					break;
				}
			}

			/* Load our HTML */
			$html = $this->load(
				'page_title',
				[
					'form'    => $form,
					'page'    => $page,
					'classes' => $classes,
				],
				false
			);

			/* Run it through a filter and output */
			Kses::output( apply_filters( 'gfpdf_field_page_name_html', $html, $page, $form ) );
		}
	}

	/**
	 * Automatically render our core PDF fields and add styles in templates to simplify there usage for users
	 *
	 * @param string $html The current HTML template being processed
	 * @param array  $form
	 * @param array  $entry
	 * @param array  $settings
	 *
	 * @return string
	 * @since 4.0
	 */
	public function autoprocess_core_template_options( $html, $form, $entry, $settings ) {
		/* Prevent core styles loading if a v3 template or using our legacy Tier 2 add-on */
		$template_info = $this->templates->get_template_info_by_id( $settings['template'] );
		if (
			( esc_html__( 'Legacy', 'gravity-forms-pdf-extended' ) !== $template_info['group'] ) &&
			( empty( $settings['advanced_template'] ) || 'Yes' !== $settings['advanced_template'] )
		) {
			$html = $this->get_core_template_styles( $settings, $entry ) . $html;
		}

		return $html;
	}

	/**
	 * Loads the core template styles and runs it through a filter
	 *
	 * @param array $entry    The Gravity Form entry being processed
	 * @param array $settings The current PDF settings
	 *
	 * @return string
	 *
	 * @since 4.0
	 */
	public function get_core_template_styles( $settings, $entry ) {
		$form = apply_filters( 'gfpdf_current_form_object', $this->gform->get_form( $entry['form_id'] ), $entry, __FUNCTION__ );

		$html = $this->load_core_template_styles( $settings, $form, $entry );

		$html = apply_filters( 'gfpdf_pdf_core_template_html_output', $html, $form, $entry, $settings );
		$html = apply_filters( 'gfpdf_pdf_core_template_html_output_' . $form['id'], $html, $form, $entry, $settings );

		return $html;
	}

	/**
	 * Load our core PDF template settings
	 *
	 * @param array $settings Current PDF Settings being processed
	 * @param array $form Current form being processed (added in 6.5)
	 * @param array $entry Current form being processed (added in 6.5)
	 *
	 * @return string|WP_Error
	 *
	 * @since 4.0
	 */
	public function load_core_template_styles( $settings, $form = [], $entry = [] ) {
		return $this->load(
			'core_template_styles',
			[
				'settings' => $settings,
				'form'     => $form,
				'entry'    => $entry,
			],
			false
		);
	}

	/**
	 * Allow PDF HTML Mark-up when using wp_kses_post() during PDF generation
	 *
	 * @param array $tags
	 *
	 * @return array
	 *
	 * @since 5.1.1
	 */
	public function allow_pdf_html( $tags ) {
		return Kses::get_allowed_pdf_tags( $tags );
	}

	/**
	 * Allow PDF CSS Mark-up when using wp_kses_post() during PDF generation
	 *
	 * @param array $styles
	 *
	 * @return array
	 *
	 * @since 5.1.1
	 */
	public function allow_pdf_css( $styles ) {
		return Kses::get_allowed_pdf_styles( $styles );
	}

	/**
	 * @param array $form_data
	 *
	 * @return void
	 *
	 * @since 6.4.0
	 */
	public function maybe_view_form_data( $form_data ) {

		/* phpcs:ignore WordPress.Security.NonceVerification.Recommended */
		if ( ! isset( $_GET['data'] ) ) {
			return;
		}

		/* Disable if PDF Debug Mode off AND the environment is production */
		if ( $this->options->get_option( 'debug_mode', 'No' ) === 'No' && ( ! function_exists( 'wp_get_environment_type' ) || wp_get_environment_type() === 'production' ) ) {
			return;
		}

		/* Check if user has permission to view info */
		if ( ! $this->gform->has_capability( 'gravityforms_view_settings' ) ) {
			return;
		}

		print '<pre>';
		/* phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r */
		print_r( $form_data );
		print '</pre>';

		exit;
	}
}