-
-
Save keif/1621510 to your computer and use it in GitHub Desktop.
SIMPLX Widgeteer 0.8.4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
SIMPLX Widgeteer 0.8.4.kb | |
UPDATE 120116 10:59 | |
Made a nested foreach loop to handle placeholders with the same parent reference. | |
UPDATE 120115 16:59 | |
Changed so that the default chunkMatchingSelector is "", which is more likely to be the case. | |
UPDATE 120114 02:57 | |
Updated the reset concept again as i had not considered the problem | |
enough. Now the reference should be correctly set to the root of the | |
traversal history stack for every new placeholder in the iteration. | |
UPDATE 120113 00:04 | |
Found that i didn't reset the array iterator when going through namespaced placeholders. Fixed but untested. | |
UPDATE 111120 13:26 | |
NEW FEATURES: | |
Added event more debug info to make it easy to see the parsing progress. | |
UPDATE 111119 15:41 | |
NEW FEATURES: | |
Added plenty of debug info to make it easy to see the parsing progress. | |
UPDATE 111117 16:56 | |
NEW FEATURES: | |
Added Chunks and Snippet call :) | |
1 Dataset | |
3 Templates | |
1 Snippet call | |
Added Chunk caching by using a static class variable. | |
I have added simple support for peeking and grabbing values which are located in the nested structure INSIDE the current object. | |
Example: | |
Lets say that we are parsing this contact object, | |
--------------------------------------------------------------- | |
{ | |
"objecttypename":"contact", | |
"firstname":"Lisa", | |
"lastname":"Johnson", | |
"phone":"+46 555 131415", | |
"email":"[email protected]", | |
"address":[ | |
{ | |
"objecttypename":"address", | |
"type":"home", | |
"name":"My Little House", | |
"street":"That Way 123", | |
"geodata":{ | |
"longitude":"-70.044636", | |
"latitude":"+42.689060" | |
} | |
} | |
] | |
} | |
--------------------------------------------------------------------- | |
You can now do this to get the "longitude" while at the root level of the object, | |
[[+address.geodata.longitude]] | |
:D | |
UPCOMING | |
Conditional peek and grab using the same method as the Controller. This will give you regexp support etc. | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<title>[[++site_name]] - [[*pagetitle]]</title> | |
<base href="[[++site_url]]" /> | |
</head> | |
<body> | |
<h2>Something should show up down there</h2> | |
[[!simplx_widgeteer? | |
&dataSetUrl=`http://modxclub.com/rss-feed` | |
&preprocessor=`widgeteer_preprocessor_xml2json` | |
&useChunkMatching=`true` | |
&chunkPrefix=`modx.feed.tpl_` | |
]] | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<b>[[+title]]</b> | |
<p>[[+item]]</p> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<p> - [[+title]]</p> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[[+channel]] | |
<hr/> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
Used to load an external class definition. | |
Ditched this approach to make it simple to package the snippet using the PacMan addon. | |
Below the class definition you find the actual snippet code... | |
*/ | |
//require_once($modx->config['base_path']."assets/snippets/simplx/simplx_widgeteer.php"); | |
if(!class_exists('simplx_widgeteer')){ | |
class simplx_widgeteer{ | |
public $debugmode = true; | |
public $dataSet; | |
public $dataSetUrl; | |
public $dataSetArray; | |
public $dataSetRoot; | |
public $useChunkMatching = true; | |
public $chunkMatchingSelector = ''; | |
public $staticChunkName = ''; | |
public $chunkPrefix = ''; | |
public $chunkMatchRoot = false; | |
public $preprocessor = ''; | |
private $iterator = 0; | |
private $traversalStack = array(); | |
private $traversalObjectStack = array(); | |
private $traversalContext = ''; | |
// Only one instance per request. | |
private static $chunkCache = array(); | |
public function preprocess($dSet){ | |
global $modx; | |
if ($this->preprocessor) { | |
//if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: preprocess(), Processing "'.$dSet.'" using Snippet "'.$this->preprocessor.'".'); | |
$dSet = $modx->runSnippet($this->preprocessor,array('dataSet'=>$dSet)); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: preprocess(), Done processing. Dataset now contains "'.$dSet.'".'); | |
} | |
return $dSet; | |
} | |
public function loadDataSet($dSet){ | |
global $modx; | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: loadDataSet(), Dataset contains "'.$dSet.'".'); | |
$dSet = $this->preprocess($dSet); | |
$this->dataSet = $dSet; | |
//if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: loadDataSet(), Dataset after preprocessing "'.$dSet.'".'); | |
$this->dataSetArray = $this->decode($dSet); | |
if(is_array($this->dataSetArray)){ | |
//if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: loadDataSet(), Dataset after preprocessing "'.$dSet.'".'); | |
return true; | |
}else{ | |
$modx->log(modX::LOG_LEVEL_ERROR, 'Widgeteer: loadDataSet(): Exception, Unable to decode the dataset.'); | |
return false; | |
} | |
//$this->cacheDataSet($dSet); | |
} | |
public function loadCachedDataSet($dataSetKey){ | |
global $modx; | |
$dSet = $modx->cacheManager->get($dataSetKey); | |
if ($dSet) { | |
return $dSet; | |
}else{ | |
return ''; | |
} | |
} | |
public function cacheDataSet($dSet){ | |
global $modx; | |
// For now we just cache remote dataSets... | |
if ($this->dataSetUrl != '') { | |
$dataSetLocator = urlencode($this->dataSetUrl); | |
$modx->cacheManager->set(('dataSet.'.$dataSetLocator),$this->dataSetArray); | |
} | |
} | |
public function loadDataSource($dSourceURL){ | |
global $modx; | |
$result = false; | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: loadDataSource(), Fetching from URL "'.$dSourceURL.'".'); | |
if ($dSourceURL != "") { | |
$ch = curl_init(); | |
curl_setopt($ch, CURLOPT_URL, $dSourceURL); | |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | |
$output = curl_exec($ch); | |
curl_close($ch); | |
$this->dataSetUrl = $dSourceURL; | |
if ($output != "") { | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: loadDataSource(), Got the following output "'.$output.'".<br/><br/>'); | |
$result = $this->loadDataSet($output); | |
if($result){ | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: loadDataSource(), loadDataSet() returned "true".'); | |
}else{ | |
$modx->log(modX::LOG_LEVEL_ERROR, 'Widgeteer: loadDataSource(): Exception, loadDataSet() returned "false". Aborting.'); | |
} | |
}else{ | |
$modx->log(modX::LOG_LEVEL_ERROR, 'Widgeteer: loadDataSource(): Exception, no valid output from "'.$dSourceURL.'".'); | |
} | |
} | |
} | |
public function setDataRoot($elName){ | |
$this->dataSetRoot = $elName; | |
$this->dataSetArray = $this->dataSetArray[$this->dataSetRoot]; | |
} | |
public function decode($json){ | |
return json_decode($json,true); | |
} | |
public function encode($object){ | |
return json_encode($object); | |
} | |
function parse(&$obj=null){ | |
global $modx; | |
$result = ''; | |
if(!isset($obj)){ | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: parse() Got no initial argument.'); | |
if($this->dataSetArray){ | |
$obj = &$this->dataSetArray; | |
}else{ | |
$modx->log(modX::LOG_LEVEL_ERROR, 'Widgeteer: parse(): Exception, Missing valid dataset. Aborting.'); | |
return false; | |
} | |
}else{ | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: parse() starting with argument "'.json_encode($obj).'".'); | |
} | |
if($this->dataSetRoot != ''){ | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: parse(), Checking existance of dataSetRoot "'.$this->dataSetRoot.'".'); | |
/* | |
if(array_key_exists($this->dataSetRoot,$this->dataSetArray)){ | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: parse(), dataSetRoot "'.$this->dataSetRoot.'" was found in the dataset.'); | |
}else{ | |
$modx->log(modX::LOG_LEVEL_ERROR, 'Widgeteer: parse(): Exception, dataSetRoot "'.$this->dataSetRoot.'" was NOT found in the dataset. Aborting.'); | |
return false; | |
} | |
*/ | |
$context = $this->dataSetRoot; | |
} | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG,''); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: parse(), Starting recursive parse.'); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: parse(), -------------------------------------'); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG,''); | |
foreach ($obj as $key => &$val) { | |
switch($this->typeCheck($val)){ | |
case "list": | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: parse(), This item ("'.$key.'") is a list ([]). Calling parseList().'); | |
$result = $this->parseList($val,$key); | |
break; | |
case "object": | |
if(!$this->dataSetRoot){ | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: parse(), This item ("'.$key.'") is an object ({}). Calling parseObject().'); | |
$result = $this->parseObject($val,$key); | |
} | |
break; | |
case "simple": | |
if(!$this->dataSetRoot){ | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: parse(), This item ("'.$key.'") is a simple type (string or number). Calling parseSimpleType().'); | |
$result = $this->parseSimpleType($val,$key); | |
} | |
break; | |
default : | |
break; | |
} | |
$obj[$key] = $result; | |
} | |
$result = implode(' ',$obj); | |
// If this is the last render call we have the option to wrap the result in the | |
// rootChunk. | |
if($this->chunkMatchRoot == 'true'){ | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: parse(), Chunk matching root element.'); | |
$rootChunk = $modx->getChunk(($this->chunkPrefix.$this->dataSetRoot)); | |
if($rootChunk != ''){ | |
$result = str_replace('[[+content]]',$result,$rootChunk); | |
}else{ | |
} | |
} | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: parse(), Done parsing. Returning "'.$result.'".'); | |
return $result; | |
} | |
function parseObject(&$obj,$context){ | |
global $modx; | |
$result = ''; | |
/* | |
FIX | |
Add a reference to the actual, untemplated, object. | |
Now the stack contains templated data | |
*/ | |
// Add the object to the stack | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, | |
' | |
Widgeteer: parseobject() adding object "'.$context.'" to stack "'.json_encode($obj).'". | |
'); | |
$this->traversalObjectStack[$context] = $obj; | |
foreach ($obj as $key => &$val) { | |
switch($this->typeCheck($val)){ | |
case 'list': | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: parseObject(), This item ("'.$key.'") is a list ([]). Calling parseList().'); | |
$result = $this->parseList($val,$key); | |
break; | |
case 'object': | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: parseObject(), This item ("'.$key.'") is an object ({}). Calling parseObject().'); | |
$result = $this->parseObject($val,$key); | |
break; | |
case 'simple': | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: parseObject(), This item ("'.$key.'") is a simple type (string or number). Calling parseSimpleType().'); | |
$result = $this->parseSimpleType($val,$key); | |
break; | |
default: | |
break; | |
} | |
$obj[$key] = $result; | |
} | |
$result = $this->template($obj,$context); | |
//if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: parseobject() popping object "'.$context.'" from stack.'); | |
// Pop it from the stack | |
//array_pop($this->traversalObjectStack); | |
return $result; | |
} | |
function parseList(&$list,&$context){ | |
global $modx; | |
$result = ''; | |
$iterator = 0; | |
foreach ($list as &$index) { | |
switch($this->typeCheck($index)){ | |
case 'list': | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: parseList(), This item ("'.$context.'") is a list ([]). Calling parseList().'); | |
$result = $this->parseList($index,$iterator); | |
break; | |
case 'object': | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: parseList(), This item ("'.$context.'") is an object ({}). Calling parseObject().'); | |
$result = $this->parseObject($index,$context); | |
break; | |
case 'simple': | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: parseList(), This item ("'.$context.'") is a simple type (string or number). Calling parseSimpleType().'); | |
$result = $this->parseSimpleType($index,$context); | |
break; | |
default: | |
break; | |
} | |
$list[$iterator] = $result; | |
$iterator++; | |
} | |
$result = implode(' ',$list); | |
return $result; | |
} | |
function parseSimpleType(&$value,&$context){ | |
global $modx; | |
$prefContext = ($this->chunkPrefix.$context); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: parseSimpleType(), This item ("'.$context.'") contains value "'.$value.'".'); | |
if(!array_key_exists($prefContext,self::$chunkCache)){ | |
self::$chunkCache[$prefContext] = $modx->getChunk($prefContext); | |
$chunk = self::$chunkCache[$prefContext]; | |
}else{ | |
$chunk = self::$chunkCache[$prefContext]; | |
} | |
if($chunk){ | |
$result = str_replace('[[+value]]',$value,$chunk); | |
return $result; | |
}else{ | |
return $value; | |
} | |
} | |
function parseFieldPointer(&$type,&$context){ | |
global $modx; | |
$chunk = $modx->getChunk(($this->chunkPrefix.$context)); | |
if($chunk != ''){ | |
$result = str_replace('[[+value]]',$type,$chunk); | |
return $result; | |
}else{ | |
return $type; | |
} | |
} | |
function typeCheck(&$var){ | |
$val = ''; | |
if(is_array($var)){ | |
if ($this->is_assoc($var)) { | |
$val = 'object'; | |
}else{ | |
$val = 'list'; | |
} | |
}else{ | |
$val = 'simple'; | |
} | |
return $val; | |
} | |
function template(&$collection,$tmplName) { | |
global $modx; | |
$res = null; | |
$tempVar; | |
if ($this->useChunkMatching) { | |
// Get the current chunkMatchingSelector key from the $collection list. | |
// This is used later to choose which Chunk to use as template. | |
if(array_key_exists($this->chunkMatchingSelector,$collection)){ | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: template(), chunkMatchingSelector "'.$this->chunkMatchingSelector.'" was found in collection "'.$tmplName.'".'); | |
$chunkName = $collection[$this->chunkMatchingSelector]; | |
}else{ | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: template(), chunkMatchingSelector "'.$this->chunkMatchingSelector.'" was NOT found in collection "'.$tmplName.'".'); | |
$chunkName = ''; | |
} | |
if ($chunkName === '') { | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: template(), Chunk name is "".'); | |
/* | |
If nothing was returned from the assignment above we have found no selector. We have to | |
use another way to match the current collection in the $collection list. | |
The way that json is structured it is very likely that the parent key is the name of the | |
object type in the collection. | |
Example | |
{ | |
"contact":[ | |
{ | |
"name":"Mini Me", | |
"shoesize":{"eu":"23"} | |
}, | |
{ | |
"name":"Big Dude", | |
"shoesize":{"eu":"49"} | |
} | |
] | |
} | |
In the example above its implied that each item in the "contact" collection is of typ... contact :) | |
Similarly the "shoesize" property is a complex value that would be best matched to the key "shoesize". | |
*/ | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: template(), It is very likely that the parent key is the name of the object type. Setting $chunkName to "'.$tmplName.'"'); | |
$chunkName = $tmplName; | |
}else{ | |
} | |
if($chunkName != ''){ | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: template(), parsing Chunk "'.$chunkName.'".'); | |
//$tempVar = $modx->parseChunk(($this->chunkPrefix.''.$chunkName), $collection, '[[+', ']]'); | |
$tempVar = $this->parseChunk(($this->chunkPrefix.''.$chunkName), $collection, '[[+', ']]'); | |
$res .= $tempVar; | |
}else{ | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: template(), $chunkName is still empty.'); | |
} | |
}else{ | |
//$tempVar .= $modx->parseChunk($this->staticChunkName, $collection, '[[+', ']]'); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: template(), Chunk matching is turned off. Using static Chunk "'.$this->staticChunkName.'".'); | |
$tempVar .= $this->parseChunk($this->staticChunkName, $collection, '[[+', ']]'); | |
$res .= $tempVar; | |
} | |
if(!$res){ | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: template(), parseChunk() returned an invalid result. Setting the template result to "".'); | |
$res = ''; | |
}else{ | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: template(), parseChunk() returned a valid result. Calling templateNSPlaceholders() to find and template namespaced tags.'); | |
$res = $this->templateNSPlaceholders($res); | |
} | |
return $res; | |
} | |
function parseChunk($chunkName, $chunkArr, $prefix='[[+', $suffix=']]'){ | |
global $modx; | |
$chunk=''; | |
if(!array_key_exists($chunkName,self::$chunkCache)){ | |
self::$chunkCache[$chunkName] = $modx->getChunk($chunkName); | |
$chunk = self::$chunkCache[$chunkName]; | |
}else{ | |
$chunk = self::$chunkCache[$chunkName]; | |
} | |
if (!empty($chunk) || $chunk === '0') { | |
if(is_array($chunkArr)) { | |
reset($chunkArr); | |
while (list($key, $value)= each($chunkArr)) { | |
$chunk= str_replace($prefix.$key.$suffix, $value, $chunk); | |
} | |
} | |
} | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: parseChunk(), Done parsing, returning "'.$chunk.'".'); | |
return $chunk; | |
} | |
// Utility function to check type of Array | |
function is_assoc (&$arr) { | |
try{ | |
return (is_array($arr) && (!count($arr) || count(array_filter(array_keys($arr),'is_string')) == count($arr))); | |
}catch(Exception $e){ | |
return false; | |
} | |
} | |
// Templates namespaced placeholders | |
function templateNSPlaceholders($chunk){ | |
global $modx; | |
$collection = null; | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: Starting templateNSPlaceholders(). Checking "'.$chunk.'"'); | |
// Find any unparsed placeholders | |
$nsSeparator = '.'; | |
$forwardSeparator = '-'; | |
$backSeparator = '+'; | |
$patternSeparator = '?'; | |
$placeholders; | |
$pattern = "/\[\[\+[^\]]*\]\]/"; | |
preg_match_all($pattern, $chunk, $placeholders); | |
if(!is_array($placeholders) || count($placeholders[0])<=0){ | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: templateNSPlaceholders(), there where no placeholders in this chunk. Returning what we got.'); | |
return $chunk; | |
} | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: templateNSPlaceholders(), we got placeholders "'.json_encode($placeholders).'"'); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG,' '); | |
// Set local references to the traversal stack (history stack). Local refs should speed up access. | |
$stackRootPointer = &$this->traversalObjectStack; | |
$pointer = &$stackRootPointer; | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: templatePlaceholders() The traversal stack has the following items: "'.json_encode($pointer).'"'); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG,' '); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: templatePlaceholders() Going into the placeholders foreach.'); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG,' '); | |
foreach($placeholders as $placeholder){ | |
foreach ($placeholder as $ph) { | |
$value = ''; | |
// Make a local copy for performance impr. | |
$current = $ph; | |
// Only parse the placeholder if it has a separator | |
if(!strpos($current,$nsSeparator)===false){ | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: templatePlaceholders() the current placeholder is: "'.$current.'"'); | |
// Remove the tags | |
$path = str_replace(array('[[+',']]'), '', $current); | |
// Explode the current placeholder using the namespace separator | |
$parts = explode($nsSeparator,$path); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: templatePlaceholders() After the cleanup the placeholder looks like this: "'.json_encode($parts).'" .'); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: templatePlaceholders() Looping through the parts of the current placeholder.'); | |
// Iteration counter | |
$i = 1; | |
// Lets loop through all parts in the namespace array. | |
foreach($parts as $part){ | |
switch($part){ | |
case '<': | |
break; | |
case '>': | |
break; | |
case '?': | |
break; | |
default: | |
/* | |
Ok, lets look in the current array position if we have a match for the namespace part. | |
Right now we only support cronological paths so if the part is not found, its no | |
use iterating on, so we simply return the chunk we got. | |
*/ | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: templatePlaceholders() Rotation nr "'.$i.'".'); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG,' '); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: templatePlaceholders() The current part is "'.$part.'".'); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG,' '); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: templatePlaceholders() Lets start looking in the stack at our present position.'); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG,' '); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: templatePlaceholders() The current pointer in the stack contains: "'.json_encode($pointer).'".'); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG,' '); | |
// Get a pointer to the current value | |
$value = &$pointer[$part]; | |
if(!isset($value)){ | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: templatePlaceholders() The current position in the stack had no "'.$part.'" reference. This means that the path is invalid and we can set value to "".'); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG,' '); | |
unset($value); | |
$value = ''; | |
} | |
/* | |
Got something! Lets see if its a string/num/bool, or an array... | |
*/ | |
// If we still have an array, we havent reached the target | |
if(is_array($value)){ | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: templatePlaceholders() We got an array back from the current stack position "'.json_encode($value).'".'); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG,' '); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: templatePlaceholders() We got an array back from the current stack position "'.json_encode($value).'".'); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG,' '); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: templatePlaceholders() Backing up to the previous item in the stack position.'); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG,' '); | |
$i++; | |
// unset the pointer so that we dont screw with the history stack | |
unset($pointer); | |
// Redirect the pointer ref to the new, current position in the traversal history stack | |
$pointer = &$value; | |
// unset the value ref so that we dont screw with the history stack | |
unset($value); | |
}else{ | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: templatePlaceholders() The current position returned the string "'.$value.'". Lets keep it for templating.'); | |
// Else we can parse and return. | |
// Replace the original placeholder with the retrieved value. | |
//$chunk = str_replace(('[[+'.$currentMatch.']]'),$value,$chunk); | |
} | |
} | |
} | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: templatePlaceholders() done with parsing this placeholder. Lets replace the it with this value "'.$value.'"'); | |
// Replace the original placeholder with the retrieved value. | |
$chunk = str_replace(('[[+'.$path.']]'),$value,$chunk); | |
// unset the pointer so that we dont screw with the history stack | |
unset($pointer); | |
// Backup to the beginning of the stack so that the next placeholder can reference the complete history. | |
$pointer = $stackRootPointer; | |
} | |
} | |
} | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: templatePlaceholders() done with parsing all placeholders.'); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG,' '); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: templatePlaceholders() returning "'.$chunk.'"'); | |
if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG,' '); | |
return $chunk; | |
} | |
// Facilitates Chunk caching | |
function getChunkTemplate($templateName){ | |
if(array_key_exists($templateName,self::$chunkCache)){ | |
return self::$chunkCache[$templateName]; | |
}else{ | |
self::$chunkCache[$templateName] &= $modx->getChunk($templateName); | |
return self::$chunkCache[$templateName]; | |
} | |
} | |
// Facilitates Chunk processing using cached objects | |
function parseChunkTemplate($templateName,&$collection){ | |
if(array_key_exists($templateName,self::$chunkCache)){ | |
return $modx->parseChunk(($this->chunkPrefix.''.$chunkName), $collection, '[[+', ']]'); | |
}else{ | |
return $modx->getChunk($templateName); | |
} | |
} | |
} | |
}else{ | |
} | |
/* | |
---------------------------------------------------------------------------------------------- | |
Below is the actual snippet code which sets defaults, validates the input, instatiates the | |
Widgeteer object and runs the logic... | |
*/ | |
$dataSourceUrl = isset($dataSourceUrl) ? $dataSourceUrl : 'null'; | |
$dataSourceUrl = isset($dataSetUrl) ? $dataSetUrl : $dataSourceUrl; //New interface parameter to mend naming consistency issue. | |
$staticChunkName = isset($staticChunkName) ? $staticChunkName : 'null'; | |
$dataSet = isset($dataSet) ? ($dataSet) : 'null'; | |
$useChunkMatching = isset($useChunkMatching) ? $useChunkMatching : true; | |
$chunkMatchingSelector = isset($chunkMatchingSelector) ? $chunkMatchingSelector : ''; | |
$dataSetRoot = isset($dataSetRoot) ? $dataSetRoot : 'null'; | |
$chunkMatchRoot = isset($chunkMatchRoot) ? $chunkMatchRoot : false; | |
$chunkPrefix = isset($chunkPrefix) ? $chunkPrefix : ''; | |
$dataSet = str_replace(array('|xq|','|xe|','|xa|'),array('?','=','&') , $dataSet); | |
$preprocessor = isset($preprocessor) ? $preprocessor : ''; | |
$debugmode = isset($debugmode) ? $debugmode : true; | |
if($debugmode){ | |
$modx->setLogLevel(modX::LOG_LEVEL_DEBUG); | |
} | |
if($dataSourceUrl == 'null' && $dataSet == 'null'){ | |
print '{"result":[{"objecttypename":"exception","errorcode"="0","message":"The dataSet parameter is empty."}]}'; | |
}else{ | |
$w = new simplx_widgeteer(); | |
$w->debugmode = $debugmode; | |
/* | |
PHP bug perhaps? $useChunkMatching evaluates as true even if its false!? | |
I have to "switch poles" in order to get the right effect... | |
*/ | |
if($useChunkMatching && $staticChunkName != 'null'){ | |
$w->useChunkMatching = false; | |
$w->staticChunkName = $staticChunkName; | |
}else{ | |
$w->useChunkMatching = true; | |
$w->chunkMatchingSelector = $chunkMatchingSelector; | |
} | |
$w->chunkMatchRoot = $chunkMatchRoot; | |
$w->chunkPrefix = $chunkPrefix; | |
$w->preprocessor = $preprocessor; | |
if($dataSourceUrl != 'null'){ | |
$dataSourceUrl = urldecode($dataSourceUrl); | |
$w->loadDataSource($dataSourceUrl); | |
}else{ | |
$w->loadDataSet(utf8_encode($dataSet)); | |
} | |
if($dataSetRoot != 'null'){ | |
$w->setDataRoot($dataSetRoot); | |
} | |
return $w->parse(); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{"list":{ | |
"contacts":[ | |
{ | |
"objecttypename":"contact", | |
"firstname":"Lars", | |
"lastname":"Wallin", | |
"phone":"+46 555 155555", | |
"email":"[email protected]", | |
"address":[ | |
{ | |
"type":"home", | |
"name":"My Home", | |
"street":"My Way 7", | |
"geodata":{ | |
"longitude":"-74.044636", | |
"latitude":"+40.689060", | |
"sealevel":{"m":"1000"} | |
}, | |
"geodata2":{ | |
"longitude":"-72.044636", | |
"latitude":"+41.689060" | |
} | |
}, | |
{ | |
"type":"away", | |
"name":"My Summer House", | |
"street":"Back wood 45" | |
} | |
] | |
}, | |
{ | |
"objecttypename":"contact", | |
"firstname":"Lisa", | |
"lastname":"Johnson", | |
"phone":"+46 555 131415", | |
"email":"[email protected]", | |
"address":[ | |
{ | |
"objecttypename":"address", | |
"type":"home", | |
"name":"My Little House", | |
"street":"That Way 123", | |
"geodata":{ | |
"longitude":"-70.044636", | |
"latitude":"+42.689060" | |
}, | |
"geodata2":{ | |
"longitude":"-71.044636", | |
"latitude":"+12.689060" | |
} | |
} | |
] | |
}, | |
{ | |
"objecttypename":"contact", | |
"firstname":"Peter", | |
"lastname":"Swift", | |
"phone":"+46 555 757677", | |
"email":"[email protected]", | |
"address":[ | |
{ | |
"objecttypename":"address", | |
"type":"home", | |
"name":"Any Bench", | |
"street":"Central Park", | |
"geodata":{ | |
"longitude":"-71.044636", | |
"latitude":"+43.689060" | |
} | |
} | |
] | |
} | |
] | |
}} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[[!simplx_widgeteer? | |
&dataSet=`[[$widgeteer_dataset_contactlist]]` | |
&dataSetRoot=`list` | |
&useChunkMatching=`true` | |
&chunkPrefix=`widgeteer_template_` | |
&chunkMatchingSelector=`objecttypename` | |
]] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<ul> | |
<li> | |
Name:<br/> | |
[[+name]] | |
</li> | |
<li> | |
Street:<br/> | |
[[+street]] | |
<br/>Geo tag:<br/> | |
<!-- Examples of "peek and grab" below --> | |
lat:[[+geodata.latitude]] | |
</br> | |
long:[[+geodata.latitude]] | |
</br> | |
sea level:[[+geodata.sealevel.m]] m | |
</li> | |
</ul> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<li> | |
<b> | |
[[+firstname]], [[+lastname]] | |
</b> | |
<br/> | |
[[+phone]] | |
<br/> | |
[[+email]] | |
<br/> | |
Address:<br/> | |
[[+address]] | |
<br/> | |
</li> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment