Wrong plug-in rendering format event called

« Publish or Depreciate Comments :: b2evolution seems to create invalid XHTML for empty bloglist »
Author Message
kwa
Posted: Mon Feb 12, 2007 05:25     Topic subject: Wrong plug-in rendering format event called

I'm developing a very simple video plug-in with both HTML and XML rendering. In the HTML format, the video is inserted to the post. In the XML format, a "click here to see the video" link is inserted instead.

My plug-in implements the following event handlers:

RenderItemAsHtml()
RenderItemAsXml()

Those functions implementation (two lines of code, it could not have been simplier) does not include a call to the other one. I mean: the encountered bug does not appear to come from the plug-in itself.

It appears the XML rendering format is used to display HTML pages on random basis.

I haven't investigated furthermore, but I assume the issue comes from the rendering cache.

Back to top
 
kwa
Posted: Thu Feb 15, 2007 22:37

I'm not very familiar with the plug-in's cache, but it appears rendered content is cached as is without taking into account the rendering format.

Does anyone know how to deactivate the plug-ins' cache?

Back to top
 
blueyed
Posted: Wed Feb 21, 2007 19:56

Do you mean that sometimes the content in the blog itself was displayed as what should have been in the feeds instead? Have you emptied the pre-rendering cache in the mean time? Or edited the item?

I've experienced this bug myself with the YouTube plugin maybe: sometimes the youtube-tag was not rendered - I had to forcefully clear the cache (in "Tools").

The rendering format _should_ get taken into account however (and the youtube plugin uses the same method for XML and HTML).

It may be fixed in the 1.9.x branch - at least I have not experienced it in a while - but what I just thought that may have fixed it should be in the 1.9.2 release already.

At least there's a format column in the T_item__prerendering table.

You might want to take a look at Item::get_prerendered_content() (in blogs/inc/MODEL/items/_item.class.php) where all this stuff happens.
There you could also force to disable the cache (which is a item cache rather than a plugin cache), by setting $use_cache = false instead of the "$use_cache-detection".

edit: Can you provide your plugin as a testcase?

Back to top
 
kwa
Posted: Wed Feb 21, 2007 23:35

Thanks for your answer, blueyed! I'm going to investigate that strange behavior again tomorrow. (I've experienced both seeing HTML rendering format in XML and XML in HTML, however, since the HTML is accessed much more frequently, the XML format contains HTML rendering in most cases.)

Back to top
 
blueyed
Posted: Wed Feb 21, 2007 23:59

What do you mean with "XML"?

I've meant to say that the feeds are mostly displayed as "HTML". At least the content part e.g. in Atom feeds.

The format is rather meant as a hint of output format, not delivery format.

But anyway, the behaviour should be consistent.. ;)

Back to top
 
kwa
Posted: Fri Feb 23, 2007 00:51

Here is a test plug-in (defined by default as 'opt-in', so you have to activate it for your test post):

PHP

<?php
// HTML / XML TEST PLUGIN
// _htmlxml.plugin.php
 
if( !defined('EVO_MAIN_INIT') ) die'Please, do not access this page directly.' );
 
class HtmlXml_plugin extends Plugin
{
    var $name 'Html / Xml Plugin';
    var $code 'b2eHtmlXml';
    var $priority 100;
    var $version '0.4';
    var $author 'kwa';
    var $help_url '';  // empty URL defaults to manual wiki, in this case: http://manual.b2evolution.net/Plugins/test_plugin';
    
    /*
     * These variables MAY be overriden.
     */
    var $apply_rendering 'opt-in';
    var $number_of_installs 1;
    var $group 'rendering';
    
    var $short_desc;
    var $long_desc;
 
    function PluginInit( & $params )
    {
        $this->short_desc T_'HTML / XML rendering test plugin.' );
        $this->long_desc T_'This plug-in is a simple test, nothing else.' );
    }
 
    function RenderItemAsHtml( & $params )
    {
        $params['data'] = 'RenderItemAsHtml() '.$params['data'];
    }
 
 
    /**
     * Perform rendering
     */
    function RenderItemAsXml( & $params )
    {
        $params['data'] = 'RenderItemAsXml() '.$params['data'];
    }
}
 
/*
 nolog */
?>

It is intended to:

  • add the text "RenderItemAsXml()" at the beginning of each post where the RenderItemAsXml() function has been called;
  • [*]add the text "RenderItemAsHtml()" at the beginning of each post where the RenderItemAsHtml() function has been called.[/list:u]

Back to top
 
kwa
Posted: Fri Feb 23, 2007 01:02

After installing the Html / Xml Plugin, then writing a test post with the plugin activated, I've done the following:

  • test #1:
    • flushed the rendering cache;
    • displayed the RSS2 feed version of the blog;
    • read the result: "RenderItemAsXml()";[/list:u]
    • test #2:
      • flushed the rendering cache;
      • displayed the "standard web" version of the blog;
      • read the result: "RenderItemAsHtml()";[/list:u]
      • test #3:
        • flushed the rendering cache;
        • displayed the RSS2 feed version of the blog;
        • read the result: "RenderItemAsXml()";
        • displayed the "standard web" version of the blog;
        • read the result: "RenderItemAsHtml() RenderItemAsXml()" (BUGGY RESULT);[/list:u]
        • test #4:
          • flushed the rendering cache;
          • displayed the "standard web" version of the blog;
          • read the result: "RenderItemAsHtml()";
          • displayed the RSS2 feed version of the blog;
          • read the result: "RenderItemAsXml()".[/list:u]
          • [/list:u]
            The behavior appears to not be consistent to me between tests #3 and #4.

Back to top
 
kwa
Posted: Fri Feb 23, 2007 01:04

When writing rendering plugins, I've thought that:

  • RenderItemAsXml() is called for feeds versions of the posts only;
  • RenderItemAsHtml() is called for "standard web" versions of the posts only;
  • [*]there is no case where both functions can be called on the same rendering process.[/list:u]Am I wrong?

Back to top
 
blueyed
Posted: Fri Feb 23, 2007 20:13

Yeah! There was a bug. The fix is here: http://evocms.cvs.sourceforge.net/evocms/b2evolution/blogs/inc/MODEL/items/_item.class.php?r1=1.75.2.27&r2=1.75.2.28&pathrev=v-1-9 (you only need the second block).

The problem was that $Item->content got passed by reference and when the feed has been called before the regular html, $Item->content had been changed when it came to the RenderItemAsHtml call.

Thanks for providing a testcase to trigger this down.

It will be fixed in 1.9.3.

Back to top
 
kwa
Posted: Fri Feb 23, 2007 20:34

Yeah! A cool bug fix! Thanks a lot! :-D

Back to top
 
blueyed
Posted: Fri Feb 23, 2007 20:35

Have you confirmed that it works already? :)

Back to top
 
kwa
Posted: Fri Feb 23, 2007 20:40

Err... in fact, not yet. :roll: I'm going to test it tomorrow and come back here to share my discoveries. :p

Back to top
 
kwa
Posted: Sun Feb 25, 2007 04:12

After installing the Html / Xml Plugin, then writing a test post with the plugin activated, I've done the following with the updated _item.class.php:

  • test #1:
    • flushed the rendering cache;
    • displayed the RSS2 feed version of the blog;
    • read the result: "RenderItemAsHtml()" (expected to read "RenderItemAsXml()");[/list:u]
    • test #2:
      • flushed the rendering cache;
      • displayed the "standard web" version of the blog;
      • read the result: "RenderItemAsHtml()";[/list:u]
      • test #3:
        • flushed the rendering cache;
        • displayed the RSS2 feed version of the blog;
        • read the result: "RenderItemAsHtml()" (expected to read "RenderItemAsXml()");
        • displayed the "standard web" version of the blog;
        • read the result: "RenderItemAsHtml();[/list:u]
        • test #4:
          • flushed the rendering cache;
          • displayed the "standard web" version of the blog;
          • read the result: "RenderItemAsHtml()";
          • displayed the RSS2 feed version of the blog;
          • read the result: "RenderItemAsHtml()" (expected to read "RenderItemAsXml()").[/list:u]
          • [/list:u]
            I'm surprised to see the RenderItemAsXml() never called.

Back to top
 
blueyed
Posted: Sun Feb 25, 2007 16:26

I've said this before:
- For most feeds the "html" format gets used, e.g. in the "<content:encoded>" tag of the RSS2 feed
- In the "<description>" tag "xml" gets used for RSS2.

$format is the display format, not the delivery format.

This may be confusing and maybe it's even not logical - but has nothing to do with the original bug.

Looks like it's fixed..

Back to top
 
kwa
Posted: Sun Feb 25, 2007 17:21

Okay. That looks confusing, but I can understand why it is done like this.

However, I have the following issue: I include JavaScript ads in my posts when displayed on the web site. I wish to avoid including them in RSS feeds, since most RSS readers deactivate JavaScript anyway. In some future, I would like to add adds using some other format (images with links appear to be great).

Moreover, since CSS are not included (nor even referenced) by the RSS feeds, I wish to modify the RSS output of my blog. Here too, I would need to have different behavior between both "web site format" and "RSS format".

Can I do so using plug-ins?

Back to top
 
blueyed
Posted: Sun Feb 25, 2007 17:37

You could try looking at the global $skin variable and derive from its value if it's a feed or normal skin.

There should be some better way to handle this in the future.

Maybe the events should rather be RenderItemForFeed and RenderItemForBlog - as an example.

Back to top
 
fplanque
Posted: Sun Feb 25, 2007 18:38

Do we want to introduce some kind of "channel" param to the rendering events?

Values could be 'http' or 'feed'.

We could even give more information like:
'http:custom', 'http:natural_pink', 'feed:_rss2', 'feed:_atom'

Would that work on solving the issue of providing a different rendering based on the channel?

However, this will add an additional key to the cache and make the table grow by the number of different feeds.
Maybe it's not wise to have too much detail about the channel.

Back to top
 
kwa
Posted: Sun Feb 25, 2007 19:08

blueyed wrote:

You could try looking at the global $skin variable and derive from its value if it's a feed or normal skin.

As fplanque notices, the cache is an issue here, since even if I use the $skin variable, the resulting rendering is going to be cached once as HTML rendering without taking into account any "channel" information...

Back to top
 
blueyed
Posted: Sun Feb 25, 2007 19:21

I've believed that RenderItemAsXml would always get used for the feeds and therefor the "format" was used in the event - to avoid triggering a plugin that may only handle XML/feeds.

Instead of having the output format in the event name (like now) we should use the "channel" (http or feed - though feed is also http) therein.

OTOH, now with the item cache in place, it may be the best solution to just have a single RenderItem event (because it gets cached). The only drawback here would be that you can't selectivly disable e.g. the feed rendering of a plugin (through disabling the particular event of the plugin) - but that's not the recommened anyway.

But there are also the DisplayItem* events to get considered: they are not cached and IMHO those should get renamed to have the "channel" in the event name.

Back to top
 
blueyed
Posted: Sun Feb 25, 2007 19:23

kwa wrote:

blueyed wrote:

You could try looking at the global $skin variable and derive from its value if it's a feed or normal skin.

As fplanque notices, the cache is an issue here, since even if I use the $skin variable, the resulting rendering is going to be cached once as HTML rendering without taking into account any "channel" information...

Yeah, you're right. Then using the DisplayItem* hooks should work.

Back to top
 
wil
Posted: Sun Jun 3, 2007 10:37

I was wondering if RenderItemAsXml is not called when processing feeds, what else triggers that event?

I got my plugin to detect whether it's rendering a feed or html by checking if SkinBeginHtmlHead is or isn't called: If it doesn't get called, it doesn't actually mean that it's rendering a feed, rather, it means that styles and scripts are not included (i.e. when feeds are rendered) therefore, my plugin should fallback to "vanilla" rendering which doesn't rely on JavaScript of Stylesheets.

Anyway, back to topic, repeating what is stated earlier: if XXXItemAsXml (and XXXItemAsText too) isn't called when rendering, what does?

Oh yeah, and I noticed that feeds are implemented as skins and their content-calling code is no different from normal skins which probably explains why feeds also get rendered as html? I'm not really one of the developers so I may be, and would be, wrong.

Back to top
 
blueyed
Posted: Sun Jun 3, 2007 19:25

RenderItemAsXml gets used for format "xml", but that is not used in all feeds.
That's somehow a design mistake and it will be fixed in 2.0 - if I remember correctly.

Back to top