soberwp/controller

Lifecycle / hook for when the_post is available

OwenMelbz opened this issue · 10 comments

Hi - currently we have 2 hooks for __before and __after however it would be good to have a hook available once the post was ready.

For example it means you could do something like

public function __content_ready()
{
    $indexer = new Indexer(get_the_content());
}

Normally you'd do something like this in a __construct but as this fires before everything is booted.

Does this make sense?

I can look into getting a __ready hook added for the next release.

@OwenMelbz I'm looking at getting this added, but before I do, can you give me a use-case for this? Could the same not be achieved with __after() as all the data is loaded then?

This might be achievable with the __after() but we couldnt see how :D

So the situation we had was that we needed to access the HTML from the_content THEN set a variable for the template. e.g. so it was something like

PageController {

public function __construct(ContentManipulator $manipulator)
    $this->manipulator = $manipulator;
}

public function __ready()
{
    $this->manipulator->setOriginalContent(get_the_content());
}

public function manipulatedContent()
{
    return $this->manipulator->getManipulatedContent();
}

public function extras()
{
    return $this->manipulator->getExtrasFromContent();
}

}

So in our blade template we can then use $manipulated_content rather than the_content and we also get $extras.

The reason we had to do this was because in the CMS there it the WordPress WYSIWYG - the client adds various content such as:

<h2>Section 1</h2>
<p>Para</p>

<h2>Section 2</h2>
<p>Para</p>

<h2>Section 3</h2>
<p>Para</p>

The content manipulator modifies the markup into

<h2 id="section-1">Section 1</h2>
<p>Para</p>

<h2 id="section-2">Section 2</h2>
<p>Para</p>

<h2 id="section-3">Section 3</h2>
<p>Para</p>

it also returns an array of those sections e.g.

$extras = [
[
    "label" => "Section 1",
    "anchor" => "section-1"
],
[
    "label" => "Section 2",
    "anchor" => "section-2"
],
[
    "label" => "Section 3",
    "anchor" => "section-3"
]
];

So then we have a sidebar with all the sections with jump links, and the main content in the middle.

Tadaaa?!

You could use after(), for example;

    public function __after()
    {
        $content = $this->data['post']->post_content;
        $this->manipulator->setOriginalContent($content);
        $this->data['post']->post_content = $this->manipulator->getManipulatedContent();
    }

This would overwrite the existing post_content content.

I could include __ready() in which case, $this->data['post'] would be available in Controller, but I'm not sure how widely it would be used.

You could also include the following in __construct and use the other functions as you have them.

$this->manipulator->setOriginalContent(get_post()->post_content);

Does get_post()->post_content have all the filters applied? or raw

I think it's raw, but you can apparently do this to apply filters;

$post = get_post();
$output = apply_filters('the_content', get_post()->post_content);

If you want a one liner;

$this->manipulator->setOriginalContent(apply_filters('the_content', get_post()->post_content));

Right lol - I think this is why I came to the conclusion that it started to get quite messy.

Personally I feel the example I provided is clean and descriptive which is why I was hoping we could use the hooks more effectively

So there's one of two improvements I could make.

I could either create $this->post with all $post object, which would be easy to get title, permalink, content, etc. (eg. $this->post->post_title)

Or I could use setup_postdata($post) to make the hooks work. I guess this would be more inline with what users are used too, and would make your example above work. It just feels nasty, but that's WP I guess.

Having testing more, get_the_content() is the only function that has an issue running in a controller. get_the_title(), get_permalink(), etc all work as expected. So this is looking pretty edge-case. Going to close for now.