<?php
use BrizyPlaceholders\ContentPlaceholder;
use BrizyPlaceholders\ContextInterface;
class BrizyPro_Content_Placeholders_PostLoop extends Brizy_Content_Placeholders_Abstract
{
/**
* BrizyPro_Content_Placeholders_PostLoop constructor.
*
* @param string $label
* @param string $placeholder
*
* @throws Exception
*/
public function __construct($label, $placeholder)
{
$this->setLabel($label);
$this->setPlaceholder($placeholder);
$this->setDisplay(self::DISPLAY_BLOCK);
$this->setGroup(null);
}
private function getDynamicContentConfig(Brizy_Content_Context $context)
{
$provider = new Brizy_Content_PlaceholderProvider($context);
return $provider->getGroupedPlaceholders();
}
/**
* @param ContextInterface $context
* @param ContentPlaceholder $contentPlaceholder
* @return false|mixed|string
*/
public function getValue(ContextInterface $context, ContentPlaceholder $contentPlaceholder)
{
$attributes = $contentPlaceholder->getAttributes();
$attributes = array_map( function ( $value ) {
return html_entity_decode( $value, ENT_QUOTES );
}, $attributes );
$posts = $this->getPosts($attributes);
$globalProduct = isset($GLOBALS['product']) ? $GLOBALS['product'] : null;
$content = '';
// that is bad.. but there is no easy way to return ids instead of content
if (isset($attributes['content_type']) && $attributes['content_type'] === 'json') {
return json_encode([
'collection' => $posts,
'config' => ['*' => ['dynamicContent' => $this->getDynamicContentConfig($context)]]
]);
}
//$placeholderProvider = new Brizy_Content_PlaceholderProvider( $context );
//$extractor = new \BrizyPlaceholders\Extractor( $context->getProvider() );
//list( $contentPlaceholders, $placeholderInstances, $newContent ) = $extractor->extract( $content );
$replacer = new \BrizyPlaceholders\Replacer($context->getProvider());
foreach ((array)$posts as $postId) {
// this method will initialize the WP_Post instance avoiding the adding it to cache
// this way we avoid huge memory usage..
$post = $this->getWpPostInstance($postId);
if (!$post) continue;
if ('product' === $post->post_type) {
$GLOBALS['product'] = wc_get_product($post);
}
$newContext = Brizy_Content_ContextFactory::createContext($context->getProject(), null, $post, null, true);
$newContext->setProvider($context->getProvider());
Brizy_Content_ContextFactory::makeContextGlobal($newContext);
$content .= $replacer->replacePlaceholders($contentPlaceholder->getContent(), $newContext);
Brizy_Content_ContextFactory::clearGlobalContext();
}
if (isset($GLOBALS['product'])) {
unset($GLOBALS['product']);
if ($globalProduct) {
$GLOBALS['product'] = $globalProduct;
}
}
$content = do_shortcode($content);
return $content;
}
protected function getWpPostInstance($id)
{
global $wpdb;
$_post = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->posts WHERE ID = %d LIMIT 1", $id));
if (!$_post) {
return false;
}
$_post = sanitize_post($_post, 'raw');
return new WP_Post($_post);
}
/**
* @return mixed|string
*/
protected function getOptionValue()
{
return $this->getReplacePlaceholder();
}
/**
* @param $attributes
*
* @return array
*/
protected function getPosts($attributes)
{
$paged = $this->getPageVar();
// avoid flooding the cache
$query = null;
if (isset($attributes['query']) && !empty($attributes['query'])) {
$params = array(
'fields' => 'ids',
'posts_per_page' => isset($attributes['count']) ? $attributes['count'] : 3,
'orderby' => isset($attributes['orderby']) ? $attributes['orderby'] : 'none',
'order' => isset($attributes['order']) ? $attributes['order'] : 'ASC',
'post_type' => isset($attributes['post_type']) ? $attributes['post_type'] : array_keys(get_post_types(['public' => true])),
'paged' => $paged,
);
$wpParseArgs = wp_parse_args($attributes['query']);
$params = array_merge($params, $wpParseArgs);
} else {
global $wp_query;
$params = $wp_query->query_vars;
$params['fields'] = 'ids';
$params['orderby'] = isset($attributes['orderby']) ? $attributes['orderby'] : (isset($params['orderby']) ? $params['orderby'] : null);
$params['order'] = isset($attributes['order']) ? $attributes['order'] : (isset($params['order']) ? $params['order'] : null);
$params['posts_per_page'] = isset($attributes['count']) ? (int)$attributes['count'] : (isset($params['posts_per_page']) ? $params['posts_per_page'] : null);
$params['post__not_in'] = array_merge((array)$params['post__not_in'],isset($attributes['post__not_in']) ? explode(',',$attributes['post__not_in']) : []);
$params['post__in'] = array_merge((array)$params['post__in'],isset($attributes['post__in']) ? explode(',',$attributes['post__in']) : []);
//$params['post_type'] = isset($attributes['post_type']) ? $attributes['post_type'] : (isset($params['post_type']) ? $params['post_type'] : null);
$params['paged'] = (int)$paged;
}
if (isset($attributes['offset']) && $attributes['offset'] > 0) {
$ids = $this->getOffsetPostIds($params, $attributes['offset']);
$params['post__not_in'] = array_merge(isset($params['post__not_in']) ? $params['post__not_in'] : [], $ids);
}
$params = apply_filters('brizy_post_loop_args', $params);
$query = new WP_Query($params);
$posts = $query->posts;
wp_reset_postdata();
unset($query);
return $posts;
}
/**
* @return int|mixed
*/
private function getPageVar()
{
if ($paged = get_query_var(self::getPaginationKey())) {
return (int)$paged;
}
return 1;
}
/**
* Return the pagination key. bpage is the default value.
*
* @return mixed|void
*/
public static function getPaginationKey()
{
return apply_filters('brizy_postloop_pagination_key', 'bpage');
}
private function getOffsetPostIds($params, $offset)
{
$params['posts_per_page'] = $offset;
$params['paged'] = 1;
$query = new WP_Query($params);
$ids = $query->posts;
unset($query);
return $ids;
}
}