config = wp_parse_args($placement_config, [ 'position' => 2, 'location' => 'after_paragraph', 'alignment' => 'default', 'readmore_text' => __('Read More', 'adpagex'), 'target_element' => '', 'show_readmore' => 'no' ]); } /** * Process content - hỗ trợ tất cả vị trí với hoặc không có readmore */ public function process_content($content, $ad_html = '', $placement_config = []) { if (!empty($placement_config)) { $this->set_config($placement_config); } // Kiểm tra có bật readmore không $use_readmore = !empty($this->config['show_readmore']) && $this->config['show_readmore'] === 'yes'; $location = $this->config['location'] ?? 'after_paragraph'; switch ($location) { case 'after_content': return $use_readmore ? $this->insert_after_content_with_readmore($content, $ad_html) : $this->insert_after_content_simple($content, $ad_html); case 'before_content': return $use_readmore ? $this->insert_before_content_with_readmore($content, $ad_html) : $this->insert_before_content_simple($content, $ad_html); case 'after_paragraph': case 'before_paragraph': return $use_readmore ? $this->insert_at_paragraph_with_readmore($content, $ad_html) : $this->insert_at_paragraph_simple($content, $ad_html); case 'after_image': case 'before_image': return $use_readmore ? $this->insert_at_image_with_readmore($content, $ad_html) : $this->insert_at_image_simple($content, $ad_html); case 'after_heading': case 'before_heading': return $use_readmore ? $this->insert_at_heading_with_readmore($content, $ad_html) : $this->insert_at_heading_simple($content, $ad_html); case 'custom_element': return $use_readmore ? $this->insert_at_custom_element_with_readmore($content, $ad_html) : $this->insert_at_custom_element_simple($content, $ad_html); default: return $use_readmore ? $this->insert_at_paragraph_with_readmore($content, $ad_html) : $this->insert_at_paragraph_simple($content, $ad_html); } } // ========================= // SIMPLE INSERTIONS (NO READMORE) // ========================= private function insert_after_content_simple($content, $ad_html) { return $content . $ad_html; } private function insert_before_content_simple($content, $ad_html) { return $ad_html . $content; } private function insert_at_paragraph_simple($content, $ad_html) { $paragraph = max(1, (int)$this->config['position']); $location = $this->config['location']; if ($location === 'before_paragraph') { return $this->insert_before_paragraph_simple($content, $ad_html, $paragraph); } else { return $this->insert_after_paragraph_simple($content, $ad_html, $paragraph); } } private function insert_after_paragraph_simple($content, $ad_html, $paragraph_number) { $closingTag = '
'; $offset = 0; $paragraphs_found = 0; while (($pos = stripos($content, $closingTag, $offset)) !== false) { $paragraphs_found++; if ($paragraphs_found == $paragraph_number) { return substr($content, 0, $pos + strlen($closingTag)) . $ad_html . substr($content, $pos + strlen($closingTag)); } $offset = $pos + strlen($closingTag); } return $content . $ad_html; } private function insert_before_paragraph_simple($content, $ad_html, $paragraph_number) { $pattern = '/]*)>/i';
preg_match_all($pattern, $content, $matches, PREG_OFFSET_CAPTURE);
if (count($matches[0]) >= $paragraph_number) {
$target_paragraph = $matches[0][$paragraph_number - 1];
$insert_pos = $target_paragraph[1];
return substr($content, 0, $insert_pos) . $ad_html . substr($content, $insert_pos);
}
return $content . $ad_html;
}
private function insert_at_image_simple($content, $ad_html)
{
$image_number = max(1, (int)$this->config['position']);
$location = $this->config['location'];
$pattern = '/ nested inside blockquote/figure/li (same as Ad Inserter defaults)
$paragraphs = $xpath->query('//p[normalize-space() != "" and not(ancestor::blockquote) and not(ancestor::figure) and not(ancestor::li)]');
if ($paragraphs->length < $paragraph) {
if ($paragraphs->length === 0) {
return $this->insert_after_content_with_readmore($content, $ad_html);
}
$paragraph = $paragraphs->length;
}
$target_paragraph = $paragraphs->item($paragraph - 1);
if (!$target_paragraph) {
return $this->insert_after_content_with_readmore($content, $ad_html);
}
$readmore_button = $this->build_readmore_button($readmore_id);
// Parse ad HTML as real HTML (not XML) — appendXML fails silently on ]+>/i';
preg_match_all($pattern, $content, $matches, PREG_OFFSET_CAPTURE);
if (count($matches[0]) < $image_number) {
return $content . $ad_html;
}
$target_image = $matches[0][$image_number - 1];
$img_offset = $target_image[1];
$img_length = strlen($target_image[0]);
if ($location === 'before_image') {
$insert_pos = $img_offset;
} else {
$insert_pos = $img_offset + $img_length;
}
return substr($content, 0, $insert_pos) . $ad_html . substr($content, $insert_pos);
}
private function insert_at_heading_simple($content, $ad_html)
{
$heading_number = max(1, (int)$this->config['position']);
$location = $this->config['location'];
$pattern = '/
]+>/i';
preg_match_all($pattern, $content, $matches, PREG_OFFSET_CAPTURE);
if (count($matches[0]) < $image_number) {
if (count($matches[0]) === 0) {
return $this->insert_after_content_with_readmore($content, $ad_html);
}
$image_number = count($matches[0]);
}
$target_image = $matches[0][$image_number - 1];
$img_offset = $target_image[1];
$img_length = strlen($target_image[0]);
$readmore_button = $this->build_readmore_button($readmore_id);
if ($location === 'before_image') {
$insert_pos = $img_offset;
$remaining_content = substr($content, $insert_pos);
} else {
$insert_pos = $img_offset + $img_length;
$remaining_content = substr($content, $insert_pos);
}
return substr($content, 0, $insert_pos) .
$ad_html .
$readmore_button .
'';
}
private function insert_at_heading_with_readmore($content, $ad_html)
{
$heading_number = max(1, (int)$this->config['position']);
$location = $this->config['location'];
$readmore_id = 'adpagex-readmore-' . uniqid();
$pattern = '/