We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 45766
    • 78 Posts
    Hi, not sure if this is an foolish question but i hope there is help for me - somewhere, outside wink

    I am using the widgeteer extra to get JSON from an API and show it at my MODx website.

    The Template-Chunk i used to show the items contains placeholder like [[+eventName]].

    Till now i thought its possible to use output filters for each placeholder but in this case they don't work.
    Do i have to activate the possibility to use output-filter in the snippet which generates the placeholders? If yes, HOW?

    This question has been answered by multiple community members. See the first response.

      • 3749
      • 24,544 Posts
      I'm not familiar with widgeteer or what it returns, but there are several possible options.

      First, the output modifiers should work for that. If you show us how you've applied them we might be able to help tweak them.

      Second, you always have the option of a custom output modifier.

      Third, you can create a custom snippet that uses $modx->runSnippet() to run the snippet that gets the JSON, set your own placeholders, then use $modx->getChunk on the Tpl chunk to create the output.

      Fourth, you can create a custom snippet, but steal the code from the extra to get the JSON data, then create the output as above.

      It would help if we could see your Tpl chunk, the output you want, and an example of the JSON data.

        Did I help you? Buy me a beer
        Get my Book: MODX:The Official Guide
        MODX info for everyone: http://bobsguides.com/modx.html
        My MODX Extras
        Bob's Guides is now hosted at A2 MODX Hosting
        • 45766
        • 78 Posts
        Hi Bob,

        thanks for your quick reply!

        Here is how i used it.

        TEMPLATE
        [[simplx_widgeteer?
          &dataSetUrl=`https://xxxxxxxx.de/visitor/events/?apikey=xxxxxxx`
          &useChunkMatching=`false`
          &staticChunkName=`persoo_eventlisting`        
        ]]
        


        CHUNK
        [[+imageURL:phpthumbof=`&w=500&h=500&zc=1`]
        <img src="[[!phpthumbof? &input=`[[+imageURL]]` &options=`&w=640&h=48&zc=0&aoe=0&far=0`]]" alt="" />
        [[+endDate:strtotime:date=`%a %b %e, %Y`]]
        


        JSON
        "endDate":1483138800000,
        "imageURL":"https://xxxxxxx.de/besucher/api/public-image/for-event/440cffe1-d68e-48e7-8a3d-c1238ff8e18f",
        


        Here is what widgeteer makes

        <?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,$preprocessor=null){
                    global $modx;   
                    
        	    if ($preprocessor) {	      	      	      
                      
        	      $dSet = $modx->runSnippet($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; 
        	    $dset;	
        	    
        	    if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: loadDataSet(), Dataset contains "'.$dSet.'".'); 	
        
        	    if($this->preprocessor){	     	                  
        	      $dSet = $this->preprocess($dSet,$this->preprocessor);
        	      $this->dataSet = $dSet;
                    }
        	    	            	    	    
        	    
                    $this->dataSetArray = $this->decode($dSet);
        	    
        	    if(is_array($this->dataSetArray)){
        	      
        	      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 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;
        	}	    
        
              
        	// Templates namespaced placeholders
        	function templateNSPlaceholders($chunk){
        	  global $modx;
        	  $collection = null;
        	  $currentType = '';
        	  
        	  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,' ');	 
        	  	  	  	  
        	  // The actual result of the preg_match is in the first index of the $placeholders array.
        	  $placeholders = $placeholders[0];
        	  	  
        	  foreach($placeholders as $placeholder){
        		
        		$value = '';
        
        		// Make a local copy for performance impr.
        		$current = $placeholder;	      
        	  
        	  	// 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
        				
        				  $currentType = $this->typeCheck($value);
        			
        				  if($currentType!=='simple'){
            
        				    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,' ');	  
        
        
        				    // Increment the i counter which is just used for debug purposes. 
        				    $i++;
        					
        				    // unset the pointer so that we dont screw with the history stack
        				    unset($pointer);
        
        				    // If we got an array, we need to step into it to get something usefull.
        				    if($currentType==='list'){	
        				      if($this->debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Widgeteer: templatePlaceholders() * Current stack item is an array.'); 		  
        				      $pointer = &$value[0];   
        				    
        				    }else{
        				      // 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.');
        				  }
        			   }			   			
        			}
            
        		    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);
        	}
              }    
        
              // 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;
        	  }
              }    	
        
              function typeCheck(&$var){
        	$val = '';
        	if(is_array($var)){
        	  if ($this->is_assoc($var)) {
        	    $val = 'object';
        	    
        	  }else{
        	    $val = 'list';
        	  }
        	}else{
        	  $val = 'simple';
        	}       
        	return $val;  
              }
            
            }
          
        
          }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 
        [ed. note: stefan79w last edited this post 9 years, 10 months ago.]
          • 45766
          • 78 Posts
          Hi Bob,

          i watched at the snippet-code and try to find the position where the magic happens. But maybe because i am not an developer i didn't find anything.

          I also tryed to find code snippets to build an "own" modx snippet which tooks JSON from an URL checks automatically which objects it has and which informations they includes, put them into placeholders and make it possible to render each with an chunk.

          Maybe i need more coffee wink
            • 3749
            • 24,544 Posts
            First, you're missing a closing bracket on this line:

            [[+imageURL:phpthumbof=`&w=500&h=500&zc=1`]


            It's worth trying it with that fixed, but I don't think that's the problem. I think the Widgeteer code may not recognize the imageURL placeholder as a placeholder because of the output modifier. It's looking for the traditional form of a placeholder:

            [[+placeholder_name]]



            The solution could be something like this (untested):


            Template:


            [[!GetData?
              &dataSetUrl=`https://xxxxxxxx.de/visitor/events/?apikey=xxxxxxx`
            ]]
            
            [[$persoo_eventlisting]]
            



            /* GetData snippet */
            
            $dSourceURL = $modx->getOption('dataSetUrl', $scriptProperties, '');
            
            if (!empty($dSourceURL)) {
                $ch = curl_init();
                curl_setopt($ch, CURLOPT_URL, $dSourceURL);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                $result = curl_exec($ch);
                curl_close($ch);  
            
                if ($result !== false) {
                    $data = json_decode($result);
                    if (!empty($data)) {
                         $modx->setPlaceholder('endDate', $data['endDate']);
                         $modx->setPlaceholder('imageURL', $data['imageURL']);
                    } else {
                        $modx->log(modX::LOG_LEVEL_ERROR, 'json_decode failed');
                    }
            
                } else {
                    $modx->log(modX::LOG_LEVEL_ERROR, 'cURL failed');
                }
            } else {
                $modx->log(modX::LOG_LEVEL_ERROR, 'dataSetURL is empty');
            }
            
            return '';


              Did I help you? Buy me a beer
              Get my Book: MODX:The Official Guide
              MODX info for everyone: http://bobsguides.com/modx.html
              My MODX Extras
              Bob's Guides is now hosted at A2 MODX Hosting
              • 45766
              • 78 Posts
              Yes, this ( ] ) was an copy paste error. Does not work with two ], too wink

              Your solution is a direction in which I thought before your answer. However, I am not advanced, because it became too complex for me because:


              1. There could be more than one object and i dont know how to build the repetition and say use this template for each object
              2. endDate and Image are just two informations of an object, there are much more and i thought there must be an solution without coding the informations hard into the script (but this is just an nice to have because i like clever scripts, even though i didn't know how to write them wink )

              Just for my understanding. I thought there is an general way to handle repetitions because any other extra what lists resources by using an chunk works with other extras (like phpthumbof) and output-filters. Am i wrong?
                • 45766
                • 78 Posts
                Ok, here is what i am currently working at

                >>>UPDATE<<<

                I thing i got it. But not sure if its bullshit, can you please habe a look?


                <?php
                /*
                
                use in template
                [[!persooBesucher?
                  &dataSetUrl=`xxx`
                  &dataSetApiKey=`xxx`
                  &tpl=`persoo-api`
                ]]
                
                */
                
                
                // get options and set variables
                $dSourceURL = $modx->getOption('dataSetUrl', $scriptProperties, '');
                $dSourceAPIKey = $modx->getOption('dataSetApiKey', $scriptProperties, '');
                $tplChunk = $modx->getOption('tpl', $scriptProperties, '');
                
                // get JSON
                if (!empty($dSourceURL)) {
                	$s = curl_init();
                	curl_setopt($s,CURLOPT_URL, $dSourceURL); 
                	curl_setopt($s,CURLOPT_HTTPHEADER,array('apikey:' . $dSourceAPIKey)); 
                	curl_setopt($s,CURLOPT_TIMEOUT, 30); 
                	curl_setopt($s,CURLOPT_RETURNTRANSFER,true);
                	$result = curl_exec($s);
                	curl_close($s);
                	
                	if ($result !== false) {
                		//decode JSON
                    $data = json_decode($result,true);
                    
                    if (!empty($data)) {
                    
                    	// TESTAUSGABE print_r($data);
                    	// for each object set placeholder and generate output
                    	$output = '';
                    	
                    	foreach ($data as $event) {
                    		
                    		$output .= $modx->getChunk($tplChunk,array(
                    		   $modx->setPlaceholder('id', $event['id']),
                    		   $modx->setPlaceholder('displayName', $event['displayName']),
                    		   $modx->setPlaceholder('introText', $event['introText']),
                    		   $modx->setPlaceholder('description', $event['description']),
                    		   $modx->setPlaceholder('imageURL', $event['imageURL']),
                    		   $modx->setPlaceholder('imageRegularURL', $event['imageRegularURL']),
                    		   $modx->setPlaceholder('imageCroppedURL', $event['imageCroppedURL']),
                    		   $modx->setPlaceholder('eventLink', $event['eventLink']),
                    		   $modx->setPlaceholder('formularLink', $event['formularLink']),
                    		   $modx->setPlaceholder('startDate', $event['startDate']),
                    		   $modx->setPlaceholder('endDate', $event['endDate']),
                    		   $modx->setPlaceholder('sumOpenVisitor', $event['sumOpenVisitor']),
                    		   $modx->setPlaceholder('sumConfirmedVisitor', $event['sumConfirmedVisitor']),
                    		   $modx->setPlaceholder('endDate', $event['endDate']),
                    		   $modx->setPlaceholder('sumAppearedVisitor', $event['sumAppearedVisitor']),
                    		   $modx->setPlaceholder('freeVisitors', $event['freeVisitors']),
                    		   $modx->setPlaceholder('maxVisitors', $event['maxVisitors']),
                    		   // toDo array imageDimensions
                    		));
                    	     
                    	
                    	}
                    	
                    	return $output;
                    	
                      
                    } else {
                			$modx->log(modX::LOG_LEVEL_ERROR, 'json_decode failed');
                    }
                 
                  } else {
                		$modx->log(modX::LOG_LEVEL_ERROR, 'cURL failed');
                  }
                } else {
                		$modx->log(modX::LOG_LEVEL_ERROR, 'dataSetURL is empty');
                }
                return '';
                
                [ed. note: stefan79w last edited this post 9 years, 10 months ago.]
                  • 45766
                  • 78 Posts
                  Ok, one (hopefully) last Question. Any idea why this here is not working? Would be the nice to have i wished today morning laugh

                  foreach ($data as $event) {
                      	
                                  $placeholders = array();
                                  foreach ($event as $key => $value) {
                                      if (!is_array($value)) {
                                          $placeholders[$key] = $value;
                                      }
                                  }
                  
                                  $output .= $modx->getChunk($tplChunk, $placeholders);
                              }
                  
                  • discuss.answer
                    • 3749
                    • 24,544 Posts
                    I think you may be doing more work than you have to. wink

                    After the json_decode() line, the subarrays in the $data array may already be what you need as the second argument to getChunk().

                    This might do it without using the $placeholder variable or the inner foreach loop:

                    foreach ($data as $event) {
                       $output .= $modx->getChunk($tplChunk, $event);
                    }
                    
                    return $output;
                    
                      Did I help you? Buy me a beer
                      Get my Book: MODX:The Official Guide
                      MODX info for everyone: http://bobsguides.com/modx.html
                      My MODX Extras
                      Bob's Guides is now hosted at A2 MODX Hosting
                    • discuss.answer
                      • 45766
                      • 78 Posts
                      Good Morning Bob!

                      Life could be so easy … ;)

                      Thanks, this works fine! So here is the final snippet which gets JSON from an URL and render it using a chunk:

                      Template call
                      [[!persooBesucher?
                        &dataSetUrl=`https://xxx`
                        &dataSetApiKey=`xxx`
                        &tpl=`persoo-api`
                      ]]
                      


                      Chunk
                      Use the JSON ID as Placeholder (example)
                      <img src="[[+imageCroppedURL:phpthumbof=`&w=300&h=100&zc=1`]]" alt="" /><br /><br />
                      [[+endDate:strtotime:date=`%a %b %e, %Y`]]
                      



                      Snippet (persooBesucher)
                      <?php
                      // get options and set variables
                      $dSourceURL = $modx->getOption('dataSetUrl', $scriptProperties, '');
                      $dSourceAPIKey = $modx->getOption('dataSetApiKey', $scriptProperties, '');
                      $tplChunk = $modx->getOption('tpl', $scriptProperties, '');
                      
                      // get JSON
                      if (!empty($dSourceURL)) {
                      	$s = curl_init();
                      	curl_setopt($s,CURLOPT_URL, $dSourceURL); 
                      	curl_setopt($s,CURLOPT_HTTPHEADER,array('apikey:' . $dSourceAPIKey)); 
                      	curl_setopt($s,CURLOPT_TIMEOUT, 30); 
                      	curl_setopt($s,CURLOPT_RETURNTRANSFER,true);
                      	$result = curl_exec($s);
                      	curl_close($s);
                      	
                      	if ($result !== false) {
                      		//decode JSON
                          $data = json_decode($result,true);
                          
                          if (!empty($data)) {
                          
                          	// TESTAUSGABE print_r($data);
                          	// for each object set placeholder and generate output
                          	$output = '';
                          	
                          	foreach ($data as $event) {
                          	       $output .= $modx->getChunk($tplChunk, $event);
                          	}
                          	
                          	return $output;
                          	
                            
                          } else {
                      			$modx->log(modX::LOG_LEVEL_ERROR, 'json_decode failed');
                          }
                       
                        } else {
                      		$modx->log(modX::LOG_LEVEL_ERROR, 'cURL failed');
                        }
                      } else {
                      		$modx->log(modX::LOG_LEVEL_ERROR, 'dataSetURL is empty');
                      }
                      return '';