public static function RemoveBlocksFromString($st, $tagStartBlock, $tagEndBlock, $posStart = 0) { // Remove all blocks/substrings starting with $tagStartBlock and ending with $tagEndBlock, ex. "<div" and "</div>" removes all divs from html code if (empty($st)) { return $st; } $r = ""; $posLastEnd = $posStart; while (true) { // find bounds of next block: $posBlock = strpos($st, $tagStartBlock, $posLastEnd); $addstr = $posBlock !== false ? substr($st, $posLastEnd, $posBlock - $posLastEnd) : substr($st, $posLastEnd); $r .= $addstr; // add to result the substring before block (starts from 0 or from end of last block) or remaining part after all blocks if ($posBlock === false) { break; } // no more blocks $posLastEnd = OEDynUtils::FindEndBlock($st, $posBlock + 1, $tagStartBlock, $tagEndBlock); // end of this block if ($posLastEnd < 0) { return $st; } // error, non-terminated block $posLastEnd += strlen($tagEndBlock); // first character after this block } return $r; // = $st with all blocks removed }
function __SplitCodeIntoColumns($st, &$allDBValues) { /* Split inner iterator code into "output columns" - synchronous parts, normally corresponding to <td> tags. If there is no split, code is considered to be 1 column "Output column" is, for example, a column of DBGrid (html table showing query results) Main reason to split is that a column may have rows with ROWSPANS, if data is grouped (ex. several values in column B corresponding to 1 value in column A) * * * */ //echo "Entering __SplitCodeIntoColumns()<br/>";var_dump($st); $arCodeParts = array(); $arCodeParts[]['code'] = ''; $arCodeParts[0]['codeNoSubIt'] = ''; $arCodeParts[0]['usedDBValues'] = array(); if ($st === null || $st === '' || strpos($st, '</td>') === false) { // no parts return $this->__AddAllCodeAsOnePart($st, $arCodeParts, $allDBValues); // a single part, no html columns } // go through all <td> that are not in subiterators: $currLen = 0; // part of string currently processed or already processed $lastPartEnd = -1; // pos of last character of code already added to $arCodeParts $posAfterLastIterator = 0; // pos of first character after last-found subiterator $inTD = false; // currently inside <td> $posTD = -1; // position of last-found <td> tag in $st $partInd = -1; // part counter, modified in __AddAndAnalyseCodePart() while (true) { // process till next subiterator or till end of code string: $posIterator = strpos($st, $this->ITSTART, $posAfterLastIterator); // find next <!--__OEITSTART $stBeforeIterator = $posIterator !== false ? substr($st, $posAfterLastIterator, $posIterator - $posAfterLastIterator) : substr($st, $posAfterLastIterator); $currLen = $posAfterLastIterator + strlen($stBeforeIterator); //echo "\$stBeforeIterator:<br/>";var_dump($stBeforeIterator); // the following loop applies to substring before/between/after subiterator block(s): // in the currently processed substring, process <td></td> as well as html outside them // (note that beginning of <td> may be before last subiterator, i.e. in one of previous substrings, not in $stBeforeIterator) while (true) { if ($inTD) { // currently inside <td> // find </td> nd see if it's inside $stBeforeIterator (before next subiterator): $pos = OEDynUtils::FindEndBlock($st, $posTD + 1, '<td', '</td>'); // find closing </td>, consider possible sub-tables inside <td> if ($pos === false || $pos < $posTD) { echo '<br/><br/>!!!!!!!!!!!!IT ERR 1<br/>$st<br/>'; return $this->__AddAllCodeAsOnePart($st, $arCodeParts, $allDBValues); } // error - <td> tag is not closed $pos += strlen('</td>') - 1; // pos of last character of code part if ($pos >= $currLen) { break; } // </td> is after subiterator, not in current substring; process in next WHILE iteration // add and analyse new code part corresponding to <td>..</td>: $this->__AddAndAnalyseCodePart($st, $posTD, $pos, $partInd, $arCodeParts, $allDBValues); // ex ....[<td....</td>].... $lastPartEnd = $pos; $inTD = false; // quitting <td> //echo "outTD<br/>"; } $endReached = $lastPartEnd + 1 === strlen($st); // true if no more code left if ($endReached) { return $arCodeParts; } // all processed if (!$inTD) { // currently outside <td> $pos = strpos($st, '<td', $lastPartEnd + 1); if ($pos === false) { // no more <td>, but some code remains at the end - add as last part and exit: $this->__AddAndAnalyseCodePart($st, $lastPartEnd + 1, strlen($st), $partInd, $arCodeParts, $allDBValues); // ex ....</td>[</tr>] return $arCodeParts; } if ($pos >= $currLen) { break; } // <td> is after subiterator, not in current substring; process in next WHILE iteration // new <td> found: //echo "inTD<br/>"; $posTD = $pos; $inTD = true; // now we are inside <td> // if there's any code before this <td> (ex. <tr> at beginning of iterator) not yet added as a part, add new part: if ($posTD - ($lastPartEnd + 1) > 0) { $this->__AddAndAnalyseCodePart($st, $lastPartEnd + 1, $posTD - 1, $partInd, $arCodeParts, $allDBValues); // ex [<tr>]<td>.... $lastPartEnd = $posTD - 1; } } if (!$inTD) { break; } // no more parts } if ($posIterator === false) { echo '<br/><br/>!!!!!!!!!!!!IT ERR 0<br/>$st<br/>'; // error, normally should never happen return $this->__AddAllCodeAsOnePart($st, $arCodeParts, $allDBValues); } // Bypass subiterator: // find substring corresponding to iterator: $posAfterLastIterator = OEDynUtils::FindEndBlock($st, $posIterator + 1, $this->ITSTART, $this->ITEND); if ($posAfterLastIterator < 0) { echo '<br/><br/>!!!!!!!!!!!!IT ERR 2<br/>$st<br/>'; // error, missing end of subiterator return $this->__AddAllCodeAsOnePart($st, $arCodeParts, $allDBValues); } $posAfterLastIterator += strlen($this->ITEND); // position just after the iterator } return $arCodeParts; }