We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 40761
    • 10 Posts
    Hello All,

    I need a clue about nesting snippet calls in chunks, and what the order of evaluation is for nested snippet calls.

    I have a chunk named expandingList. Inside the chunk is a call to a snippet named getWord. getWord does a DB call to get a word based on a parameter. The parameter is not hardcoded, instead it is represented by a placeholder tag.

    I have another snippet named getExpandingList which takes in a parameter that is the actual parameter for getWord. It uses $modx->getChunk() to get the chunk, and then set the parameter to getWord using str_repalce on the placeholder tag before returning it.

    Now getExpandingList works fine if called once. It runs, then getWord runs. So, getWord returns a value for the parameter passed in to getExpandingList. I know this because both snippets are sending messages into a log file.

    But, if I call getExpandingList several times in the same page, sometimes getWord is run before getExpandingList.

    How can I force order of evaluation when dynamically modifying chunks that contain embedded snippet calls? Or is there a different way to do this?

    Of course, I could just have getExpandingList call getWord directly, but that breaks the power of having getWord embedded in the chunk.

    Any clues appreciated!

    Thanks,
    Mark
      • 4172
      • 5,888 Posts
      your code?
        -------------------------------

        you can buy me a beer, if you like MIGX

        http://webcmsolutions.de/migx.html

        Thanks!
      • Why can't you have getExpandingList just set a unique placeholder to use in getWord for this?
          • 40761
          • 10 Posts
          Hey Guys,

          Sorry I didn't reply today. I'll post code and explain in a bit more depth on Monday. Thanks for the replies...

          -- Mark
            • 40761
            • 10 Posts
            Hello All,

            Sorry I haven't posted sooner, but its been a busy week. First, some replies:

            @bruno, code attached, see the end of this post. I haven't attached all the code, but I have attached the four key pieces:
            getWord (snippet)
            expandingList (chunk)
            getExpandingList (snippet)
            userForm (chunk)

            The other three pieces in this example are all chunks, and they contain three calls to getWord, all of which (strangely enough) work.

            @opengeek, what I'm doing here is recursive, so I don't know how I could have getExpandingList set placeholders for getWord. In this example, userForm calls both getWord and getExpandingList. The expandingList chunk contains a call to getWord. And, other chunks/snippets are passed in to getExpandingList which contain calls to getWord. To clarify, here is a tree diagram of the chunks and snippets in the order in which they are encountered:

            userForm
            	getWord
            	getWord
            	getWord
            	getWord
            	getWord
            	getWord
            	getWord
            	getWord
            	getExpandingList
            		expandingList
            			getWord
            			getPhoneNumberForms
            				phoneNumberForm
            					getWord
            					getWord
            					getWord
            	getExpandingList
            		expandingList
            			getWord -- FAILS
            			addressForm
            				getWord
            				getWord
            				getWord
            	getExpandingList
            		expandingList
            			getWord -- FAILS
            			groupsForm
            				getWord
            				getWord
            				getWord	
            	getExpandingList
            		expandingList
            			getWord -- FAILS
            			permissionsForm
            				getWord
            				getWord
            				getWord
            	getExpandingList
            		expandingList
            			getWord -- FAILS
            			ipAddressForm
            				getWord
            				getWord
            				getWord
            


            Note that only 4 of the calls to getWord fail (marked above). They fail because getExpandingList hasn't changed [listTitle] yet. All the other calls work.

            In summary, all I'm asking for is ideas, I know I'm going to have to figure this out. But, any clues about how nested chunks and snippets are processed would be appreciated, incuding what parts of modx source to read, or any debugging techniques that might help.

            -- Grateful Mrex

            ********

            Now, some code. While the code may seem long, the majority of it is checking incoming parameters. Also, $logger is reference to a singleton Logger object, that simply writes messages to a log file. All the calls are usually turned off by setting $debug to false.

            Here is getWord:
            	//
            	// getWord -- Copyright 2012 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            	//
            	// Translates a word into the current language using the GSIDictionary table, given the word
            	// and an optional two letter language code.  Gets the current language from $_SESSION[ "curLang" ].
            	// If &language is not specified, it defaults to "en" for english.
            	//
            	// Parameters:
            	//		&word 		-- required
            	//		&language 	-- optional
            	//
            
            	$debug	= $_SESSION[ "debug" ];
            	$logger	= $_SESSION[ "logger" ];
            	$retVal	= "";
            
            
            		//
            		// Check the parameters
            		//
            
            
            		// Check &debugOn parameter
            
            	if ( isset( $debugOn )) {
            		$debug	= true;
            	}
            	if ( $debug ) {
            		$logger->log( "In getWord" );
            	}
            
            		// Check &word parameter
            
            	if ( !isset( $word )) {
            		if ( $debug ) {
            			$logger->log( "\$word not set, exiting", 1 );
            		}
            		return $retVal;
            	} else if ( $word == "" ) {
            		if ( $debug ) {
            			$logger->log( "\$word is empty, exiting", 1 );
            		}
            		return $retVal;
            	}
            	$retVal		= $word;
            	if ( $debug ) {
            		$logger->log( "\$word = [" . $word . "]", 1 );
            	}
            
            		// Check $_SESSION[ "curLang' ]
            
            	$toLang	= "en";
            	if ( isset( $_SESSION[ "curLang" ])) {
            		$toLang	= $_SESSION[ "curLang" ];
            	} else if ( $debug ) {
            		$logger->log( "\$_SESSION[ \"curLang\" ] is not set, defaulting to english", 1 );
            	}
            	if ( $debug ) {
            		$logger->log( "\$toLang = [" . $toLang . "]", 1 );
            	}
            
            		// Check &language parameter
            
            	$fromLang = "en";
            	if ( isset( $language )) {
            		$fromLang	= $language;
            	} else if ( $debug ) {
            		$logger->log( "\$language parameter is not set, defaulting to english", 1 );
            	}
            	if ( $debug ) {
            		$logger->log( "\$fromLang = [" . $fromLang . "]", 1 );
            	}
            
            
            		//
            		// Query the database 
            		//
            
            
            	$procArgs	= array( $word, $fromLang, $toLang );
            	$gsiDB		= new Database();
            	try {
            		$gsiDB->openDB();
            		$gsiDB->execProcedure( "up_TranslateByGSIDictionary", $procArgs );
            
            		if ( $gsiDB->numrows > 0 ) {
            			if ( $debug ) {
            				$logger->log( "Found translation", 1 );
            			}
            
            				// set properties to incoming data from DB
            
            			$gsiDB->result->data_seek( 0 );
            			$row	= $gsiDB->result->fetch_assoc();
            
            			$retVal	= utf8_encode( $row[ $toLang ]);
            
            		} else {
            			if ( $debug ) {
            				$logger->log( "Can't find translation for this word", 1 );
            			}
            		}
            
            	} catch ( Exception $ex ) {
            		$logger->log( "Exception caught in getWord: [" . $ex->getMessage() . "]", 1 );
            	}
            	$gsiDB->closeDB();
            
            		// Return 
            
            	if ( $debug ) {
            		$logger->log( "\$retVal = [$retVal]", 1 );
            		$logger->log( "Done getWord", 1 );
            	}
            
            	return $retVal;
            


            Here is the expandingList chunk, with the call to getWord in it. Note the placeholder [listTitle] as the
            &word parameter for the call, along with the other placeholders [listName] and [listContent]:

            	<div id = "[listName]" >
            		<div id = "[listName]Detail"
            				class = "sectionHeader"
            				onclick = "showHideDiv( '[listName]Toggle', '[listName]List' );">
            			<span id = "[listName]Toggle"
            					class = "expandBox openBox"></span>
            			<p>[[!getWord? &word = `[listTitle]` &debugOn = `true` ]]</p>
            		</div>
            		<div id = "[listName]List" class = "hide" >
            			[listContent]
            		</div>
            		<p />
            	</div>
            


            Here is getExpandingList:
            	//
            	// getExpandingList -- Copyright 2012 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            	//
            	// creates an expanding list using the expandingList chunk.  Embedds another chunk or the results of a snippet.
            	//
            	// Parameters:
            	//	&listName -- the name of the list
            	//  &listTitle -- the title of the list
            	//	&listSnippet -- the modx call for a snippet, with parameters
            	//	$listChunk -- the call for a chunk
            	//
            	// Note: only one of &listSnippet and &listChunk are required.
            	//
            
            	$debug	= $_SESSION[ Utils::SKEY_DEBUG ];
            	$logger	= $_SESSION[ Utils::SKEY_LOGGER ];
            	$retVal	= "";
            
            		// Check &debugOn parameter
            
            	if ( isset( $debugOn )) {
            		$debug	= true;
            	}
            	if ( $debug ) {
            		$logger->log( "In getExpandingList" );
            		$logger->log( "count( \$scriptProperties ) = [" . print_r( $scriptProperties, true ) . "]", 1 );
            	}
            
            		//
            		// Check the parameters
            		//
            
            
            		// Check &listName parameter
            
            	if ( !( $listName = Utils::getSnippetParameter( "listName", $scriptProperties ))) {
            		if ( $debug ) {
            			$logger->log( "&listName missing or empty, exiting", 1 );
            		}
            		return $retVal;
            	}
            
            		// Check &listTitle parameter
            
            	if ( !( $listTitle = Utils::getSnippetParameter( "listTitle", $scriptProperties ))) {
            		if ( $debug ) {
            			$logger->log( "&listTitle missing or empty, exiting", 1 );
            		}
            		return $retVal;
            	}
            
            		// Check &listContent parameters
            
            	$listContent	= Utils::getSnippetParameter( "listContent", $scriptProperties );
            	if ( $listContent === false ) {
            		if ( $debug ) {
            			$logger->log( "Missing listContent parameter, using empty string", 1 );
            		}
            		$listContent	= "";
            	}
            
            		// Get the expandingList chunk
            
            	$list	= $modx->getChunk( 'expandingList' );
            
            		// Replace listName, listTitle, listSnippet and listChunk
            
            	$list	= str_replace( "[listName]", $listName, $list );
            	$list	= str_replace( "[listTitle]", $listTitle, $list );
            	$list	= str_replace( "[listContent]", $listContent, $list );
            
            		// Evaluate the result?
            
            	$retVal	= $list;
            
            		// Return 
            
            	if ( $debug ) {
            		$logger->log( "strlen( \$retVal ) = [" . strlen( $retVal ) . "]", 1 );
            		$logger->log( "Done getExpandingList", 1 );
            	}
            
            	return $retVal;
            


            Finally, here is the userForm chunk, which calls getExpandingList and getWord many times:
            	<div id = "userForm" >
            		<span class = "fieldLabel" >[[!getWord? &word = `Last Changed` ]]:</span>
            		 
            		<span id = "ufDateChanged"> </span>
            		 
            		<span class = "fieldLabel" >[[!getWord? &word = `Added` ]]:</span>
            		<span id = "ufDateAdded"> </span>
            
            		<table id = "manageUserTable1" class = "formTable" >
            			<tr>
            				<td class = "fieldLabel" >
            					[[!getWord? &word = `ID` ]]
            				</td>
            				<td class = "fieldLabel" >
            					[[!getWord? &word = `Username` ]]
            				</td>
            				<td class = "fieldLabel" >
            					[[!getWord? &word = `Password` ]]
            				</td>
            				<td class = "fieldLabel" >
            					[[!getWord? &word = `Expires` ]]
            				</td>
            				<td class = "fieldLabel" >
            					[[!getWord? &word = `User Type` ]]
            				</td>
            				<td class = "fieldLabel" >
            					[[!getWord? &word = `Email` ]]
            				</td>
            			</tr>
            			<tr>
            				<td >
            					<span id = "ufID" ></span>
            				</td>
            				<td >
            					<input id = "ufUserName" class = "textField" type = "text" >
            				</td>
            				<td>
            					<input id = "ufPasswordBtn" type = "button" value = "Reset" >
            				</td>
            				<td >
            					<input id = "ufExpires" class = "textField" type = "text" >
            				</td>
            				<td >
            					<select id = "ufTypeID" >
            						<option value = ""></option
            					</select>
            				</td>
            				<td >
            					<input id = "ufEmail" class = "textField" type = "text" >
            				</td>
            			</tr>
            		</table>
            		<table id = "manageUserTable1" class = "formTable" >
            			<tr>
            				<td>
            					<span class = "fieldLabel" >[[!getWord? &word = `Supervisor` ]]:</span> 
            					<br />
            					<a id = "supervisor" href = "javascript: alert( 'Not implemented yet' );" >First Last</a>
            				</td>
            				<td>
            					<span class = "fieldLabel" >[[!getWord? &word = `Notes` ]]:</span> 
            				</td>
            				<td>
            					<textarea id = "ufNotes" class = "textArea" ></textarea>
            				</td>
            			</tr>
            		</table>
            		<input id = "ufID" type = "hidden" value = "">
            		<input id = "ufPassword" type = "hidden" value = "">
            		<input id = "ufTempLink" type = "hidden" value = "">
            		<input id = "ufSupervisorID" type = "hidden" value = "">
            		<p />
            		<input id = "ufFindBtn" type = "button" value = "find" > 
            		<input id = "ufNewBtn" type = "button" value = "new" > 
            		<input id = "ufSaveBtn" type = "button" value = "save" > 
            		<input id = "ufDeleteBtn" type = "button" value = "delete" > 
            		<p />
            
            
            	[[!getExpandingList? &listName = `managePhoneNumbers`,
            							&listTitle = `Phone Numbers`,
            							&listContent = `[[!getPhoneNumberForms? &id = `1`]]`,
            							&debugOn = `true`  ]]
            	[[!getExpandingList? &listName = `manageAddresses`,
            							&listTitle = `Addresses`,
            							&listContent = `[[$addressForm]]`,
            							&debugOn = `true` ]]
            	[[!getExpandingList? &listName = `manageGroups`,
            							&listTitle = `Groups`,
            							&listContent = `[[$groupsForm]]` ]]
            	[[!getExpandingList? &listName = `managePermissions`,
            							&listTitle = `Permissions`,
            							&listContent = `[[$permissionsForm]]` ]]
            	[[!getExpandingList? &listName = `manageIPAddresses`,
            							&listTitle = `IP Addresses`,
            							&listContent = `[[$ipAddressForm]]`,
            							&debugOn = `true` ]]
            
            	</div>