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