Smarty Forum Index Smarty
WARNING: All discussion is moving to https://reddit.com/r/smarty, please go there! This forum will be closing soon.

Improvments to register_resource / resource behaviour

 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Feature Requests
View previous topic :: View next topic  
Author Message
dthought
Smarty Regular


Joined: 21 Apr 2003
Posts: 55
Location: Melbourne, Australia

PostPosted: Tue Nov 30, 2004 11:20 pm    Post subject: Improvments to register_resource / resource behaviour Reply with quote

Ahh, the joys of using register_resource.

At the moment I'm working with a project that reads templates from two separate places - a project-specific templates folder and a 'core' folder that is common across other projects using the same framework (for stuff like login, error messages, etc).

At the moment I access these templates by doing stuff like
{include file="core:ext/templates/mytemplate.tpl"} which is all lovely.

However, if I add another resource, eg. someotherplace:othertemplate.tpl, then I have to copy the same four callback functions but give them different names in PHP, even if their internals are the same, save for where they point the "true" directory: to.

A nice way I thought of to get around this would be to have a configurable lookup array, something like:
array(
'core' => '/path/to/core',
'otherplace => '/path/elsewhere'
);
and so on, with the keys matching the relevant directory: name. However, it would appear that short of hacking Smarty to reveal a few more of its scary internal variables, there is no way to determine which resource key is currently being called!

So a nice feature I would like to see is that when Smarty runs its callback, it sends a fourth optional variable which contains the current resource's key name. That would make life so much easier and cleaner! (-;

Hopefully that wasn't too long winded... if I can clarify anything there, please ask!
Back to top
View user's profile Send private message Visit poster's website
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Wed Dec 01, 2004 12:01 am    Post subject: Reply with quote

It's a nice idea but I unless I am missing something, I don't think it makes much sense. If you register a callback with Smarty (say "core") then Smarty necessarily calls resource functions with "core" already assumed as part of the function name. Why pass the very same name (essentially) of the function you are calling? A function *must* know its name!

I think what you possibly want is a more generic resource, say "Local" (or whatever) that handles the mappings you mention. You would then reference your templates using something like file="local:core/ext/templates/mytemplate.tpl". Note that you can use any funky syntax you are willing to parse for the filename so something like "local:core|ext/templates/mytemplate.tpl" or "local:core:ext/templates/mytemplate.tpl" can be made to work very easily.

If you need an example of custom filename-syntax parsing, you can look here.
Back to top
View user's profile Send private message
dthought
Smarty Regular


Joined: 21 Apr 2003
Posts: 55
Location: Melbourne, Australia

PostPosted: Wed Dec 01, 2004 3:16 am    Post subject: Reply with quote

Thanks for your reply, boots Smile

Not quite what I was thinking of though.

Let's say this is part of some framework code, which is passed to Smarty to register resources required for a project:

Code:
$this->_config_elements["_SMARTY"]["RESOURCE"] = array(
   "core" => array(
      "smarty_resource_core_source",
      "smarty_resource_core_timestamp",
      "smarty_resource_core_secure",
      "smarty_resource_core_trusted"
   ),
   "base" => array(
      "smarty_resource_base_source",
      "smarty_resource_base_timestamp",
      "smarty_resource_base_secure",
      "smarty_resource_base_trusted"
   )
);


And the associated function callbacks

Code:
function smarty_resource_core_source($tpl_name, &$tpl_source, &$smarty)
{
   $file = map_path_core($tpl_name);
   if (is_file($file)) {
      $tpl_source = $smarty->_read_file($file);
      return TRUE;
   }
   return FALSE;
}
   
function smarty_resource_core_timestamp($tpl_name, &$tpl_timestamp, &$smarty)
{
   $file = map_path_core($tpl_name);
   if (is_file($file)) {
      $tpl_timestamp = filemtime($file);
      return TRUE;
   }
   return FALSE;
}
   
function smarty_resource_core_secure($tpl_name, &$smarty)
{
   return TRUE;
}
   
function smarty_resource_core_trusted($tpl_name, &$smarty)
{
   return TRUE;
}
   
function map_path_core($path)
{
   return realpath($_SERVER['DOCUMENT_ROOT'] . "/some/path/" . $path);
}
//-----------------------------------------------------------------------------//
function smarty_resource_base_source($tpl_name, &$tpl_source, &$smarty)
{
   $file = map_path_base($tpl_name);
   if (is_file($file)) {
      $tpl_source = $smarty->_read_file($file);
      return TRUE;
   }
   return FALSE;
}
   
function smarty_resource_base_timestamp($tpl_name, &$tpl_timestamp, &$smarty)
{
   $file = map_path_base($tpl_name);
   if (is_file($file)) {
      $tpl_timestamp = filemtime($file);
      return TRUE;
   }
   return FALSE;
}
   
function smarty_resource_base_secure($tpl_name, &$smarty)
{
   return TRUE;
}

function smarty_resource_base_trusted($tpl_name, &$smarty)
{
   return TRUE;
}

function map_path_base($path)
{
   return realpath($_SERVER['DOCUMENT_ROOT'] . "/another/different/path/" . $path);
}


Now, the only difference between those two sets of four functions is the path in map_path_[resource name]. What I would like to do, is rather than have to have four functions whose purpose is virtually identical save for one minor change, is have say, a lookup array like this:

Code:
$resource_lookup = array(
   'core' => $_SERVER['DOCUMENT_ROOT'] . "/some/path/",
   'base' => $_SERVER['DOCUMENT_ROOT'] . "/another/different/path/"
);


And have something like a fourth parameter sent from Smarty when it uses this resource, as in:

Code:
function smarty_resource_source($tpl_name, &$tpl_source, &$smarty, $resource_name) { }


So I can then do this:

Code:
$file = map_path_core($tpl_name, $resource_lookup[$resource_name]);


And just add to my config array all the paths as needed, saving lots of parsing time from PHP and lots of code spaghetti headaches. I believe that something like this would still allow the old way to work, the only difference is that the functions are now aware what their executing resource is (-:

Make sense now? Bad idea? Good idea?
Back to top
View user's profile Send private message Visit poster's website
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Wed Dec 01, 2004 3:54 am    Post subject: Reply with quote

I think (think, mind-you) that I understand what you are getting at -- basically the same thing you said in your first post, yes? I do see the merit of a generalized filesystem mapper as you suggest. Yet tell me, how would you call a resource? I assume:

{include file="core:foo.tpl"}
{include file="base:foo.tpl"}

Okay, that's all fine and good but how does that get called behind the scenes? Are you suggesting a default resource handler that is called in the case where a resource isn't found? If not, I don't see how it might work -- what if I don't want a filesystem backed resource? Besides, doesn't that just amount to the idea I suggested earlier? If you set default_resource_handler to (say) 'local' then you can use paths like "core|foo.tpl" (or even "core/foo.tpl") and your local: resource can take care of the details of the real path mapping.

I do apologize if I (continue) to fail to see what you are suggesting -- I do think it is a good idea to generalize the mapping, I'm just not entirely sure I see how you would have it implemented, syntax wise.
Back to top
View user's profile Send private message
dthought
Smarty Regular


Joined: 21 Apr 2003
Posts: 55
Location: Melbourne, Australia

PostPosted: Mon Dec 13, 2004 4:52 am    Post subject: Reply with quote

boots wrote:
{include file="core:foo.tpl"}
{include file="base:foo.tpl"}

Okay, that's all fine and good but how does that get called behind the scenes? Are you suggesting a default resource handler that is called in the case where a resource isn't found?


What I am suggesting, is that Smarty pass an additional, and optional, variable to its callback functions that contains the name before the : that was called.

So, for example with core:, it would pass an extra variable to the callback functions that contains the string, 'core'. You could then write your function to use this string variable to do a generalised lookup in a config array.

I believe that this allows you to write things as they are currently - with a separate set of callbacks for each resource - or with the extra variable being passed, one set of callbacks that can use the called resource's name to determine where it should look.

It's a bit of a sod to explain... hopefully though I'll eventually write something which has enough clarity to it Very Happy
Back to top
View user's profile Send private message Visit poster's website
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Mon Dec 13, 2004 7:16 am    Post subject: Reply with quote

Hi again dthought!

dthought wrote:
It's a bit of a sod to explain... hopefully though I'll eventually write something which has enough clarity to it Very Happy


Yes, I think you should write an example resource that shows how you think it would work. I still don't get it. If you write call "core:foo.tpl" then Smarty will call (for example) smarty_resource_core_source(). If the function already has "core" in its name, why tell it that it is being called with "core"? That's the part I am not following. I feel like we really aren't seeing eye-to-eye on this one Wink
Back to top
View user's profile Send private message
themightychris
Smarty Rookie


Joined: 02 Jan 2005
Posts: 6
Location: Bucks County, Pennsylvania, US

PostPosted: Wed Jan 05, 2005 8:38 am    Post subject: Reply with quote

I understand what he means I think, maybe I can make it clearer.

Quote:

Yes, I think you should write an example resource that shows how you think it would work. I still don't get it. If you write call "core:foo.tpl" then Smarty will call (for example) smarty_resource_core_source().


the core in "core:foo.tpl" is from the first parameter of register_resource but the function names are independently specified in the second parameter.

say, for example, that I wanted to impliment a database resource that could work with several different dbms's. Most of the code would be the same, except for a couple different connection lines, so creating and maintaining several different instances of essentially the same functions would be a pain.

The cleanest thing to do would be mapping resources like mysql: pgsql: and mssql: to the same functions.

then you could have for your function
Code:

function db_get_template ($tpl_name, &$tpl_source, &$smarty_obj, $resource_name)
{

  if($resource_name == "mysql) {
    $link = mysqlconnect(...
     ...
  }
  ...
}


You would need to add an additional optional paarameter to register_resource specifying whether or not this parameter should be passed (to each callback)

Now, what boots is saying, is why don't you just have a generic resource name and put this information into the template name part of the string and just parse it out in the beginning, for my example something like: "database:mysql/templatename"

and then just have at the top of your function
Code:

  list($resource_name, $tpl_name) = explode("/", $tpl_name, 2);


This would accomplish the exact same thing, but without a ton of modification to smarty. The only downsides are it is 1 extra line of code for you and, this could be very important to you, the syntax used in the template is not as neat

mysql:templatename vs database:mysql/templatename


I say dthought should just use the second one
Back to top
View user's profile Send private message Visit poster's website AIM Address Yahoo Messenger MSN Messenger
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Fri Jan 07, 2005 2:07 am    Post subject: Reply with quote

IMHO I'd say that the proper way to map functions in this case would be to use wrapper functions:
[php:1:0c6a45a9d0]<?php
function mysql_get_template ($tpl_name, &$tpl_source, &$smarty_obj, $resource_name)
{
return db_get_template($tpl_name, $tpl_source, $smarty_obj, $resource_name)
}
?>[/php:1:0c6a45a9d0]

or if you are really lazy and need this all the time, write an extended register_resrouce method in an extended Smarty class that had better mapping features. Don't forget that you aren't limited to db:mysql/foo/bar syntax. You could also use db:mysql:foo/bar if that makes more sense for you. Of course, having the connection type specified (mysql, etc) seems a little too much for the template itself. Well, I feel like I'm beating this poor horse at this point so I will stop here Smile
Back to top
View user's profile Send private message
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Feature Requests All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP