PluginProbe
Advanced Ads – Ad Manager & AdSense / 1.40.1
Advanced Ads – Ad Manager & AdSense v1.40.1
2.0.26 2.0.25 2.0.24 2.0.23 2.0.22 2.0.21 1.38.0 1.39.0 1.39.1 1.39.2 1.39.3 1.39.4 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.40.0 1.40.1 1.40.2 All 348 releases
advanced-ads / admin / includes / class-ad-type.php
class-ad-type.php
1,085 lines 31.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Class Advanced_Ads_Admin_Ad_Type
5 */
6 class Advanced_Ads_Admin_Ad_Type {
7 /**
8 * Instance of this class.
9 *
10 * @var object
11 */
12 protected static $instance = null;
13
14 /**
15 * Post type slug
16 *
17 * @since 1.0.0
18 * @var string
19 */
20 protected $post_type = '';
21
22 /**
23 * Register hooks function related to the ad type
24 */
25 private function __construct() {
26 // Register column headers.
27 add_filter(
28 'manage_advanced_ads_posts_columns',
29 [
30 $this,
31 'ad_list_columns_head',
32 ]
33 );
34 add_filter( 'manage_advanced_ads_posts_custom_column', [ $this, 'ad_list_columns' ], 10, 2 );
35 // Add custom filter views.
36 add_action( 'restrict_manage_posts', [ $this, 'ad_list_add_filters' ] );
37 add_filter( 'default_hidden_columns', [ $this, 'hide_ad_list_columns' ], 10, 2 );
38 add_filter( 'bulk_post_updated_messages', [ $this, 'ad_bulk_update_messages' ], 10, 2 );
39 // order ad lists.
40 add_filter( 'request', [ $this, 'ad_list_request' ] );
41 add_action( 'all_admin_notices', [ $this, 'no_ads_yet_notice' ] );
42 // Manipulate post data when post is created.
43 add_filter( 'wp_insert_post_data', [ $this, 'prepare_insert_post_data' ] );
44 // Save ads post type.
45 // @source https://developer.wordpress.org/reference/hooks/save_post_post-post_type/
46 add_action( 'save_post_advanced_ads', [ $this, 'save_ad' ] );
47 add_action( 'delete_post', [ $this, 'delete_ad' ] );
48 add_action( 'edit_form_top', [ $this, 'edit_form_above_title' ] );
49 add_action( 'edit_form_after_title', [ $this, 'edit_form_below_title' ] );
50 add_action( 'dbx_post_sidebar', [ $this, 'edit_form_end' ] );
51 add_action( 'post_submitbox_misc_actions', [ $this, 'add_submit_box_meta' ] );
52 add_action( 'admin_enqueue_scripts', [ $this, 'use_code_editor' ] );
53 add_filter( 'post_updated_messages', [ $this, 'ad_update_messages' ] );
54 add_filter( 'gettext', [ $this, 'replace_cheating_message' ], 20, 2 );
55 add_action( 'current_screen', [ $this, 'run_on_ad_edit_screen' ] );
56 add_filter( 'pre_wp_unique_post_slug', [ $this, 'pre_wp_unique_post_slug' ], 10, 6 );
57 add_filter( 'view_mode_post_types', [ $this, 'remove_view_mode' ] );
58 add_filter( 'get_user_option_user-settings', [ $this, 'reset_view_mode_option' ] );
59 add_filter( 'screen_settings', [ $this, 'add_screen_options' ], 10, 2 );
60 add_action( 'wp_loaded', [ $this, 'save_screen_options' ] );
61 add_action( 'load-edit.php', [ $this, 'set_screen_options' ] );
62
63 $this->post_type = constant( 'Advanced_Ads::POST_TYPE_SLUG' );
64 }
65
66 /**
67 * Return an instance of this class.
68 *
69 * @return object A single instance of this class.
70 */
71 public static function get_instance() {
72 // If the single instance hasn't been set, set it now.
73 if ( null === self::$instance ) {
74 self::$instance = new self();
75 }
76
77 return self::$instance;
78 }
79
80 /**
81 * Check if an ad is not valid for 'Post Content' placement
82 *
83 * @param Advanced_Ads_Ad $ad object.
84 *
85 * @return string with error if not valid, empty string if valid
86 */
87 public static function check_ad_dom_is_not_valid( Advanced_Ads_Ad $ad ) {
88 $ad_content = ( isset( $ad->content ) ) ? $ad->content : '';
89 if ( ! extension_loaded( 'dom' ) || ! $ad_content ) {
90 return false;
91 }
92
93 $wp_charset = get_bloginfo( 'charset' );
94 $ad_dom = new DOMDocument( '1.0', $wp_charset );
95
96 $libxml_previous_state = libxml_use_internal_errors( true );
97 // clear existing errors.
98 libxml_clear_errors();
99 // source for this regex: http://stackoverflow.com/questions/17852537/preg-replace-only-specific-part-of-string.
100 $ad_content = preg_replace( '#(document.write.+)</(.*)#', '$1<\/$2', $ad_content ); // escapes all closing
101 // html tags.
102 $ad_dom->loadHtml( '<!DOCTYPE html><html><meta http-equiv="Content-Type" content="text/html; charset=' . $wp_charset . '" /><body>' . $ad_content );
103
104 $errors = '';
105 foreach ( libxml_get_errors() as $error ) {
106 // continue, if there is '&' symbol, but not HTML entity; or if an "invalid" tag is found.
107 if ( stripos( $error->message, 'htmlParseEntityRef:' ) || preg_match( '/tag \S+ invalid/i', $error->message ) ) {
108 continue;
109 }
110 $errors .= print_r( $error, true );
111 }
112
113 libxml_use_internal_errors( $libxml_previous_state );
114
115 return $errors;
116 }
117
118 /**
119 * Add heading for extra column of ads list
120 * remove the date column
121 *
122 * @param string[] $columns array with existing columns.
123 *
124 * @return string[]
125 */
126 public function ad_list_columns_head( $columns ) {
127 $new_columns = [];
128
129 foreach ( $columns as $key => $value ) {
130 $new_columns[ $key ] = $value;
131 // add ad icon column after the checkbox
132 if ( $key === 'cb' ) {
133 $new_columns['ad_type'] = __( 'Type', 'advanced-ads' );
134 continue;
135 }
136
137 if ( $key === 'title' ) {
138 $new_columns['title'] = __( 'Name', 'advanced-ads' );
139 $new_columns['ad_description'] = __( 'Notes', 'advanced-ads' );
140 $new_columns['ad_preview'] = __( 'Preview', 'advanced-ads' );
141 $new_columns['ad_size'] = __( 'Size', 'advanced-ads' );
142 $new_columns['ad_timing'] = __( 'Ad Planning', 'advanced-ads' );
143 $new_columns['ad_shortcode'] = __( 'Ad Shortcode', 'advanced-ads' );
144 }
145 }
146
147 $allowed_columns = [
148 'cb', // checkbox.
149 'title',
150 'author',
151 'ad_type',
152 'ad_description',
153 'ad_preview',
154 'ad_size',
155 'ad_timing',
156 'ad_shortcode',
157 'taxonomy-advanced_ads_groups',
158 ];
159
160 /**
161 * Filter the allowed columns for Advanced Ads post type list.
162 *
163 * @param string[] $allowed_columns The allowed column names.
164 */
165 $allowed_columns = (array) apply_filters( 'advanced-ads-ad-list-allowed-columns', $allowed_columns );
166
167 return array_intersect_key( $new_columns, array_flip( $allowed_columns ) );
168 }
169
170 /**
171 * Add ad list column content
172 *
173 * @param string $column_name name of the column.
174 * @param int $ad_id id of the ad.
175 *
176 * @return void
177 */
178 public function ad_list_columns( $column_name, $ad_id ) {
179 $ad = new Advanced_Ads_Ad( $ad_id );
180
181 switch ( $column_name ) {
182 case 'ad_type':
183 $this->ad_list_columns_type( $ad );
184 break;
185 case 'ad_description':
186 $this->ad_list_columns_description( $ad );
187 break;
188 case 'ad_preview':
189 $this->ad_list_columns_preview( $ad );
190 break;
191 case 'ad_size':
192 $this->ad_list_columns_size( $ad );
193 break;
194 case 'ad_timing':
195 $this->ad_list_columns_timing( $ad );
196 break;
197 case 'ad_shortcode':
198 $this->ad_list_columns_shortcode( $ad );
199 }
200 }
201
202 /**
203 * Display ad details in ads list.
204 *
205 * @param string $column_name Column name.
206 * @param int $ad_id Ad id.
207 *
208 * @return void
209 * @deprecated
210 * @see Advanced_Ads_Admin_Ad_Type::ad_list_columns_preview()
211 */
212 public function ad_list_columns_content( $column_name, $ad_id ) {
213 $ad = new Advanced_Ads_Ad( $ad_id );
214 $this->ad_list_columns_preview( $ad );
215 }
216
217 /**
218 * Display the ad type icon in the ads list.
219 *
220 * @param Advanced_Ads_Ad $ad ad object.
221 *
222 * @return void
223 */
224 private function ad_list_columns_type( Advanced_Ads_Ad $ad ) {
225 $ad_types = Advanced_Ads::get_instance()->ad_types;
226 if ( ! array_key_exists( $ad->type, $ad_types ) ) {
227 echo esc_html( $ad->type );
228 return;
229 }
230
231 $size = $this->get_ad_size_string( $ad );
232
233 include ADVADS_BASE_PATH . 'admin/views/ad-list/type.php';
234 }
235
236 /**
237 * Display the ad description in the ads list
238 *
239 * @param Advanced_Ads_Ad $ad ad object.
240 *
241 * @return void
242 */
243 private function ad_list_columns_description( Advanced_Ads_Ad $ad ) {
244 $description = wp_trim_words( $ad->description, 50 );
245
246 include ADVADS_BASE_PATH . 'admin/views/ad-list/description.php';
247 }
248
249 /**
250 * Display an ad preview in ads list.
251 *
252 * @param Advanced_Ads_Ad $ad ad object.
253 *
254 * @return void
255 */
256 private function ad_list_columns_preview( $ad ) {
257 $types = Advanced_Ads::get_instance()->ad_types;
258 $type = ( ! empty( $types[ $ad->type ]->title ) ) ? $types[ $ad->type ]->title : 0;
259
260 if ( ! $type ) {
261 return;
262 }
263
264 if ( ! empty( $type ) ) {
265 $types[ $ad->type ]->render_preview( $ad );
266 }
267
268 do_action( 'advanced-ads-ad-list-details-column-after', $ad );
269 }
270
271 /**
272 * Display the ad size in the ads list
273 *
274 * @param Advanced_Ads_Ad $ad ad object.
275 *
276 * @return void
277 */
278 private function ad_list_columns_size( $ad ) {
279 $size = $this->get_ad_size_string( $ad );
280
281 if ( empty( $size ) ) {
282 return;
283 }
284
285 include ADVADS_BASE_PATH . 'admin/views/ad-list/size.php';
286 }
287
288 /**
289 * Display ad timing in ads list
290 *
291 * @param Advanced_Ads_Ad $ad ad object.
292 *
293 * @return void
294 */
295 public function ad_list_columns_timing( $ad ) {
296 $expiry = false;
297 $post_future = false;
298 $post_start = get_post_time( 'U', true, $ad->id );
299 $html_classes = 'advads-filter-timing';
300 $expiry_date_format = get_option( 'date_format' ) . ', ' . get_option( 'time_format' );
301
302 if ( isset( $ad->expiry_date ) && $ad->expiry_date ) {
303 $html_classes .= ' advads-filter-any-exp-date';
304
305 $expiry = $ad->expiry_date;
306 if ( $ad->expiry_date < time() ) {
307 $html_classes .= ' advads-filter-expired';
308 }
309 }
310 if ( $post_start > time() ) {
311 $post_future = $post_start;
312 $html_classes .= ' advads-filter-future';
313 }
314
315 ob_start();
316 do_action_ref_array(
317 'advanced-ads-ad-list-timing-column-after',
318 [
319 $ad,
320 &$html_classes,
321 ]
322 );
323 $content_after = ob_get_clean();
324
325 include ADVADS_BASE_PATH . 'admin/views/ad-list/timing.php';
326 }
327
328 /**
329 * Display ad shortcode in ads list
330 *
331 * @param Advanced_Ads_Ad $ad ad object.
332 *
333 * @return void
334 */
335 public function ad_list_columns_shortcode( $ad ) {
336 include ADVADS_BASE_PATH . 'admin/views/ad-list/shortcode.php';
337 }
338
339 /**
340 * Hide certain columns on the ad list by default.
341 *
342 * @param array $hidden an array of columns hidden by default.
343 * @param WP_Screen $screen WP_Screen object of the current screen.
344 *
345 * @return array
346 */
347 public function hide_ad_list_columns( $hidden, $screen ) {
348 if ( isset( $screen->id ) && 'edit-' . Advanced_Ads::POST_TYPE_SLUG === $screen->id ) {
349 $hidden[] = 'ad_description';
350 $hidden[] = 'author';
351 $hidden[] = 'ad_size';
352 $hidden[] = 'ad_shortcode';
353 }
354
355 return $hidden;
356 }
357
358 /**
359 * Adds filter dropdowns before the 'Filter' button on the ad list table
360 *
361 * @return void
362 */
363 public function ad_list_add_filters() {
364 $screen = get_current_screen();
365 if ( ! isset( $screen->id ) || 'edit-advanced_ads' !== $screen->id ) {
366 return;
367 }
368 include ADVADS_BASE_PATH . 'admin/views/ad-list-filters.php';
369 }
370
371 /**
372 * Edit ad bulk update messages
373 *
374 * @param array $messages existing bulk update messages.
375 * @param array $counts numbers of updated ads.
376 *
377 * @return array
378 *
379 * @see wp-admin/edit.php
380 */
381 public function ad_bulk_update_messages( array $messages, array $counts ) {
382 $post = get_post();
383
384 $messages[ Advanced_Ads::POST_TYPE_SLUG ] = [
385 // translators: %s is the number of ads.
386 'updated' => _n( '%s ad updated.', '%s ads updated.', $counts['updated'], 'advanced-ads' ),
387 // translators: %s is the number of ads.
388 'locked' => _n( '%s ad not updated, somebody is editing it.', '%s ads not updated, somebody is editing them.', $counts['locked'], 'advanced-ads' ),
389 // translators: %s is the number of ads.
390 'deleted' => _n( '%s ad permanently deleted.', '%s ads permanently deleted.', $counts['deleted'], 'advanced-ads' ),
391 // translators: %s is the number of ads.
392 'trashed' => _n( '%s ad moved to the Trash.', '%s ads moved to the Trash.', $counts['trashed'], 'advanced-ads' ),
393 // translators: %s is the number of ads.
394 'untrashed' => _n( '%s ad restored from the Trash.', '%s ads restored from the Trash.', $counts['untrashed'], 'advanced-ads' ),
395 ];
396
397 return $messages;
398 }
399
400 /**
401 * Order ads by title on ads list
402 *
403 * @param array $vars array with request vars.
404 *
405 * @return array
406 */
407 public function ad_list_request( $vars ) {
408 // if we shouldn't filter this return $vars array.
409 if (
410 ! isset( $vars['post_type'] )
411 || $vars['post_type'] !== Advanced_Ads::POST_TYPE_SLUG
412 || ! is_admin()
413 || wp_doing_ajax()
414 ) {
415 return $vars;
416 }
417
418 // order ads by title on ads list by default
419 if ( empty( $vars['orderby'] ) ) {
420 add_action( 'pre_get_posts', [ $this, 'default_ad_list_order' ] );
421 }
422
423 if ( $vars['orderby'] === 'expiry_date' ) {
424 $vars['orderby'] = 'meta_value';
425 $vars['meta_key'] = Advanced_Ads_Ad_Expiration::POST_META;
426 $vars['order'] = strtoupper( $vars['order'] ) === 'DESC' ? 'DESC' : 'ASC';
427
428 if ( isset( $_GET['addate'] ) && $_GET['addate'] === 'advads-filter-expired' ) {
429 $vars['post_status'] = Advanced_Ads_Ad_Expiration::POST_STATUS;
430 }
431 }
432
433 return $vars;
434 }
435
436 /**
437 * Set default ad list order.
438 *
439 * @param WP_Query $query The current WP_Query, passed by reference.
440 *
441 * @return void
442 */
443 public function default_ad_list_order( WP_Query $query ) {
444 if ( ! $query->is_main_query() ) {
445 return;
446 }
447
448 $query->set( 'orderby', 'title' );
449 $query->set( 'order', 'ASC' );
450 }
451
452 /**
453 * Show instructions to create first ad above the ad list
454 *
455 * @return string
456 */
457 public function no_ads_yet_notice() {
458 $screen = get_current_screen();
459 if ( ! isset( $screen->id ) || 'edit-advanced_ads' !== $screen->id ) {
460 return;
461 }
462
463 // get number of ads.
464 $existing_ads = Advanced_Ads::get_number_of_ads();
465
466 // only display if there are no more than 2 ads.
467 if ( 3 > $existing_ads ) {
468 echo '<div class="advads-ad-metabox postbox" style="clear: both; margin: 10px 20px 0 2px;">';
469 include ADVADS_BASE_PATH . 'admin/views/ad-list-no-ads.php';
470 echo '</div>';
471 }
472 }
473
474 /**
475 * Prepare the ad post type to be saved
476 *
477 * @param int $post_id id of the post.
478 * @todo handling this more dynamic based on ad type
479 */
480 public function save_ad( $post_id ) {
481 // phpcs:disable WordPress.Security.NonceVerification.Missing
482 if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_edit_ads' ) ) // only use for ads, no other post type.
483 || ! isset( $_POST['post_type'] )
484 || $this->post_type !== $_POST['post_type']
485 || ! isset( $_POST['advanced_ad']['type'] )
486 || wp_is_post_revision( $post_id ) ) {
487 return;
488 }
489
490 // get ad object.
491 $ad = new Advanced_Ads_Ad( $post_id );
492 if ( ! $ad instanceof Advanced_Ads_Ad ) {
493 return;
494 }
495
496 // filter to allow change of submitted ad settings.
497 $_POST['advanced_ad'] = apply_filters( 'advanced-ads-ad-settings-pre-save', $_POST['advanced_ad'] );
498
499 $ad->type = wp_unslash( $_POST['advanced_ad']['type'] );
500
501 /**
502 * Deprecated since introduction of "visitors" in 1.5.4
503 */
504 if ( isset( $_POST['advanced_ad']['visitor'] ) ) {
505 $ad->set_option( 'visitor', $_POST['advanced_ad']['visitor'] );
506 } else {
507 $ad->set_option( 'visitor', [] );
508 }
509 // visitor conditions.
510 if ( isset( $_POST['advanced_ad']['visitors'] ) ) {
511 $ad->set_option( 'visitors', $_POST['advanced_ad']['visitors'] );
512 } else {
513 $ad->set_option( 'visitors', [] );
514 }
515 $ad->url = 0;
516 if ( isset( $_POST['advanced_ad']['url'] ) ) {
517 // May contain placeholders added by the tracking add-on.
518 $ad->url = trim( $_POST['advanced_ad']['url'] );
519 }
520
521 // save size.
522 $ad->width = 0;
523 if ( isset( $_POST['advanced_ad']['width'] ) ) {
524 $ad->width = absint( $_POST['advanced_ad']['width'] );
525 }
526 $ad->height = 0;
527 if ( isset( $_POST['advanced_ad']['height'] ) ) {
528 $ad->height = absint( $_POST['advanced_ad']['height'] );
529 }
530
531 if ( ! empty( $_POST['advanced_ad']['description'] ) ) {
532 $ad->description = esc_textarea( $_POST['advanced_ad']['description'] );
533 } else {
534 $ad->description = '';
535 }
536
537 if ( ! empty( $_POST['advanced_ad']['content'] ) ) {
538 $ad->content = $_POST['advanced_ad']['content'];
539 } else {
540 $ad->content = '';
541 }
542
543 $output = isset( $_POST['advanced_ad']['output'] ) ? $_POST['advanced_ad']['output'] : [];
544
545 // Find Advanced Ads shortcodes.
546 if ( ! empty( $output['allow_shortcodes'] ) ) {
547 $shortcode_pattern = get_shortcode_regex(
548 [
549 'the_ad',
550 'the_ad_group',
551 'the_ad_placement',
552 ]
553 );
554 $output['has_shortcode'] = preg_match( '/' . $shortcode_pattern . '/s', $ad->content );
555 }
556
557 // Set output.
558 $ad->set_option( 'output', $output );
559
560 if ( ! empty( $_POST['advanced_ad']['conditions'] ) ) {
561 $ad->conditions = $_POST['advanced_ad']['conditions'];
562 } else {
563 $ad->conditions = [];
564 }
565 // prepare expiry date.
566 if ( isset( $_POST['advanced_ad']['expiry_date']['enabled'] ) ) {
567 $year = absint( $_POST['advanced_ad']['expiry_date']['year'] );
568 $month = absint( $_POST['advanced_ad']['expiry_date']['month'] );
569 $day = absint( $_POST['advanced_ad']['expiry_date']['day'] );
570 $hour = absint( $_POST['advanced_ad']['expiry_date']['hour'] );
571 $minute = absint( $_POST['advanced_ad']['expiry_date']['minute'] );
572
573 $expiration_date = sprintf( '%04d-%02d-%02d %02d:%02d:%02d', $year, $month, $day, $hour, $minute, '00' );
574 $valid_date = wp_checkdate( $month, $day, $year, $expiration_date );
575
576 if ( ! $valid_date ) {
577 $ad->expiry_date = 0;
578 } else {
579 $gm_date = date_create( $expiration_date, Advanced_Ads_Utils::get_wp_timezone() );
580 $gm_date->setTimezone( new DateTimeZone( 'UTC' ) );
581 $gm_date = $gm_date->format( 'Y-m-d-H-i' );
582 list( $year, $month, $day, $hour, $minute ) = explode( '-', $gm_date );
583 $ad->expiry_date = gmmktime( $hour, $minute, 0, $month, $day, $year );
584 }
585 } else {
586 $ad->expiry_date = 0;
587 }
588
589 $image_id = ( isset( $_POST['advanced_ad']['output']['image_id'] ) ) ? absint( $_POST['advanced_ad']['output']['image_id'] ) : 0;
590 if ( $image_id ) {
591 $attachment = get_post( $image_id );
592 if ( $attachment && 0 === $attachment->post_parent ) {
593 wp_update_post(
594 [
595 'ID' => $image_id,
596 'post_parent' => $post_id,
597 ]
598 );
599 }
600 }
601
602 // phpcs:enable
603
604 $ad->save();
605 }
606
607 /**
608 * Prepare main post data for ads when being saved.
609 *
610 * Set default title if it is empty.
611 *
612 * @param array $data An array of slashed post data.
613 * @return array
614 */
615 public static function prepare_insert_post_data( $data ) {
616 if ( Advanced_Ads::POST_TYPE_SLUG === $data['post_type']
617 && '' === $data['post_title'] ) {
618 if ( function_exists( 'wp_date' ) ) {
619 // The function wp_date was added in WP 5.3.
620 $created_time = wp_date( get_option( 'date_format' ) ) . ' ' . wp_date( get_option( 'time_format' ) );
621 } else {
622 // Just attach the post date raw form.
623 $created_time = $data['post_date'];
624 }
625
626 // Create timestamp from current data.
627 $data['post_title'] = sprintf(
628 // Translators: %s is the time the ad was first saved.
629 __( 'Ad created on %s', 'advanced-ads' ),
630 $created_time
631 );
632 }
633
634 return $data;
635 }
636
637 /**
638 * Prepare the ad post type to be removed
639 *
640 * @param int $post_id id of the post.
641 */
642 public function delete_ad( $post_id ) {
643 global $wpdb;
644
645 if ( ! current_user_can( 'delete_posts' ) ) {
646 return;
647 }
648
649 if ( $post_id > 0 ) {
650 $post_type = get_post_type( $post_id );
651 if ( $post_type === $this->post_type ) {
652 /**
653 * Images uploaded to an image ad type get the `_advanced-ads_parent_id` meta key from WordPress automatically
654 * the following SQL query removes that meta data from any attachment when the ad is removed.
655 */
656 $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->postmeta WHERE meta_key = %s AND meta_value = %d", '_advanced-ads_parent_id', $post_id ) );
657 }
658 }
659 }
660
661 /**
662 * Add information above the ad title
663 *
664 * @param object $post WordPress post type object.
665 *
666 * @since 1.5.6
667 */
668 public function edit_form_above_title( $post ) {
669 if ( ! isset( $post->post_type ) || $post->post_type !== $this->post_type ) {
670 return;
671 }
672
673 // highlight Dummy ad if this is the first ad.
674 if ( ! Advanced_Ads::get_number_of_ads() ) {
675 ?>
676 <style>.advanced-ads-type-list-dummy {
677 font-weight: bold;
678 }</style>
679 <?php
680 }
681
682 $ad = new Advanced_Ads_Ad( $post->ID );
683
684 $placement_types = Advanced_Ads_Placements::get_placement_types();
685 $placements = Advanced_Ads::get_ad_placements_array(); // -TODO use model
686
687 // display general and wizard information.
688 include ADVADS_BASE_PATH . 'admin/views/ad-info-top.php';
689 // Don’t show placement options if this is an ad translated with WPML since the placement might exist already.
690 if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
691 $trid = apply_filters( 'wpml_element_trid', null, $post->ID );
692 $translations = apply_filters( 'wpml_get_element_translations', null, $trid, 'Advanced_Ads' );
693 if ( count( $translations ) > 1 ) {
694 return;
695 }
696 }
697 /**
698 * Display ad injection information after ad is created.
699 *
700 * Set `advanced-ads-ad-edit-show-placement-injection` to false if you want to prevent the box from appearing
701 */
702 if ( isset( $_GET['message'] ) && 6 === $_GET['message'] && apply_filters( 'advanced-ads-ad-edit-show-placement-injection', true ) ) {
703 include ADVADS_BASE_PATH . 'admin/views/placement-injection-top.php';
704 }
705 }
706
707 /**
708 * Add information about the ad below the ad title
709 *
710 * @param WP_Post $post WordPress Post object.
711 *
712 * @return void
713 * @deprecated
714 */
715 public function edit_form_below_title( $post ) {}
716
717 /**
718 * Add information below the ad edit form
719 *
720 * @param WP_Post $post WordPress Post object.
721 *
722 * @since 1.7.3
723 */
724 public function edit_form_end( $post ) {
725 if ( $post->post_type !== $this->post_type ) {
726 return;
727 }
728
729 include ADVADS_BASE_PATH . 'admin/views/ad-info-bottom.php';
730 }
731
732 /**
733 * Add meta values below submit box
734 *
735 * @since 1.3.15
736 */
737 public function add_submit_box_meta() {
738 global $post, $wp_locale;
739
740 if ( Advanced_Ads::POST_TYPE_SLUG !== $post->post_type ) {
741 return;
742 }
743
744 $ad = new Advanced_Ads_Ad( $post->ID );
745
746 // get time set for ad or current timestamp (both GMT).
747 $utc_ts = $ad->expiry_date ? $ad->expiry_date : time();
748 $utc_time = date_create( '@' . $utc_ts );
749 $tz_option = get_option( 'timezone_string' );
750 $exp_time = clone $utc_time;
751
752 if ( $tz_option ) {
753 $exp_time->setTimezone( Advanced_Ads_Utils::get_wp_timezone() );
754 } else {
755 $tz_name = Advanced_Ads_Utils::get_timezone_name();
756 $tz_offset = substr( $tz_name, 3 );
757 $off_time = date_create( $utc_time->format( 'Y-m-d\TH:i:s' ) . $tz_offset );
758 $offset_in_sec = date_offset_get( $off_time );
759 $exp_time = date_create( '@' . ( $utc_ts + $offset_in_sec ) );
760 }
761
762 list( $curr_year, $curr_month, $curr_day, $curr_hour, $curr_minute ) = explode( '-', $exp_time->format( 'Y-m-d-H-i' ) );
763 $enabled = 1 - empty( $ad->expiry_date );
764
765 include ADVADS_BASE_PATH . 'admin/views/ad-submitbox-meta.php';
766 }
767
768 /**
769 * Use CodeMirror for plain text input field
770 *
771 * Needs WordPress 4.9 and higher
772 *
773 * @since 1.8.15
774 */
775 public function use_code_editor() {
776 global $wp_version;
777 if ( 'advanced_ads' !== get_current_screen()->id || defined( 'ADVANCED_ADS_DISABLE_CODE_HIGHLIGHTING' ) || - 1 === version_compare( $wp_version, '4.9' ) ) {
778 return;
779 }
780
781 // Enqueue code editor and settings for manipulating HTML.
782 $settings = wp_enqueue_code_editor( [ 'type' => 'application/x-httpd-php' ] );
783
784 // Bail if user disabled CodeMirror.
785 if ( false === $settings ) {
786 return;
787 }
788
789 wp_add_inline_script(
790 'code-editor',
791 sprintf( 'jQuery( function() { if( jQuery( "#advads-ad-content-plain" ).length && typeof Advanced_Ads_Admin !== "undefined" ){ Advanced_Ads_Admin.editor = wp.codeEditor.initialize( "advads-ad-content-plain", %s ); Advanced_Ads_Admin.editor.codemirror.on("keyup", Advanced_Ads_Admin.check_ad_source); jQuery( function() { Advanced_Ads_Admin.check_ad_source(); } ); } } );', wp_json_encode( $settings ) )
792 );
793 }
794
795 /**
796 * Edit ad update messages
797 *
798 * @param array $messages existing post update messages.
799 *
800 * @return array $messages
801 *
802 * @since 1.4.7
803 * @see wp-admin/edit-form-advanced.php
804 */
805 public function ad_update_messages( $messages = [] ) {
806 $post = get_post();
807
808 // added to hide error message caused by third party code that uses post_updated_messages filter wrong.
809 if ( ! is_array( $messages ) ) {
810 return $messages;
811 }
812
813 $messages[ Advanced_Ads::POST_TYPE_SLUG ] = [
814 0 => '', // Unused. Messages start at index 1.
815 1 => __( 'Ad updated.', 'advanced-ads' ),
816 4 => __( 'Ad updated.', 'advanced-ads' ), /* translators: %s: date and time of the revision */
817 5 => isset( $_GET['revision'] ) ? sprintf( __( 'Ad restored to revision from %s', 'advanced-ads' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
818 6 => __( 'Ad saved.', 'advanced-ads' ), // published.
819 7 => __( 'Ad saved.', 'advanced-ads' ), // saved.
820 8 => __( 'Ad submitted.', 'advanced-ads' ),
821 9 => sprintf(
822 // translators: %1$s is a date.
823 __( 'Ad scheduled for: <strong>%1$s</strong>.', 'advanced-ads' ),
824 // translators: Publish box date format, see http://php.net/date.
825 date_i18n( __( 'M j, Y @ G:i', 'advanced-ads' ), strtotime( $post->post_date ) )
826 ),
827 10 => __( 'Ad draft updated.', 'advanced-ads' ),
828 ];
829
830 return $messages;
831 }
832
833 /**
834 * Whether to show the wizard welcome message or not
835 *
836 * @return bool true, if wizard welcome message should be displayed
837 * @since 1.7.4
838 */
839 public function show_wizard_welcome() {
840 $user_id = get_current_user_id();
841 if ( ! $user_id ) {
842 return true;
843 }
844
845 $hide_wizard = get_user_meta( $user_id, 'advanced-ads-hide-wizard', true );
846 global $post;
847
848 return ( ! $hide_wizard && 'edit' !== $post->filter ) ? true : false;
849 }
850
851 /**
852 * Whether to start the wizard by default or not
853 *
854 * @since 1.7.4
855 * return bool true, if wizard should start automatically
856 */
857 public function start_wizard_automatically() {
858 $user_id = get_current_user_id();
859 if ( ! $user_id ) {
860 return true;
861 }
862
863 $hide_wizard = get_user_meta( $user_id, 'advanced-ads-hide-wizard', true );
864
865 global $post;
866
867 // true the ad already exists, if the wizard was never started or closed.
868 return ( 'edit' !== $post->filter && ( ! $hide_wizard || 'false' === $hide_wizard ) ) ? true : false;
869 }
870
871 /**
872 * Replace 'You need a higher level of permission.' message if user role does not have required permissions.
873 *
874 * @param string $translated_text Translated text.
875 * @param string $untranslated_text Text to translate.
876 *
877 * @return string $translation Translated text.
878 */
879 public function replace_cheating_message( $translated_text, $untranslated_text ) {
880 global $typenow;
881
882 if ( isset( $typenow ) && 'You need a higher level of permission.' === $untranslated_text && $typenow === $this->post_type ) {
883 $translated_text = __( 'You don’t have access to ads. Please deactivate and re-enable Advanced Ads again to fix this.', 'advanced-ads' )
884 . '&nbsp;<a href="' . ADVADS_URL . 'manual/user-capabilities/?utm_source=advanced-ads&utm_medium=link&utm_campaign=wrong-user-role#You_dont_have_access_to_ads" target="_blank">' . __( 'Get help', 'advanced-ads' ) . '</a>';
885 }
886
887 return $translated_text;
888 }
889
890 /**
891 * General stuff after ad edit page is loaded and screen variable is available
892 */
893 public function run_on_ad_edit_screen() {
894 $screen = get_current_screen();
895
896 if ( ! isset( $screen->id ) || 'advanced_ads' !== $screen->id ) {
897 return;
898 }
899
900 // Remove parent group dropdown in ad edit.
901 add_filter(
902 'wp_dropdown_cats',
903 [
904 $this,
905 'remove_parent_group_dropdown',
906 ],
907 10,
908 2
909 );
910 }
911
912 /**
913 * Remove parent group dropdown from ad group taxonomy
914 *
915 * @param string $output parent group HTML.
916 * @param array $arguments additional parameters.
917 *
918 * @return string new parent group HTML
919 */
920 public function remove_parent_group_dropdown( $output, $arguments ) {
921 if ( 'newadvanced_ads_groups_parent' === $arguments['name'] ) {
922 $output = '';
923 }
924
925 return $output;
926 }
927
928 /**
929 * Create a unique across all post types slug for the ad.
930 * Almost all code here copied from `wp_unique_post_slug()`.
931 *
932 * @param string $override_slug Short-circuit return value.
933 * @param string $slug The desired slug (post_name).
934 * @param int $post_ID Post ID.
935 * @param string $post_status The post status.
936 * @param string $post_type Post type.
937 * @param int $post_parent Post parent ID.
938 *
939 * @return string
940 */
941 public function pre_wp_unique_post_slug( $override_slug, $slug, $post_ID, $post_status, $post_type, $post_parent ) {
942 if ( Advanced_Ads::POST_TYPE_SLUG !== $post_type ) {
943 return $override_slug;
944 }
945
946 global $wpdb, $wp_rewrite;
947
948 $feeds = $wp_rewrite->feeds;
949 if ( ! is_array( $feeds ) ) {
950 $feeds = [];
951 }
952
953 // Advanced Ads post types slugs must be unique across all types.
954 $check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND ID != %d LIMIT 1";
955 $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $slug, $post_ID ) );
956
957 if ( $post_name_check || in_array( $slug, $feeds, true ) || 'embed' === $slug ) {
958 $suffix = 2;
959 do {
960 $alt_post_name = substr( $slug, 0, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix";
961 $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $alt_post_name, $post_ID ) );
962 $suffix ++;
963 } while ( $post_name_check );
964 $override_slug = $alt_post_name;
965 }
966
967 return $override_slug;
968 }
969
970 /**
971 * Remove the View Mode setting in Screen Options
972 *
973 * @param array $view_mode_post_types post types that have the View Mode option.
974 *
975 * @return array
976 */
977 public function remove_view_mode( $view_mode_post_types ) {
978 unset( $view_mode_post_types['advanced_ads'] );
979
980 return $view_mode_post_types;
981 }
982
983 /**
984 * Set the removed post list mode to "List", if it was set to "Excerpt".
985 *
986 * @param string $user_options Query string containing user options.
987 *
988 * @return string
989 */
990 public function reset_view_mode_option( $user_options ) {
991 return str_replace( '&posts_list_mode=excerpt', '&posts_list_mode=list', $user_options );
992 }
993
994 /**
995 * Register custom screen options on the ad overview page.
996 *
997 * @param string $options Screen options HTML.
998 * @param WP_Screen $screen Screen object.
999 *
1000 * @return string
1001 */
1002 public function add_screen_options( $options, WP_Screen $screen ) {
1003 if ( $screen->base !== 'edit' || $screen->id !== 'edit-advanced_ads' ) {
1004 return $options;
1005 }
1006
1007 $show_filters = (bool) $screen->get_option( 'show-filters' );
1008
1009 // If the default WordPress screen options don't exist, we have to force the submit button to show.
1010 add_filter( 'screen_options_show_submit', '__return_true' );
1011 ob_start();
1012 require ADVADS_BASE_PATH . 'admin/views/ad-list/screen-options.php';
1013
1014 return $options . ob_get_clean();
1015 }
1016
1017 /**
1018 * Save the screen option setting.
1019 *
1020 * @return void
1021 */
1022 public function save_screen_options() {
1023 if ( ! isset( $_POST['advanced-ads-screen-options'] ) || ! is_array( $_POST['advanced-ads-screen-options'] ) ) {
1024 return;
1025 }
1026
1027 check_admin_referer( 'screen-options-nonce', 'screenoptionnonce' );
1028
1029 $user = wp_get_current_user();
1030
1031 if ( ! $user ) {
1032 return;
1033 }
1034
1035 // sanitize options
1036 update_user_meta( $user->ID, 'advanced-ads-ad-list-screen-options', [
1037 'show-filters' => ! empty( $_POST['advanced-ads-screen-options']['show-filters'] ),
1038 ] );
1039 }
1040
1041 /**
1042 * Add the screen options to the WP_Screen options
1043 *
1044 * @return void
1045 */
1046 public function set_screen_options() {
1047 $screen = get_current_screen();
1048
1049 if ( ! isset( $screen->id ) || $screen->id !== 'edit-advanced_ads' ) {
1050 return;
1051 }
1052
1053 $screen_options = get_user_meta( get_current_user_id(), 'advanced-ads-ad-list-screen-options', true );
1054 if ( ! is_array( $screen_options ) ) {
1055 return;
1056 }
1057 foreach ( $screen_options as $option_name => $value ) {
1058 add_screen_option( $option_name, $value );
1059 }
1060 }
1061
1062 /**
1063 * Get the ad size string to display in post list.
1064 *
1065 * @param Advanced_Ads_Ad $ad Ad object.
1066 *
1067 * @return string
1068 */
1069 private function get_ad_size_string( Advanced_Ads_Ad $ad ) {
1070 // load ad size.
1071 $size = '';
1072 if ( ! empty( $ad->width ) || ! empty( $ad->height ) ) {
1073 $size = sprintf( '%d &times; %d', $ad->width, $ad->height );
1074 }
1075
1076 /**
1077 * Filter the ad size string to display in the ads post list.
1078 *
1079 * @param string $size Size string.
1080 * @param Advanced_Ads_Ad $ad Ad object.
1081 */
1082 return (string) apply_filters( 'advanced-ads-list-ad-size', $size, $ad );
1083 }
1084 }
1085