GravityView  2.17
The best, easiest way to display Gravity Forms entries on your website.
class-gravityview-field-notes.php
Go to the documentation of this file.
1 <?php
2 /**
3  * Notes Field
4  *
5  * @package GravityView
6  * @license GPL2+
7  * @since 1.17
8  * @author Katz Web Services, Inc.
9  * @link https://gravityview.co
10  * @copyright Copyright 2016, Katz Web Services, Inc.
11  */
12 
13 /**
14  * Add Entry Notes
15  * @since 1.17
16  */
18 
19  /**
20  * @var string Current __FILE__
21  * @since 1.17
22  */
23  static $file;
24 
25  /**
26  * @var string plugin_dir_path() of the current field file
27  * @since 1.17
28  */
29  static $path;
30 
31  /**
32  * @var bool Are we doing an AJAX request?
33  * @since 1.17
34  */
35  private $doing_ajax = false;
36 
37  /**
38  * The name of the GravityView field type
39  * @var string
40  */
41  var $name = 'notes';
42 
43  var $icon = 'dashicons-admin-comments';
44 
45  function __construct() {
46 
47  self::$path = plugin_dir_path( __FILE__ );
48  self::$file = __FILE__;
49 
50  $this->doing_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;
51 
52  $this->add_hooks();
53 
54  parent::__construct();
55  }
56 
57  /**
58  * Add AJAX hooks, [gv_note_add] shortcode, and template loading paths
59  *
60  * @since 1.17
61  *
62  * @return void
63  */
64  private function add_hooks() {
65 
66  add_shortcode( 'gv_note_add', array( 'GravityView_Field_Notes', 'get_add_note_part' ) );
67 
68  add_action( 'wp', array( $this, 'maybe_delete_notes'), 1000 );
69  add_action( 'wp_ajax_nopriv_gv_delete_notes', array( $this, 'maybe_delete_notes') );
70  add_action( 'wp_ajax_gv_delete_notes', array( $this, 'maybe_delete_notes') );
71 
72  add_action( 'wp', array( $this, 'maybe_add_note'), 1000 );
73  add_action( 'wp_ajax_nopriv_gv_note_add', array( $this, 'maybe_add_note') );
74  add_action( 'wp_ajax_gv_note_add', array( $this, 'maybe_add_note') );
75 
76  // add template path to check for field
77  add_filter( 'gravityview_template_paths', array( $this, 'add_template_path' ) );
78  add_filter( 'gravityview/template/fields_template_paths', array( $this, 'add_template_path' ) );
79 
80  add_action( 'wp_enqueue_scripts', array( $this, 'register_scripts') );
81  add_action( 'gravityview/field/notes/scripts', array( $this, 'enqueue_scripts' ) );
82 
83  add_filter( 'gravityview_entry_default_fields', array( $this, 'add_entry_default_field' ), 10, 3 );
84  }
85 
86 
87  /**
88  * Add Entry Notes to the Add Field picker in Edit View
89  *
90  * @see GravityView_Admin_Views::get_entry_default_fields()
91  *
92  * @since 1.17
93  *
94  * @param array $entry_default_fields Fields configured to show in the picker
95  * @param array $form Gravity Forms form array
96  * @param string $zone Current context: `directory`, `single`, `edit`
97  *
98  * @return array Fields array with notes added, if in Multiple Entries or Single Entry context
99  */
100  public function add_entry_default_field( $entry_default_fields, $form, $zone ) {
101 
102  if( in_array( $zone, array( 'directory', 'single' ) ) ) {
103  $entry_default_fields['notes'] = array(
104  'label' => __( 'Entry Notes', 'gk-gravityview' ),
105  'type' => 'notes',
106  'desc' => __( 'Display, add, and delete notes for an entry.', 'gk-gravityview' ),
107  'icon' => 'dashicons-admin-comments',
108  );
109  }
110 
111  return $entry_default_fields;
112  }
113 
114  /**
115  * Register scripts and styles used by the Notes field
116  *
117  * @since 1.17
118  *
119  * @return void
120  */
121  public function register_scripts() {
122  $css_file = gravityview_css_url( 'entry-notes.css', GravityView_Field_Notes::$path . 'assets/css/' );
123  wp_register_style( 'gravityview-notes', $css_file, array(), GV_PLUGIN_VERSION );
124  wp_register_script( 'gravityview-notes', plugins_url( '/assets/js/entry-notes.js', GravityView_Field_Notes::$file ), array( 'jquery' ), GV_PLUGIN_VERSION, true );
125  }
126 
127  /**
128  * Enqueue, localize field scripts and styles
129  *
130  * @since 1.17
131  *
132  * @return void
133  */
134  public function enqueue_scripts() {
135  global $wp_actions;
136 
137  if( ! wp_script_is( 'gravityview-notes', 'enqueued' ) ) {
138  wp_enqueue_style( 'gravityview-notes' );
139  wp_enqueue_script( 'gravityview-notes' );
140  }
141 
142  if( ! wp_script_is( 'gravityview-notes', 'done' ) ) {
143 
144  $strings = self::strings();
145 
146  wp_localize_script( 'gravityview-notes', 'GVNotes', array(
147  'ajaxurl' => admin_url( 'admin-ajax.php' ),
148  'text' => array(
149  'processing' => $strings['processing'],
150  'delete_confirm' => $strings['delete-confirm'],
151  'note_added' => $strings['added-note'],
152  'error_invalid' => $strings['error-invalid'],
153  'error_empty_note' => $strings['error-empty-note'],
154  ),
155  ) );
156  }
157  }
158 
159  /**
160  * Verify permissions, check if $_POST is set and as expected. If so, use process_add_note
161  *
162  * @since 1.17
163  *
164  * @see process_add_note
165  *
166  * @return void
167  */
168  function maybe_add_note() {
169  if ( ! isset( $_POST['action'] ) || 'gv_note_add' !== $_POST['action'] ) {
170  return;
171  }
172 
173  if ( ! GVCommon::has_cap( 'gravityview_add_entry_notes' ) ) {
174  gravityview()->log->error( "The user isn't allowed to add entry notes." );
175 
176  return;
177  }
178 
179  $post = wp_unslash( $_POST );
180 
181  if ( $this->doing_ajax ) {
182  parse_str( $post['data'], $data );
183  } else {
184  $data = $post;
185  }
186 
187  $this->process_add_note( (array) $data );
188  }
189 
190  /**
191  * Handle adding a note.
192  *
193  * Verify the request. If valid, add the note. If AJAX request, send response JSON.
194  *
195  * @since 1.17
196  *
197  * @var array $data {
198  * @type string $action "gv_note_add"
199  * @type string $entry-slug Entry slug or ID to add note to
200  * @type string $gv_note_add Nonce with action "gv_note_add_{entry slug}" and name "gv_note_add"
201  * @type string $_wp_http_referer Relative URL to submitting page ('/view/example/entry/123/')
202  * @type string $gv-note-content Note content
203  * @type string $add_note Submit button value ('Add Note')
204  * }
205  *
206  * @return void
207  */
208  private function process_add_note( $data ) {
209 
210  $error = false;
211  $success = false;
212 
213  if( empty( $data['entry-slug'] ) ) {
214 
215  $error = self::strings('error-invalid');
216  gravityview()->log->error( 'The note is missing an Entry ID.' );
217 
218  } else {
219 
220  $valid = wp_verify_nonce( $data['gv_note_add'], 'gv_note_add_' . $data['entry-slug'] );
221 
222  $has_cap = GVCommon::has_cap( 'gravityview_add_entry_notes' );
223 
224  if( ! $has_cap ) {
225  $error = self::strings( 'error-cap-add' );
226  gravityview()->log->error( 'Adding a note failed: the user does not have the "gravityview_add_entry_notes" capability.' );
227  } elseif ( $valid ) {
228 
229  $entry = gravityview_get_entry( $data['entry-slug'], true, false );
230 
231  $added = $this->add_note( $entry, $data );
232 
233  // Error adding note
234  if ( is_wp_error( $added ) ) {
235 
236  $error = $added->get_error_message();
237 
238  } else {
239 
240  // Confirm the note was added, because GF doesn't return note ID on success
241  $note = GravityView_Entry_Notes::get_note( $added );
242 
243  // Possibly email peeps about this great new note
244  $this->maybe_send_entry_notes( $note, $entry, $data );
245 
246  if ( $note ) {
247  $success = self::display_note( $note, ! empty( $data['show-delete'] ) );
248  gravityview()->log->debug( 'The note was successfully created', array( 'data' => compact( 'note', 'data' ) ) );
249  } else {
250  $error = self::strings('error-add-note');
251  gravityview()->log->error( 'The note was not successfully created', array( 'data' => compact( 'note', 'data' ) ) );
252  }
253  }
254  } else {
255  $error = self::strings('error-invalid');
256  gravityview()->log->error( 'Nonce validation failed; the note was not created' );
257  }
258  }
259 
260 
261  if( $this->doing_ajax ) {
262  if( $success ) {
263  wp_send_json_success( array( 'html' => $success ) );
264  } else {
265  $error = $error ? $error : self::strings( 'error-invalid' );
266  wp_send_json_error( array( 'error' => esc_html( $error ) ) );
267  }
268  }
269  }
270 
271  /**
272  * Possibly delete notes, if request is proper.
273  *
274  * Verify permissions. Check expected $_POST. Parse args, then send to process_delete_notes
275  *
276  * @since 1.17
277  *
278  * @see process_delete_notes
279  *
280  * @return void
281  */
282  function maybe_delete_notes() {
283 
284  if ( ! GVCommon::has_cap( 'gravityview_delete_entry_notes' ) ) {
285  return;
286  }
287 
288  if ( isset( $_POST['action'] ) && 'gv_delete_notes' === $_POST['action'] ) {
289 
290  $post = wp_unslash( $_POST );
291  if ( $this->doing_ajax ) {
292  parse_str( $post['data'], $data );
293  } else {
294  $data = $post;
295  }
296 
297  $required_args = array(
298  'gv_delete_notes' => '',
299  'entry-slug' => '',
300  );
301 
302  $data = wp_parse_args( $data, $required_args );
303 
304  $this->process_delete_notes( $data );
305  }
306  }
307 
308  /**
309  * Handle deleting notes
310  *
311  * @var array $data {
312  * @type string $action "gv_delete_notes"
313  * @type string $entry-slug Entry slug or ID to add note to
314  * @type string $gv_delete_notes Nonce with action "gv_delete_notes_{entry slug}" and name "gv_delete_notes"
315  * @type string $_wp_http_referer Relative URL to submitting page ('/view/example/entry/123/')
316  * @type int[] $note Array of Note IDs to be deleted
317  * }
318  *
319  * @return void
320  */
321  function process_delete_notes( $data ) {
322 
323  $valid = wp_verify_nonce( $data['gv_delete_notes'], 'gv_delete_notes_' . $data['entry-slug'] );
324  $has_cap = GVCommon::has_cap( 'gravityview_delete_entry_notes' );
325  $success = false;
326 
327  if ( $valid && $has_cap ) {
328  GravityView_Entry_Notes::delete_notes( $data['note'] );
329  $success = true;
330  }
331 
332  if( $this->doing_ajax ) {
333 
334  if( $success ) {
335  wp_send_json_success();
336  } else {
337  if ( ! $valid ) {
338  $error_message = self::strings( 'error-invalid' );
339  } else {
340  $error_message = self::strings( 'error-permission-delete' );
341  }
342 
343  wp_send_json_error( array( 'error' => $error_message ) );
344  }
345  }
346  }
347 
348  /**
349  * Include this extension templates path
350  *
351  * @since 1.17
352  *
353  * @param array $file_paths List of template paths ordered
354  *
355  * @return array File paths with `./` and `./partials/` paths added
356  */
357  public function add_template_path( $file_paths ) {
358 
359  $file_paths[ 172 ] = self::$path;
360  $file_paths[ 173 ] = self::$path . 'partials/';
361 
362  return $file_paths;
363  }
364 
365  public function field_options( $field_options, $template_id, $field_id, $context, $input_type, $form_id ) {
366 
367  unset( $field_options['show_as_link'] );
368 
369  $notes_options = array(
370  'notes' => array(
371  'type' => 'checkboxes',
372  'label' => __('Note Settings', 'gk-gravityview'),
373  'desc' => sprintf( _x('Only users with specific capabilities will be able to view, add and delete notes. %sRead more%s.', '%s is opening and closing HTML link', 'gk-gravityview' ), '<a href="https://docs.gravityview.co/article/311-gravityview-capabilities">', '</a>' ),
374  'options' => array(
375  'view' => array(
376  'label' => __( 'Display notes?', 'gk-gravityview' ),
377  ),
378  'view_loggedout' => array(
379  'label' => __( 'Display notes to users who are not logged-in?', 'gk-gravityview' ),
380  'requires' => 'view',
381  ),
382  'add' => array(
383  'label' => __( 'Enable adding notes?', 'gk-gravityview' ),
384  ),
385  'email' => array(
386  'label' => __( 'Allow emailing notes?', 'gk-gravityview' ),
387  'requires' => 'add',
388  ),
389  'delete' => array(
390  'label' => __( 'Allow deleting notes?', 'gk-gravityview' ),
391  ),
392  ),
393  'value' => array( 'view' => 1, 'add' => 1, 'email' => 1 ),
394  ),
395  );
396 
397  return $notes_options + $field_options;
398  }
399 
400  /**
401  * Get strings used by the Entry Notes field
402  *
403  * Use `gravityview/field/notes/strings` filter to modify the strings
404  *
405  * @since 1.17
406  *
407  * @param string $key If set, return the string with the key of $key
408  *
409  * @return array|string Array of strings with keys and values. If $key is set, returns string. If missing $strings[ $key ], empty string.
410  */
411  static public function strings( $key = '' ) {
412 
413  $strings = array(
414  'add-note' => __( 'Add Note', 'gk-gravityview' ),
415  'added-note' => __( 'Note added.', 'gk-gravityview' ),
416  'content-label' => __( 'Note Content', 'gk-gravityview' ),
417  'delete' => __( 'Delete', 'gk-gravityview' ),
418  'delete-confirm' => __( 'Are you sure you want to delete the selected notes?', 'gk-gravityview' ),
419  'caption' => __( 'Notes for this entry', 'gk-gravityview' ),
420  'toggle-notes' => __( 'Toggle all notes', 'gk-gravityview' ),
421  'no-notes' => __( 'There are no notes.', 'gk-gravityview' ),
422  'processing' => __( 'Processing&hellip;', 'gk-gravityview' ),
423  'other-email' => __( 'Other email address', 'gk-gravityview' ),
424  'email-label' => __( 'Email address', 'gk-gravityview' ),
425  'email-placeholder' => _x('[email protected]', 'Example email address used as a placeholder', 'gk-gravityview'),
426  'subject-label' => __( 'Subject', 'gk-gravityview' ),
427  'subject' => __( 'Email subject', 'gk-gravityview' ),
428  'default-email-subject' => __( 'New entry note', 'gk-gravityview' ),
429  'email-footer' => __( 'This note was sent from {url}', 'gk-gravityview' ),
430  'also-email' => __( 'Also email this note to', 'gk-gravityview' ),
431  'error-add-note' => __( 'There was an error adding the note.', 'gk-gravityview' ),
432  'error-invalid' => __( 'The request was invalid. Refresh the page and try again.', 'gk-gravityview' ),
433  'error-empty-note' => _x( 'Note cannot be blank.', 'Message to display when submitting a note without content.', 'gk-gravityview' ),
434  'error-cap-delete' => __( 'You don\'t have the ability to delete notes.', 'gk-gravityview' ),
435  'error-cap-add' => __( 'You don\'t have the ability to add notes.', 'gk-gravityview' ),
436  );
437 
438  /**
439  * @filter `gravityview/field/notes/strings` Modify the text used in the Entry Notes field. Sanitized by `esc_html` after return.
440  * @since 1.17
441  * @param array $strings Text in key => value pairs
442  */
443  $strings = gv_map_deep( apply_filters( 'gravityview/field/notes/strings', $strings ), 'esc_html' );
444 
445  if( $key ) {
446  return isset( $strings[ $key ] ) ? $strings[ $key ] : '';
447  }
448 
449  return $strings;
450  }
451 
452  /**
453  * Generate HTML output for a single note
454  *
455  * @since 1.17
456  *
457  * @param object $note Note object with id, user_id, date_created, value, note_type, user_name, user_email vars
458  * @param bool $show_delete Whether to show the bulk delete inputs
459  *
460  * @since 2.0
461  * @param \GV\Template_Context $context The context.
462  *
463  * @return string HTML
464  */
465  static public function display_note( $note, $show_delete = false, $context = null ) {
466 
467  if( ! is_object( $note ) ) {
468  return '';
469  }
470 
471  $note_content = array(
472  'avatar' => get_avatar( $note->user_id, 48 ),
473  'user_name' => $note->user_name,
474  'user_email' => $note->user_email,
475  'added_on' => esc_html__( 'added on {date_created_formatted}', 'gk-gravityview' ),
476  'value' => wpautop( esc_html( $note->value ) ),
477  'date_created' => $note->date_created,
478  'date_created_formatted' => GFCommon::format_date( $note->date_created, false ),
479  'user_id' => intval( $note->user_id ),
480  'note_type' => $note->note_type,
481  'note_id' => intval( $note->id ),
482  );
483 
484  /**
485  * @filter `gravityview/field/notes/content` Modify the note content before rendering in the template
486  * @since 1.17
487  * @param array $note_content Array of note content that will be replaced in template files
488  * @param object $note Note object with id, user_id, date_created, value, note_type, user_name, user_email vars
489  * @param boolean $show_delete True: Notes are editable. False: no editing notes.
490  * @since 2.0
491  * @param \GV\Template_Context $context The context.
492  */
493  $note_content = apply_filters( 'gravityview/field/notes/content', $note_content, $note, $show_delete, $context );
494 
495  $note_row_template = ( $show_delete && GVCommon::has_cap( 'gravityview_delete_entry_notes' ) ) ? 'row-editable' : 'row';
496 
497  if ( $context instanceof \GV\Template_Context ) {
498 
499  ob_start();
500  $context->template->get_template_part( 'note', 'detail', true );
501  $note_detail_html = ob_get_clean();
502 
503  ob_start();
504  $context->template->get_template_part( 'note', $note_row_template, true );
505  $note_row = ob_get_clean();
506  } else {
507  /** @deprecated path */
508  ob_start();
509  GravityView_View::getInstance()->get_template_part( 'note', 'detail' );
510  $note_detail_html = ob_get_clean();
511 
512  ob_start();
513  GravityView_View::getInstance()->get_template_part( 'note', $note_row_template );
514  $note_row = ob_get_clean();
515  }
516 
517  foreach ( $note_content as $tag => $value ) {
518  $note_detail_html = str_replace( '{' . $tag . '}', $value, $note_detail_html );
519  }
520 
521  $replacements = array(
522  '{note_id}' => $note_content['note_id'],
523  '{row_class}' => 'gv-note',
524  '{note_detail}' => $note_detail_html
525  );
526 
527  // Strip extra whitespace in template
528  $output = gravityview_strip_whitespace( $note_row );
529 
530  foreach ( $replacements as $tag => $replacement ) {
531  $output = str_replace( $tag, $replacement, $output );
532  }
533 
534  return $output;
535  }
536 
537  /**
538  * Add a note.
539  *
540  * @since 1.17
541  *
542  * @see GravityView_Entry_Notes::add_note This method is mostly a wrapper
543  *
544  * @param array $entry
545  * @param array $data Note details array
546  *
547  * @return int|WP_Error
548  */
549  private function add_note( $entry, $data ) {
550  global $current_user, $wpdb;
551 
552  $user_data = get_userdata( $current_user->ID );
553 
554  $note_content = trim( $data['gv-note-content'] );
555 
556  if( empty( $note_content ) ) {
557  return new WP_Error( 'gv-add-note-empty', __( 'The note is empty.', 'gk-gravityview' ) );
558  }
559 
560  $return = GravityView_Entry_Notes::add_note( $entry['id'], $user_data->ID, $user_data->display_name, $note_content, 'gravityview/field/notes' );
561 
562  return $return;
563  }
564 
565  /**
566  * Get the Add Note form HTML
567  *
568  * @since 1.17
569  *
570  * @since 2.0
571  * @param array $atts Shortcode attributes for entry ID
572  * @param \GV\Template_Context $context The context, when called outside of a shortcode
573  *
574  * @return string HTML of the Add Note form, or empty string if the user doesn't have the `gravityview_add_entry_notes` cap
575  */
576  public static function get_add_note_part( $atts, $context = null ) {
577 
578  $atts = shortcode_atts( array( 'entry' => null ), $atts );
579 
580  if( ! GVCommon::has_cap( 'gravityview_add_entry_notes' ) ) {
581  gravityview()->log->error( 'User does not have permission to add entry notes ("gravityview_add_entry_notes").' );
582  return '';
583  }
584 
585  if ( $context instanceof \GV\Template_Context ) {
586 
587  ob_start();
588  $context->template->get_template_part( 'note', 'add-note', true );
589  $add_note_html = ob_get_clean();
590 
591  $visibility_settings = $context->field->notes;
592  $gv_entry = $context->entry;
593  } else {
595 
596  ob_start();
597  $gravityview_view->get_template_part( 'note', 'add-note' );
598  $add_note_html = ob_get_clean();
599 
600  $visibility_settings = $gravityview_view->getCurrentFieldSetting( 'notes' );
601 
602  if ( $atts['entry'] ) {
603  $entry = GFAPI::get_entry( $atts['entry'] );
604  }
605 
606  if ( ! isset( $entry ) || ! $entry ) {
607  $entry = $gravityview_view->getCurrentEntry();
608  }
609 
610  $gv_entry = \GV\GF_Entry::from_entry( $entry );
611  }
612 
613 
614  // Strip extra whitespace in template
615  $add_note_html = gravityview_strip_whitespace( $add_note_html );
616  $entry_slug = $gv_entry->get_slug();
617  $nonce_field = wp_nonce_field( 'gv_note_add_' . $entry_slug, 'gv_note_add', false, false );
618 
619  // Only generate the dropdown if the field settings allow it
620  $email_fields = '';
621  if( ! empty( $visibility_settings['email'] ) ) {
622  $email_fields = self::get_note_email_fields( $entry_slug );
623  }
624 
625  $add_note_html = str_replace( '{entry_slug}', $entry_slug, $add_note_html );
626  $add_note_html = str_replace( '{nonce_field}', $nonce_field, $add_note_html );
627  $add_note_html = str_replace( '{show_delete}', (string) intval( empty( $visibility_settings['delete'] ) ? 0 : $visibility_settings['delete'] ), $add_note_html );
628  $add_note_html = str_replace( '{email_fields}', $email_fields, $add_note_html );
629  $add_note_html = str_replace( '{url}', esc_url_raw( add_query_arg( array() ) ), $add_note_html );
630 
631  return $add_note_html;
632  }
633 
634  /**
635  * Get array of emails addresses from the stored entry
636  *
637  * @since 1.17
638  *
639  * @return array Array of email addresses connected to the entry
640  */
641  private static function get_note_emails_array() {
642 
644 
645  //getting email values
646  $email_fields = GFCommon::get_email_fields( $gravityview_view->getForm() );
647 
648  $entry = $gravityview_view->getCurrentEntry();
649 
650  $note_emails = array();
651 
652  foreach ( $email_fields as $email_field ) {
653  if ( ! empty( $entry["{$email_field->id}"] ) && is_email( $entry["{$email_field->id}"] ) ) {
654  $note_emails[] = $entry["{$email_field->id}"];
655  }
656  }
657 
658  /**
659  * @filter `gravityview/field/notes/emails` Modify the dropdown values displayed in the "Also email note to" dropdown
660  * @since 1.17
661  * @param array $note_emails Array of email addresses connected to the entry
662  * @param array $entry Current entry
663  */
664  $note_emails = apply_filters( 'gravityview/field/notes/emails', $note_emails, $entry );
665 
666  return (array) $note_emails;
667  }
668 
669  /**
670  * Generate a HTML dropdown of email values based on email fields from the current form
671  *
672  * @uses get_note_emails_array
673  *
674  * @since 1.17
675  *
676  * @param int|string $entry_slug Current entry unique ID
677  *
678  * @return string HTML output
679  */
680  private static function get_note_email_fields( $entry_slug = '' ) {
681 
682  if( ! GVCommon::has_cap( 'gravityview_email_entry_notes' ) ) {
683  gravityview()->log->error( 'User does not have permission to email entry notes ("gravityview_email_entry_notes").' );
684  return '';
685  }
686 
687  $entry_slug_esc = esc_attr( $entry_slug );
688 
689  $note_emails = self::get_note_emails_array();
690 
691  $strings = self::strings();
692 
693  /**
694  * @filter `gravityview/field/notes/custom-email` Whether to include a Custom Email option for users to define a custom email to mail notes to
695  * @since 1.17
696  * @param bool $include_custom Default: true
697  */
698  $include_custom = apply_filters( 'gravityview/field/notes/custom-email', true );
699 
700  ob_start();
701 
702  if ( ! empty( $note_emails ) || $include_custom ) { ?>
703  <div class="gv-note-email-container">
704  <label for="gv-note-email-to-<?php echo $entry_slug_esc; ?>" class="screen-reader-text"><?php echo $strings['also-email']; ?></label>
705  <select class="gv-note-email-to" name="gv-note-to" id="gv-note-email-to-<?php echo $entry_slug_esc; ?>">
706  <option value=""><?php echo $strings['also-email']; ?></option>
707  <?php foreach ( $note_emails as $email ) {
708  ?>
709  <option value="<?php echo esc_attr( $email ); ?>"><?php echo esc_html( $email ); ?></option>
710  <?php }
711  if( $include_custom ) { ?>
712  <option value="custom"><?php echo self::strings('other-email'); ?></option>
713  <?php } ?>
714  </select>
715  <fieldset class="gv-note-to-container">
716  <?php if( $include_custom ) { ?>
717  <div class='gv-note-to-custom-container'>
718  <label for="gv-note-email-to-custom-<?php echo $entry_slug_esc; ?>"><?php echo $strings['email-label']; ?></label>
719  <input type="text" name="gv-note-to-custom" placeholder="<?php echo $strings['email-placeholder']; ?>" id="gv-note-to-custom-<?php echo $entry_slug_esc; ?>" value="" />
720  </div>
721  <?php } ?>
722  <div class='gv-note-subject-container'>
723  <label for="gv-note-subject-<?php echo $entry_slug_esc; ?>"><?php echo $strings['subject-label']; ?></label>
724  <input type="text" name="gv-note-subject" placeholder="<?php echo $strings['subject']; ?>" id="gv-note-subject-<?php echo $entry_slug_esc; ?>" value="" />
725  </div>
726  </fieldset>
727  </div>
728  <?php }
729 
730  // TODO: Add a filter
731  return ob_get_clean();
732  }
733 
734  /**
735  * If note has an email to send, and the user has the right caps, send it
736  *
737  * @since 1.17
738  *
739  * @param false|object $note If note was created, object. Otherwise, false.
740  * @param array $entry Entry data.
741  * @param array $data $_POST data.
742  *
743  * @return void Tap in to Gravity Forms' `gform_after_email` action if you want a return result from sending the email.
744  */
745  private function maybe_send_entry_notes( $note = false, $entry = array(), $data = array() ) {
746 
747  if( ! $note || ! GVCommon::has_cap('gravityview_email_entry_notes') ) {
748  gravityview()->log->debug( 'User doesn\'t have "gravityview_email_entry_notes" cap, or $note is empty', array( 'data' => $note ) );
749  return;
750  }
751 
752  gravityview()->log->debug( '$data', array( 'data' => $data ) );
753 
754  //emailing notes if configured
755  if ( ! empty( $data['gv-note-to'] ) ) {
756 
757  $default_data = array(
758  'gv-note-to' => '',
759  'gv-note-to-custom' => '',
760  'gv-note-subject' => '',
761  'gv-note-content' => '',
762  'current-url' => '',
763  );
764 
765  $current_user = wp_get_current_user();
766  $email_data = wp_parse_args( $data, $default_data );
767 
768  $from = $current_user->user_email;
769  $to = $email_data['gv-note-to'];
770 
771  /**
772  * Documented in get_note_email_fields
773  * @see get_note_email_fields
774  */
775  $include_custom = apply_filters( 'gravityview/field/notes/custom-email', true );
776 
777  if( 'custom' === $to && $include_custom ) {
778  $to = $email_data['gv-note-to-custom'];
779  gravityview()->log->debug( 'Sending note to a custom email address: {to}', array( 'to' => $to ) );
780  }
781 
782  if ( ! GFCommon::is_valid_email_list( $to ) ) {
783  gravityview()->log->error( '$to not a valid email or email list (CSV of emails): {to}', array( 'to' => print_r( $to, true ), 'data' => $email_data ) );
784  return;
785  }
786 
787  $bcc = false;
788  $reply_to = $from;
789  $subject = trim( $email_data['gv-note-subject'] );
790 
791  // We use empty() here because GF uses empty to check against, too. `0` isn't a valid subject to GF
792  $subject = empty( $subject ) ? self::strings( 'default-email-subject' ) : $subject;
793  $message = $email_data['gv-note-content'];
794  $email_footer = self::strings( 'email-footer' );
795  $from_name = $current_user->display_name;
796  $message_format = 'html';
797 
798  /**
799  * @filter `gravityview/field/notes/email_content` Modify the values passed when sending a note email
800  * @see GVCommon::send_email
801  * @since 1.17
802  * @param array $email_settings Values being passed to the GVCommon::send_email() method: 'from', 'to', 'bcc', 'reply_to', 'subject', 'message', 'from_name', 'message_format', 'entry', 'email_footer'
803  */
804  $email_content = apply_filters( 'gravityview/field/notes/email_content', compact( 'from', 'to', 'bcc', 'reply_to', 'subject', 'message', 'from_name', 'message_format', 'entry', 'email_footer' ) );
805 
806  extract( $email_content );
807 
808  $is_html = ( 'html' === $message_format );
809 
810  // Add the message footer
811  $message .= $this->get_email_footer( $email_footer, $is_html, $email_data );
812 
813  /**
814  * @filter `gravityview/field/notes/wpautop_email` Should the message content have paragraphs added automatically, if using HTML message format
815  * @since 1.18
816  * @param bool $wpautop_email True: Apply wpautop() to the email message if using; False: Leave as entered (Default: true)
817  */
818  $wpautop_email = apply_filters( 'gravityview/field/notes/wpautop_email', true );
819 
820  if ( $is_html && $wpautop_email ) {
821  $message = wpautop( $message );
822  }
823 
824  GVCommon::send_email( $from, $to, $bcc, $reply_to, $subject, $message, $from_name, $message_format, '', $entry, false );
825 
826  $form = isset( $entry['form_id'] ) ? GFAPI::get_form( $entry['form_id'] ) : array();
827 
828  /**
829  * @see https://www.gravityhelp.com/documentation/article/10146-2/ It's here for compatibility with Gravity Forms
830  */
831  do_action( 'gform_post_send_entry_note', __METHOD__, $to, $from, $subject, $message, $form, $entry );
832  }
833  }
834 
835  /**
836  * Get the footer for Entry Note emails
837  *
838  * `{url}` is replaced by the URL of the page where the note form was embedded
839  *
840  * @since 1.18
841  * @see GravityView_Field_Notes::strings The default value of $message_footer is set here, with the key 'email-footer'
842  *
843  * @param string $email_footer The message footer value
844  * @param bool $is_html True: Email is being sent as HTML; False: sent as text
845  *
846  * @return string If email footer is not empty, return the message with placeholders replaced with dynamic values
847  */
848  private function get_email_footer( $email_footer = '', $is_html = true, $email_data = array() ) {
849 
850  $output = '';
851 
852  if( ! empty( $email_footer ) ) {
853  $url = \GV\Utils::get( $email_data, 'current-url' );
854  $url = html_entity_decode( $url );
855  $url = site_url( $url );
856 
857  $content = $is_html ? "<a href='{$url}'>{$url}</a>" : $url;
858 
859  $email_footer = str_replace( '{url}', $content, $email_footer );
860 
861  $output .= "\n\n$email_footer";
862  }
863 
864  return $output;
865  }
866 }
867 
$url
Definition: post_image.php:25
Modify field settings by extending this class.
const GV_PLUGIN_VERSION(! GravityKit\GravityView\Foundation\meets_min_php_version_requirement(__FILE__, '7.2.0'))
Constants.
Definition: gravityview.php:34
static delete_notes( $note_ids=array())
Delete an array of notes Alias for GFFormsModel::delete_notes()
static getInstance( $passed_post=NULL)
if(! function_exists( 'gravityview_sanitize_html_class')) gravityview_strip_whitespace( $string)
Replace multiple newlines, tabs, and spaces with a single space.
static get_note_email_fields( $entry_slug='')
Generate a HTML dropdown of email values based on email fields from the current form.
get_email_footer( $email_footer='', $is_html=true, $email_data=array())
Get the footer for Entry Note emails.
maybe_send_entry_notes( $note=false, $entry=array(), $data=array())
If note has an email to send, and the user has the right caps, send it.
enqueue_scripts()
Enqueue, localize field scripts and styles.
field_options( $field_options, $template_id, $field_id, $context, $input_type, $form_id)
gravityview_get_entry( $entry_slug, $force_allow_ids=false, $check_entry_display=true, $view=null)
Return a single entry object.
global $post
Definition: delete-entry.php:7
static from_entry( $entry)
Construct a instance from a Gravity Forms entry array.
maybe_delete_notes()
Possibly delete notes, if request is proper.
gravityview_css_url( $css_file='', $dir_path='')
Functions that don&#39;t require GravityView or Gravity Forms API access but are used in the plugin to ex...
if(gravityview() ->plugin->is_GF_25()) $form
add_hooks()
Add AJAX hooks, [gv_note_add] shortcode, and template loading paths.
if(empty( $field_settings['content'])) $content
Definition: custom.php:37
register_scripts()
Register scripts and styles used by the Notes field.
gv_map_deep( $value, $callback)
Maps a function to all non-iterable elements of an array or an object.
static send_email( $from, $to, $bcc, $reply_to, $subject, $message, $from_name='', $message_format='html', $attachments='', $entry=false, $notification=false)
Send email using GFCommon::send_email()
static display_note( $note, $show_delete=false, $context=null)
Generate HTML output for a single note.
maybe_add_note()
Verify permissions, check if $_POST is set and as expected.
add_template_path( $file_paths)
Include this extension templates path.
$visibility_settings
Definition: notes.php:11
static strings( $key='')
Get strings used by the Entry Notes field.
static get_note( $note_id)
Get a single note by note ID.
if(empty( $created_by)) $form_id
add_entry_default_field( $entry_default_fields, $form, $zone)
Add Entry Notes to the Add Field picker in Edit View.
static get( $array, $key, $default=null)
Grab a value from an array or an object or default.
static add_note( $lead_id, $user_id, $user_name, $note='', $note_type='gravityview')
Alias for GFFormsModel::add_note() with default note_type of &#39;gravityview&#39;.
gravityview()
The main GravityView wrapper function.
static get_add_note_part( $atts, $context=null)
Get the Add Note form HTML.
static get_note_emails_array()
Get array of emails addresses from the stored entry.
add_note( $entry, $data)
Add a note.
$entry_slug
Definition: notes.php:30
static has_cap( $caps='', $object_id=null, $user_id=null)
Alias of GravityView_Roles_Capabilities::has_cap()
$entry
Definition: notes.php:27
if(false !==strpos( $value, '00:00')) $field_id
string $field_id ID of the field being displayed
Definition: time.php:22
$strings
Definition: notes.php:29
$show_delete
Definition: notes.php:33