static function preg_replace_dom(DOMNode $dom, array $exclude = array()) { if (empty($dom->childNodes)) { return; } foreach ($dom->childNodes as $node) { // if the node is in the exclude list, skip it and its children if (in_array($node->nodeName, $exclude)) { continue; } if ($node instanceof DOMText) { $totalcount = 0; // try and match all glossary words we have in the foreach (self::$glossary as &$data) { $data_offset = $data->ref; if (empty($data->inuse) || !$data->inuse) { continue; } $replace = "XXX_GLOSSARY_" . $data_offset . "_\$1_XXX"; $count = 0; // UNCOMMENT and CHANGE $data->limit to $base_data->limit to make sure that alt words // share the same count and the main word. //$base_data = $data; //if ($data->base_offset > -1) // $base_data = self::$glossary[$data->base_offset]; $node->nodeValue = preg_replace_callback($data->regex, function ($match) use($data_offset) { return "XXX_GLOSSARY_" . base64_encode($data_offset) . "_" . base64_encode($match[0]) . "_XXX"; //return str_replace('$1', $match[0], $replace); }, $node->nodeValue, $data->limit, $count); if ($count) { $data->limit -= $count; $totalcount += $count; } } if ($totalcount) { $runs = 0; // run counter incase it goes wrong and gets carried away // temp node that we are working on $temp = $node; // find tag in node text if (function_exists("mb_strpos")) { $pos = mb_strpos($temp->nodeValue, "XXX_GLOSSARY_"); } else { $pos = strpos($temp->nodeValue, "XXX_GLOSSARY_"); } while ($pos !== FALSE && $runs++ < 50) { // split the text node around the match $new = $temp->splitText($pos); // remove match text from split text and retrieve info list($elem, $new->nodeValue) = explode("_XXX", $new->nodeValue, 2); // parse the info found $elem = substr($elem, 13); list($elem, $text) = explode("_", $elem, 2); $elem = base64_decode($elem); $text = base64_decode($text); // lookup info we saved earlier $data_offset = self::$glo_ref[$elem]; $info = self::$glossary[$data_offset]; // build link element $link_elem = FSS_Glossary::$cdom->createElement('a', $text); $link_elem->setAttribute("href", $info->href); $link_elem->setAttribute("class", 'fss_glossary_word'); $link_elem->setAttribute("ref", $info->ref); $link_elem->setAttribute("context", FSS_Glossary::$context); // insert link element before 2nd part of text split $temp->parentNode->insertBefore($link_elem, $new); // copy the new node over the old temp one $temp = $new; // find the text again if (function_exists("mb_strpos")) { $pos = mb_strpos($temp->nodeValue, "XXX_GLOSSARY_"); } else { $pos = strpos($temp->nodeValue, "XXX_GLOSSARY_"); } } } } else { FSS_Glossary::preg_replace_dom($node, $exclude); } } }