Foren / Cotonti / Core Labs / set metas from standalone plugin

12NächsteLetzte

dervan
#1 24. Februar 2009, 20:18
known problem:
impossible to set metas from standalone plugin

the cause of problem:
header is included and parsed before launching of standalone plugin

possible solution:
header may be included (with pointers technique) after launching of standalone plugin

this solution works without problems in Seditio 121
link (in russian)


code from current system/core/plug/plug.inc.php in trac:
	/* ============= */

	require_once $cfg['system_dir'] . '/header.php';

	$t = new XTemplate($path_skin);

	$extp = array();

	if (is_array($sed_plugins))
	{
		foreach($sed_plugins as $i => $k)
		{
			if ($k['pl_hook']=='standalone' && $k['pl_code']==$e)
			{ $extp[$i] = $k; }
		}
	}

	if (count($extp)==0)
	{
		header("Location: " . SED_ABSOLUTE_URL . sed_url('message', "msg=907", '', true));
		exit;
	}

	if (is_array($extp))
	{ foreach($extp as $k => $pl) { include_once($cfg['plugins_dir'].'/'.$pl['pl_code'].'/'.$pl['pl_file'].'.php'); } }

	if ($autoassigntags)
	{
		$plugin_title = (empty($plugin_title)) ? $L['plu_title'] : $plugin_title;

		if($cfg['homebreadcrumb'])
		{
			$bhome = '<a href="'.$cfg['mainurl'].'">'.sed_cc($cfg['maintitle']).'</a> '.$cfg['separator'].' ';
		}
		else
		{
			$bhome = '';
		}

		$t-> assign(array(
			"PLUGIN_TITLE" => $bhome . '<a href="'.sed_url('plug', "e=$e").'">'.$plugin_title."</a>",
			"PLUGIN_SUBTITLE" => $plugin_subtitle,
			"PLUGIN_BODY" => $plugin_body
		));
	}

	$t->parse("MAIN");
	$t->out("MAIN");

	require_once $cfg['system_dir'] . '/footer.php';


modified code with this solution:
	/* ============= */

	$t_plug = new XTemplate($path_skin);
	$t =& $t_plug;

	$extp = array();

	if (is_array($sed_plugins))
	{
		foreach($sed_plugins as $i => $k)
		{
			if ($k['pl_hook']=='standalone' && $k['pl_code']==$e)
			{ $extp[$i] = $k; }
		}
	}

	if (count($extp)==0)
	{
		header("Location: " . SED_ABSOLUTE_URL . sed_url('message', "msg=907", '', true));
		exit;
	}

	if (is_array($extp))
	{ foreach($extp as $k => $pl) { include_once($cfg['plugins_dir'].'/'.$pl['pl_code'].'/'.$pl['pl_file'].'.php'); } }

	unset($t);
	require_once $cfg['system_dir'] . '/header.php';
	unset($t);
	$t =& $t_plug;

	if ($autoassigntags)
	{
		$plugin_title = (empty($plugin_title)) ? $L['plu_title'] : $plugin_title;

		if($cfg['homebreadcrumb'])
		{
			$bhome = '<a href="'.$cfg['mainurl'].'">'.sed_cc($cfg['maintitle']).'</a> '.$cfg['separator'].' ';
		}
		else
		{
			$bhome = '';
		}

		$t-> assign(array(
			"PLUGIN_TITLE" => $bhome . '<a href="'.sed_url('plug', "e=$e").'">'.$plugin_title."</a>",
			"PLUGIN_SUBTITLE" => $plugin_subtitle,
			"PLUGIN_BODY" => $plugin_body
		));
	}

	$t->parse("MAIN");
	$t->out("MAIN");
	unset($t, $t_plug);

	require_once $cfg['system_dir'] . '/footer.php';
Kilandor
#2 24. Februar 2009, 20:26
There is no need for this, actually you can modify things in the <head> section. Because we no longer use sed_htmlmetas() except for in pfs and thats only till its re-written.

$out['head_head'] may be used to input any needed data into <head></head> it outputs to {HEADER_HEAD} and is a default tag.

Actually all of the below can easily be modified. by hooking into header.main

$t->assign(array (
	"HEADER_TITLE" => $plug_title.$out['fulltitle'],
	"HEADER_DOCTYPE" => $cfg['doctype'],
	"HEADER_CSS" => $cfg['css'],
	"HEADER_COMPOPUP" => $out['compopup'],
	"HEADER_LOGSTATUS" => $out['logstatus'],
	"HEADER_WHOSONLINE" => $out['whosonline'],
	"HEADER_TOPLINE" => $cfg['topline'],
	"HEADER_BANNER" => $cfg['banner'],
	"HEADER_GMTTIME" => $usr['gmttime'],
	"HEADER_USERLIST" => $out['userlist'],
	"HEADER_NOTICES" => $out['notices'],
	"HEADER_BASEHREF" => $out['basehref'],
	"HEADER_META_CONTENTTYPE" => $out['meta_contenttype'],
	"HEADER_META_CHARSET" => $out['meta_charset'],
	"HEADER_META_DESCRIPTION" => $out['meta_desc'],
	"HEADER_META_KEYWORDS" => $out['meta_keywords'],
	"HEADER_META_LASTMODIFIED" => $out['meta_lastmod'],
	"HEADER_HEAD" => $out['head_head'],
));
Trustmaster
#3 24. Februar 2009, 20:32
Disagreed with Kilandor. Mostly standalone plugs would like to put the results of some processing into keywords/title. If you do that with a special header plugin part, that means that you have to do the processing twice, which is a waste. So if dervan's suggestion does not have any negative consequences, I would prefer it.
May the Source be with you!
Orkan
#4 25. Februar 2009, 03:16
I dunno why, but something tells me it isn't a good idea..

Some more specialized plugins may not work after this change.
And this will require at least 2 hooks, so why dont use hook:output for that?

$output = preg_replace(
'/<meta(.+)name="keywords"([^>]+)>/i', 
'<meta name="keywords" content="'.$my_plugin['meta_keywords'].'" />', 
$output, 1);
Perl - the only language that looks the same before and after RSA encryption.
Trustmaster
#5 25. Februar 2009, 03:20
What we need to find out is what exactly those specialized plugins are.
May the Source be with you!
Orkan
#6 25. Februar 2009, 03:42
anyway, it doesn't look too professional, isnt?

$t_plug = new XTemplate($path_skin);
$t =& $t_plug;

:-P
Perl - the only language that looks the same before and after RSA encryption.
dervan
#7 25. Februar 2009, 04:29
Orkan, what is wrong in the use of pointers?
Trustmaster
#8 25. Februar 2009, 04:44
It is deprecated in PHP5, because in PHP5 objects are passed by reference by default.
May the Source be with you!
dervan
#9 25. Februar 2009, 05:19
Trustmaster, thanks
Kilandor
#10 25. Februar 2009, 11:09
Actually using output hook in that method would be alot worse and more difficult orkan. Since all the keywords and such can be hooked into by header.main anyways.

The only way that moving where header is included would be if a plugin used any data generated by header, which is possible. Then it would completely break it, I truthfully don't know any off hand like this, but it may break future things like a more updated Whoisonline tracking method.

I can see the reason for moving it, but it doesn't solve all the problems. Also do remember this, we will be getting more advanced hooking methods, so that a hook is only loaded on certain pages/area's. By moving the header all it does is save that hook, and in some cases yes maybe extra processing.

The handling of $t won't be hard, i've already thought of how it can be done, because yes you have to store the $t from the plugin, and hold it till header parsed, then let main use the $t from the plugin.
Orkan
#11 25. Februar 2009, 15:58
# dervan : Orkan, what is wrong in the use of pointers?

Well, all Im saying - it is not a procedural approach.
It should be avoided, like GOTO command in C++, it only makes the code more difficult to read.

From the other hand, what if I wanna use footer hook to set metas? see, its not perfect anyway...

I really like the output buffering feature implemented in PHP - it seems to be perfect solution here IMO.
You can have nesting buffers for all three parts: header, body and footer.. and hook them separately.

<?PHP
$counter = 0;

function callback_header($header)
{	
	global $counter;
	return (++$counter).' - callback_header(), content: '.$header.'<br>';
}
function callback_body($body)
{	
	global $counter;
	return (++$counter).' - callback_body(), content: '.$body.'<br>';
}
function callback_footer($footer)
{	
	global $counter;
	return (++$counter).' - callback_footer(), content: '.$footer.'<br>';
}


ob_start('callback_header');
echo 'echo_1_header<br>';

ob_start('callback_body');
echo 'echo_2_body<br>';

ob_start('callback_footer');
echo 'echo_3_footer<br>';

while(@ob_end_flush());


?>


and this will output:
3 - callback_header(), content: echo_1_header
2 - callback_body(), content: echo_2_body
1 - callback_footer(), content: echo_3_footer

see? the callback_header() is processed by ob_end_flush() last, but it is sent to the browser as first :-)


Also, to get rid of additional hook include()'s - which is a waste, one can define (in the core) three global arrays for preg_replace() to use in these callbacks accordingly.
Perl - the only language that looks the same before and after RSA encryption.

Dieser Beitrag wurde von Orkan (am 25. Februar 2009, 16:53, vor 15 Jahre) bearbeitet
dervan
#12 25. Februar 2009, 18:35
# Orkan : It should be avoided, like GOTO command in C++, it only makes the code more difficult to read.
no no no, not like goto :)
it's any little trick with $t object that used by header.php and plug.inc.php both


# Orkan : I really like the output buffering feature implemented in PHP - it seems to be perfect solution here IMO.
ol korekt :)
i'm awaiting for your solution of problem on this carcass
Orkan
#13 25. Februar 2009, 20:18
# dervan :
no no no, not like goto :)
it's any little trick with $t object that used by header.php and plug.inc.php both

sorry, I didnt make myself clear enough. I mentioned GOTO as an example only. I understood your solution. however, you must admit that it only makes the code more difficult to read, right?

# dervan : i'm awaiting for your solution of problem on this carcass

this method is rather simple..
Basically each "main module", for example system/core/plug/plug.inc.php, should start with ob_start('name_of_callback_function') including header.php and footer.php as well.

just a note:

common.php
if ($cfg['gzip'])
	{ @ob_start('ob_gzhandler'); }
else
	{ ob_start(); }

ob_start('sed_outputfilters');

I would replace ob_start('sed_outputfilters') with just ob_start() to catch some warning messages, etc.. they will be discarded anyway at the end of common.php by simple @ob_end_clean(); - or even completely remove this buffer?

I can implement it, just want to hear from Kilandor, Trustmaster what they think?
Perl - the only language that looks the same before and after RSA encryption.

Dieser Beitrag wurde von Orkan (am 25. Februar 2009, 20:32, vor 15 Jahre) bearbeitet
Trustmaster
#14 25. Februar 2009, 21:25
What I don't like about parsing the output buffer is that it is fulltext parsing. Well, Seditio's advanced rewrite acted this way, and it added about 10% to render time. I know this one won't go so complex. But it doesn't look like strong design.
May the Source be with you!
Orkan
#15 25. Februar 2009, 22:23
what do you mean by "it is fulltext parsing" ?

each callback will process only a part of "fulltext", ie. callback_header($header) will only process parsed header.tpl output
Perl - the only language that looks the same before and after RSA encryption.

12NächsteLetzte