GFPDFModelModel_Templates

Model_Actions.

Defined (1)

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

/src/model/Model_Templates.php  
  1. class Model_Templates extends Helper_Abstract_Model { 
  2.  
  3. /** 
  4. * Holds our Helper_Templates object 
  5. * used to ease access to our PDF templates 
  6. * @var \GFPDF\Helper\Helper_Templates 
  7. * @since 4.1 
  8. */ 
  9. protected $templates; 
  10.  
  11. /** 
  12. * Holds our log class 
  13. * @var \Monolog\Logger|LoggerInterface 
  14. * @since 4.1 
  15. */ 
  16. protected $log; 
  17.  
  18. /** 
  19. * Holds our Helper_Data object 
  20. * which we can autoload with any data needed 
  21. * @var \GFPDF\Helper\Helper_Data 
  22. * @since 4.1 
  23. */ 
  24. protected $data; 
  25.  
  26. /** 
  27. * Holds our Helper_Misc object 
  28. * Makes it easy to access common methods throughout the plugin 
  29. * @var \GFPDF\Helper\Helper_Misc 
  30. * @since 4.1 
  31. */ 
  32. protected $misc; 
  33.  
  34.  
  35. /** 
  36. * Model_Templates constructor. 
  37. * @param Helper_Templates $templates 
  38. * @param LoggerInterface $log 
  39. * @param Helper_Data $data 
  40. * @param Helper_Misc $misc 
  41. * @since 4.1 
  42. */ 
  43. public function __construct( Helper_Templates $templates, LoggerInterface $log, Helper_Data $data, Helper_Misc $misc ) { 
  44. /** Assign our internal variables */ 
  45. $this->templates = $templates; 
  46. $this->data = $data; 
  47. $this->log = $log; 
  48. $this->misc = $misc; 
  49.  
  50. /** 
  51. * AJAX Endpoint to handle the uploading of PDF templates 
  52. * @param string $_POST ['nonce'] a valid nonce 
  53. * @since 4.1 
  54. */ 
  55. public function ajax_process_uploaded_template() { 
  56.  
  57. $this->misc->handle_ajax_authentication( 'Process Uploaded Template Zip Package' ); 
  58.  
  59. /** Validate uploaded file */ 
  60. try { 
  61. $storage = new FileSystem( $this->data->template_tmp_location ); 
  62. $file = new File( 'template', $storage ); 
  63. $zip_path = $this->move_template_to_tmp_dir( $file ); 
  64. } catch ( Exception $e ) { 
  65. $this->log->addWarning( 'File validation and move failed', [ 
  66. 'file' => $_FILES,  
  67. 'error' => $e->getMessage(),  
  68. ] ); 
  69.  
  70. /** Bad Request */ 
  71. wp_die( '400', 400 ); 
  72.  
  73. /** Unzip and check the PDF templates look valid */ 
  74. try { 
  75. $this->unzip_and_verify_templates( $zip_path ); 
  76. } catch ( Exception $e ) { 
  77. $this->cleanup_template_files( $zip_path ); 
  78.  
  79. $this->log->addWarning( 'File validation and move failed', [ 
  80. 'file' => $_FILES,  
  81. 'error' => $e->getMessage(),  
  82. ] ); 
  83.  
  84. header( 'Content-Type: application/json' ); 
  85. echo json_encode( [ 
  86. 'error' => $e->getMessage(),  
  87. ] ); 
  88.  
  89. /** Bad Response */ 
  90. wp_die( '', 400 ); 
  91.  
  92. /** Copy all the files to the active PDF working directory */ 
  93. $unzipped_dir_name = $this->get_unzipped_dir_name( $zip_path ); 
  94. $template_path = $this->templates->get_template_path(); 
  95.  
  96. $results = $this->misc->copyr( $unzipped_dir_name, $template_path ); 
  97.  
  98. /** Get the template headers now all the files are in the right location */ 
  99. $headers = $this->get_template_info( glob( $unzipped_dir_name . '*.php' ) ); 
  100.  
  101. /** Fix template path */ 
  102. $headers = array_map( function( $header ) use ( $unzipped_dir_name, $template_path ) { 
  103. $header['path'] = str_replace( $unzipped_dir_name, $template_path, $header['path'] ); 
  104. return $header; 
  105. }, $headers ); 
  106.  
  107. /** Run PDF template SetUp method if required */ 
  108. $this->maybe_run_template_setup( $headers ); 
  109.  
  110. /** Cleanup tmp uploaded files */ 
  111. $this->cleanup_template_files( $zip_path ); 
  112.  
  113. if ( is_wp_error( $results ) ) { 
  114. /** Internal Server Error */ 
  115. wp_die( '500', 500 ); 
  116.  
  117. /** Return newly-installed template headers */ 
  118. header( 'Content-Type: application/json' ); 
  119. echo json_encode( [ 
  120. 'templates' => $headers,  
  121. ] ); 
  122.  
  123. /** Okay Response */ 
  124. wp_die( '', 200 ); 
  125.  
  126. /** 
  127. * Execute the setUp method on any templates that impliment it 
  128. * @param array $headers Contains the array returned from $this->get_template_info() 
  129. * @since 4.1 
  130. */ 
  131. public function maybe_run_template_setup( $headers = [] ) { 
  132. foreach( $headers as $template ) { 
  133. $config = $this->templates->get_config_class( $template['id'] ); 
  134.  
  135. /** Check if the PDF config impliments our Setup/TearDown interface and run the tear down */ 
  136. if( in_array( 'GFPDF\Helper\Helper_Interface_Setup_TearDown', class_implements( $config ) ) ) { 
  137. $config->setUp(); 
  138.  
  139. /** 
  140. * AJAX Endpoint for deleting user-uploaded PDF templates 
  141. * @param string $_POST ['nonce'] a valid nonce 
  142. * @param string $_POST ['id'] a valid PDF template ID 
  143. * @since 4.1 
  144. */ 
  145. public function ajax_process_delete_template() { 
  146.  
  147. $this->misc->handle_ajax_authentication( 'Delete PDF Template' ); 
  148.  
  149. $template_id = ( isset( $_POST['id'] ) ) ? $_POST['id'] : ''; 
  150.  
  151. /** Get all the necessary PDF template files to delete */ 
  152. try { 
  153. $this->delete_template( $template_id ); 
  154. } catch ( Exception $e ) { 
  155. /** Bad Request */ 
  156. wp_die( '400', 400 ); 
  157.  
  158. header( 'Content-Type: application/json' ); 
  159. echo json_encode( true ); 
  160.  
  161. /** Okay Response */ 
  162. wp_die( '', 200 ); 
  163.  
  164. /** 
  165. * Delete's a PDF templates files 
  166. * @param string $template_id 
  167. * @throws Exception 
  168. * @since 4.1 
  169. */ 
  170. public function delete_template( $template_id ) { 
  171. try { 
  172. $files = $this->templates->get_template_files_by_id( $template_id ); 
  173. $config = $this->templates->get_config_class( $template_id ); 
  174.  
  175. /** Check if the PDF config impliments our Setup/TearDown interface and run the tear down */ 
  176. if( in_array( 'GFPDF\Helper\Helper_Interface_Setup_TearDown', class_implements( $config ) ) ) { 
  177. $config->tearDown(); 
  178.  
  179. /** Remove the PDF template files */ 
  180. foreach ( $files as $file ) { 
  181. unlink( $file ); 
  182.  
  183. } catch ( Exception $e ) { 
  184. throw $e; /** throw further down the chain */ 
  185.  
  186. /** 
  187. * AJAX Endpoint for building the template select box options (so we don't have to recreate the logic in React) 
  188. * @param string $_POST ['nonce'] a valid nonce 
  189. * @since 4.1 
  190. */ 
  191. public function ajax_process_build_template_options_html() { 
  192. $this->misc->handle_ajax_authentication( 'Build Template Options HTML' ); 
  193.  
  194. $options_class = GPDFAPI::get_options_class(); 
  195.  
  196. $registered_settings = $options_class->get_registered_fields(); 
  197. $template_settings = $registered_settings['form_settings']['template']; 
  198.  
  199. $templates = $template_settings['options']; 
  200. $value = $options_class->get_form_value( $template_settings ); 
  201.  
  202. header( 'Content-Type: application/text' ); 
  203. echo $options_class->build_options_for_select( $templates, $value ); 
  204.  
  205. /** Okay Response */ 
  206. wp_die( '', 200 ); 
  207.  
  208. /** 
  209. * Validations, renames and moves the uploaded zip file to an appropriate location 
  210. * @param \Upload\File $file 
  211. * @return string The full path of the final resting place of the uploaded zip file 
  212. * @since 4.1 
  213. */ 
  214. public function move_template_to_tmp_dir( File $file) { 
  215. /** Validate our uploaded file and move to the PDF tmp directory for further processing */ 
  216. $file->setName( uniqid() ); 
  217.  
  218. $file->addValidations( [ 
  219. new Extension( 'zip' ),  
  220. new Size( '10240K' ), /** allow 10MB upload * accounts for fonts, PDF and PHP files */ 
  221. ] ); 
  222.  
  223. /** Do a check to ensure fileinfo is loaded. It should be loaded by default but in some cases this isn't so */ 
  224. if ( extension_loaded( 'fileinfo' ) ) { 
  225. $file->addValidations( [ 
  226. new Mimetype( [ 'application/zip', 'application/octet-stream' ] ),  
  227. ] ); 
  228.  
  229. $file->upload(); 
  230.  
  231. return $this->data->template_tmp_location . $file->getNameWithExtension(); 
  232.  
  233. /** 
  234. * Gets the full path to a new directory which is based on the zip file's unique name 
  235. * @param string $zip_path The full path to the zip file 
  236. * @return string 
  237. * @since 4.1 
  238. */ 
  239. public function get_unzipped_dir_name( $zip_path ) { 
  240. return dirname( $zip_path ) . '/' . basename( $zip_path, '.zip' ) . '/'; 
  241.  
  242. /** 
  243. * Extracts the zip file, checks there are valid PDF template files found and retreives information about them 
  244. * @param $zip_path The full path to the zip file 
  245. * @return array The PDF template headers from the valid files 
  246. * @throws Exception Thrown if a PDF template file isn't valid 
  247. * @since 4.1 
  248. */ 
  249. public function unzip_and_verify_templates( $zip_path ) { 
  250. $this->enable_wp_filesystem(); 
  251.  
  252. $dir = $this->get_unzipped_dir_name( $zip_path ); 
  253. $results = unzip_file( $zip_path, $dir ); 
  254.  
  255. /** If the unzip failed we'll throw an error */ 
  256. if ( is_wp_error( $results ) ) { 
  257. throw new Exception( $results->get_error_message() ); 
  258.  
  259. /** Check unziped templates for a valid v4 header, or v3 string pattern */ 
  260. $files = glob( $dir . '*.php' ); 
  261.  
  262. if ( ! is_array( $files ) || sizeof( $files ) === 0 ) { 
  263. throw new Exception( esc_html__( 'No valid PDF template found in Zip archive.', 'gravity-forms-pdf-extended' ) ); 
  264.  
  265. $this->check_for_valid_pdf_templates( $files ); 
  266.  
  267. /** 
  268. * Sniffs the PHP file for signs that it's a valid Gravity PDF tempalte file 
  269. * @param array $files The full paths to the PDF templates 
  270. * @return array The PDF template header information 
  271. * @throws Exception Thrown if file found not to be valid 
  272. * @since 4.1 
  273. */ 
  274. public function check_for_valid_pdf_templates( $files = [] ) { 
  275. foreach ( $files as $file ) { 
  276.  
  277. /** Check if we have a valid v4 template header in the file */ 
  278. $info = get_file_data( $file, $this->templates->get_template_header_details() ); 
  279.  
  280. if ( ! isset( $info['template'] ) || strlen( $info['template'] ) === 0 ) { 
  281. /** Check if it's a v3 template */ 
  282. $fp = fopen( $file, 'r' ); 
  283. $file_data = fread( $fp, 8192 ); 
  284. fclose( $fp ); 
  285.  
  286. /** Check the first 8kiB contains the string RGForms or GFForms, which signifies our v3 templates */ 
  287. if ( strpos( $file_data, 'RGForms' ) === false && strpos( $file_data, 'GFForms' ) === false ) { 
  288. throw new Exception( sprintf( esc_html__( 'The PHP file %s is not a valid PDF Template.', 'gravity-forms-pdf-extended' ), basename( $file ) ) ); 
  289.  
  290. /** 
  291. * Get the PDF template info to pass to our application 
  292. * @param array $files 
  293. * @return array 
  294. * @since 4.1 
  295. */ 
  296. public function get_template_info( $files = [] ) { 
  297. return array_map( function ( $file ) { 
  298. return $this->templates->get_template_info_by_path( $file ); 
  299. }, $files ); 
  300.  
  301. /** 
  302. * Remove the zip file and the unzipped directory 
  303. * @param $zip_path The full path to the zip file 
  304. * @since 4.1 
  305. */ 
  306. public function cleanup_template_files( $zip_path ) { 
  307. $dir = $this->get_unzipped_dir_name( $zip_path ); 
  308.  
  309. $this->misc->rmdir( $dir ); 
  310. unlink( $zip_path ); 
  311.  
  312. /** 
  313. * A hack to ensure we can use unzip_file() without worrying about 
  314. * credentials being prompted. 
  315. * @since 4.1 
  316. */ 
  317. private function enable_wp_filesystem() { 
  318.  
  319. /** This occurs on an AJAX call so don't need to worry about removing the filter afterwards */ 
  320. add_filter( 'filesystem_method', function () { 
  321. return 'direct'; 
  322. } ); 
  323.  
  324. WP_Filesystem();