class-advanced-ads-admin.php
485 lines
| 1 | <?php |
| 2 | |
| 3 | /** |
| 4 | * Advanced Ads. |
| 5 | * |
| 6 | * @package Advanced_Ads_Admin |
| 7 | * @author Thomas Maier <thomas.maier@webgilde.com> |
| 8 | * @license GPL-2.0+ |
| 9 | * @link http://webgilde.com |
| 10 | * @copyright 2013-2015 Thomas Maier, webgilde GmbH |
| 11 | */ |
| 12 | |
| 13 | /** |
| 14 | * Plugin class. This class should ideally be used to work with the |
| 15 | * administrative side of the WordPress site. |
| 16 | * |
| 17 | * @package Advanced_Ads_Admin |
| 18 | * @author Thomas Maier <thomas.maier@webgilde.com> |
| 19 | */ |
| 20 | class Advanced_Ads_Admin { |
| 21 | |
| 22 | /** |
| 23 | * Instance of this class. |
| 24 | * |
| 25 | * @since 1.0.0 |
| 26 | * @var object |
| 27 | */ |
| 28 | protected static $instance = null; |
| 29 | |
| 30 | /** |
| 31 | * Instance of admin notice class. |
| 32 | * |
| 33 | * @since 1.5.2 |
| 34 | * @var object |
| 35 | */ |
| 36 | protected $notices = null; |
| 37 | |
| 38 | /** |
| 39 | * Slug of the settings page |
| 40 | * |
| 41 | * @since 1.0.0 |
| 42 | * @var string |
| 43 | */ |
| 44 | public $plugin_screen_hook_suffix = null; |
| 45 | |
| 46 | /** |
| 47 | * general plugin slug |
| 48 | * |
| 49 | * @since 1.0.0 |
| 50 | * @var string |
| 51 | */ |
| 52 | protected $plugin_slug = ''; |
| 53 | |
| 54 | /** |
| 55 | * Initialize the plugin by loading admin scripts & styles and adding a |
| 56 | * settings page and menu. |
| 57 | * |
| 58 | * @since 1.0.0 |
| 59 | */ |
| 60 | private function __construct() { |
| 61 | if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) { |
| 62 | new Advanced_Ads_Ad_Ajax_Callbacks; |
| 63 | add_action( 'plugins_loaded', array( $this, 'wp_plugins_loaded_ajax' ) ); |
| 64 | } else { |
| 65 | add_action( 'plugins_loaded', array( $this, 'wp_plugins_loaded' ) ); |
| 66 | } |
| 67 | // add shortcode creator to TinyMCE |
| 68 | Advanced_Ads_Shortcode_Creator::get_instance(); |
| 69 | Advanced_Ads_Admin_Licenses::get_instance(); |
| 70 | } |
| 71 | |
| 72 | /** |
| 73 | * license handling legacy code after moving license handling code to Advanced_Ads_Admin_Licenses |
| 74 | * |
| 75 | * @since version 1.7.16 (early January 2017) |
| 76 | */ |
| 77 | public function deactivate_license( $addon = '', $plugin_name = '', $options_slug = '' ){ return Advanced_Ads_Admin_Licenses::get_instance()->deactivate_license( $addon = '', $plugin_name = '', $options_slug = '' ); } |
| 78 | public function get_license_status( $slug = '' ){ return Advanced_Ads_Admin_Licenses::get_instance()->get_license_status( $slug = '' ); } |
| 79 | |
| 80 | /** |
| 81 | * actions and filter available after all plugins are initialized |
| 82 | */ |
| 83 | public function wp_plugins_loaded() { |
| 84 | /* |
| 85 | * Call $plugin_slug from public plugin class. |
| 86 | * |
| 87 | */ |
| 88 | $plugin = Advanced_Ads::get_instance(); |
| 89 | $this->plugin_slug = $plugin->get_plugin_slug(); |
| 90 | |
| 91 | add_action( 'current_screen', array( $this, 'current_screen' ) ); |
| 92 | |
| 93 | // Load admin style sheet and JavaScript. |
| 94 | add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_styles' ) ); |
| 95 | add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ), 9 ); |
| 96 | |
| 97 | // update placements |
| 98 | add_action( 'admin_init', array('Advanced_Ads_Placements', 'update_placements') ); |
| 99 | |
| 100 | // check for update logic |
| 101 | add_action( 'admin_notices', array($this, 'admin_notices') ); |
| 102 | |
| 103 | // add links to plugin page |
| 104 | add_filter( 'plugin_action_links_' . ADVADS_BASE, array( $this, 'add_plugin_links' ) ); |
| 105 | |
| 106 | // display information when user is going to disable the plugin |
| 107 | add_filter( 'admin_footer', array( $this, 'add_deactivation_logic' ) ); |
| 108 | // add_filter( 'after_plugin_row_' . ADVADS_BASE, array( $this, 'display_deactivation_message' ) ); |
| 109 | |
| 110 | // disable adding rel="noopener noreferrer" to link added through TinyMCE for rich content ads |
| 111 | add_filter( 'tiny_mce_before_init', array( $this, 'tinymce_allow_unsafe_link_target' ) ); |
| 112 | |
| 113 | Advanced_Ads_Admin_Meta_Boxes::get_instance(); |
| 114 | Advanced_Ads_Admin_Menu::get_instance(); |
| 115 | Advanced_Ads_Admin_Ad_Type::get_instance(); |
| 116 | Advanced_Ads_Admin_Settings::get_instance(); |
| 117 | } |
| 118 | |
| 119 | /** |
| 120 | * actions and filters that should also be available for ajax |
| 121 | */ |
| 122 | public function wp_plugins_loaded_ajax() { |
| 123 | // needed here in order to work with Quick Edit option on ad list page |
| 124 | Advanced_Ads_Admin_Ad_Type::get_instance(); |
| 125 | |
| 126 | add_action( 'wp_ajax_advads_send_feedback', array( $this, 'send_feedback' ) ); |
| 127 | add_action( 'wp_ajax_advads_load_rss_widget_content', array( 'Advanced_Ads_Admin_Meta_Boxes', 'dashboard_widget_function_output' ) ); |
| 128 | } |
| 129 | |
| 130 | /** |
| 131 | * Return an instance of this class. |
| 132 | * |
| 133 | * @since 1.0.0 |
| 134 | * |
| 135 | * @return object A single instance of this class. |
| 136 | */ |
| 137 | public static function get_instance() { |
| 138 | // If the single instance hasn't been set, set it now. |
| 139 | if ( null == self::$instance ) { |
| 140 | self::$instance = new self; |
| 141 | } |
| 142 | |
| 143 | return self::$instance; |
| 144 | } |
| 145 | |
| 146 | /** |
| 147 | * general stuff after page is loaded and screen variable is available |
| 148 | */ |
| 149 | public function current_screen(){ |
| 150 | $screen = get_current_screen(); |
| 151 | |
| 152 | if( !isset( $screen->id ) ){ |
| 153 | return; |
| 154 | } |
| 155 | |
| 156 | switch( $screen->id ){ |
| 157 | case 'edit-advanced_ads' : // ad overview page |
| 158 | case 'advanced_ads' : // ad edit page |
| 159 | // remove notice about missing first ad |
| 160 | Advanced_Ads_Admin_Notices::get_instance()->remove_from_queue( 'nl_intro' ); |
| 161 | break; |
| 162 | } |
| 163 | } |
| 164 | |
| 165 | /** |
| 166 | * Register and enqueue admin-specific style sheet. |
| 167 | * |
| 168 | * @since 1.0.0 |
| 169 | */ |
| 170 | public function enqueue_admin_styles() { |
| 171 | wp_enqueue_style( $this->plugin_slug . '-admin-styles', plugins_url( 'assets/css/admin.css', __FILE__ ), array(), ADVADS_VERSION ); |
| 172 | if( self::screen_belongs_to_advanced_ads() ){ |
| 173 | // jQuery ui smoothness style 1.11.4 |
| 174 | wp_enqueue_style( $this->plugin_slug . '-jquery-ui-styles', plugins_url( 'assets/jquery-ui/jquery-ui.min.css', __FILE__ ), array(), '1.11.4' ); |
| 175 | } |
| 176 | //wp_enqueue_style( 'jquery-style', '//code.jquery.com/ui/1.11.3/themes/smoothness/jquery-ui.css' ); |
| 177 | } |
| 178 | |
| 179 | /** |
| 180 | * Register and enqueue admin-specific JavaScript. |
| 181 | * |
| 182 | * @since 1.0.0 |
| 183 | * |
| 184 | * @return null Return early if no settings page is registered. |
| 185 | */ |
| 186 | public function enqueue_admin_scripts() { |
| 187 | |
| 188 | // global js script |
| 189 | wp_enqueue_script( $this->plugin_slug . '-admin-global-script', plugins_url( 'assets/js/admin-global.js', __FILE__ ), array('jquery'), ADVADS_VERSION ); |
| 190 | wp_enqueue_script( $this->plugin_slug . '-admin-find-adblocker', plugins_url( 'assets/js/advertisement.js', __FILE__ ), array(), ADVADS_VERSION ); |
| 191 | |
| 192 | // register ajax nonce |
| 193 | $params = array( |
| 194 | 'ajax_nonce' => wp_create_nonce( 'advanced-ads-admin-ajax-nonce' ), |
| 195 | ); |
| 196 | wp_localize_script( $this->plugin_slug . '-admin-global-script', 'advadsglobal', $params ); |
| 197 | |
| 198 | if( self::screen_belongs_to_advanced_ads() ){ |
| 199 | wp_register_script( $this->plugin_slug . '-admin-script', plugins_url( 'assets/js/admin.js', __FILE__ ), array( 'jquery', 'jquery-ui-autocomplete' , 'jquery-ui-button' ), ADVADS_VERSION ); |
| 200 | wp_register_script( $this->plugin_slug . '-wizard-script', plugins_url( 'assets/js/wizard.js', __FILE__ ), array('jquery'), ADVADS_VERSION ); |
| 201 | |
| 202 | // jquery ui |
| 203 | wp_enqueue_script( 'jquery-ui-accordion' ); |
| 204 | wp_enqueue_script( 'jquery-ui-button' ); |
| 205 | wp_enqueue_script( 'jquery-ui-tooltip' ); |
| 206 | |
| 207 | // just register this script for later inclusion on ad group list page |
| 208 | wp_register_script( 'inline-edit-group-ads', plugins_url( 'assets/js/inline-edit-group-ads.js', __FILE__ ), array('jquery'), ADVADS_VERSION ); |
| 209 | |
| 210 | // register admin.js translations |
| 211 | $translation_array = array( |
| 212 | 'condition_or' => __( 'or', 'advanced-ads' ), |
| 213 | 'condition_and' => __( 'and', 'advanced-ads' ), |
| 214 | 'after_paragraph_promt' => __( 'After which paragraph?', 'advanced-ads' ), |
| 215 | ); |
| 216 | wp_localize_script( $this->plugin_slug . '-admin-script', 'advadstxt', $translation_array ); |
| 217 | |
| 218 | wp_enqueue_script( $this->plugin_slug . '-admin-script' ); |
| 219 | wp_enqueue_script( $this->plugin_slug . '-wizard-script' ); |
| 220 | } |
| 221 | |
| 222 | //call media manager for image upload only on ad edit pages |
| 223 | $screen = get_current_screen(); |
| 224 | if( isset( $screen->id ) && Advanced_Ads::POST_TYPE_SLUG === $screen->id ) { |
| 225 | // the 'wp_enqueue_media' function can be executed only once and should be called with the 'post' parameter |
| 226 | // in this case, the '_wpMediaViewsL10n' js object inside html will contain id of the post, that is necessary to view oEmbed priview inside tinyMCE editor. |
| 227 | // since other plugins can call the 'wp_enqueue_media' function without the 'post' parameter, Advanced Ads should call it earlier. |
| 228 | global $post; |
| 229 | wp_enqueue_media( array( 'post' => $post ) ); |
| 230 | } |
| 231 | |
| 232 | } |
| 233 | |
| 234 | /** |
| 235 | * check if the current screen belongs to Advanced Ads |
| 236 | * |
| 237 | * @since 1.6.6 |
| 238 | * @return bool true if screen belongs to Advanced Ads |
| 239 | */ |
| 240 | static function screen_belongs_to_advanced_ads(){ |
| 241 | |
| 242 | if( ! function_exists( 'get_current_screen' ) ){ |
| 243 | return false; |
| 244 | } |
| 245 | |
| 246 | $screen = get_current_screen(); |
| 247 | //echo $screen->id; |
| 248 | if( !isset( $screen->id ) ) { |
| 249 | return false; |
| 250 | } |
| 251 | |
| 252 | $advads_pages = apply_filters( 'advanced-ads-dashboard-screens', array( |
| 253 | 'advanced-ads_page_advanced-ads-groups', // ad groups |
| 254 | 'edit-advanced_ads', // ads overview |
| 255 | 'advanced_ads', // ad edit page |
| 256 | 'advanced-ads_page_advanced-ads-placements', // placements |
| 257 | 'advanced-ads_page_advanced-ads-settings', // settings |
| 258 | 'toplevel_page_advanced-ads', // overview |
| 259 | 'admin_page_advanced-ads-debug', // debug |
| 260 | // 'advanced-ads_page_advanced-ads-support', // support |
| 261 | 'admin_page_advanced-ads-import-export', // import & export |
| 262 | )); |
| 263 | |
| 264 | if( in_array( $screen->id, $advads_pages )){ |
| 265 | return true; |
| 266 | } |
| 267 | |
| 268 | return false; |
| 269 | } |
| 270 | |
| 271 | |
| 272 | /** |
| 273 | * get action from the params |
| 274 | * |
| 275 | * @since 1.0.0 |
| 276 | */ |
| 277 | public function current_action() { |
| 278 | if ( isset($_REQUEST['action']) && -1 != $_REQUEST['action'] ) { |
| 279 | return $_REQUEST['action']; |
| 280 | } |
| 281 | |
| 282 | return false; |
| 283 | } |
| 284 | |
| 285 | |
| 286 | /** |
| 287 | * get DateTimeZone object for the WP installation |
| 288 | */ |
| 289 | public static function get_wp_timezone() { |
| 290 | $_time_zone = get_option( 'timezone_string' ); |
| 291 | $time_zone = new DateTimeZone( 'UTC' ); |
| 292 | if ( $_time_zone ) { |
| 293 | $time_zone = new DateTimeZone( $_time_zone ); |
| 294 | } else { |
| 295 | $gmt_offset = floatval( get_option( 'gmt_offset' ) ); |
| 296 | $sign = ( 0 > $gmt_offset )? '-' : '+'; |
| 297 | $int = floor( abs( $gmt_offset ) ); |
| 298 | $frac = abs( $gmt_offset ) - $int; |
| 299 | |
| 300 | $gmt = ''; |
| 301 | if ( $gmt_offset ) { |
| 302 | $gmt .= $sign . zeroise( $int, 2 ) . ':' . zeroise( 60 * $frac, 2 ); |
| 303 | $time_zone = date_create( '2017-10-01T12:00:00' . $gmt )->getTimezone(); |
| 304 | } |
| 305 | |
| 306 | } |
| 307 | return $time_zone; |
| 308 | } |
| 309 | |
| 310 | /** |
| 311 | * get literal expression of timezone |
| 312 | */ |
| 313 | public static function timezone_get_name( $DTZ ) { |
| 314 | if ( $DTZ instanceof DateTimeZone ) { |
| 315 | $TZ = timezone_name_get( $DTZ ); |
| 316 | if ( 'UTC' == $TZ ) { |
| 317 | return 'UTC+0'; |
| 318 | } |
| 319 | if ( false === strpos( $TZ, '/' ) ) { |
| 320 | $TZ = 'UTC' . $TZ; |
| 321 | } else { |
| 322 | $TZ = sprintf( __( 'time of %s', 'advanced-ads' ), $TZ ); |
| 323 | } |
| 324 | return $TZ; |
| 325 | } |
| 326 | return 'UTC+0'; |
| 327 | } |
| 328 | |
| 329 | /** |
| 330 | * initiate the admin notices class |
| 331 | * |
| 332 | * @since 1.5.3 |
| 333 | */ |
| 334 | public function admin_notices(){ |
| 335 | // display ad block warning to everyone who can edit ads |
| 336 | if( current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_edit_ads') ) ) { |
| 337 | if ( $this->screen_belongs_to_advanced_ads() ){ |
| 338 | include ADVADS_BASE_PATH . 'admin/views/notices/adblock.php'; |
| 339 | include ADVADS_BASE_PATH . 'admin/views/notices/jqueryui_error.php'; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | if( current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_edit_ads') ) ) { |
| 344 | $this->notices = Advanced_Ads_Admin_Notices::get_instance()->notices; |
| 345 | Advanced_Ads_Admin_Notices::get_instance()->display_notices(); |
| 346 | } |
| 347 | } |
| 348 | |
| 349 | /** |
| 350 | * add links to the plugins list |
| 351 | * |
| 352 | * @since 1.6.14 |
| 353 | * @param arr $links array of links for the plugins, adapted when the current plugin is found. |
| 354 | * @param str $file the filename for the current plugin, which the filter loops through. |
| 355 | * @return array $links |
| 356 | */ |
| 357 | public function add_plugin_links( $links ) { |
| 358 | |
| 359 | if( ! is_array( $links ) ){ |
| 360 | return $links; |
| 361 | } |
| 362 | |
| 363 | // add link to settings |
| 364 | //$settings_link = '<a href="' . admin_url( 'admin.php?page=advanced_ads&page=advanced-ads-settings' ) . '">' . __( 'Settings', 'advanced-ads' ) . '</a>'; |
| 365 | //array_unshift( $links, $settings_link ); |
| 366 | |
| 367 | // add link to support page |
| 368 | $support_link = '<a href="' . esc_url( admin_url( 'admin.php?page=advanced-ads-settings#top#support' ) ) . '">' . __( 'Support', 'advanced-ads' ) . '</a>'; |
| 369 | array_unshift( $links, $support_link ); |
| 370 | |
| 371 | // add link to add-ons |
| 372 | $extend_link = '<a href="' . ADVADS_URL . 'add-ons/#utm_source=advanced-ads&utm_medium=link&utm_campaign=plugin-page" target="_blank">' . __( 'Add-Ons', 'advanced-ads' ) . '</a>'; |
| 373 | array_unshift( $links, $extend_link ); |
| 374 | |
| 375 | return $links; |
| 376 | } |
| 377 | |
| 378 | /** |
| 379 | * display deactivation logic on plugins page |
| 380 | * |
| 381 | * @since 1.7.14 |
| 382 | */ |
| 383 | public function add_deactivation_logic(){ |
| 384 | |
| 385 | $screen = get_current_screen(); |
| 386 | if ( ! isset( $screen->id ) || ! in_array( $screen->id, array( 'plugins', 'plugins-network' ), true ) ) { |
| 387 | return; |
| 388 | } |
| 389 | |
| 390 | $current_user = wp_get_current_user(); |
| 391 | if ( !($current_user instanceof WP_User) ){ |
| 392 | $from = ''; |
| 393 | $email = ''; |
| 394 | } else { |
| 395 | $from = $current_user->user_nicename . ' <' . trim( $current_user->user_email ) . '>'; |
| 396 | $email = $current_user->user_email; |
| 397 | } |
| 398 | |
| 399 | include ADVADS_BASE_PATH . 'admin/views/feedback-disable.php'; |
| 400 | } |
| 401 | |
| 402 | /** |
| 403 | * send feedback via email |
| 404 | * |
| 405 | * @since 1.7.14 |
| 406 | */ |
| 407 | public function send_feedback(){ |
| 408 | |
| 409 | if ( isset( $_POST['formdata'] ) ) { |
| 410 | parse_str( $_POST['formdata'], $form ); |
| 411 | } |
| 412 | |
| 413 | if( ! wp_verify_nonce( $form[ 'advanced_ads_disable_form_nonce' ], 'advanced_ads_disable_form' ) ){ |
| 414 | die(); |
| 415 | } |
| 416 | |
| 417 | $text = ''; |
| 418 | if( isset( $form[ 'advanced_ads_disable_text' ] ) ){ |
| 419 | $text = implode( "\n\r", $form[ 'advanced_ads_disable_text' ] ); |
| 420 | } |
| 421 | |
| 422 | // get first version to see if this is a new problem or might be an older on |
| 423 | $options = Advanced_Ads_Plugin::get_instance()->internal_options(); |
| 424 | $installed = isset( $options['installed'] ) ? date( 'd.m.Y', $options['installed'] ) : '–'; |
| 425 | |
| 426 | $text .= "\n\n" . home_url() . " ($installed)"; |
| 427 | |
| 428 | $headers = array(); |
| 429 | |
| 430 | $from = isset( $form['advanced_ads_disable_from'] ) ? $form['advanced_ads_disable_from'] : ''; |
| 431 | // the user clicked on the "don’t disable" button or if an address is given in the form then use that one |
| 432 | if( ( isset( $_POST['feedback'] ) && $_POST['feedback'] && 'false' !== $_POST['feedback'] ) |
| 433 | || ( |
| 434 | isset( $form['advanced_ads_disable_reason'] ) |
| 435 | && in_array( $form['advanced_ads_disable_reason'], array( 'technical issue', 'get help' ) ) |
| 436 | && !empty( $form[ 'advanced_ads_disable_reply_email' ] ) ) ) |
| 437 | { |
| 438 | $email = isset( $form[ 'advanced_ads_disable_reply_email' ] ) ? trim( $form[ 'advanced_ads_disable_reply_email' ] ) : $current_user->email; |
| 439 | $current_user = wp_get_current_user(); |
| 440 | $name = ($current_user instanceof WP_User) ? $current_user->user_nicename : ''; |
| 441 | $from = $name . ' <' . $email . '>'; |
| 442 | $text .= "\n\n PLEASE REPLY"; |
| 443 | } |
| 444 | if( $from ){ |
| 445 | $headers[] = "From: $from"; |
| 446 | $headers[] = "Reply-To: $from"; |
| 447 | } |
| 448 | |
| 449 | $subject = isset( $form['advanced_ads_disable_reason'] ) ? $form['advanced_ads_disable_reason'] : '(no reason given)'; |
| 450 | |
| 451 | $success = wp_mail( 'improve@wpadvancedads.com', $subject, $text, $headers ); |
| 452 | |
| 453 | die(); |
| 454 | |
| 455 | } |
| 456 | |
| 457 | public function tinymce_allow_unsafe_link_target( $mceInit ) { |
| 458 | |
| 459 | // check if we are on the ad edit screen |
| 460 | if( ! function_exists( 'get_current_screen' ) ){ |
| 461 | return $mceInit; |
| 462 | } |
| 463 | |
| 464 | $screen = get_current_screen(); |
| 465 | if( isset( $screen->id ) && $screen->id === 'advanced_ads' ) { |
| 466 | $mceInit['allow_unsafe_link_target'] = true; |
| 467 | } |
| 468 | |
| 469 | return $mceInit; |
| 470 | } |
| 471 | |
| 472 | /** |
| 473 | * sort visitor and display condition arrays alphabetically by their label |
| 474 | * |
| 475 | * @since 1.8.12 |
| 476 | */ |
| 477 | static function sort_condition_array_by_label( $a, $b ){ |
| 478 | if( ! isset( $a['label'] ) || ! isset( $b['label'] ) ){ |
| 479 | return; |
| 480 | } |
| 481 | return strcmp( strtolower( $a['label'] ), strtolower( $b['label'] ) ); |
| 482 | } |
| 483 | |
| 484 | } |
| 485 |