$method,
'timeout' => 20,
'headers' => array(
'Authorization' => 'Bearer ' . $key,
'Accept' => 'application/json',
'User-Agent' => 'Diretsa-WordPress/' . DIRETSA_VERSION . '; ' . home_url('/'),
),
));
if (is_wp_error($response)) {
/* translators: %s: the network error message. */
return new WP_Error('diretsa_unreachable', sprintf(__('Diretsa could not be reached: %s', 'diretsa'), $response->get_error_message()));
}
$code = (int) wp_remote_retrieve_response_code($response);
$body = json_decode(wp_remote_retrieve_body($response), true);
if ($code < 200 || $code >= 300) {
/* translators: %d: HTTP status code. */
$message = is_array($body) && !empty($body['error']) ? $body['error'] : sprintf(__('Diretsa answered with HTTP %d.', 'diretsa'), $code);
return new WP_Error('diretsa_http_' . $code, $message);
}
return is_array($body) ? $body : array();
}
/** Fetch the site, its placements and tags, and keep them for the front end. */
function diretsa_refresh($key = null) {
$data = diretsa_api('GET', '/wp/v1/site', $key);
if (is_wp_error($data)) {
return $data;
}
update_option('diretsa_site', $data, true);
update_option('diretsa_site_fetched', time(), false);
return $data;
}
/** The cached site data, or an empty array. */
function diretsa_site() {
$data = get_option('diretsa_site', array());
return is_array($data) ? $data : array();
}
/** One placement from the cache, by product id. */
function diretsa_placement($product_id) {
$site = diretsa_site();
foreach ((isset($site['placements']) ? $site['placements'] : array()) as $p) {
if (isset($p['product_id']) && $p['product_id'] === $product_id) {
return $p;
}
}
return null;
}
/* ---------------------------------------------------- Keep tags current */
register_activation_hook(__FILE__, function () {
if (!wp_next_scheduled('diretsa_refresh_event')) {
wp_schedule_event(time() + HOUR_IN_SECONDS, 'twicedaily', 'diretsa_refresh_event');
}
});
register_deactivation_hook(__FILE__, function () {
wp_clear_scheduled_hook('diretsa_refresh_event');
});
add_action('diretsa_refresh_event', function () {
if (get_option('diretsa_key')) {
diretsa_refresh();
}
});
/* ---------------------------------------------------- Verification tag */
/** Until Diretsa has checked the site, put its verification tag in the page head. */
add_action('wp_head', function () {
$site = diretsa_site();
if (empty($site['site']) || !empty($site['site']['verified']) || empty($site['site']['verification']['token'])) {
return;
}
printf("\n", esc_attr($site['site']['verification']['token']));
}, 1);
/* ------------------------------------------------------- Showing ads */
/**
* Is this the address of Diretsa's ad server script? Only https addresses on
* diretsa.com (or its subdomains) are loaded.
*/
function diretsa_is_ad_script_url($url) {
$parts = wp_parse_url($url);
if (empty($parts['scheme']) || 'https' !== $parts['scheme'] || empty($parts['host'])) {
return false;
}
$host = strtolower($parts['host']);
return 'diretsa.com' === $host || '.diretsa.com' === substr($host, -12);
}
/**
* The ad slot for a placement: Diretsa's ad server fills each element
* with the ad booked for that zone. The markup is built here from the zone
* numbers Diretsa sends, and the ad server's script is loaded with
* wp_enqueue_script(), so no HTML or script from the API is printed.
*/
function diretsa_render_ad($product_id) {
$product_id = sanitize_text_field((string) $product_id);
$p = $product_id ? diretsa_placement($product_id) : null;
$zones = ($p && !empty($p['ad']) && is_array($p['ad'])) ? $p['ad'] : array();
$slots = '';
foreach ($zones as $zone) {
$zone_id = isset($zone['zone_id']) ? absint($zone['zone_id']) : 0;
$revive_id = isset($zone['revive_id']) ? preg_replace('/[^a-f0-9]/', '', strtolower((string) $zone['revive_id'])) : '';
$script = isset($zone['script_url']) ? (string) $zone['script_url'] : '';
if (!$zone_id || 32 !== strlen($revive_id) || !diretsa_is_ad_script_url($script)) {
continue;
}
$slots .= sprintf('', $zone_id, esc_attr($revive_id));
if (!wp_script_is('diretsa-ads', 'enqueued')) {
wp_enqueue_script('diretsa-ads', esc_url_raw($script), array(), null, array('in_footer' => true, 'strategy' => 'async')); // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion -- the ad server's script, versioned by the ad server.
}
}
if ('' === $slots) {
return current_user_can('manage_options')
/* translators: %s: the placement ID used in the shortcode or block. */
? ''
: '';
}
$size = isset($p['size']) ? sanitize_html_class($p['size']) : '';
return '
' . $slots . '
';
}
add_shortcode('diretsa_ad', function ($atts) {
$atts = shortcode_atts(array('id' => ''), $atts, 'diretsa_ad');
return diretsa_render_ad($atts['id']);
});
/** Block: "Diretsa ad". Rendered on the server so the tag always comes from the cache. */
add_action('init', function () {
wp_register_script('diretsa-block', plugins_url('assets/block.js', __FILE__), array('wp-blocks', 'wp-element', 'wp-components', 'wp-block-editor', 'wp-i18n'), DIRETSA_VERSION, true);
register_block_type('diretsa/ad', array(
'api_version' => 2,
'editor_script' => 'diretsa-block',
'attributes' => array('placement' => array('type' => 'string', 'default' => '')),
'render_callback' => function ($attributes) {
return diretsa_render_ad(isset($attributes['placement']) ? $attributes['placement'] : '');
},
));
});
add_action('enqueue_block_editor_assets', function () {
$site = diretsa_site();
$options = array();
foreach ((isset($site['placements']) ? $site['placements'] : array()) as $p) {
if (!empty($p['ad'])) {
$options[] = array('value' => $p['product_id'], 'label' => $p['name'] . ' (' . $p['size'] . ')');
}
}
wp_localize_script('diretsa-block', 'diretsaPlacements', $options);
});
/** Classic widget: "Diretsa ad". */
class Diretsa_Ad_Widget extends WP_Widget {
public function __construct() {
parent::__construct('diretsa_ad', __('Diretsa ad', 'diretsa'), array('description' => __('Shows one of your Diretsa ad placements.', 'diretsa')));
}
public function widget($args, $instance) {
$html = diretsa_render_ad(isset($instance['placement']) ? $instance['placement'] : '');
if ($html !== '') {
echo $args['before_widget'] . $html . $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- before/after_widget come from the theme; $html is built from escaped parts in diretsa_render_ad().
}
}
public function form($instance) {
$current = isset($instance['placement']) ? $instance['placement'] : '';
$site = diretsa_site();
echo '
';
echo '
';
}
public function update($new, $old) {
return array('placement' => sanitize_text_field(isset($new['placement']) ? $new['placement'] : ''));
}
}
add_action('widgets_init', function () {
register_widget('Diretsa_Ad_Widget');
});
/* ------------------------------------------------------------- Admin */
add_action('admin_menu', function () {
add_options_page(__('Diretsa', 'diretsa'), __('Diretsa', 'diretsa'), 'manage_options', 'diretsa', 'diretsa_settings_page');
});
add_filter('plugin_action_links_' . plugin_basename(__FILE__), function ($links) {
array_unshift($links, '' . esc_html__('Settings', 'diretsa') . '');
return $links;
});
/** Handle the settings page's buttons (connect, refresh, verify, disconnect). */
add_action('admin_post_diretsa', function () {
if (!current_user_can('manage_options')) {
wp_die(esc_html__('You are not allowed to do this.', 'diretsa'));
}
check_admin_referer('diretsa_action');
$action = isset($_POST['diretsa_action']) ? sanitize_key(wp_unslash($_POST['diretsa_action'])) : '';
$notice = '';
$type = 'success';
if ($action === 'connect') {
$key = isset($_POST['diretsa_key']) ? trim(sanitize_text_field(wp_unslash($_POST['diretsa_key']))) : '';
if (strpos($key, 'dwp_') !== 0) {
$notice = __('That is not a Diretsa connection key. It starts with dwp_ and is shown once when you create it in Media Control.', 'diretsa');
$type = 'error';
} else {
$data = diretsa_refresh($key);
if (is_wp_error($data)) {
$notice = $data->get_error_message();
$type = 'error';
} else {
update_option('diretsa_key', $key, false);
/* translators: %s: the site's name in Diretsa. */
$notice = sprintf(__('Connected to %s.', 'diretsa'), $data['site']['name']);
}
}
} elseif ($action === 'refresh') {
$data = diretsa_refresh();
$notice = is_wp_error($data) ? $data->get_error_message() : __('Placements and ad tags updated.', 'diretsa');
$type = is_wp_error($data) ? 'error' : 'success';
} elseif ($action === 'verify') {
$r = diretsa_api('POST', '/wp/v1/verify');
if (is_wp_error($r)) {
$notice = $r->get_error_message();
$type = 'error';
} elseif (!empty($r['verified'])) {
diretsa_refresh();
$notice = __('Your site is verified. You can now add placements in Media Control and they will appear here.', 'diretsa');
} else {
$notice = __('Diretsa could not find the verification tag yet. If you use a caching plugin, clear its cache, then try again.', 'diretsa');
$type = 'warning';
}
} elseif ($action === 'disconnect') {
delete_option('diretsa_key');
delete_option('diretsa_site');
delete_option('diretsa_site_fetched');
delete_transient('diretsa_earnings');
$notice = __('Disconnected. Ads from Diretsa no longer appear on this site. Revoke the key in Media Control too.', 'diretsa');
}
set_transient('diretsa_notice_' . get_current_user_id(), array('text' => $notice, 'type' => $type), 60);
wp_safe_redirect(admin_url('options-general.php?page=diretsa'));
exit;
});
/** Earnings for the last 30 days, cached for an hour. */
function diretsa_earnings() {
$cached = get_transient('diretsa_earnings');
if (is_array($cached)) {
return $cached;
}
$data = diretsa_api('GET', '/wp/v1/earnings');
if (!is_wp_error($data)) {
set_transient('diretsa_earnings', $data, HOUR_IN_SECONDS);
}
return $data;
}
function diretsa_rand($n) {
return 'R' . number_format((float) $n, 2, '.', ' ');
}
function diretsa_earnings_box() {
$e = diretsa_earnings();
if (is_wp_error($e)) {
echo '
' . esc_html__('Connect your site', 'diretsa') . '
';
/* translators: %s: link to Diretsa Media Control. */
echo '
' . wp_kses_post(sprintf(__('Sign in to Diretsa Media Control. Add this site under My sites if it is not there yet.', 'diretsa'), 'https://diretsa.com/publisher/sites')) . '
';
echo '
' . esc_html__('Open the site and choose Connect WordPress. Copy the connection key (it starts with dwp_).', 'diretsa') . '
';
echo '
' . esc_html__('Paste it here and choose Connect.', 'diretsa') . '
', esc_html(sprintf(/* translators: 1: this site's host name, 2: the domain the key was made for. */ __('This WordPress site is %1$s but the key is for %2$s. Ads and verification only work on the site the key was made for.', 'diretsa'), $host, $site['domain'])));
}
echo '
' . esc_html__('Verification', 'diretsa') . '
';
if (!empty($site['verified'])) {
echo '
✓ ' . esc_html__('Verified: Diretsa has confirmed you own this site.', 'diretsa') . '
';
} else {
echo '
' . esc_html__('The plugin has added Diretsa\'s verification tag to your home page. Choose Check verification to let Diretsa confirm it.', 'diretsa') . '