/**
  * Simple wp ajax interface for ad selection.
  *
  * Provides a single ad given ID and selection method.
  */
 public function advads_ajax_ad_select()
 {
     // set proper header
     header('Content-Type: application/json; charset: utf-8');
     // allow modules / add ons to test (this is rather late but should happen before anything important is called)
     do_action('advanced-ads-ajax-ad-select-init');
     // init handlers
     $selector = Advanced_Ads_Select::get_instance();
     $methods = $selector->get_methods();
     $method = isset($_REQUEST['ad_method']) ? (string) $_REQUEST['ad_method'] : null;
     $id = isset($_REQUEST['ad_id']) ? (string) $_REQUEST['ad_id'] : null;
     $arguments = isset($_REQUEST['ad_args']) ? $_REQUEST['ad_args'] : array();
     if (is_string($arguments)) {
         $arguments = stripslashes($arguments);
         $arguments = json_decode($arguments, true);
     }
     $adIds = isset($_REQUEST['ad_ids']) ? $_REQUEST['ad_ids'] : null;
     if (is_string($adIds)) {
         $adIds = json_decode($adIds, true);
     }
     $response = array();
     if (isset($methods[$method]) && isset($id)) {
         $advads = Advanced_Ads::get_instance();
         if (is_array($adIds)) {
             // ads loaded previously and passed by query
             $advads->current_ads += $adIds;
         }
         $l = count($advads->current_ads);
         // build content
         $content = $selector->get_ad_by_method($id, $method, $arguments);
         $adIds = array_slice($advads->current_ads, $l);
         // ads loaded by this request
         $response = array('status' => 'success', 'item' => $content, 'id' => $id, 'method' => $method, 'ads' => $adIds);
     } else {
         // report error
         $response = array('status' => 'error', 'message' => 'No valid ID or METHOD found.');
     }
     echo json_encode($response);
     die;
 }
 /**
  * inject ads directly into the content
  *
  * @since 1.2.1
  * @param string $placement_id id of the placement
  * @param arr $options placement options
  * @param string $content
  * @return type
  * @link inspired by http://www.wpbeginner.com/wp-tutorials/how-to-insert-ads-within-your-post-content-in-wordpress/
  */
 public static function &inject_in_content($placement_id, $options, &$content)
 {
     /*
      * hot-fixed to support some tags under idealised conditions.
      * this does ignore:
      * - autop() messups
      * - nesting of any kind
      * - non-valid XHTML (i.e. wild HTML)
      *
      * 'after' is experimental as the concept requires DOM and is not fully deterministic across implementations.
      * it falls back to 'before' n+1-th element or 'after' closing tag of the n-th.
      */
     $tag = isset($options['tag']) ? $options['tag'] : 'p';
     $position = isset($options['position']) ? $options['position'] : 'after';
     $paragraph_id = isset($options['index']) ? $options['index'] : 1;
     $offset = 0;
     $insertAt = null;
     // sanitise
     $tag = preg_quote(strtolower($tag), '`');
     $before = $position !== 'after';
     $paragraph_id = max(1, (int) $paragraph_id);
     // detect n-th tag
     $matches = array();
     while (1 === preg_match("`<{$tag}(?=[ >/])(?:[^>]+/>|.+?(?:</{$tag}\\s*>|(?=<{$tag}(?=[ >/])|\$)))`Ssi", $content, $matches, PREG_OFFSET_CAPTURE, $offset)) {
         $offset = $matches[0][1];
         // skip empty
         // -TODO should only ignore whitespaces, not all special chars
         if ('' === preg_replace('/&[a-z0-9#]+;|\\s+/i', '', strip_tags(htmlspecialchars($matches[0][0])))) {
             continue;
         }
         $paragraph_id--;
         if ($paragraph_id <= 0) {
             $insertAt = $before ? $offset : $offset + strlen($matches[0][0]);
             break;
         }
         // start at next offset
         $offset += strlen($matches[0][0]);
     }
     if (isset($insertAt)) {
         $ad_content = Advanced_Ads_Select::get_instance()->get_ad_by_method($placement_id, 'placement', $options);
         if ($insertAt === false) {
             $content .= $ad_content;
             // fallback: end-of-content
         } else {
             $content = substr($content, 0, $insertAt) . $ad_content . substr($content, $insertAt);
         }
         return $content;
     }
     return $content;
 }
 /**
  * injected ad into content (before and after)
  * displays ALL ads
  *
  * @since 1.1.0
  * @param str $content post content
  */
 public function inject_content($content = '')
 {
     // run only within the loop on single pages of public post types
     $public_post_types = get_post_types(array('public' => true, 'publicly_queryable' => true), 'names', 'or');
     // check if admin allows injection in all places
     $options = $this->plugin->options();
     if (!isset($options['content-injection-everywhere'])) {
         // check if this is a singular page within the loop
         if (!is_singular($public_post_types) || !in_the_loop()) {
             return $content;
         }
     }
     $placements = get_option('advads-ads-placements', array());
     if (!apply_filters('advanced-ads-can-inject-into-content', true, $content, $placements)) {
         return $content;
     }
     foreach ($placements as $_placement_id => $_placement) {
         if (empty($_placement['item']) || !isset($_placement['type'])) {
             continue;
         }
         $_options = isset($_placement['options']) ? $_placement['options'] : array();
         switch ($_placement['type']) {
             case 'post_top':
                 // TODO broken: does not serve placement but serves ad directly
                 $content = Advanced_Ads_Select::get_instance()->get_ad_by_method($_placement_id, Advanced_Ads_Select::PLACEMENT, $_options) . $content;
                 break;
             case 'post_bottom':
                 $content .= Advanced_Ads_Select::get_instance()->get_ad_by_method($_placement_id, Advanced_Ads_Select::PLACEMENT, $_options);
                 break;
             case 'post_content':
                 $content = Advanced_Ads_Placements::inject_in_content($_placement_id, $_options, $content);
                 break;
         }
     }
     return $content;
 }
Beispiel #4
0
 /**
  * inject ads directly into the content
  *
  * @since 1.2.1
  * @param string $placement_id id of the placement
  * @param arr $options placement options
  * @param string $content
  * @return type
  * @link inspired by http://www.wpbeginner.com/wp-tutorials/how-to-insert-ads-within-your-post-content-in-wordpress/
  */
 public static function &inject_in_content($placement_id, $options, &$content)
 {
     // test ad is emtpy
     $whitespaces = json_decode('"\\t\\n\\r \\u00A0"');
     $adContent = Advanced_Ads_Select::get_instance()->get_ad_by_method($placement_id, 'placement', $options);
     if (trim($adContent, $whitespaces) === '') {
         return $content;
     }
     // parse document as DOM (fragment - having only a part of an actual post given)
     // -TODO may want to verify the wpcharset is supported by server (mb_list_encodings)
     // prevent messages from dom parser
     $wpCharset = get_bloginfo('charset');
     // check if mbstring exists
     if (!function_exists('mb_convert_encoding')) {
         if ($wpCharset === "UTF-8") {
             $content = htmlspecialchars_decode(htmlentities($content, ENT_COMPAT, $wpCharset, false));
         } else {
             return $content;
         }
     } else {
         $content = mb_convert_encoding($content, 'HTML-ENTITIES', $wpCharset);
     }
     // check which priority the wpautop filter has; might have been disabled on purpose
     $wpautop_priority = has_filter('the_content', 'wpautop');
     if ($wpautop_priority && Advanced_Ads_Plugin::get_instance()->get_content_injection_priority() < $wpautop_priority) {
         $content = wpautop($content);
     }
     $dom = new DOMDocument('1.0', $wpCharset);
     // may loose some fragments or add autop-like code
     libxml_use_internal_errors(true);
     // avoid notices and warnings - html is most likely malformed
     $success = $dom->loadHtml('<!DOCTYPE html><html><meta http-equiv="Content-Type" content="text/html; charset=' . $wpCharset . '" /><body>' . $content);
     libxml_use_internal_errors(false);
     if ($success !== true) {
         // -TODO handle cases were dom-parsing failed (at least inform user)
         return $content;
     }
     // parse arguments
     $tag = isset($options['tag']) ? $options['tag'] : 'p';
     $tag = preg_replace('/[^a-z0-9]/i', '', $tag);
     // simplify tag
     // only has before and after
     $before = isset($options['position']) && $options['position'] === 'before';
     $paragraph_id = isset($options['index']) ? $options['index'] : 1;
     $paragraph_id = max(1, (int) $paragraph_id);
     $paragraph_select_from_bottom = isset($options['start_from_bottom']) && $options['start_from_bottom'];
     // select positions
     $xpath = new DOMXPath($dom);
     $items = $xpath->query('/html/body/' . $tag);
     $offset = null;
     $options = array('allowEmpty' => false);
     // if there are too few items at this level test nesting
     $options['itemLimit'] = $tag === 'p' ? 2 : 1;
     // allow hooks to change some options
     $options = apply_filters('advanced-ads-placement-content-injection-options', $options, $tag);
     if ($items->length < $options['itemLimit']) {
         $items = $xpath->query('/html/body/*/' . $tag);
     }
     // try third level as last resort
     if ($items->length < $options['itemLimit']) {
         $items = $xpath->query('/html/body/*/*/' . $tag);
     }
     // allow to select other elements
     $items = apply_filters('advanced-ads-placement-content-injection-items', $items, $xpath, $tag);
     // filter empty tags from items
     $paragraphs = array();
     foreach ($items as $item) {
         if ($options['allowEmpty'] || isset($item->textContent) && trim($item->textContent, $whitespaces) !== '') {
             $paragraphs[] = $item;
         }
     }
     $paragraph_count = count($paragraphs);
     if ($paragraph_count >= $paragraph_id) {
         $offset = $paragraph_select_from_bottom ? $paragraph_count - $paragraph_id : $paragraph_id - 1;
         // convert HTML to XML!
         $adDom = new DOMDocument('1.0', $wpCharset);
         libxml_use_internal_errors(true);
         $adDom->loadHtml('<!DOCTYPE html><html><meta http-equiv="Content-Type" content="text/html; charset=' . $wpCharset . '" /><body>' . $adContent);
         $adNode = $adDom->lastChild->lastChild;
         // >html>body
         libxml_use_internal_errors(false);
         $adContent = $adDom->saveXML($adNode);
         $adContent = substr($adContent, 6, -7);
         $adNode = $dom->createDocumentFragment();
         $adNode->appendXML($adContent);
         // inject
         $node = apply_filters('advanced-ads-placement-content-injection-node', $paragraphs[$offset], $tag, $before);
         if ($before) {
             $refNode = $node;
             $items = $xpath->query('/html/body/' . $tag);
             $refNode->parentNode->insertBefore($adNode, $refNode);
         } else {
             // append before next node or as last child to body
             $refNode = $node->nextSibling;
             if (isset($refNode)) {
                 $refNode->parentNode->insertBefore($adNode, $refNode);
             } else {
                 // append to body; -TODO using here that we only select direct children of the body tag
                 $paragraphs[$offset]->parentNode->appendChild($adNode);
             }
         }
     }
     // convert to text-representation
     $content = $dom->saveHTML();
     // remove head and tail (required for dom parser but unwanted for content)
     $content = substr($content, stripos($content, '<body>') + 6);
     $content = str_replace(array('</body>', '</html>'), '', $content);
     // no fall-back desired: if there are too few paragraphs do nothing
     // fix shortcode quotes (malformed by backend editor)
     $matches = array();
     if (0 < preg_match_all('/\\[[^]]+\\]/Siu', $content, $matches, PREG_OFFSET_CAPTURE) && isset($matches[0])) {
         foreach ($matches[0] as $match) {
             $offset = $match[1];
             $content = substr($content, 0, $offset) . str_replace(array('“', '″', '&#8220;', '&quote;', '&#8243;'), '"', $match[0]) . substr($content, $offset + strlen($match[0]));
         }
     }
     return $content;
 }
Beispiel #5
0
 /**
  * control the output of the group by type and amount of ads
  *
  * @since 1.4.8
  * @return str $output output of ad(s) by ad
  */
 public function output()
 {
     if (!$this->id) {
         return;
     }
     // load ads
     $ads = $this->load_all_ads();
     if ($ads === array()) {
         return;
     }
     // get ad weights serving as an order here
     $weights = $this->get_ad_weights();
     asort($weights);
     // if ads and weights don’t have the same keys, update weights array
     if (count($weights) == 0 && count($ads) > 0 || count($weights) != count($ads) || array_diff_key($weights, $ads) != array() || array_diff_key($ads, $weights) != array()) {
         $this->update_ad_weights();
         $weights = $this->ad_weights;
     }
     // remove ads with 0 ad weight
     foreach ($weights as $_ad_id => $_ad_weight) {
         if ($_ad_weight === 0) {
             unset($weights[$_ad_id]);
         }
     }
     // order ads based on group type
     switch ($this->type) {
         case 'ordered':
             // order to highest weight first
             arsort($weights);
             $ordered_ad_ids = array_keys($weights);
             break;
         default:
             // default
             $ordered_ad_ids = $this->shuffle_ads($ads, $weights);
     }
     $ordered_ad_ids = apply_filters('advanced-ads-group-output-ad-ids', $ordered_ad_ids, $this->type, $ads, $weights);
     // load the ad output
     $output = array();
     $ads_displayed = 0;
     $ad_count = apply_filters('advanced-ads-group-ad-count', $this->ad_count, $this);
     $ad_select = Advanced_Ads_Select::get_instance();
     foreach ($ordered_ad_ids as $_ad_id) {
         // load the ad object
         $ad = $ad_select->get_ad_by_method($_ad_id, Advanced_Ads_Select::AD, $this->ad_args);
         if ($ad !== null) {
             $output[] = $ad;
             $ads_displayed++;
             // break the loop when maximum ads are reached
             if ($ads_displayed === $ad_count) {
                 break;
             }
         }
     }
     // add the group to the global output array
     $advads = Advanced_Ads::get_instance();
     $advads->current_ads[] = array('type' => 'group', 'id' => $this->id, 'title' => $this->name);
     // filter grouped ads output
     $output_string = implode('', apply_filters('advanced-ads-group-output-array', $output, $this));
     // filter final group output
     return apply_filters('advanced-ads-group-output', $output_string, $this);
 }
/**
 * return content of an ad placement
 *
 * @since 1.1.0
 * @param string $id slug of the ad placement
 *
 */
function get_ad_placement($id = '')
{
    return Advanced_Ads_Select::get_instance()->get_ad_by_method($id, 'placement');
}
 /**
  * control the output of the group by type and amount of ads
  *
  * @since 1.4.8
  * @param array/null ordered_ad_ids ordered ids of the ads that belong to the group
  * @return str $output output of ad(s) by ad
  */
 public function output($ordered_ad_ids = false)
 {
     // if $ordered_ad_ids was not passed to the function, load it
     $ordered_ad_ids = $ordered_ad_ids === false ? $this->get_ordered_ad_ids() : $ordered_ad_ids;
     if ($ordered_ad_ids === null) {
         return;
     }
     // load the ad output
     $output = array();
     $ads_displayed = 0;
     $ad_count = apply_filters('advanced-ads-group-ad-count', $this->ad_count, $this);
     $ad_select = Advanced_Ads_Select::get_instance();
     foreach ($ordered_ad_ids as $_ad_id) {
         // load the ad object
         $ad = $ad_select->get_ad_by_method($_ad_id, Advanced_Ads_Select::AD, $this->ad_args);
         if ($ad !== null) {
             $output[] = $ad;
             $ads_displayed++;
             // break the loop when maximum ads are reached
             if ($ads_displayed === $ad_count) {
                 break;
             }
         }
     }
     // add the group to the global output array
     $advads = Advanced_Ads::get_instance();
     $advads->current_ads[] = array('type' => 'group', 'id' => $this->id, 'title' => $this->name);
     // filter grouped ads output
     $output_string = implode('', apply_filters('advanced-ads-group-output-array', $output, $this));
     // filter final group output
     return apply_filters('advanced-ads-group-output', $output_string, $this);
 }