function __construct(&$content, $fieldContent) { $this->content =& $content; // TO DO validate valid? $this->valid = true; // error_log('*********************************'); $this->fieldContent = $fieldContent; // keyword is up to first bracket $this->keyword = trim(substr($fieldContent, 0, strpos($fieldContent, '('))); // error_log('Field Content = ' . $fieldContent); // error_log('Keyword = ' . $this->keyword); // Get content of function / field $this->fieldFunction = substr($fieldContent, strpos($fieldContent, '(') + 1, strlen($fieldContent) - strlen($this->keyword) - 2); // find in $this->inAtPos = strpos($this->fieldFunction, 'in @'); // error_log(' In keyword found at pos = ' . $this->inAtPos ); // get the variable name for the loop $this->varName = trim(substr($this->fieldFunction, 0, $this->inAtPos)); // error_log('VarName ' . $this->varName); // get the collection text $this->collectionContent = trim(substr($this->fieldFunction, $this->inAtPos + 3, $this->findClosingBracket($this->fieldFunction) - ($this->inAtPos + 3))); //error_log('Collection Content = ' . $this->collectionContent); $this->collection = $this->explodeCollection($this->collectionContent); // error_log(print_r($this->collection,1)); $item = array_shift($this->collection); // error_log("ITEM: " . $item['item']); if ($item['item'] == "@Page") { $item = array_shift($this->collection); // error_log("ITEM2: " . $item['item']); $this->collectionType = $item['item']; // get the section ID if ($item['item'] == "Sections") { $this->sectionID = $item['options']; } } else { $this->collectionType = "UNKNOWN"; } // Now get the content to loop output. e.g. between the first { and last } $this->startLoopPos = strpos($this->fieldFunction, '{'); $this->loopContent = substr($this->fieldFunction, $this->startLoopPos + 1); // error_log('*********************************'); /* Two options at the moment Children and Sections {|@foreach(item in @Page.Children.Where("!hidePage")) { <li>{|@item.Name|}</li> }|} {|@foreach(section in @Page.Sections(1)) { <h2>{|@section.heading1|}</h2> } */ $loopOutput = ''; switch ($this->collectionType) { case "Children": // now count the children - TO DO this will be more complicated with filters and sort orders and limits (e.g. first 5 ) @item.SomeField.Where('someethingisTrue'); $numChildren = 0; // as per sections below - copy and paste - TODO refactor if (isset($content->variables[$this->varName])) { $this->valid = false; $this->fieldContent = "Variable name error - already exists"; } else { $this->content->variables[$this->varName]['type'] = "child"; } if (isset($this->content->relatedContent) && count($this->content->relatedContent) > 0) { $sortByPos = pos_in_multiarray("SortBy", $this->collection, "item"); $paginationPos = pos_in_multiarray("Pagination", $this->collection, "item"); // error_log(print_r($this->collection,1)); $relatedContent = $this->content->relatedContent; // error_log(print_r($relatedContent,1)); // error_log("FIRST: ". $this->content->relatedContent[0]['lastUpdatedDate']); // if sortByPos has been found in the template function collection if ($sortByPos >= 0) { // sort! $sortStr = $this->collection[$sortByPos]["options"]; // if there is " DESC" in the string then set descending sort to true and replace $descPos = strpos(strtoupper($sortStr), " DESC"); $meta = array(); // look for descending if ($descPos) { $meta['descending'] = true; $sortStr = substr($sortStr, 0, $descPos); } else { $meta['descending'] = false; } $meta['field'] = trim(str_replace('"', '', $sortStr)); // check if a field is an internal field and not a content field (e..g nodeID or createdDate $internalFields = array("nodeID", "nodeName", "level", "pageType", "URL", "createdDate", "createdById", "createdBy", "lastUpdatedDate", "lastUpdatedBy", "lastUpdatedBy", "lastUpdatedById", "sortOrder"); if (in_array($meta['field'], $internalFields)) { $meta['internalField'] = true; } else { $meta['internalField'] = false; } usort($relatedContent, content_sorter($meta)); } // if pagination is found then we do pagination! if ($paginationPos >= 0) { $pageNum = 1; // get name of the page url variable $pageVar = $this->collection[$paginationPos]["options"]; if (isset($content->requestVars[$pageVar]) && is_numeric($content->requestVars[$pageVar]) && $content->requestVars[$pageVar] > 0) { $pageNum = $content->requestVars[$pageVar]; } // list requested page worth of results $count = 0; $itemsPerPage = 3; $lowerLimit = ($pageNum - 1) * $itemsPerPage; $upperLimit = $pageNum * $itemsPerPage; foreach ($relatedContent as $child) { // TO DO more matching if we us .Where('something is true'); // Check if it's a child if ($child['level'] == 1) { $numChildren++; if ($count >= $lowerLimit && $count < $upperLimit) { // set the current child node ID $this->content->variables[$this->varName]['childID'] = $child['nodeID']; // Now get the CMS helper to parse the loop content. $loopOutput .= $this->content->parseTemplate($this->loopContent); } $count++; } } // now add the pagination controls $loopOutput .= $this->CreatePaginationLinks($pageNum, $numChildren, $itemsPerPage, "/" . $content->pagePath . "/", $pageVar); } else { // List all foreach ($relatedContent as $child) { // TO DO more matching if we us .Where('something is true'); // Check if it's a child if ($child['level'] == 1) { $numChildren++; // set the current child node ID $this->content->variables[$this->varName]['childID'] = $child['nodeID']; // Now get the CMS helper to parse the loop content. $loopOutput .= $this->content->parseTemplate($this->loopContent); } } } } break; case "Sections": // first find the fields in the sections template section // $fields = parent::findFields($this->loopContent); // add the field var name to the variables in the content of the main CMS helper // check if this is already set and throw an error if it is (to stop nested use of the same var name - probably valid in programming // but too hard to deal with here if (isset($content->variables[$this->varName])) { $this->valid = false; $this->fieldContent = "Variable name error - already exists"; } else { $this->content->variables[$this->varName]['type'] = "Section"; $this->content->variables[$this->varName]['sectionID'] = $this->sectionID; } if (isset($this->content->sections[$this->sectionID])) { foreach ($this->content->sections[$this->sectionID]['sectionInstances'] as $section) { $childOutput = ''; $lastChildPos = 0; // for each section Instance update the @section variable in the content variable with the current instance $this->content->variables[$this->varName]['type'] = 'section'; $this->content->variables[$this->varName]['sectionInstanceID'] = $section; // Now get the CMS helper to parse the loop content. $loopOutput .= $this->content->parseTemplate($this->loopContent); } } // finally kill the variable in case it's reused in a future loop unset($this->content->variables[$this->varName]); break; default: if (DEBUG) { $loopOutput = "ERROR - invalid collection"; } else { $loopOutput = ""; } break; } // finally add the loop output to the main output $this->fieldContent = $loopOutput; }
function pos_in_multiarray($elem, $array, $field) { $top = sizeof($array) - 1; $bottom = 0; $count = 0; while ($bottom <= $top) { $curElem = $array[$bottom][$field]; if (trim($array[$bottom][$field]) == trim($elem)) { return $count; } else { if (is_array($array[$bottom][$field])) { if (pos_in_multiarray($elem, $array[$bottom][$field])) { return $count; } } } $bottom++; $count++; } return -1; }