Closed (fixed)
Project:
Rep[lacement]Tags
Version:
5.x-1.x-dev
Component:
RepTag .tags module
Priority:
Normal
Category:
Support request
Assigned:
Unassigned
Reporter:
Created:
25 Sep 2007 at 10:02 UTC
Updated:
23 Aug 2008 at 12:23 UTC
Jump to comment: Most recent file
Comments
Comment #1
profix898 commentedNot sure I got you right, but as I understand it you are requesting something like this:
You want to type
$tag(arg1=abc, arg2=def)$and reptag should replace that with<tag arg1="abc" arg2="def" />. Is that right? If so, it should be easy to implement, but it opens a security hole unless you have a whitelist of allowed tags.Comment #2
buffos commentedlet me put an example more abstract
Lets define $sometag(arg1,arg2) = Hi. My name is %arg1 and my age is %arg2
The = sign i put was for default values we sometimes put in functions if arguments are omitted.
so for example if i define the tag as
$sometag(arg1="tom", arg2="19") = Hi. My name is %arg1 and my age is %arg2
if i write
$sometag(nick,25) it will output-> Hi. My name is nick and my age is 25
if i just write
$sometag it will output -> Hi. My name is tom and my age is 19
which are the default values.
I hope this example is simpler.
Why would it introduce a security hole. ?
Comment #3
profix898 commentedDo you mean this functionality to be generic, i.e. $mytag... is translated directly into the output? Or do you think about a .tags module, where you 'define' these tags explicitly? In the first case the user could type any tag, even if he/she doesnt have the rights to do so. In the second case that wont be a problem.
Comment #4
buffos commentedIt does not matter if its a sitewide tag or a special module tag (if i really understood your question)
Now when the reptag finds the $sometag$ it replaces it with the defined text.
What i was suggesting is making it a step ahead. replace the text and if i find a place holder %arg for example replace it with the first argument, if i find a second %arg replace it with the second argument and so on.
For example
sometag(arg1,arg2,arg3) = sometext %arg and sometext %arg and even more text.
Now if i type $sometag$ it will output--> sometext %arg and sometext %arg and even more text.
if the module makes a second pass and replaced the first %arg with arg1 the second %arg with arg2 and the third %arg with arg3.
it would really be helpfull.
Comment #5
buffos commentedCorrection
"Now if i type $sometag$ it will output--> sometext %arg and sometext %arg and even more text.
BUT IF i type $sometage(arg1,arg2,arg3)$ then if the module makes a second pass and replaced the first %arg with arg1 the second %arg with arg2 and the third %arg with arg3.
it would really be helpfull.
Comment #6
profix898 commentedThere is a difference between sidewide/user tags and module tags for your feature request:
As module tags are processed after sidewide/user tags is it also possible to include module tags (like {DATE}, ...) in the replacement text for sidewide/user tags. For example:
Say you have a sidewide tag defined as follows
$WELCOME$ => 'Hi {USERNAME}! Welcome to ...'. Because{USERNAME}is a tag from system.tags, the final output will beHi UserX! Welcome to ....There are two possible solutions for this case:
$SOMETAG$ => 'This text contains a $PLACEHOLDER$'. In the second pass$PLACEHOLDER$could be replaced with a second table tag named$PLACEHOLDER$. You would however need to define the placeholder tags separately. Thats almost trivial to implement because the only change is to process table tags twice.$SOMETAG(...)$that allows to specify placeholder replacements directly as part of the tag. Problematic because you would need special 'reserved' characters - '(' and ')' in this example - to recognize the syntax. You would also need to make the tag field much larger in the db and the UI and you would need an extra complex UI to be able to specify default values for your placeholders.Comment #7
profix898 commentedTrivial patch for solution #1.
Comment #8
buffos commentedCase 1 is highly problematic. The reason it deprives the essense of the parametric approach, the dynamic nature
Case 2 would be nice (if it is possible) I think ( beeing reserved is not so important) . You can always use { or [ or [[ or $$ or what ever you like to signal start and end of place holding.
If it cannot be done .. no prob :)
Comment #9
profix898 commentedIt is possible in .tags modules already, but for table tags I think approach #2 adds too much complexity. We could think about placeholder arguments as part of the tag definition, but at least a UI to specify default values is overly complex IMO.
Comment #10
buffos commentedif the problem its UI you dont need something new.
In the existing UI
LEFT you define tag right the reptag
sometag hi i am %arg and my age is %arg
TILL HERE nothing new.
The only thing that needs to change is parsing . Let me place it in althorithmic steps.
LET the calling reptag be
$sometag(nick,34)$
1) If inside the $ $ there is no ( and ) then use the normal procedure and just output the text
2) if the are () then create an array of the values as args[] = {nick,34} in our case (its just splitting the string when comma occurs)
3) then to the output text (which is currently "hi i am %arg and my age is %arg")
do the following :replace the first instance of %arg with args[0] the second instance of %args with args[1]
4) output the newly create string.
Very simple string manipulation i think and you dont need to change a bit of the UI.
Comment #11
profix898 commentedAha :) I got you wrong about the defaults. Sorry! But I think we should extend the syntax a little then ...
DEFINITION
tag:
$SOMETAG{arg1=abc,arg2=def}$replacement:
'This text contains %arg1 and %arg2.'OUTPUT
... $SOMETAG$ ...results in... This text contains abc and def.... $SOMETAG{xyz}$ ...results in... This text contains xyz and def.... $SOMETAG{,xyz}$ ...results in... This text contains abc and xyz.... $SOMETAG{klm,mno}$ ...results in... This text contains klm and mno.What do you think?
We should also keep in mind that the tag definition can be quite vast, e.g.
$THISISMYTAG{arg1='Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt', arg2= ... }. Thats why I originally expected a different UI to specify the defaults.Comment #12
buffos commentedBullseye.
Although defaults are not a must. Just an extra feature of arguments.
So if you skip default values you dont need ANYTHING new in the definition
$SOMETAG$ will just do for definition
and then $SOMETAGE(a1,a2,a3,a4,a5)$ {it does not matter how many arguments} because the procedure is just the same
1) split the string a1,a2,a3,a4,a5 with delimiter , and create array args
2) currentargument=0;position=0;
2) while (position = findnext(outputtext,"%arg",position))
{ replace(outputtext,"%arg",args[currentargument++],position) //just replace in the string outputtext the string %arg with the argument stored in the array args and its the currentargument , and the starting position of the %arg string is position
}//endwhile
ofcourse functions are schematic but the procedure is as simple as that (unfortunatelly i dont code in php :)
So if you leave defaults out, the procedure is really easy i think.
Dont you agree?
Comment #13
profix898 commentedThe major difference between #11 and #12 is that in #11 you have keyed arguments (like %arg1, %arg2, ...) while in #12 there are identical arguments replaced in order of appearance. And I'm not really convinced this being a good solution. Do you have any real world use cases or examples for this functionality? I somehow think that keyed arguments are a) more Drupal-like (see %-variables for mails and stuff) and b) much easier to extend in the future. They are c) also better from the usability point of view because you dont need to worry about order. If you - for example - reword your replacement text with #12 you would also need to edit every node containing the tag to preserve the order the arguments appear.
I can write you a patch for #12, but I dont think I will implement un-keyed dynamic arguments in reptag (unless you convince me ;)). One solution that I could agree on is to introduce #11 without the defaults and think about a nice way to handle/specify default values in D6 (where the UI is completely reworked). For now (D5) we would have:
DEFINITION
tag:
$SOMETAG{arg1,arg2}$replacement:
'This text contains %arg1 and %arg2.'OUTPUT
... $SOMETAG{arg1=abc,arg2=def}$ ...results in... This text contains abc and def.Comment #14
buffos commentedactually keyed or not args is the same. I thought it would be a little bit easier to program non keyed args and much FASTER because replacement requires only ONE pass (as each time you encounter an %arg you trigger a replacement). The keyed replacement is slower as you require to pass the output string as many times as the number of arguments to find %argN.
Just that. Actually there is not difference in the result. In the unkeyed solution order is defined by occurence of %arg. In the keyed order is defined by naming convention.
The final result is the same but i think unkeyed is way much faster to parse and replace (did i convince you? xexe.)
Comment #15
profix898 commentedSo you are fine with keyed arguments in principle, right? I dont think the unkeyed way is faster but slower. In unkeyed case you need a loop to iterate over the %arg positions and replace every %arg with an argument in order of appearance (as you said:
while (position = findnext(outputtext,"%arg",position))). With keyed arguments however order doesnt matter and you can replace all arguments at once with a single call to str_replace().Comment #16
buffos commentedIt seems that keyed are faster but in fact they are not.
Let me tell you why.
What a find_replace(sourcestring,findstring,replacestring) function does is search through an array (string = array of chars) to find an instrance of findstring
This is LINEAR procedure. Let me discribe a worst case senario.
Let as have a string of N characters where N is big. And we have to replace K strings that are ALL at the end of the source string ( i mean "blablabla.... %arg1 %arg2...)
The search function will find the arg1 after searching all characters before arg1 . The same applies to arg2 and so on.
So the search function will have to traverse the array of chars N*K times appox (where K is the number of arguments)
In the unkeyed way you the search will just be N times (because the last search provides the position the %arg placeholder was found)
If N is big and K increases we have a huge difference in implementation times.
In the keyed version the overload is just hidden under the search function.
I dont know if i explained it it well
Comment #17
profix898 commentedI didnt benchmark any of these cases, but in my experience its faster to use str_replace(), which is available as function in php with optimized code (C/C++ or stg), than to write a loop in php syntax iterating over the elements. Also your K is quite small (max 10-20) unless you specify really many arguments. All in all I dont think you will ever notice a difference between both implementations at all. The str_ functions are much faster than their regexp counterparts, that are used in reptag to support sophisticated expressions.
The questions are:
1. Do we need what you requested/suggested here
2. Whats the safest way (in respect to usability and extensibility) to implement it
Comment #18
buffos commentedMay i provide some simple example.
the image tag (which exist in a module ofcourse but its an easy example)
You would not need to write a module to post an image. Just define a tag as
$IMAGE(path,size,title) for example.. and you have your image
I for example use it to embed a chess game viewer in a post. How?
To embedd it i just need to copy paste a certain code + the body of the chess game. So my solution now is to create TWO TAGS
a $STARTTAG$ and and $ENDTAG$. They simple hold the code that must be place on the body of the post and are SPLITTED at the place the gamescore (moves) must be inserted. So the user writes $STARTTAG$chessmoves....$ENDTAG$ and its working perfectly.
So i am simulating an ONE parameter TAG. TAG(chessmoves). If i want to simulate 2 parameters i have to manually create 3 tags and so on.
I can list so many examples.
I let my users use the tags but ofcourse i never allow them to create tags (for security reasons)
Comment #19
profix898 commentedI have added support for parametric reptags to the 6.x version of the module. Marking 'patch (to be ported)' as a reminder to think about the 5.x version as well.
Comment #20
profix898 commentedDone.
Comment #21
Anonymous (not verified) commentedAutomatically closed -- issue fixed for two weeks with no activity.
Comment #22
summit commentedHi, just installed the latest drupal 5.* dev version. Couldn't find the parametric tags...
Thanks a lot for going into this!
greetings,
Martijn
Comment #23
buffos commentedJust download the latest dev install and then go to your admin section at reptags settings page and look under Expert settings.
You have to enable parametric tags.
It works fine by the way (i have not tested for default arguments) but parametric tags are GREAT
Comment #24
avpadernoComment #25
Anonymous (not verified) commentedAutomatically closed -- issue fixed for two weeks with no activity.