Extension:FeaturedPageTeaser

What can this extension do?
Display daily "teaser" excerpt from a page linked on the {ns:4} wiki.GIS.com:Featured_Pages page

Usage
"FeaturedPage.php" - The "Page of the Day" is selected sequentially, starting from a random position in the file, "wiki.GIS.com:Featured_Pages". The chosen pages must be shown as links, i.e. PageName. Text within this page is ignored, and may be used for comments. It is recommended that the administrator use a numbered list for easy reference to what has been chosen today and what will be chosen next, i.e.:

...etc.
 * 1) PageName1
 * 2) PageName2

When the number of page links changes, the rotation will resume from a random location, cycle normally through the list and continue cycling.

Typical Mediawiki implementation for the calling page:  chars=760 
 * style="padding:0 10px 0 10px;" |
 * style="padding:0 10px 0 10px;" |

Options
The following variables can be passed from the calling page: Variable       Default   Explanation chars          650       maximum number of TEXT characters to be returned days              0       +/- day(s) offset for links in Featured_Pages rotation

Installation
To install this extension, add the following to LocalSettings.php: require_once("$IP/extensions/FeaturedPageTeaser/FeaturedPageTeaser.php");

These files are read & executed, set permissions to 775. From the command line in the Test directory type: chmod -R 775 ./*

Code : FeaturedPageTeaser.php
'),       array ( 'start' => ':$$',       'end'  => '$$'),        // ul tables ;        array ( 'start' => "\n***",        'end'  => "\n"),        array ( 'start' => "\n**",         'end'  => "\n"),        array ( 'start' => "\n*",          'end'  => "\n"),        array ( 'start' => "\n###",        'end'  => "\n"),        array ( 'start' => "\n##",         'end'  => "\n"),        array ( 'start' => "\n#",          'end'  => "\n"),         array ( 'start' => 'Category:', 'end'  => ),        array ( 'start' => ),         // double curly-braces (Cite)        array ( 'start' => ),         array ( 'start' => ),         // curly-brace pipe (Tables - tables can contain images)        array ( 'start' => '{|',           'end'  => '|}'),    );

foreach ($remove as $markup ) { rmStr ($text, $markup['start'], $markup['end']); } }

/* * Remove data in string between markers $startMarker and $endMarker */ function rmStr( &$text=, $startMarker=, $endMarker='') { $len  = strlen ($text); $smLen = strlen ($startMarker); $emLen = strlen ($endMarker); if (strlen($text) < $smLen) return; $newtext = ''; $ptr  = 0; $changed = false; while ($ptr < $len) { $found = stripos ($text, $startMarker, $ptr); $endTag = stripos ($text, $endMarker, $found +$smLen); if (!$endTag) $endTag = $len; if ($found !== false) { // test for nested markers // special cases:  '[[Image:' '[[Category:' etc. need to test for nested '[['            if ($endMarker == ']]') {                     $nextStart = @strpos ($text, , $found + $smLen);                if (!$nextStart)                    $nextStart = $len;                while ($nextStart < $endTag) {                    $nextStart = @strpos ($text, '[[', $nextStart + 2);                    $endTag = @strpos ($text, , $endTag + $emLen);                    if (!$endTag)                        $endTag = $len;                }            }            elseif ($endMarker == '}}') {    // nested {{ tags ?                $nextStart = @strpos ($text, '{{', $found + $smLen);                if (!$nextStart)                    $nextStart = $len;                while ($nextStart < $endTag) {                    $nextStart = @strpos ($text, '{{', $nextStart + 2);                    $endTag = @strpos ($text, '}}', $endTag + $emLen);                    if (!$endTag)                        $endTag = $len;                }            }            $nextStart = @strpos ($text, $startMarker, $found + $smLen);            if (!$nextStart)                $nextStart = $len;            while (($nextStart !== false) && ($nextStart < $endTag)) {                $nextStart = @strpos ($text, $startMarker, $nextStart + 2);                $endTag = @strpos ($text, $endMarker, $endTag + $emLen);                if (!$endTag)                    $endTag = $len;            }            // copy up to the start tag            $newtext .= substr( $text, $ptr, $found - $ptr);            // move the pointer beyond the end tag UNLESS newline            if ($endMarker == "\n")                $endTag--; // endTag newline on a table may also be a startTag!            $ptr = ($endTag + $emLen < $len) ? $endTag + $emLen : $len;            $changed = true;        }        else {            // no more tags - finish copy            $newtext .= substr ($text, $ptr, $len - $ptr);            $ptr = $len;        }    }    if ($changed)        $text = $newtext; }

/* * Translate link tags within $text */ function WikiLinks ( &$text='' ) { if ($text == '') return ''; $len = strlen ($text); $ptr = 0; $newtext = ''; $changed = false; // internal links first while ($ptr < $len) { $startlink = strpos ($text, , $ptr);       if (!$startlink) {            if (!$changed)                break; // nothing to do            $startlink = $len;        }        else            $changed = true;        $endlink = strpos ($text, , $startlink); if (!$endlink) $endlink = $len; $pipe = strpos ($text, '|', $startlink); if (!$pipe) $pipe = $endlink; $linkhref = ''; $linktext = ''; if ($pipe < $endlink) { $linktext = substr( $text, $startlink+2, $pipe - $startlink-2 ); $linkhref = str_replace( ' ', '_', $linktext ); // fix '_' in link name

// look for parenthesis within the link - those data are ignored for link text // ex: Bearing_(navigation) $parenStart = strpos( $linktext, '(' );           if ($parenStart !== false) {                $parenEnd = strpos( $linktext, ')', $parenStart +1); if ($parenEnd) { $newhref = substr( $linktext, 0, $parenEnd +1 - $parenStart ); $newhref = trim( $newhref ); $linktext = $newhref; }           }            // check for additional pipes (thumb, size, alignment etc) and go to the last one (Title) while ($pipe < $endlink) { $nextPipe = strpos ($text, '|', $pipe+1); if (($nextPipe == false) || ($nextPipe > $endlink)) break; $pipe = $nextPipe; }           $linktext = substr( $text, $pipe+1, $endlink - $pipe-1 ); }       else { $linktext = substr( $text, $startlink+2, $endlink - $startlink-2 ); $linkhref = str_replace( ' ', '_', $linktext ); // fix '_' in link name }       $newtext .= substr ($text, $ptr, $startlink - $ptr); $newtext .= "$linktext"; $ptr = ($endlink + 2 < $len) ? $endlink + 2 : $len; }   if ($changed) $text = $newtext; // now external links: $len = strlen ($text); $ptr = 0; $newtext = ''; while ($ptr < $len) { $startlink = strpos ($text, '[http', $ptr); if ($startlink === false) { if ($changed === false) break;        // nothing to do            $startlink = $len; }       else $changed = true; $endlink = strpos ($text, ']', $startlink); if (!$endlink) $endlink = $len; $space = strpos ($text, ' ', $startlink); if (!$space) $space = $endlink; $linkhref = ''; $linktext = ''; if ($space < $endlink) { $linktext = substr( $text, $startlink+1, $space - $startlink-1 ); $linkhref = str_replace( ' ', '_', $linktext ); // fix '_' in link name // look for parenthesis within the link - those data are ignored for link text $parenStart = strpos( $linktext, '(' );           if ($parenStart) {                $parenEnd = strpos( $linktext, ')', $parenStart +1); if ($parenEnd) { $newhref = substr( $linktext, $parenStart, $parenEnd +1 - $parenStart ); $newhref = trim( $newhref ); $linktext = $newhref; }           }            $linktext = substr( $text, $space+1, $endlink - $space-1 ); }       else { $linktext = substr( $text, $startlink+1, $endlink - $startlink-1 ); $linkhref = str_replace( ' ', '_', $linktext ); // fix '_' in link name }       $newtext .= substr ($text, $ptr, $startlink - $ptr); $newtext .= "$linktext"; $ptr = ($endlink + 1 < $len) ? $endlink + 1 : $len; }   if ($changed) $text = $newtext; }

/* * Replace Wiki Headers with Html */ function WikiHeadersHTML ( &$text='' ) { if ($text == "\n") { $text = ''; return; }   $mstart = '';  // temporary start marker $mend  = '@@@';  // temporary end marker // direct conversion array: Bold, Italics, & Headers $convert = array (       array ( 'oldstart'  => "",     'oldend'    => "", 'newstart'   => " ",    'newend'    => " "),        array ( 'oldstart'  => "",       'oldend'    => "", 'newstart'   => "",        'newend'    => ""),        array ( 'oldstart'  => "",        'oldend'    => "", 'newstart'   => " ",        'newend'    => " "),        array ( 'oldstart'  => " ",  'oldend'    => " ", 'newstart' => "",          'newend'    => ""),        array ( 'oldstart'  => "\n======",  'oldend'    => "======", 'newstart'   => "\n ",    'newend'    => " "),        array ( 'oldstart'  => "\n=====",   'oldend'    => "=====", 'newstart'   => "\n ",    'newend'    => " "),        array ( 'oldstart'  => "\n====",    'oldend'    => "====", 'newstart'   => "\n ",    'newend'    => " "),        array ( 'oldstart'  => "\n===",     'oldend'    => "===", 'newstart'   => "\n ",    'newend'    => " "),        array ( 'oldstart'  => "\n==",      'oldend'    => "==", 'newstart'   => "\n ",    'newend'    => " "),        array ( 'oldstart'  => "\n=",       'oldend'    => "=", 'newstart' => " ",      'newend'    => " "),        array ( 'oldstart'  => "\n\n",      'oldend'    => "\n", 'newstart' => "\n",        'newend'    => "\n"),    ); foreach ($convert as $markup ) { $findstring = "%.*{$markup['oldstart']}(.*){$markup['oldend']}.*%"; $finds = preg_match_all ($findstring, $text, $matches, PREG_OFFSET_CAPTURE); // The following is done "manually" because $matches does not return all matches when there are several before a newline: if ($finds) { $ptr = 0; $len = strlen( $text ); $newtext = ''; while ($ptr < $len) { $start = strpos( $text, $markup['oldstart'], $ptr); if ($start === false) break; $newtext .= substr( $text, $ptr, $start - $ptr ); $end = strpos( $text, $markup['oldend'], $start + strlen( $markup['oldstart'] )); if ($end === false) { $ptr = $start; break; }               else { $start = $start + strlen( $markup['oldstart'] ); $substrlen = $end - $start; $newtext .= $markup['newstart']. substr( $text, $start, $substrlen). $markup['newend']; $ptr = $end + strlen( $markup['oldend']); }           }            $newtext .= substr( $text, $ptr, $len - $ptr); $text = $newtext; }   }    // remove leading newlines; $ptr = 0; $max = strlen ($text) -1; $newlines = 0; While ($text [$ptr] == "\n") { $newlines++; if ($ptr < $max) $ptr++; else break; }   if (strlen($text) - $newlines)  // quick test for only-newlines $text = substr ($text, $newlines, strlen($text) - $newlines); else $text = ''; }

/* * Truncate as needed, add "...more" link */ function WikiMore( &$text='', $chars=32767 ) { if ($text == '') return ''; global $fpTitle, $wgScript; $len = strlen( $text ); $endTag = array ('>', '/', ' ');   // after a '<', these signal the end of a tag name $whitespace = array ( ' ', "\n", "\t", '-', ',', '.', ':', ';', '>' ); $tagmap = array;   // a tag map of this $text: //  $tagmap [char#]['name']  // name of tag starting at char# //                 ['close'] // closing tag starts here $textSize = ($len > $chars) ? $chars : $len -1; // write text data into map $textChars = 0; $ptr = 0; while ($textChars < $textSize) { if ($text [$ptr] == '<') {   // open tag $tagStart = $ptr++; $tagName = ''; // get the name of this tag if ($text [$ptr] == '/') {       // closing an earlier tag while (!in_array ($text [++$ptr], $endTag) ) $tagName .= $text [$ptr]; $tagmap[$tagStart]['name'] = $tagName; // point 'open' tag to beginning of its closure foreach ($tagmap as $loc=>$key) { if (isset ($key['name']) &&                       ($key ['name'] == $tagName) &&                        (!isset( $key ['close'])) ) $tagmap [$loc]['close'] = $tagStart; }           }            else { // new tag - get the name while (!in_array ($text [$ptr], $endTag) ) $tagName .= $text [$ptr++]; $tagmap [$tagStart]['name'] = $tagName; }           if (($text [$ptr] == '/') && ($text [$ptr +1] == '>'))     // tag closes itself  ' />' $tagmap[$tagStart]['close'] = $tagStart;

// go to the end of this tag while ($text [$ptr] != '>') $ptr++; }       while (isset($text[$ptr+1]) && ($text [++$ptr] != '<'))        // a '<' in text will be a problem $textChars++; if (!isset ($text[$ptr+1]) && ($textChars < $textSize))    // tags exaggerated small size ? $textChars = $textSize; }   // we ended with text - adjust pointer to $textSize & look for whitespace so a word is not truncated $overshot = $textChars - $textSize; $ptr = $ptr - $overshot; while (!in_array( $text [$ptr], $whitespace)) $ptr--; $newtext = substr( $text, 0, $ptr+1 ); // include the whitespace flag in case of '-', '.', ',' etc.    // see whether any tags need closure, and close them in proper order krsort($tagmap); foreach ($tagmap as $loc) if (!isset ($loc ['close'])) $newtext .= '';      // add "more..." link $newtext .= " ... More... "; $text = $newtext; } ?>

Demonstration
A Demonstration is available at wiki.gis.com