0

I'm working through a spec list for a new project which has the following feature:

Display all CPT's from a specific category on an archive page, then insert an advert (CPT) into the loop after every 4th CPT and insert a content block after every 6th CPT.

So basically this layout which repeats itself until all CPT's from a specific category are displayed:

X X X
X A X
C X X

X = custom post type A = advert (another CPT) C = static content

Is this possible with WordPress, and if so, what should be the best way to approach this issue? Already read something about loops within loops and using a $count to insert the content at specific numbers but I've never worked with that before.

3
  • @birgire post injection class might be a good starting point Commented Feb 11, 2016 at 9:35
  • I'm almost 100% sure that, the class as it stands, would be perfect in you scenario as well. You can either download the plugin or add the class in your theme and test it Commented Feb 11, 2016 at 9:40
  • @PieterGoosen thanks for dusting off that answer ;-) Hopefully it can be of any use here.
    – birgire
    Commented Feb 11, 2016 at 10:24

1 Answer 1

1

Depending on what your static content and ad will be, I might be tempted to create a custom post type and add an ads post and a static content post, then use @birgire post injector class to take care of the injection of these two posts where you need them. You might need to alter the injector class a bit to suite your exact needs.

I have quickly written a more generic class (which is very very basic, you should extend this) which you can use to inject any type of string content where you need it. You can (must) improve/modify/ it as you see fit. Note that no data sanitation or validation is done, so you would want to take care of that as well according you your exact need

class MultiInjector
{
    /**
     * @var array $specialContent;
     * @access protected     
     * @since 1.0.0
     */
    protected $specialContent;

    /**
     * @var array $specialContent;
     * @access protected     
     * @since 1.0.0
     */
    protected $arrayValues;

    /**
     * @var array $pairs;
     * @access protected     
     * @since 1.0.0
     */
    protected $pairs;

    /**
     * Constructor
     *
     * @param array $specialContent; = []
     * @since 1.0.0
     */         
    public function __construct( $specialContent = [] )
    {
        $this->specialContent = $specialContent;
    }

    public function init()
    {
        add_action( 'the_post', [$this, 'thePost'] );       
    }

    /**
     * Protected method specialContentValidated()
     *
     * Make sure we have post positions, if not, set defauls. Also, reset
     * all array keys to numeric values
     *
     * @since 1.0.0
     */ 
    protected function specialContentValidated()
    {
        $arrayValues = false;

        if (    $this->specialContent 
             && is_array( $this->specialContent )
        ) {
            $arrayValues = array_values( $this->specialContent );
            // Loop over the array of special content and set defaults if no custom values exist
            foreach ( $arrayValues as $key=>$value ) {
                $defaults = [
                    'content'      => 'This is default content, make sure to set your own',
                    'postPosition' => $key
                ];
                $arrayValues[$key] = wp_parse_args( $value, $defaults );
            }
        }
        $this->arrayValues = $arrayValues;
    }

    /**
     * Protected method positions()
     *
     * Save an array of $key/postPosition pairs
     *
     * @since 1.0.0
     */ 
    protected function positions()
    {
        $this->specialContentValidated();

        $pairs = false;

        if ( $this->arrayValues ) {
            foreach ( $this->arrayValues as $key=>$value )
                $pairs[$key] = $value['postPosition'];
        }

        $this->pairs = $pairs;
    }       

    public function thePost()
    {
        // Make sure this is the main query, if not, bail
        if ( !in_the_loop() )
            return;

        $this->positions();

        // Make sure we have special content to add, if not bail
        if ( false === $this->arrayValues )
            return;

        // Set a static post counter to count the amount of posts
        static $postCount = 0;

        // Search for the post position in the $this->pairs array 
        $position = array_search( $postCount, $this->pairs );
        if ( false !== $position ) {
            // Everything checks out, display our custom content
            echo $this->arrayValues[$position]['content'];
        }

        // Update the counter 
        $postCount++;
    }
}

You can then use it as follow

add_action ( 'wp', function ()
{
    $args = [
        0 => [
                'content' => 'This is my content',
                'postPosition' => 4
            ],
        1 => [
                'content' => 'This is my other content',
                'postPosition' => 6
            ]
    ];
    $q = new MultiInjector( $args );
    $q->init();
});
2
  • 1
    This is neat, sounds like what the OP is looking for.
    – birgire
    Commented Feb 12, 2016 at 11:06
  • Any feedback on this issue? Commented Jul 9, 2016 at 9:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.