Key Values Plugin
Yes, I realize Movable Type is not a general-purpose content management system, but if you're in a pinch it can do wonders. Especially with this plugin, which allows you to associate other bits of data with your entries which can be extracted conviently in your templates. (Click the more link for more information.)
Availability
You can download this plugin here: mtkeyvalues-1_53.zip
Installation
To install, place the 'keyvalues.pl' file in your Movable Type 'plugins' directory. The 'keyvalues.pm' file should be placed in a 'bradchoate' subdirectory underneath your Movable Type 'extlib' directory. Your installation should look like this:
- (mt home)/plugins/keyvalues.pl
- (mt home)/extlib/bradchoate/keyvalues.pm
Refer to the Movable Type documentation for more information regarding plugins.
This plugin has a tag called "IfKeyMatches" that requires the 'regex' plugin, also available from my web site.
Description
This plugin allows you to store key/value pairs of data in your Movable Type fields. These values can be extracted and used in your templates in a very flexible manner.
Tags made available through this plugin:
- <MTKeyValues>: Container tag for accessing your key/value data.
- <MTKeyValuesHeader>: Lets you print a 'header' block within an iterating KeyValues tag.
- <MTKeyValuesFooter>: Lets you print a 'footer' block within an iterating KeyValues tag.
- <MTIfKeyExists>: Tests whether a key exists (given a name).
- <MTIfNoKeyExists>: Tests whether a key does not exist (given a name).
- <MTIfKeyMatches>: This tag will test the name of a key against a value or pattern. Note: if matching against a regular expression, this tag will require the 'regex' plugin (see installation instructions above).
- <MTIfKeyNotMatched>: Outputs contained text if a given key is not matched using a 'IfKeyMatches' tag.
- <MTKeyName>: Outputs the name of a key (only useful when iterating over key/value pairs).
- <MTKeyValue>: Outputs the value of a key. Can output value by name or will output the value of the current key when iterating over key/value pairs.
- <MTKeyValuesStripped>: Outputs the source of your key/value pairs without the key/value data. This allows you to retain the use of your field(s) for regular blog data and use them to store key/value data at the same time.
<MTKeyValues>
These attributes are allowed:
- delimiter: Defaults to '='.
- pattern: Only processes key/value pairs matching the regular expresssion provided. (Requires 'regex' plugin-- see installation instructions above.)
- source: Defines the source of the key/value pairs. Default source is the current entry's 'Additonal Text' field.
- iterate: if this attribute is given (ie: iterate="1"), then the contained data is output for each key/value pair that exists.
This tag has two modes of operation. The normal way it works it to output anything contained within the tag once (regardless of the key/value pairs you have defined). The other way is to output the contained data multiple times for as many keys you have defined.
Examples:
Given an 'additional entry text' of this:
Blah blah blah. Blah blah blah.... This is the regular text followed by the key/value pairs which are in the form of key=value. rating=3 link=http://www.bradchoate.com/ name=Brad Choate
And a portion in an 'Individual Archive Template' like this:
<MTKeyValues>
Extended entry (without key value data):
[[<MTEntryMore>]]<br />
Name: <MTKeyValue key="name"><br />
Link: <a href="<MTKeyValue
key="link">">
<MTKeyValue
key="link"></a><br />
<MTIfKeyExists key="rating">
Rating: <MTKeyValue key="rating"><br />
</MTIfKeyExists>
<MTIfKeyExists key="favorite">
This is my favorite site!<br />
</MTIfKeyExists>
</MTKeyValues>
This will output:
Extended entry (without key value data):
[[Blah blah blah. Blah
blah blah.... This is
the regular text followed by the key/value
pairs which are in the form of key=value.]]<br />
Name: Brad Choate<br />
Link: <a href="http://www.bradchoate.com/">
http://www.bradchoate.com/</a><br />
Rating: 3<br />
See? The other way to use KeyValues is like this:
Key value pairs:
<MTKeyValues iterate="1"> <MTKeyName>: <MTKeyValue><br /> </MTKeyValues>
This will output (again using our sample data above):
name: Brad Choate<br /> link: http://www.bradchoate.com/<br /> rating: 3<br />
Now you might want to just output some of those key/value pairs:
<MTKeyValues iterate="1" pattern="m/a/"> <MTKeyValuesHeader> Here are the keys with 'a' in their name:<br /> </MTKeyValuesHeader> <MTKeyName>: <MTKeyValue><br /> </MTKeyValues>
The above will output all keys with 'a' in their name:
Here are the keys with 'a' in their name:<br /> name: Brad Choate<br /> rating: 3<br />
The 'source' attribute lets you define where your key/values are coming from. The default is the 'additional entry text' field for your blog entries. But you can put key/value pairs anywhere! You might want to store some in your blog description... If you do, this is how you would extract them (note that for the 'source' attribute, you use [ and ] instead of < and > to delimit the MT tags):
<MTKeyValues source="[MTBlogDescription]"> <body bgcolor="<MTKeyValue key="bgcolor">"> </MTKeyValues>
Now that might look weird, but if you have 'bgcolor=#ff0000' in your blog description, this will produce:
<body bgcolor="#ff0000">
A red background-- not recommended for those with weak stomachs!
You can also write multiline values. If you use this syntax in your entry data:
address== 123 Anywhere Street Anytown USA ==address
Or subsitute your delimiter of choice for '='... you just use two instead of one to indicate the multiline format. To be recognized, there shouldn't be any blank space to the right of the opening '==' and the closing '==' should be at the start of the line. If you want to assign the value of your delimiter to a key, you'll have to write it like this:
mykey== = ==mykey
<MTKeyValuesHeader>
This tag may be used within the KeyValues tag for producing a header if there are keys available. This is only useful when using the 'iterating' attribute of the KeyValues tag.
<MTKeyValuesFooter>
This tag may be used within the KeyValues tag for producing a footer if there are keys available. This is only useful when using the 'iterating' attribute of the KeyValues tag.
<MTIfKeyExists>
This tag allows you to test for the existence of a particular key.
These attributes are allowed:
- key: Name of the key to look for.
Example:
<MTKeyValues> <MTIfKeyExists key="somekey"> 'somekey' exists! </MTIfKeyExists> </MTKeyValues>
<MTIfNoKeyExists>
This tag allows you to test for the existence of a particular key.
These attributes are allowed:
- key: Name of the key to look for.
Example:
<MTKeyValues> <MTIfNoKeyExists key="somekey"> 'somekey' doesn't exist! </MTIfNoKeyExists> </MTKeyValues>
<MTIfKeyMatches>
This tag allows you to test whether or not a given key matches a particular value OR if the value matches a given pattern.
These attributes are allowed:
- key: Name of the key to test.
- value: Value to compare against.
- pattern: Regular expression patten to test the value against.
Example:
<MTKeyValues> <MTIfKeyMatches key="color" value="blue"> Color is blue </MTIfKeyMatches> <MTIfKeyMatches key="color" value="red"> Color is red </MTIfKeyMatches> <MTIfKeyMatches key="color" value="green"> Color is green </MTIfKeyMatches> <MTIfKeyNotMatched key="color"> Color is not red, green or blue </MTIfKeyNotMatched> </MTKeyValues>
Here's how you would use the 'pattern' attribute:
<MTKeyValues> <MTIfKeyMatches key="color" pattern="m/(red|green|blue)/"> Color is red, green or blue </MTIfKeyMatches> <MTIfKeyNotMatched key="color"> Color is not red, green or blue </MTIfKeyNotMatched> </MTKeyValues>
<MTIfKeyNotMatched>
This tag allows you to output data if a given key has not been matched against using the 'IfKeyMatches' tags.
These attributes are allowed:
- key: Name of the key to test.
See the 'IfKeyMatches' tag for examples.
<MTKeyValue>
This tag produces the value of a particular key OR if it is within an iterating KeyValues tag, it will print the current value.
These attributes are allowed:
- default: Expression to use as a default in case the key does not exist. This value can contain nested MT tags in the form of [MT...].
See the 'KeyValues' tag for examples.
<MTKeyName>
This tag produces the key name of the current key from an iterating KeyValues tag.
See the 'KeyValues' tag for examples.
<MTKeyValuesStripped>
Outputs the source of your key/value pairs without the key/value data. This allows you to retain the use of your field(s) for regular blog data and use them to store key/value data at the same time.
Here's how you'd use it:
<MTKeyValues> <MTKeyValuesStripped> </MTKeyValues>
License
Released under the MIT License.
Changelog
- 1.52: Fix for cases where contents of KeyValues tag is empty..
- 1.52: Corrected closure tags for embedded expressions.
- 1.51: Fix for 'source' attribute of MTKeyValues tag.
- 1.5: 'key' attributes can now be Movable Type expressions. Ie: <MTKeyValue key="[MTSomeTag]">
- 1.42: Fix to make KeyValues return any errors from MT tags it processes.
- 1.41: Bugfix for 'pattern' attribute of the KeyValues tag.
- 1.4: Added multiline support.
- 1.3: Altered the way key/values are stripped so they don't leave blank lines.
- 1.2: Addition of the KeyValuesHeader, KeyValuesFooter tags.
- 1.1: The KeyValue tag now supports a default attribute.
- 1.0: Initial release
Hmm... so how do I use test for normal extended entries? I put MTEntryIfExtended inside MTKeyValues, but it is always true then. If I use MTEntryIfExtended outside of MTKeyValues, it shows true when there is keyvalues.
Yeah, I've thought about that. In practice, in the blogs where I have used key/values, I only assign them for entries that have an extended entry anyway. But if you want to have key/values for entries where you don't have any real data in the 'extended entry text' field, you could either:
1) add a key called 'extended' and test for it using the IfKeyMatches tag
2) use the IfEmpty plugin (also found here) and test the EntryMore value (or KeyValuesStripped if you're not storing them in the extended entry field) like this:
<MTKeyValues>
<MTIfNotEmpty var="EntryMore">
(there is info left in the extended entry field)
</MTIfNotEmpty>
</MTKeyValues>
One of those should work for you.
I can't get this to work with the MTCategoryDescription. I do like this in my category archive template:
<MTKeyValues source="[MTCategoryDescription]">
<MTKeyValuesStripped>
</MTKeyValues>
... but when I rebuild I get this error:
Build entry 'The California Boom' failed: Build error in template 'Category Archive': Error in <MTEntries> tag: Error in <MTKeyValues> tag:
With no detailed error message. Perhaps it doesn't know where to get MTCategoryDescription from? I tried it with random source strings ("MTFoo") and get the same message. If I use MTBlogDescription it works. I've had a dip into the code and the MT perldocs, but the learning curve to figure this out myself looks steeper than just asking!
Thanks for the plugins,
Kief
About another plugin: MTFormatBreaks.
I know you told us it is "not formally ready for release" and on the MTForum you advised on August 23. that there was an update to 1.1 version.
Will you be releasing this after all? or will it maybe get obsolete by MT2.5?
Is there a problem with it for its unofficial state?
Sorry just curious, (also about Seth, how is he?)
Lawrence
I still have some work to do on format breaks-- there are some tags that need special handling. Blockquote for one. I haven't had time to work on it what with the baby and all (and he's doing just great-- thanks for asking!). I hope to revisit that plugin and a couple of others that are 'half-baked' at the moment pretty soon. Perhaps this weekend will yield an hour or two I can use for that.
Okay I let you work in peace...
But for these question which could be relevant:
Am I right that once you use this plugin, you should put it in every template which has {MTEntryBody} just to be sure formating on main index will be the same as on all the individual etc. pages?
Would it be usefull if it could be applied to {MTCommentBody} as well, or does this work already? (like apply_macros="1")?
On Seth: have you thought about Preventmefromdrivinginsane.com and let your visitors change dipers en do midnight feedings?
Lawrence
I'm assuming we're still discussing the format breaks plugin... yes-- you would have to use the format_breaks attribute for each place your MTEntryBody tag in order for it to be consistent. And yes, you can use the attribute with other tags like MTCommentBody. Just remember to also use the convert_breaks="0" attribute too so that MT doesn't try to format the line breaks itself.
Is it possible (currently at least) to combine this with the Macros plugin? I'm currently trying to use a macro of mine within a value, and I'm not getting any output at all.
I'm trying to combine this plug in with the MTAmazon plugin so that MT entries containing a book's ASIN number will display the book title, author, price, image, etc info using MTAmazon. I am able to get this to work when I hardcode the ASIN number into the MTAmazon tag, and I am able to retrieve an "asin=XXX" key value tag, but don't seem to be able to pass that value into <MTAmazon> using the following from within an <MTEntries> loop:
<MTEntries category="Feature" lastn="1" process_tags="1">
<MTKeyValues>
This works: <MTKeyValue key="asin"><br />
<br>
<MTIfKeyExists key="asin">
Found asin -- this shows up
<MTAmazon method="Asin" search="<MTKeyValue key="asin">" lastn="3">
... never reaches here ...
</MTAmazon>
</MTIfKeyExists>
</MTKeyValues>
</MTEntries>
Any suggestions?
Brad, can I use html in the key value pairs?
Brad, These key values are exactly what I need. One question, though. You can specify the place where the key values should be looked for in the source attribute of the MTKeyValues tag. Is it possible to specify the main entry body? I've tried
...
but that doesn't seem to work. Am I doing this entirely wrong?
Doh. Tag was stripped out. I've tried (MTKeyValues source="[MTEntryBody]")...
Hi!
I've used the KeyValues for a bookreview site of mine and it all worked just fine. I made two lists, one sorted after author and one after title.
The problem is as we entered into 2003 all my reviews from 2002 don't get listed anymore.
Any idea why?
You can see the original discussion here:
http://www.movabletype.org/cgi-bin/ikonboard/ikonboard.cgi?s=3e15b1ad6254ffff;act=ST;f=14;t=11157;st=0
Thanks in advance! :o)
Is there a way to see if the plug-in is working properly? I can't seem to get it to work in my templates, even copying and pasting examples. I'm wondering if I didn't install properly. (beyond simply copying/pasting files into proper directories?)
I can't seem to get this to work properly with the multiline output - if I put in this:
address== 123 Anywhere Street Anytown USA ==addressand use this:<MTKeyValues> <MTIfKeyExists key="address"> Address: <MTKeyValue key="address"><br /> </MTIfKeyExists> </MTKeyValues>I get this:Address: =123 Anywhere Street Anytown USAThe following hack in keyvalues.pm fixed the extra delimiter:
add this line: $value = substr($value,1);
after this line: if ($value eq $delimiter) {
Is a on the fly replacement possible and when how??
Thanx!
Brad,
Just wanted you to know, I use a great many of your plugins and while they are all great, I've found this one to be amazingly useful!
Keep up the good work!
Is it possible to store the data in a template or module instead of a blog/entry/category/etc. field? <MTKeyValues source="[MTLink template="test"]"> seemed to make sense to me, but that didn't work ;) I'm trying to make key/values for author names and URLs on the mt-plugins.org site
Brad Choate=http://www.bradchoate.com/
and then be able to use the MTKeyValue and MTKeyName tags to make a list with them or even create macros all at once. I know how to do this with php (that's how I'm doing it currently -
$authors=array("Brad Choate" => "http://bradchoate.com/ ")
but that's not as useful for pulling the data into xml feeds for the author URL :)
If I didn't make any sense, I do apologize!!! ;)
Hi Ramon,
The line you have:
<MTAmazon method="Asin" search="<MTKeyValue key="asin">" lastn="3">
Should be:
<MTAmazon method="Asin" search="[MTKeyValue key='asin']" lastn="3">
All the best,
--
Ian
I've been using this for a while with some success, but am having difficulty getting the header and footer tags to work as described.
What I'm seeing is that the header tag contents get shown on every iteration, and the footer tag contents are never shown.
For example, as input:
<MTKeyValues iterate="1" source="[MTEntryKeywords]">
<MTKeyValuesHeader>
Here are the keys:<br />
</MTKeyValuesHeader>
<MTKeyName>: <MTKeyValue><br />
</MTKeyValues>
Output:
Here are the keys:
KEYA: AAA
Here are the keys:
KEYB: BBB
Here are the keys:
KEYC: CCC
Is there a known problem in this area, or is there a misunderstanding at my end?
In partial answer to my own question, I think there is a bug in keyvalues.pm.
I can now get the MTKeyValuesHeader tag working by
(a) adding an $i++ before the end of the loop at line 115 and
(b) replacing the "!defined" clause in line 111 with 0 (false).
However, making the footer tag work looks like I would actually have to know what I was doing, so it will have to wait until tomorrow...
Looking at it fresh, the full answer to my question is that there is a bug in keyvalues.pm V1.53 that prevents the MTKeyValuesHeader and MTKeyValuesFooter tags from working correctly.
The good news is that just adding an "$i++;" line before the end of the loop (a new line 115 in this version) fixes both problems.
from Michael Stucker:
I had the same problem (the second '=' in the block delimiter being output) and it got fixed with Michael's suggested hack. Is this a good hack?
My text-formating, Textile, is messing up with my key/value entries, while the source is [MTEntryBody]. Is there a way around it?
Brad,
I think the KeyValue Plugin is great. I had no problem copying it into my mt install.
I do however have a question about the MTKeyValuesStripped tag. You see I'm running a news and events Web site. And it was my intention to use key/value pairs to rank certain articles as more important than others. I was able to do this by placeing a key/value pair in the extended entry field, TopNews=T. However I still want to use this field for extended entries. I was hoping that the MTKeyValuesStripped tag would allow me to strip the key/value pair when I displayed the entry on an archive page.
However on my archive page, the key/value pair still shows up. Did I misunderstand the purpose of the MTKeyValuesStripped tag?
Thanks for your help.
how do I strip out the key-value pairs from the entry body on my main index pages?
By enclosing my Extended entry data with a MTKeyValues tag, it strips out the key-values pair, but how do I do that for the bodies? does this depend on the archive type, i.e. will it work on indexes?
thanks.
Nevermind, i figured it out, you have to replace your MTEntryBody tag with an MTKeyValuesStripped, and make sure that enclosing MTKeyValues tag includes the source [MTEntryBody]