GFPDFModelModel_Settings

Model_Welcome_Screen.

Defined (1)

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

/src/model/Model_Settings.php  
  1. class Model_Settings extends Helper_Abstract_Model { 
  2.  
  3. /** 
  4. * Errors with the global form submission process are stored here 
  5. * @var array 
  6. * @since 4.0 
  7. */ 
  8. public $form_settings_errors; 
  9.  
  10. /** 
  11. * Holds the abstracted Gravity Forms API specific to Gravity PDF 
  12. * @var \GFPDF\Helper\Helper_Form 
  13. * @since 4.0 
  14. */ 
  15. protected $gform; 
  16.  
  17. /** 
  18. * Holds our log class 
  19. * @var \Monolog\Logger|LoggerInterface 
  20. * @since 4.0 
  21. */ 
  22. protected $log; 
  23.  
  24. /** 
  25. * Holds our Helper_Notices object 
  26. * which we can use to queue up admin messages for the user 
  27. * @var \GFPDF\Helper\Helper_Misc 
  28. * @since 4.0 
  29. */ 
  30. protected $notices; 
  31.  
  32. /** 
  33. * Holds our Helper_Abstract_Options / Helper_Options_Fields object 
  34. * Makes it easy to access global PDF settings and individual form PDF settings 
  35. * @var \GFPDF\Helper\Helper_Options_Fields 
  36. * @since 4.0 
  37. */ 
  38. protected $options; 
  39.  
  40. /** 
  41. * Holds our Helper_Data object 
  42. * which we can autoload with any data needed 
  43. * @var \GFPDF\Helper\Helper_Data 
  44. * @since 4.0 
  45. */ 
  46. protected $data; 
  47.  
  48. /** 
  49. * Holds our Helper_Misc object 
  50. * Makes it easy to access common methods throughout the plugin 
  51. * @var \GFPDF\Helper\Helper_Misc 
  52. * @since 4.0 
  53. */ 
  54. protected $misc; 
  55.  
  56. /** 
  57. * Holds our Helper_Templates object 
  58. * used to ease access to our PDF templates 
  59. * @var \GFPDF\Helper\Helper_Templates 
  60. * @since 4.0 
  61. */ 
  62. protected $templates; 
  63.  
  64. /** 
  65. * Set up our dependancies 
  66. * @param \GFPDF\Helper\Helper_Abstract_Form $gform Our abstracted Gravity Forms helper functions 
  67. * @param \Monolog\Logger|LoggerInterface $log Our logger class 
  68. * @param \GFPDF\Helper\Helper_Notices $notices Our notice class used to queue admin messages and errors 
  69. * @param \GFPDF\Helper\Helper_Abstract_Options $options Our options class which allows us to access any settings 
  70. * @param \GFPDF\Helper\Helper_Data $data Our plugin data store 
  71. * @param \GFPDF\Helper\Helper_Misc $misc Our miscellaneous class 
  72. * @param \GFPDF\Helper\Helper_Templates $templates 
  73. * @since 4.0 
  74. */ 
  75. public function __construct( Helper_Abstract_Form $gform, LoggerInterface $log, Helper_Notices $notices, Helper_Abstract_Options $options, Helper_Data $data, Helper_Misc $misc, Helper_Templates $templates ) { 
  76.  
  77. /** Assign our internal variables */ 
  78. $this->gform = $gform; 
  79. $this->log = $log; 
  80. $this->options = $options; 
  81. $this->notices = $notices; 
  82. $this->data = $data; 
  83. $this->misc = $misc; 
  84. $this->templates = $templates; 
  85.  
  86. /** 
  87. * Get the form setting error and remove any duplicates 
  88. * @since 4.0 
  89. * @return void 
  90. */ 
  91. public function setup_form_settings_errors() { 
  92.  
  93. /** set up a place to access form setting validation errors */ 
  94. $this->form_settings_errors = get_transient( 'settings_errors' ); 
  95.  
  96. /** remove multiple errors for a single form */ 
  97. if ( $this->form_settings_errors ) { 
  98. $set = false; 
  99. $updated_settings_error = []; 
  100.  
  101. /** loop through current errors */ 
  102. foreach ( $this->form_settings_errors as $error ) { 
  103. if ( $error['setting'] != 'gfpdf-notices' || ! $set ) { 
  104. $updated_settings_error[] = $error; 
  105.  
  106. if ( $error['setting'] == 'gfpdf-notices' ) { 
  107. $set = true; 
  108.  
  109. /** update transient */ 
  110. set_transient( 'settings_errors', $updated_settings_error, 30 ); 
  111.  
  112. $this->log->addNotice( 'PDF Settings Errors', [ 
  113. 'original' => $this->form_settings_errors,  
  114. 'cleaned' => $updated_settings_error,  
  115. ] ); 
  116.  
  117. /** 
  118. * If any errors have been passed back from the options.php page we will highlight the actual fields that caused them 
  119. * @param array $settings The get_registered_fields() array 
  120. * @return array 
  121. * @since 4.0 
  122. */ 
  123. public function highlight_errors( $settings ) { 
  124.  
  125. /** We fire too late to tap into get_settings_error() so our data storage holds the details */ 
  126. $errors = $this->form_settings_errors; 
  127.  
  128. /** Loop through errors if any and highlight the appropriate settings */ 
  129. if ( is_array( $errors ) && sizeof( $errors ) > 0 ) { 
  130. foreach ( $errors as $error ) { 
  131.  
  132. /** Skip over if not an error */ 
  133. if ( $error['type'] !== 'error' ) { 
  134. continue; 
  135.  
  136. /** Loop through our data until we find a match */ 
  137. $found = false; 
  138. foreach ( $settings as $key => &$group ) { 
  139. foreach ( $group as $id => &$item ) { 
  140. if ( $item['id'] === $error['code'] ) { 
  141. $item['class'] = ( isset( $item['class'] ) ) ? $item['class'] . ' gfield_error' : 'gfield_error'; 
  142. $found = true; 
  143. break; 
  144.  
  145. /** exit outer loop */ 
  146. if ( $found ) { 
  147. break; 
  148.  
  149. return $settings; 
  150.  
  151. /** 
  152. * Install the files stored in /src/templates/ to the user's template directory 
  153. * @return boolean 
  154. * @since 4.0 
  155. */ 
  156. public function install_templates() { 
  157.  
  158. $destination = $this->templates->get_template_path(); 
  159. $copy = $this->misc->copyr( PDF_PLUGIN_DIR . 'src/templates/', $destination ); 
  160. if ( is_wp_error( $copy ) ) { 
  161. $this->log->addError( 'Template Installation Error.' ); 
  162. $this->notices->add_error( sprintf( esc_html__( 'There was a problem copying all PDF templates to %s. Please try again.', 'gravity-forms-pdf-extended' ), '<code>' . $this->misc->relative_path( $destination ) . '</code>' ) ); 
  163.  
  164. return false; 
  165.  
  166. $this->notices->add_notice( sprintf( esc_html__( 'Gravity PDF Custom Templates successfully installed to %s.', 'gravity-forms-pdf-extended' ), '<code>' . $this->misc->relative_path( $destination ) . '</code>' ) ); 
  167. $this->options->update_option( 'custom_pdf_template_files_installed', true ); 
  168.  
  169. return true; 
  170.  
  171.  
  172. /** 
  173. * Removes the current font's TTF files from our font directory 
  174. * @param array $fonts The font config 
  175. * @return boolean True on success, false on failure 
  176. * @since 4.0 
  177. */ 
  178. public function remove_font_file( $fonts ) { 
  179.  
  180. $fonts = array_filter( $fonts ); 
  181. $types = [ 'regular', 'bold', 'italics', 'bolditalics' ]; 
  182.  
  183. foreach ( $types as $type ) { 
  184. if ( isset( $fonts[ $type ] ) ) { 
  185. $filename = basename( $fonts[ $type ] ); 
  186.  
  187. if ( is_file( $this->data->template_font_location . $filename ) && ! unlink( $this->data->template_font_location . $filename ) ) { 
  188. return false; 
  189.  
  190. return true; 
  191.  
  192. /** 
  193. * Check that the font name passed conforms to our expected nameing convesion 
  194. * @param string $name The font name to check 
  195. * @return boolean True on valid, false on failure 
  196. * @since 4.0 
  197. */ 
  198. public function is_font_name_valid( $name ) { 
  199.  
  200. $regex = '^[A-Za-z0-9 ]+$'; 
  201.  
  202. if ( preg_match( "/$regex/", $name ) ) { 
  203. return true; 
  204.  
  205. return false; 
  206.  
  207. /** 
  208. * Query our custom fonts options table and check if the font name already exists 
  209. * @param string $name The font name to check 
  210. * @param int|string $id The configuration ID (if any) 
  211. * @return bool True if valid, false on failure 
  212. * @since 4.0 
  213. */ 
  214. public function is_font_name_unique( $name, $id = '' ) { 
  215.  
  216. /** Get the shortname of the current font */ 
  217. $name = $this->options->get_font_short_name( $name ); 
  218.  
  219. /** Loop through default fonts and check for duplicate */ 
  220. $default_fonts = $this->options->get_installed_fonts(); 
  221.  
  222. unset( $default_fonts[ esc_html__( 'User-Defined Fonts', 'gravity-forms-pdf-extended' ) ] ); 
  223.  
  224. /** check for exact match */ 
  225. foreach ( $default_fonts as $group ) { 
  226. if ( isset( $group[ $name ] ) ) { 
  227. return false; 
  228.  
  229. $custom_fonts = $this->options->get_option( 'custom_fonts' ); 
  230.  
  231. if ( is_array( $custom_fonts ) ) { 
  232. foreach ( $custom_fonts as $font ) { 
  233.  
  234. /** Skip over itself */ 
  235. if ( ! empty( $id ) && $font['id'] == $id ) { 
  236. continue; 
  237.  
  238. if ( $name == $this->options->get_font_short_name( $font['font_name'] ) ) { 
  239. return false; 
  240.  
  241. return true; 
  242.  
  243. /** 
  244. * Handles the database updates required to save a new font 
  245. * @param array $fonts 
  246. * @return array 
  247. * @since 4.0 
  248. */ 
  249. public function install_fonts( $fonts ) { 
  250.  
  251. $types = [ 'regular', 'bold', 'italics', 'bolditalics' ]; 
  252. $errors = []; 
  253.  
  254. foreach ( $types as $type ) { 
  255.  
  256. /** Check if a key exists for this type and process */ 
  257. if ( isset( $fonts[ $type ] ) ) { 
  258. $path = $this->misc->convert_url_to_path( $fonts[ $type ] ); 
  259.  
  260. /** Couldn't find file so throw error */ 
  261. if ( is_wp_error( $path ) ) { 
  262. $errors[] = sprintf( esc_html__( 'Could not locate font on web server: %s', 'gravity-forms-pdf-extended' ), $fonts[ $type ] ); 
  263.  
  264. /** Copy font to our fonts folder */ 
  265. $filename = basename( $path ); 
  266. if ( ! is_file( $this->data->template_font_location . $filename ) && ! copy( $path, $this->data->template_font_location . $filename ) ) { 
  267. $errors[] = sprintf( esc_html__( 'There was a problem installing the font %s. Please try again.', 'gravity-forms-pdf-extended' ), $filename ); 
  268.  
  269. /** If errors were found then return */ 
  270. if ( sizeof( $errors ) > 0 ) { 
  271. $this->log->addError( 'Install Error.', [ 
  272. 'errors' => $errors,  
  273. ] ); 
  274.  
  275. return [ 'errors' => $errors ]; 
  276. } else { 
  277. /** Insert our font into the database */ 
  278. $custom_fonts = $this->options->get_option( 'custom_fonts' ); 
  279.  
  280. /** Prepare our font data and give it a unique id */ 
  281. if ( empty( $fonts['id'] ) ) { 
  282. $id = uniqid(); 
  283. $fonts['id'] = $id; 
  284.  
  285. $custom_fonts[ $fonts['id'] ] = $fonts; 
  286.  
  287. /** Update our font database */ 
  288. $this->options->update_option( 'custom_fonts', $custom_fonts ); 
  289.  
  290. /** Cleanup our fontdata directory to prevent caching issues with mPDF */ 
  291. $this->misc->cleanup_dir( $this->data->template_fontdata_location ); 
  292.  
  293.  
  294. /** Fonts sucessfully installed so return font data */ 
  295.  
  296. return $fonts; 
  297.  
  298. /** 
  299. * Turn capabilities into more friendly strings 
  300. * @param string $cap The wordpress-style capability 
  301. * @return string 
  302. * @since 4.0 
  303. */ 
  304. public function style_capabilities( $cap ) { 
  305. $cap = str_replace( 'gravityforms', 'gravity_forms', $cap ); 
  306. $cap = str_replace( '_', ' ', $cap ); 
  307. $cap = ucwords( $cap ); 
  308.  
  309. return $cap; 
  310.  
  311. /** 
  312. * AJAX Endpoint for saving the custom font 
  313. * @return void 
  314. * @since 4.0 
  315. */ 
  316. public function save_font() { 
  317.  
  318. /** User / CORS validation */ 
  319. $this->misc->handle_ajax_authentication( 'Save Font', 'gravityforms_edit_settings', 'gfpdf_font_nonce' ); 
  320.  
  321. /** Handle the validation and saving of the font */ 
  322. $payload = isset( $_POST['payload'] ) ? $_POST['payload'] : ''; 
  323. $results = $this->process_font( $payload ); 
  324.  
  325. /** If we reached this point the results were successful so return the new object */ 
  326. $this->log->addNotice( 'AJAX Endpoint Successful', [ 
  327. 'results' => $results,  
  328. ] ); 
  329.  
  330. echo json_encode( $results ); 
  331. wp_die(); 
  332.  
  333. /** 
  334. * AJAX Endpoint for deleting a custom font 
  335. * @return void 
  336. * @since 4.0 
  337. */ 
  338. public function delete_font() { 
  339.  
  340. /** User / CORS validation */ 
  341. $this->misc->handle_ajax_authentication( 'Delete Font', 'gravityforms_edit_settings', 'gfpdf_font_nonce' ); 
  342.  
  343. /** Get the required details for deleting fonts */ 
  344. $id = ( isset( $_POST['id'] ) ) ? $_POST['id'] : ''; 
  345. $fonts = $this->options->get_option( 'custom_fonts' ); 
  346.  
  347. /** Check font actually exists and remove */ 
  348. if ( isset( $fonts[ $id ] ) ) { 
  349.  
  350. if ( $this->remove_font_file( $fonts[ $id ] ) ) { 
  351. unset( $fonts[ $id ] ); 
  352.  
  353. /** Cleanup our fontdata directory to prevent caching issues with mPDF */ 
  354. $this->misc->cleanup_dir( $this->data->template_fontdata_location ); 
  355.  
  356. if ( $this->options->update_option( 'custom_fonts', $fonts ) ) { 
  357. /** Success */ 
  358. $this->log->addNotice( 'AJAX Endpoint Successful' ); 
  359. echo json_encode( [ 'success' => true ] ); 
  360. wp_die(); 
  361.  
  362. $return = [ 
  363. 'error' => esc_html__( 'Could not delete Gravity PDF font correctly. Please try again.', 'gravity-forms-pdf-extended' ),  
  364. ]; 
  365.  
  366. $this->log->addError( 'AJAX Endpoint Error', $return ); 
  367.  
  368. echo json_encode( $return ); 
  369.  
  370. /** Bad Request */ 
  371. wp_die( '', 400 ); 
  372.  
  373. /** 
  374. * Validate user input and save as new font 
  375. * @param array $font The four font fields to be processed 
  376. * @return array 
  377. * @since 4.0 
  378. */ 
  379. public function process_font( $font ) { 
  380.  
  381. /** remove any empty fields */ 
  382. $font = array_filter( $font ); 
  383.  
  384. /** Check we have the required data */ 
  385. if ( ! isset( $font['font_name'] ) || ! isset( $font['regular'] ) || 
  386. strlen( $font['font_name'] ) === 0 || strlen( $font['regular'] ) === 0 
  387. ) { 
  388.  
  389. $return = [ 
  390. 'error' => esc_html__( 'Required fields have not been included.', 'gravity-forms-pdf-extended' ),  
  391. ]; 
  392.  
  393. $this->log->addWarning( 'Validation Failed.', $return ); 
  394.  
  395. echo json_encode( $return ); 
  396.  
  397. /** Bad Request */ 
  398. wp_die( '', 400 ); 
  399.  
  400. /** Check we have a valid font name */ 
  401. $name = $font['font_name']; 
  402.  
  403. if ( ! $this->is_font_name_valid( $name ) ) { 
  404.  
  405. $return = [ 
  406. 'error' => esc_html__( 'Font name is not valid. Only alphanumeric characters and spaces are accepted.', 'gravity-forms-pdf-extended' ),  
  407. ]; 
  408.  
  409. $this->log->addWarning( 'Validation Failed.', $return ); 
  410.  
  411. echo json_encode( $return ); 
  412.  
  413. /** Bad Request */ 
  414. wp_die( '', 400 ); 
  415.  
  416. /** Check the font name is unique */ 
  417. $shortname = $this->options->get_font_short_name( $name ); 
  418. $id = ( isset( $font['id'] ) ) ? $font['id'] : ''; 
  419.  
  420. if ( ! $this->is_font_name_unique( $shortname, $id ) ) { 
  421.  
  422. $return = [ 
  423. 'error' => esc_html__( 'A font with the same name already exists. Try a different name.', 'gravity-forms-pdf-extended' ),  
  424. ]; 
  425.  
  426. $this->log->addWarning( 'Validation Failed.', $return ); 
  427.  
  428. echo json_encode( $return ); 
  429.  
  430. /** Bad Request */ 
  431. wp_die( '', 400 ); 
  432.  
  433. /** Move fonts to our Gravity PDF font folder */ 
  434. $installation = $this->install_fonts( $font ); 
  435.  
  436. /** Check if any errors occured installing the fonts */ 
  437. if ( isset( $installation['errors'] ) ) { 
  438.  
  439. $return = [ 
  440. 'error' => $installation,  
  441. ]; 
  442.  
  443. $this->log->addWarning( 'Validation Failed.', $return ); 
  444.  
  445. echo json_encode( $return ); 
  446.  
  447. /** Bad Request */ 
  448. wp_die( '', 400 ); 
  449.  
  450. /** If we got here the installation was successful so return the data */ 
  451.  
  452. return $installation; 
  453.  
  454. /** 
  455. * Find the font unique ID from the font name 
  456. * @param string $font_name 
  457. * @return string The font ID, if any 
  458. * @since 4.1 
  459. */ 
  460. public function get_font_id_by_name( $font_name ) { 
  461. $fonts = $this->options->get_option( 'custom_fonts', [] ); 
  462.  
  463. foreach ( $fonts as $id => $font ) { 
  464. if ( $font['font_name'] === $font_name ) { 
  465. return $id; 
  466.  
  467. return null; 
  468.  
  469. /** 
  470. * Create a file in our tmp directory and check if it is publically accessible (i.e no .htaccess protection) 
  471. * @param $_POST ['nonce'] 
  472. * @return boolean 
  473. * @since 4.0 
  474. */ 
  475. public function check_tmp_pdf_security() { 
  476.  
  477. /** User / CORS validation */ 
  478. $this->misc->handle_ajax_authentication( 'Check Tmp Directory', 'gravityforms_view_settings', 'gfpdf-direct-pdf-protection' ); 
  479.  
  480. /** Create our tmp file and do our actual check */ 
  481. echo json_encode( $this->test_public_tmp_directory_access() ); 
  482. wp_die(); 
  483.  
  484. /** 
  485. * Create a file in our tmp directory and verify if it's protected from the public 
  486. * @return boolean 
  487. * @since 4.0 
  488. */ 
  489. public function test_public_tmp_directory_access() { 
  490. $tmp_dir = $this->data->template_tmp_location; 
  491. $tmp_test_file = 'public_tmp_directory_test.txt'; 
  492. $return = true; 
  493.  
  494. /** create our file */ 
  495. file_put_contents( $tmp_dir . $tmp_test_file, 'failed-if-read' ); 
  496.  
  497. /** verify it exists */ 
  498. if ( is_file( $tmp_dir . $tmp_test_file ) ) { 
  499.  
  500. /** Run our test */ 
  501. $site_url = $this->misc->convert_path_to_url( $tmp_dir ); 
  502.  
  503. if ( $site_url !== false ) { 
  504.  
  505. $response = wp_remote_get( $site_url . $tmp_test_file ); 
  506.  
  507. if ( ! is_wp_error( $response ) ) { 
  508.  
  509. /** Check if the web server responded with a OK status code and we can read the contents of our file, then fail our test */ 
  510. if ( isset( $response['response']['code'] ) && $response['response']['code'] === 200 && 
  511. isset( $response['body'] ) && $response['body'] === 'failed-if-read' ) { 
  512. $return = false; 
  513.  
  514. /** Cleanup our test file */ 
  515. @unlink( $tmp_dir . $tmp_test_file ); 
  516.  
  517. return $return; 
  518.  
  519. /** 
  520. * Gets all the template information for use with our JS template selector 
  521. * @param array $strings 
  522. * @return array 
  523. * @since 4.1 
  524. */ 
  525. public function get_template_data( $strings ) { 
  526. $strings['templateList'] = $this->templates->get_all_template_info(); 
  527. $strings['activeDefaultTemplate'] = $this->options->get_option( 'default_template' ); 
  528.  
  529. $form_id = rgget( 'id' ); 
  530.  
  531. if ( $form_id ) { 
  532. $pid = ( rgget( 'pid' ) ) ? rgget( 'pid' ) : false; 
  533. if ( $pid == false ) { 
  534. $pid = ( rgpost( 'gform_pdf_id' ) ) ? rgpost( 'gform_pdf_id' ) : false; 
  535.  
  536. $pdf = $this->options->get_pdf( $form_id, $pid ); 
  537.  
  538. if ( ! is_wp_error( $pdf ) ) { 
  539. $strings['activeTemplate'] = $pdf['template']; 
  540.  
  541. return $strings;