Permalink
Browse files

API: Pass extra context information to shortcode handlers.

This allows shortcodes to perform more complex actions on the element
which contains them. For example, the element reference can be used
to add extra classes or attributes to links which provide additional
metadata.
  • Loading branch information...
1 parent f0ccdeb commit a3396874933ff8f84b705aff964bc499be2b7e18 @ajshort ajshort committed Oct 9, 2013
Showing with 24 additions and 9 deletions.
  1. +4 −1 docs/en/reference/shortcodes.md
  2. +6 −4 parsers/ShortcodeParser.php
  3. +14 −4 tests/parsers/ShortcodeParserTest.php
@@ -64,7 +64,10 @@ These parameters are passed to the callback:
will not have been parsed, and can optionally be fed back into the parser.
- The ShortcodeParser instance used to parse the content.
- The shortcode tag name that was matched within the parsed content.
-
+ - An associative array of extra information about the shortcode being parsed. For example, if the shortcode is
+ is inside an attribute, the `element` key contains a reference to the parent `DOMElement`, and the `node`
+ key the attribute's `DOMNode`.
+
## Example: Google Maps Iframe by Address
To demonstrate how easy it is to build custom shortcodes, we'll build one to display
@@ -68,6 +68,7 @@ public static function set_active($identifier) {
* this will not have been parsed, and can optionally be fed back into the parser.
* - The {@link ShortcodeParser} instance used to parse the content.
* - The shortcode tag name that was matched within the parsed content.
+ * - An associative array of extra information about the shortcode being parsed.
*
* @param string $shortcode The shortcode tag to map to the callback - normally in lowercase_underscore format.
* @param callback $callback The callback to replace the shortcode with.
@@ -102,9 +103,9 @@ public function clear() {
$this->shortcodes = array();
}
- public function callShortcode($tag, $attributes, $content) {
+ public function callShortcode($tag, $attributes, $content, $extra = array()) {
if (!isset($this->shortcodes[$tag])) return false;
- return call_user_func($this->shortcodes[$tag], $attributes, $content, $this, $tag);
+ return call_user_func($this->shortcodes[$tag], $attributes, $content, $this, $tag, $extra);
}
// --------------------------------------------------------------------------------------------------------------
@@ -332,11 +333,12 @@ protected function replaceAttributeTagsWithContent($htmlvalue) {
for($i = 0; $i < $attributes->length; $i++) {
$node = $attributes->item($i);
$tags = $this->extractTags($node->nodeValue);
+ $extra = array('node' => $node, 'element' => $node->ownerElement);
if($tags) {
$node->nodeValue = $this->replaceTagsWithText($node->nodeValue, $tags,
- function($idx, $tag) use ($parser){
- $content = $parser->callShortcode($tag['open'], $tag['attrs'], $tag['content']);
+ function($idx, $tag) use ($parser, $extra){
+ $content = $parser->callShortcode($tag['open'], $tag['attrs'], $tag['content'], $extra);
if ($content === false) {
if(ShortcodeParser::$error_behavior == ShortcodeParser::ERROR) {
@@ -6,6 +6,7 @@
class ShortcodeParserTest extends SapphireTest {
protected $arguments, $contents, $tagName, $parser;
+ protected $extra = array();
public function setUp() {
ShortcodeParser::get('test')->register('test_shortcode', array($this, 'shortcodeSaver'));
@@ -210,16 +211,25 @@ public function testtExtract() {
);
}
+ public function testExtraContext() {
+ $this->parser->parse('<a href="[test_shortcode]">Test</a>');
+
+ $this->assertInstanceOf('DOMNode', $this->extra['node']);
+ $this->assertInstanceOf('DOMElement', $this->extra['element']);
+ $this->assertEquals($this->extra['element']->tagName, 'a');
+ }
+
// -----------------------------------------------------------------------------------------------------------------
/**
* Stores the result of a shortcode parse in object properties for easy testing access.
*/
- public function shortcodeSaver($arguments, $content = null, $parser, $tagName = null) {
+ public function shortcodeSaver($arguments, $content, $parser, $tagName, $extra) {
$this->arguments = $arguments;
- $this->contents = $content;
- $this->tagName = $tagName;
-
+ $this->contents = $content;
+ $this->tagName = $tagName;
+ $this->extra = $extra;
+
return $content;
}

0 comments on commit a339687

Please sign in to comment.