GFPDFHelperHelper_Templates

Class Helper_Templates.

Defined (1)

The class is defined in the following location(s).

/src/helper/Helper_Templates.php  
  1. class Helper_Templates { 
  2.  
  3. /** 
  4. * Holds our log class 
  5. * @var \Monolog\Logger|LoggerInterface 
  6. * @since 4.1 
  7. */ 
  8. protected $log; 
  9.  
  10. /** 
  11. * Holds our Helper_Data object 
  12. * which we can autoload with any data needed 
  13. * @var \GFPDF\Helper\Helper_Data 
  14. * @since 4.1 
  15. */ 
  16. protected $data; 
  17.  
  18. /** 
  19. * Setup our class by injecting all our dependancies 
  20. * @param \Monolog\Logger|LoggerInterface $log Our logger class 
  21. * @param \GFPDF\Helper\Helper_Data $data Our plugin data store 
  22. * @since 4.1 
  23. */ 
  24. public function __construct( LoggerInterface $log, Helper_Data $data ) { 
  25.  
  26. /** Assign our internal variables */ 
  27. $this->log = $log; 
  28. $this->data = $data; 
  29.  
  30. /** 
  31. * Check if running single or multisite and return the working directory path 
  32. * @return string Path to working directory 
  33. * @since 4.1 
  34. */ 
  35. public function get_template_path() { 
  36. if ( is_multisite() ) { 
  37. return $this->data->multisite_template_location; 
  38.  
  39. return $this->data->template_location; 
  40.  
  41. /** 
  42. * Check if running single or multisite and return the working directory URL 
  43. * @return string URL to working directory 
  44. * @since 4.1 
  45. */ 
  46. public function get_template_url() { 
  47. if ( is_multisite() ) { 
  48. return $this->data->multisite_template_location_url; 
  49.  
  50. return $this->data->template_location_url; 
  51.  
  52. /** 
  53. * Gets the full list of available PDF templates 
  54. * @return array 
  55. * @since 4.1 
  56. */ 
  57. public function get_all_templates() { 
  58.  
  59. $template_list = []; 
  60. $matched_templates_basename_list = []; 
  61. $raw_templates = $this->get_unfiltered_template_list(); 
  62.  
  63. /** Loop through all files, filter out any duplicates and return a single array with all the templates */ 
  64. foreach ( $raw_templates as $template_group ) { 
  65. $unique_templates = $this->parse_unique_templates( $template_group, $matched_templates_basename_list ); 
  66. $template_list = array_merge( $template_list, $unique_templates ); 
  67.  
  68. /** Keep track of all matches by their basename (template ID) */ 
  69. $matched_templates_basename_list = array_merge( $matched_templates_basename_list, array_map( function ( $file ) { 
  70. return basename( $file, '.php' ); 
  71. }, $unique_templates ) ); 
  72.  
  73. return $template_list; 
  74.  
  75. /** 
  76. * Get a multi-dimensional array with the PDF template files 
  77. * @return array 
  78. * @since 4.1 
  79. */ 
  80. public function get_unfiltered_template_list() { 
  81. $raw_templates = []; 
  82.  
  83. /** Get current multisite templates, if any */ 
  84. if ( is_multisite() ) { 
  85. $raw_templates[] = glob( $this->data->multisite_template_location . '*.php' ); 
  86.  
  87. /** Get the current user-templates and the core templates */ 
  88. $raw_templates[] = glob( $this->data->template_location . '*.php' ); 
  89. $raw_templates[] = $this->get_core_pdf_templates(); 
  90.  
  91. return $raw_templates; 
  92.  
  93. /** 
  94. * Parse our installed PDF template files 
  95. * @return array The array of templates 
  96. * @since 4.1 
  97. */ 
  98. public function get_all_templates_by_group() { 
  99.  
  100. $template_groups = []; 
  101. $template_list = $this->get_all_templates(); 
  102.  
  103. foreach ( $template_list as $template_path ) { 
  104. $info = $this->get_template_info_by_path( $template_path ); 
  105.  
  106. if ( $this->is_template_compatible( $info['required_pdf_version'] ) ) { 
  107. $template_groups[ $info['group'] ][ $info['id'] ] = $info['template']; 
  108.  
  109. return apply_filters( 'gfpdf_template_list', $template_groups ); 
  110.  
  111. /** 
  112. * Checks if the version is compatible with Gravity PDF 
  113. * @param int|float|string $required_version The version to check against 
  114. * @return bool 
  115. * @since 4.1 
  116. */ 
  117. public function is_template_compatible( $required_version ) { 
  118. if ( version_compare( $required_version, PDF_EXTENDED_VERSION, '<=' ) ) { 
  119. return true; 
  120.  
  121. return false; 
  122.  
  123. /** 
  124. * Appends a compatibility notice to the template name if current version of Gravity PDF isn't compatible 
  125. * @param string $template_name The template ID (the PDF template basename) 
  126. * @param string|int|float $required_version The minimum required version of Gravity PDF the template needs to run 
  127. * @return string 
  128. * @since 4.1 
  129. */ 
  130. public function maybe_add_template_compatibility_notice( $template_name, $required_version ) { 
  131. if ( ! $this->is_template_compatible( $required_version ) ) { 
  132. return $template_name . ' (' . esc_html__( 'Requires Gravity PDF', 'gravity-forms-pdf-extended' ) . ' v' . $required_version . ')'; 
  133.  
  134. return $template_name; 
  135.  
  136. /** 
  137. * Filters out all $templates_to_check templates already found in the $current_template_list 
  138. * @param array $templates_to_check 
  139. * @param array $current_template_list 
  140. * @return array Full path to the unique templates 
  141. * @since 4.1 
  142. */ 
  143. private function parse_unique_templates( $templates_to_check, $current_template_list = [] ) { 
  144. $template_list = []; 
  145.  
  146. foreach ( $templates_to_check as $template ) { 
  147. $file_name = basename( $template, '.php' ); 
  148.  
  149. /** 
  150. * If the template isn't found in the current list and it's our legacy configuration file 
  151. * we'll include it in our template list 
  152. */ 
  153. if ( $file_name !== 'configuration' && $file_name !== 'configuration.archive' 
  154. && ! in_array( $file_name, $current_template_list ) 
  155. ) { 
  156. $template_list[] = $template; 
  157.  
  158. return $template_list; 
  159.  
  160. /** 
  161. * Get template header info for all PDF templates 
  162. * @return array 
  163. * @since 4.1 
  164. */ 
  165. public function get_all_template_info() { 
  166. return array_map( function ( $template_path ) { 
  167. return $this->get_template_info_by_path( $template_path ); 
  168. }, $this->get_all_templates() ); 
  169.  
  170. /** 
  171. * Get the PDF template path by the template name 
  172. * @param string $template_id The PDF template name/ID 
  173. * @param boolean $include_core Whether to check in the core plugin template folder 
  174. * @return string The full path to the matching template 
  175. * @throws Exception 
  176. * @since 4.1 
  177. */ 
  178. public function get_template_path_by_id( $template_id, $include_core = true ) { 
  179.  
  180. /** Check if template found in multisite PDF working directory */ 
  181. $path_to_test = ( is_multisite() ) ? $this->data->multisite_template_location . $template_id . '.php' : false; 
  182. if ( is_multisite() && is_file( $path_to_test ) ) { 
  183. return $path_to_test; 
  184.  
  185. /** Check if template found in PDF working directory */ 
  186. $path_to_test = $this->data->template_location . $template_id . '.php'; 
  187. if ( is_file( $path_to_test ) ) { 
  188. return $path_to_test; 
  189.  
  190. /** Check if template found in the core template files */ 
  191. $path_to_test = PDF_PLUGIN_DIR . 'src/templates/' . $template_id . '.php'; 
  192. if ( $include_core && is_file( $path_to_test ) ) { 
  193. return $path_to_test; 
  194.  
  195. throw new Exception( sprintf( 'Could not find the template: %s.php', $template_id ) ); 
  196.  
  197. /** 
  198. * Get the template information based on the template file's basename (without .php) 
  199. * @param string $template_id The PDF template basename (eg. zadani) 
  200. * @return array The template information 
  201. * @since 4.1 
  202. */ 
  203. public function get_template_info_by_id( $template_id ) { 
  204.  
  205. try { 
  206. $template_path = $this->get_template_path_by_id( $template_id ); 
  207.  
  208. return $this->get_template_info_by_path( $template_path ); 
  209. } catch ( Exception $e ) { 
  210. $this->log->addWarning( $e->getMessage() ); 
  211.  
  212. return [ 
  213. 'group' => esc_html__( 'Legacy', 'gravity-forms-pdf-extended' ),  
  214. ]; 
  215.  
  216. /** 
  217. * Get an array of the current template files on the server 
  218. * @param string $template_id 
  219. * @return array The full path to all files related to the current PDF template 
  220. * @throws Exception 
  221. * @internal This only includes the base PDF template and associated config and image files 
  222. * Any additional files aren't automatically cleaned up and should be removed 
  223. * from the PDF template configuration's tearDown() method. 
  224. * @since 4.1 
  225. */ 
  226. public function get_template_files_by_id( $template_id ) { 
  227.  
  228. $files = []; 
  229.  
  230. try { 
  231. $files[] = $this->get_template_path_by_id( $template_id, false ); 
  232. } catch ( Exception $e ) { 
  233. /** Don't process because we couldn't find the file */ 
  234. throw new Exception( 'Could not find PDF template file' ); 
  235.  
  236. try { 
  237. $files[] = $this->get_config_path_by_id( $template_id, false ); 
  238. } catch ( Exception $e ) { 
  239. /** do nothing */ 
  240.  
  241. $image = $this->get_template_image( $template_id, 'path', false ); 
  242.  
  243. if ( $image !== '' ) { 
  244. $files[] = $image; 
  245.  
  246. return $files; 
  247.  
  248. /** 
  249. * Gets the PDF template header information and returns it in a parsed format 
  250. * @param string $template_path The full path to the PDF template file 
  251. * @return array 
  252. * @since 4.1 
  253. */ 
  254. public function get_template_info_by_path( $template_path ) { 
  255. $info = get_file_data( $template_path, $this->get_template_header_details() ); 
  256.  
  257. $info['id'] = basename( $template_path, '.php' ); 
  258. $info['template'] = ( strlen( $info['template'] ) > 0 ) ? $info['template'] : $this->human_readable_template_name( $info['id'] ); 
  259. $info['group'] = ( strlen( $info['group'] ) > 0 ) ? $info['group'] : esc_html__( 'Legacy', 'gravity-forms-pdf-extended' ); 
  260. $info['description'] = ( strlen( $info['description'] ) > 0 ) ? $info['description'] : ''; 
  261. $info['author'] = ( strlen( $info['author'] ) > 0 ) ? $info['author'] : ''; 
  262. $info['author uri'] = ( strlen( $info['author uri'] ) > 0 ) ? $info['author uri'] : ''; 
  263. $info['version'] = ( strlen( $info['version'] ) > 0 ) ? $info['version'] : '1.0'; 
  264. $info['tags'] = ( strlen( $info['tags'] ) > 0 ) ? $info['tags'] : ''; 
  265. $info['path'] = $template_path; 
  266. $info['screenshot'] = $this->get_template_image( $info['id'] ); 
  267. $info['required_pdf_version'] = ( strlen( 'required_pdf_version' ) > 0 ) ? $info['required_pdf_version'] : '4.0'; 
  268.  
  269. return $info; 
  270.  
  271. /** 
  272. * The key / value parsing of the expected PDF template header in v4 
  273. * @return array 
  274. * @since 4.1 
  275. */ 
  276. public function get_template_header_details() { 
  277. /** 
  278. * We load in data from the PDF template headers 
  279. * @var array 
  280. */ 
  281. return apply_filters( 'gfpdf_template_header_details', [ 
  282. 'template' => esc_html__( 'Template Name', 'gravity-forms-pdf-extended' ),  
  283. 'version' => esc_html__( 'Version', 'gravity-forms-pdf-extended' ),  
  284. 'description' => esc_html__( 'Description', 'gravity-forms-pdf-extended' ),  
  285. 'author' => esc_html__( 'Author', 'gravity-forms-pdf-extended' ),  
  286. 'author uri' => esc_html__( 'Author URI', 'gravity-forms-pdf-extended' ),  
  287. 'group' => esc_html__( 'Group', 'gravity-forms-pdf-extended' ),  
  288. 'required_pdf_version' => esc_html__( 'Required PDF Version', 'gravity-forms-pdf-extended' ),  
  289. 'tags' => esc_html__( 'Tags', 'gravity-forms-pdf-extended' ),  
  290. ] ); 
  291.  
  292. /** 
  293. * Returns an array of the current PDF templates shipped with Gravity PDF 
  294. * @return array 
  295. * @since 4.1 
  296. */ 
  297. public function get_core_pdf_templates() { 
  298. $templates = glob( PDF_PLUGIN_DIR . 'src/templates/*.php' ); 
  299.   
  300. return ( is_array( $templates ) ) ? $templates : []; 
  301.   
  302. /** 
  303. * Gets the full path to the template's config file (if any) 
  304. * @param string $template_id 
  305. * @param bool $include_core 
  306. * @return string 
  307. * @throws Exception 
  308. * @since 4.1 
  309. */ 
  310. public function get_config_path_by_id( $template_id, $include_core = true ) { 
  311.  
  312. /** Check if there's a configuration class in the following directories */ 
  313. $test_config_paths = [ 
  314. $this->data->template_location . 'config/',  
  315. ]; 
  316.  
  317. if ( is_multisite() ) { 
  318. array_unshift( $test_config_paths, $this->data->multisite_template_location . 'config/' ); 
  319.  
  320. if ( $include_core ) { 
  321. array_push( $test_config_paths, PDF_PLUGIN_DIR . 'src/templates/config/' ); 
  322.  
  323. foreach ( $test_config_paths as $path ) { 
  324. $file = $path . $template_id . '.php'; 
  325.  
  326. if ( is_file( $file ) ) { 
  327. return $file; 
  328.  
  329. throw new Exception ( sprintf( 'Could not locate configuration for "%s" template', $template_id ) ); 
  330.  
  331. /** 
  332. * Attempts to load the current template configuration (if any) 
  333. * We first look in the PDF_EXTENDED_TEMPLATE directory (in case a user has overridden the file) 
  334. * Then we try and load the core configuration file 
  335. * @param string $template_id The template config to load 
  336. * @return object 
  337. * @since 4.1 
  338. */ 
  339. public function get_config_class( $template_id ) { 
  340.  
  341. try { 
  342. $class_path = $this->get_config_path_by_id( $template_id ); 
  343.  
  344. return $this->load_template_config_file( $class_path ); 
  345. } catch ( Exception $e ) { 
  346. $this->log->addError( $e->getMessage() ); 
  347.  
  348. /** If class still empty it's either a legacy template or doesn't have a config. Check for legacy templates which support certain fields */ 
  349. $legacy_templates = apply_filters( 'gfpdf_legacy_templates', [ 
  350. 'default-template',  
  351. 'default-template-two-rows',  
  352. 'default-template-no-style',  
  353. ] ); 
  354.  
  355. if ( in_array( $template_id, $legacy_templates ) ) { 
  356. try { 
  357. $class = $this->load_template_config_file( PDF_PLUGIN_DIR . 'src/templates/config/legacy.php' ); 
  358. } catch ( Exception $e ) { 
  359. $this->log->addError( 'Legacy Template Configuration Failed to Load' ); 
  360.  
  361. /** If there is still no class loaded we'll pass along a new empty class */ 
  362. if ( empty( $class ) ) { 
  363. $class = new stdClass(); 
  364.  
  365. return $class; 
  366.  
  367. /** 
  368. * Load our template configuration file, if it exists 
  369. * @param string $file The file to load 
  370. * @return object 
  371. * @since 4.1 
  372. * @throws Exception 
  373. */ 
  374. public function load_template_config_file( $file ) { 
  375.  
  376. $namespace = 'GFPDF\Templates\Config\\'; 
  377. $class_name = $this->get_config_class_name( $file ); 
  378. $fqcn = $namespace . $class_name; 
  379.  
  380. /** Try and load the file if the class doesn't exist */ 
  381. if ( ! class_exists( $fqcn ) && is_file( $file ) && is_readable( $file ) ) { 
  382. require_once( $file ); 
  383.  
  384. /** Insure the class we are trying to load exists and impliments our Helper_Interface_Config interface */ 
  385. if ( class_exists( $fqcn ) && in_array( 'GFPDF\Helper\Helper_Interface_Config', class_implements( $fqcn ) ) ) { 
  386. return new $fqcn(); 
  387.  
  388. throw new Exception( 'Template Configuration Failed to Load' ); 
  389.  
  390. /** 
  391. * Takes a full path to the file and converts it to the appropriate class name 
  392. * This follows the simple rules the file basename has its hyphens and spaces are converted to underscores 
  393. * then gets converted to sentence case using the underscore as a delimiter 
  394. * @param string $file The path to a file 
  395. * @return string 
  396. * @since 4.1 
  397. */ 
  398. public function get_config_class_name( $file ) { 
  399. $file = basename( $file, '.php' ); 
  400. $file = str_replace( [ '-', ' ' ], '_', $file ); 
  401.  
  402. /** Using a delimiter with ucwords doesn't appear to work correctly so go old school */ 
  403. $file_array = explode( '_', $file ); 
  404. array_walk( $file_array, function ( &$item ) { 
  405. $item = mb_convert_case( $item, MB_CASE_TITLE, 'UTF-8' ); 
  406. } ); 
  407.  
  408. $file = implode( '_', $file_array ); 
  409.  
  410. return $file; 
  411.  
  412. /** 
  413. * Converts a name into something a human can more easily read 
  414. * @param string $name The string to convert 
  415. * @return string 
  416. * @since 4.1 
  417. */ 
  418. public function human_readable_template_name( $name ) { 
  419. $name = str_replace( [ '-', '_' ], ' ', $name ); 
  420.  
  421. return mb_convert_case( $name, MB_CASE_TITLE ); 
  422.  
  423. /** 
  424. * Do a lookup for the current template image (if any) and return the url 
  425. * @param string $template The template name to look for 
  426. * @param string $type Either 'url' or 'path' 
  427. * @param bool $include_core Whether to include the core PDF templates 
  428. * @return string Full URL to image 
  429. * @since 4.1 
  430. */ 
  431. public function get_template_image( $template, $type = 'url', $include_core = true ) { 
  432.  
  433. /** Check if there's an image in the following directories */ 
  434. $test_image_paths = [ 
  435. $this->data->template_location_url . 'images/' => $this->data->template_location . 'images/',  
  436. ]; 
  437.  
  438. if ( is_multisite() ) { 
  439. $test_image_paths = [ $this->data->multisite_template_location_url . 'images/' => $this->data->multisite_template_location . 'images/' ] + $test_image_paths; 
  440.  
  441. if ( $include_core ) { 
  442. $test_image_paths[ PDF_PLUGIN_URL . 'src/templates/images/' ] = PDF_PLUGIN_DIR . 'src/templates/images/'; 
  443.  
  444. /** Check if our image exists in one of our directories and return the URL */ 
  445. $template .= '.png'; 
  446. foreach ( $test_image_paths as $url => $path ) { 
  447. if ( is_file( $path . $template ) ) { 
  448. return ( $type === 'url' ) ? $url . $template : $path . $template; 
  449.  
  450. return ''; 
  451.  
  452. /** 
  453. * Get the arguments array that should be passed to our PDF Template 
  454. * @param array $form The Gravity Form array 
  455. * @param array $fields The Gravity Form fields array, with the field ID as the array key 
  456. * @param array $entry Gravity Form Entry The Gravity Forms entry array 
  457. * @param array $form_data The form data array, formatted form the $entry array 
  458. * @param array $settings PDF Settings The current PDF settings 
  459. * @param object $config The current PDF template configuration class 
  460. * @param array $legacy_ids An array of multiple entry IDs for legacy templates only 
  461. * @return array 
  462. * @since 4.1 
  463. */ 
  464. public function get_template_arguments( $form, $fields, $entry, $form_data, $settings, $config, $legacy_ids ) { 
  465. global $gfpdf; 
  466.  
  467. /** Disable the field encryption checks which can slow down our entry queries */ 
  468. add_filter( 'gform_is_encrypted_field', '__return_false' ); 
  469.  
  470. /** See https://gravitypdf.com/documentation/v4/gfpdf_template_args/ for more details about this filter */ 
  471.  
  472. return apply_filters( 'gfpdf_template_args', [ 
  473.  
  474. 'form_id' => $form['id'], /** backwards compat */ 
  475. 'lead_ids' => $legacy_ids, /** backwards compat */ 
  476. 'lead_id' => apply_filters( 'gfpdfe_lead_id', $entry['id'], $form, $entry, $gfpdf ), /** backwards compat */ 
  477.  
  478. 'form' => $form,  
  479. 'entry' => $entry,  
  480. 'lead' => $entry,  
  481. 'form_data' => $form_data,  
  482. 'fields' => $fields,  
  483. 'config' => $config,  
  484.  
  485. 'settings' => $settings,  
  486.  
  487. 'gfpdf' => $gfpdf,  
  488.  
  489. ], $entry, $settings, $form );