-
Notifications
You must be signed in to change notification settings - Fork 0
BackDoor extension for Radiant CMS
License
aitorgr/radiant-backdoor
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
= Back Door, execute Ruby code directly inside Radiant templates ==Intro Back door is a Radiant extension that allows executing Ruby code directly inside Radiant templates. It provides the following main tags: <r:ruby>, <r:erb>, <r:if>, <r:else>, <r:unless>, <r:tag> and <r:erb_tag>. The objective of this extension is to avoid writing Radiant extensions for easy tasks. If you just need some Ruby/ERB code inside templates, this extension is for you. If you want to implement Radius tags, modify the admin interface or define some other complex behavior you should revert to writing a complete Radiant extension. Download:: git://github.com/aitorgr/radiant-backdoor.git Project home:: https://github.com/aitorgr/radiant-backdoor Current version:: 0.4.2 Author:: aitor.name[http://aitor.name] Please discuss, report bugs and comments to the Radiant user's mailing-list[http://radiantcms.org/mailing-list] or contact the author directly at me(at)aitor.name. Thanks to RubyForge for hosting this project. == Usage This extension adds the following new tags: === <r:ruby> Executes the content of the tag body as Ruby code and renders the returned value. *Usage:* <r:ruby> [ruby code] </r:ruby> *Example:* With this fine extension you have access to all this information: <r:ruby> self.inspect </r:ruby> This machine identifies itself as <r:ruby> `uname -a` </r:ruby> === <r:erb> Executes the content of the tag body as ERB code and renders the returned value. *Usage:* <r:erb> [ERB template] </r:erb> *Example:* <r:erb> <table> <tr> <th>name</th> <th>password</th> <th>uid</th> <th>gid</th> <th>class</th> <th>home_dir</th> <th>shell</th> </tr> <% File.open( "/etc/passwd") do |io| while line = io.gets next if line =~ /^\s*#/ fields = line.split( ":") %> <tr> <% fields.each do |field| %> <td> <%= field %> </td> <% end %> </tr> <% end end %> </table> </r:erb> *Caveats:* When using ruby looping constructs inside a ERB template, the Radius tags present in the template get expanded only once, and then "repeated" multiple times by the Ruby code. For example, the following code: <r:erb> <% 5.times do %> <%= <r:cycle values="1, 2, 3, 4, 5"/> %> <% end %> </r:erb> returns "11111", though intuitively it should return "12345" (ignoring whitespace). This is because the <r:cycle> tag gets expanded only once. Nearly always this is irrelevant, since Radiant tags are all side effect free, that is, they always return the same value when called multiple times in the same context. Notable exceptions are the <r:cycle> and <r:random> tags. For the case of tags with side effects, use the <r:expand> tag as documented in the description for that tag. === <r:expand> When used inside an "r:erb" tag, it expands the tag named in the "tag" attribute with the given attributes. This tag avoids the "tag only expands once inside ruby loops" problem described in the "r:erb" tag. It takes a required "tag" attribute that identifies an existing tag, and expands that tag passing it the rest of attributes. NOTE that this tag must be used inside an ERB <%= %> construct. *Usage:" <r:expand tag="tag-name" [ tag-name-attribute="value"]* /> *Example:" <r:erb> <% <r:cycle values="1, 2, 3, 4, 5" reset="true"/> %> <% 5.times do %> <%= <r:expand tag="cycle" values="1, 2, 3, 4, 5"/> %> <% end %> </r:erb> renders "23451" (ignoring whitespace) === <r:if> Renders the tag body if the given Ruby expression evaluates to true. If not it renders an inner "r:else" tag, if present. Note that there are some caveats regarding the "r:else" tag, look the description of if for more information. *Usage:* <r:if cond="[ruby expression]"> [HTML content] </r:if> <r:if cond="[ruby expression]"> [HTML content] <r:else> [HTML content] </r:else> </r:if> *Example:* <r:if cond="request.env[ 'HTTP_USER_AGENT'] =~ /MSIE/"> <!-- Internet Explorer needs some ugly hacks to render PNG images with transparency --> <div id="logo" style="filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'/images/logo.png\',sizingMethod=\'scale\');"></div> <r:else> <!-- the rest of browsers just make it rigth --> <img src="/images/logo.png" id="logo" alt="Logo"/> </r:else> </r:if> *Caveats:* There are two caveats with the "r:if/unless" and "r:else" tags (used "r:if" as example, but equally applicable to "r:unless"): * to allow the expansion of an "r:else" part inside a "r:if" tag, the containing "r:if" tag must be expanded even if the condition of the "r:if" tag evaluates to false. In this case, the body of the "r:if" tag is ignored. This is not a problem unless the body of the "r:if" tag has "side effects": <r:ruby> @counter = 0 "" </r:ruby> <r:if cond="false"> This text is evaluated and ignored, but the following "ruby" tag has a side effect that affects the "else" tag <r:ruby> @counter += 1 </r:ruby> <r:else> <r:ruby> @counter </r:ruby> </r:else> </r:if> * the rendered value of the "r:if" tag contains also any data after an "r:else" tag: <r:if cond="true"> Hello <r:else> Hello Radiant! </r:else> world! </r:if> evaluates to "Hello world!" (ignoring whitespace) === <r:unless> The inverse of the "r:if" tag. Refer to the description of the "r:if" tag for complete documentation. === <r:else> Specifies the "else" part for "r:if" and "r:unless". Refer to the description of the "r:if" tag for complete documentation. === <r:tag> Defines a new tag, which can subsequently be used as a normal Radius tag. It can be seen as a programmable and parametrized snippet. The new tag receives the tag context with the standard name "tag" (see the example below). Note that this tag must be rendered by Radiant before the tag it defines is used. This typically means that this tag must be used early in a page layout. *Usage:* <!-- define a new tag --> <r:tag name="tag-name"> [Ruby code] </r:tag> <!-- use the new defined tag --> <r:tag-name [params]> [content] </r:tag-name> *Example:* <!-- define a new tag --> <r:tag name="originating_ip"> @request.remote_ip </r:tag> <!-- use it --> Article posted from IP <r:originating_ip /> === <r:erb_tag> Same functionality as the "tag" tag but the body of the tag is interpreted as ERB code. Handy for heavy parametrized templating. *Usage:* <!-- define a new tag --> <r:tag name="tag-name"> [Ruby code] </r:tag> <!-- use the new defined tag --> <r:tag-name [params]> [content] </r:tag-name> *Example:* <!-- define a new tag --> <r:erb_tag name="article"> <div class="<%= tag.attr[ "class"] || "article" %>"> <div class="article-title"> <%= tag.attr[ "title"] %> </div> <div class="article-body"> <%= tag.expand %> </div> <div class="article-footer"> Posted in <page/> </div> </div> </r:erb> <!-- use it --> <article title="New BackDoor release"> Blah, blah, blah </article> == Attribute expansion Back Door allows evaluating tag's attributes as Ruby code. If a tag's attribute starts with the "=" symbol, the rest of the attribute is evaluated, and the attribute's value is replaced with the evaluated value. This works for both standard Radiant (Radius) tags and Back Door's own tags. As an example, consider a side-bar where we want to show first and second level pages. But for the "news" page, we want to limit the number of children to 3 and add an extra link to see all news. Without Back Door this could be implemented as: <r:children:each> <h2 class="menu-heading"> <r:link> <r:title /> </r:link> </h2> <r:if_url matches="/news/"> <r:children:each limit="3" order="desc" by="published_at"> <h3 class="menu-subheading"> <r:link> <r:title /> </r:link> </h3> </r:children:each> <h3 class="menu-subheading"> <r:link> More news... </r:link> </h3> </r:if_url> <r:unless_url matches="/news/"> <r:children:each order="desc" by="published_at"> <h3 class="menu-subheading"> <r:link> <r:title /> </r:link> </h3> </r:children:each> </r:unless_url> </r:children:each> Clearly there is too much duplication. With Back Door this can be rewritten as: <r:children:each> <h2 class="menu-heading"> <r:link> <r:title /> </r:link> </h2> <r:ruby> @news = tag.locals.page.url =~ /news/; "" </r:ruby> <r:children:each limit="=(@news ? 3: 1000)" order="desc" by="published_at"> <h3 class="menu-subheading"> <r:link> <r:title /> </r:link> </h3> </r:children:each> <r:if cond="@news"> <h3 class="menu-subheading"> <r:link> More news... </r:link> </h3> </r:if> </r:children:each> Note how the "limit" attribute of the <r:children:each> tag uses the "=" symbol to make it dynamic. == Security None to date. Arbitrary Ruby code can be executed with this extension. If you don't trust the people writing the pages in a Radiant site armed with this extension, simply don't use it. See the TODO[link:files/TODO.html] file for more information. == License The Back Door extension is available under a MIT style license. Copyright (c) 2007 Aitor Garay-Romero <me(at)aitor.name> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
About
BackDoor extension for Radiant CMS
Resources
License
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published