diff --git a/README b/README deleted file mode 100644 index 5b6ab25..0000000 --- a/README +++ /dev/null @@ -1,14 +0,0 @@ -====== Orphanswanted Plugin for DokuWiki ====== - -All documentation for the Orphanswanted Plugin is available online at: - - * http://dokuwiki.org/plugin:orphanswanted - -(c) 2006-2008 Doug Edmunds -(c) 2008-2009 Andy Webber -(c) 2009 Federico Ariel Castagnini -(c) 2010 Cyrille37 - -See COPYING for license info. - - diff --git a/README.md b/README.md new file mode 100644 index 0000000..96387f5 --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# Orphanswanted Plugin for DokuWiki + +All documentation for the Orphanswanted Plugin is available online at: + + * http://dokuwiki.org/plugin:orphanswanted + +(c) 2006-2008 Doug Edmunds +(c) 2008-2009 Andy Webber +(c) 2009 Federico Ariel Castagnini +(c) 2010 Cyrille37 +(c) 2011 Rik Blok +(c) 2016-2023 Christian Paul +(c) 2022 alexdraconian + +See COPYING for license info. diff --git a/VERSION b/VERSION deleted file mode 100644 index fa88583..0000000 --- a/VERSION +++ /dev/null @@ -1 +0,0 @@ -2010-04-11 diff --git a/conf/default.php b/conf/default.php new file mode 100644 index 0000000..3dd0895 --- /dev/null +++ b/conf/default.php @@ -0,0 +1,9 @@ + + */ +$conf['ignoredpages'] = ''; // The plugin will doesn't list the given pages + +//Setup VIM: ex: et ts=2 : diff --git a/conf/metadata.php b/conf/metadata.php new file mode 100644 index 0000000..221fab3 --- /dev/null +++ b/conf/metadata.php @@ -0,0 +1,10 @@ + + */ +$meta['ignoredpages'] = array('string'); + +//Setup VIM: ex: et ts=2 : diff --git a/helper.php b/helper.php new file mode 100644 index 0000000..8fac03e --- /dev/null +++ b/helper.php @@ -0,0 +1,205 @@ + + * @author Andy Webber + * @author Federico Ariel Castagnini + * @author Cyrille37 + * @author Matthias Schulte + * @author Rik Blok + * @author Christian Paul + * @author alexdraconian + */ +// must be run within Dokuwiki +if(!defined('DOKU_INC')) die(); +if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); + +require_once(DOKU_INC.'inc/search.php'); + +class helper_plugin_orphanswanted extends DokuWiki_Plugin { + + // three choices + // $params_array used to extract excluded namespaces for report + // orphans = orph_report_table($data, true, false, $params_array); + // wanted = orph_report_table($data, false, true), $params_array; + // valid = orph_report_table($data, true, true, $params_array); + + /** + * Find all page list with wiki's internal indexer. + */ + function _get_page_data() { + $all_pages = idx_get_indexer()->getPages(); + $pages = array(); + foreach($all_pages as $pageid) { + $pages[$pageid] = array("exists"=>page_exists($pageid), "links"=>0); + } + + foreach($all_pages as $pageid) { + + if (!page_exists($pageid)) continue; + + $relation_data = p_get_metadata($pageid, 'relation references', METADATA_DONT_RENDER); + if (!is_null($relation_data)) { + foreach($relation_data as $name => $exists) { + $pages[$name]['exists'] = $exists; + $pages[$name]['links'] = isset($pages[$name]['links']) ? $pages[$name]['links'] + 1 : 1; + } + } + } + + return $pages; + } + + function orphan_pages($params_array) { + $data = $this->_get_page_data(); + + $result = ''; + $result .= $this->orph_report_table($data, true, false, $params_array, 'orphan'); + + return $result; + } + + function wanted_pages($params_array) { + $data = $this->_get_page_data(); + + $result = ''; + $result .= $this->orph_report_table($data, false, true, $params_array, 'wanted'); + + return $result; + } + + function valid_pages($params_array) { + $data = $this->_get_page_data(); + + $result = ''; + $result .= $this->orph_report_table($data, true, true, $params_array, 'valid'); + + return $result; + } + + function all_pages($params_array) { + $data = $this->_get_page_data(); + + $result = ''; + $result .= "

Orphans

"; + $result .= $this->orph_report_table($data, true, false, $params_array, 'orphan'); + $result .= "

Wanted

"; + $result .= $this->orph_report_table($data, false, true, $params_array, 'wanted'); + $result .= "

Valid

"; + $result .= $this->orph_report_table($data, true, true, $params_array, 'valid'); + + return $result; + } + + function orph_report_table($data, $page_exists, $has_links, $params_array, $caller = null) { + global $conf; + $ignoredPages = $this->getConf('ignoredpages'); // Fetch pages which shouldn't be listed + if($ignoredPages != '') { + $ignoredPages = explode(';', $ignoredPages); + } else { + $ignoredPages = null; + } + + $show_heading = ($page_exists && $conf['useheading']) ? true : false ; + //take off $params_array[0]; + $include_array = $params_array[1]; + $exclude_array = $params_array[2]; + + $count = 1; + $output = ''; + + // for valid html - need to close the

that is feed before this + $output .= '

'; + $output .= '' + . ($show_heading ? '' : '' ) + . ($caller != "orphan" ? '' : '') + . '' + . "\n" ; + + // Sort by namespace and name + ksort($data); + + // Sort descending by existing links. + // This does not make sense for orphans since they don't have links. + if ($caller != "orphan") { + arsort($data); + } + + foreach($data as $id=>$item) { + + if( ! ((array_key_exists('exists', $item)) and ($item['exists'] == $page_exists) and (array_key_exists('links', $item)) and (($item['links'] <> 0)== $has_links)) ) continue ; + + // $id is a string, looks like this: page, namespace:page, or namespace::page + $match_array = explode(":", $id); + //remove last item in array, the page identifier + $match_array = array_slice($match_array, 0, -1); + //put it back together + $page_namespace = implode (":", $match_array); + //add a trailing : + $page_namespace = $page_namespace . ':'; + + if (empty($include_array)) { + // if inclusion list is empty then show all namespaces + $show_it = true; + } else { + // otherwise only show if in inclusion list + $show_it = false; + foreach ($include_array as $include_item) { + //add a trailing : to each $item too + $include_item = $include_item . ":"; + // need === to avoid boolean false + // strpos(haystack, needle) + // if exclusion is beginning of page's namespace, block it + if (strpos($page_namespace, $include_item) === 0) { + //there is a match, so show it and move on + $show_it = true; + break; + } + } + } + + if(!is_null($ignoredPages) && in_array($id, $ignoredPages)) { + if ($conf['allowdebug']) echo "Skipped page (global ignored): " . $id . "
"; + $show_it = false; + } elseif(isHiddenPage($id)) { + if ($conf['allowdebug']) echo "Skipped page (global hidden): " . $id . "
"; + $show_it = false; + } elseif ( $show_it ) { + //check if blocked by exclusion list + foreach ($exclude_array as $exclude_item) { + //add a trailing : to each $item too + $exclude_item = $exclude_item . ":"; + // need === to avoid boolean false + // strpos(haystack, needle) + // if exclusion is beginning of page's namespace , block it + if (strpos($page_namespace, $exclude_item) === 0) { + //there is a match, so block it and move on + $show_it = false; + break; + } + } + } + + if($show_it) { + $output .= "
' + . ($show_heading ? '' : '' ); + + if($caller != "orphan") { // Skip "link" column if user wants orphan pages only + $output .= '"; + } + $output .= "\n"; + $count++; + } + } + + $output .= "
# ID TitleLinks
$count" + . $id .'' . hsc(p_get_first_heading($id)) .'' . $item['links'] + . ($has_links ? " : Show backlinks" : '') . "
\n"; + //for valid html = need to reopen a

+ $output .= '

'; + + return $output; + } +} diff --git a/lang/de-informal/settings.php b/lang/de-informal/settings.php new file mode 100644 index 0000000..fb712a8 --- /dev/null +++ b/lang/de-informal/settings.php @@ -0,0 +1,10 @@ + + */ + +$lang['ignoredpages'] = 'Diese Seiten nie in den Ausgaben anzeigen (Trennzeichen: Semikolon)'; + +//Setup VIM: ex: et ts=2 : diff --git a/lang/de/settings.php b/lang/de/settings.php new file mode 100644 index 0000000..fb712a8 --- /dev/null +++ b/lang/de/settings.php @@ -0,0 +1,10 @@ + + */ + +$lang['ignoredpages'] = 'Diese Seiten nie in den Ausgaben anzeigen (Trennzeichen: Semikolon)'; + +//Setup VIM: ex: et ts=2 : diff --git a/lang/en/settings.php b/lang/en/settings.php new file mode 100644 index 0000000..8796acb --- /dev/null +++ b/lang/en/settings.php @@ -0,0 +1,10 @@ + + */ + +$lang['ignoredpages'] = 'Always skip these pages in the output table (Delimiter: Semicolon)'; + +//Setup VIM: ex: et ts=2 : diff --git a/plugin.info.txt b/plugin.info.txt new file mode 100644 index 0000000..045b167 --- /dev/null +++ b/plugin.info.txt @@ -0,0 +1,7 @@ +base orphanswanted +author Doug Edmunds, Cyrille37, Federico Ariel Castagnini, Andy Webber, Matthias Schulte, Christian Paul, alexdraconian +email dokuwiki@lupo49.de +date 2023-05-30 +name orphanswanted plugin +desc Display Orphans, Wanteds and Valid link tables +url http://dokuwiki.org/plugin:orphanswanted diff --git a/syntax.php b/syntax.php index 29868ca..e11a72d 100644 --- a/syntax.php +++ b/syntax.php @@ -1,398 +1,119 @@ [!]~~ :: orphans | wanted | valid | all + * + * syntax ~~ORPHANSWANTED:[@][!]~~ :: orphans | wanted | valid | all + * [@] :: optional. prefix each with @ e.g., @wiki@comments:currentyear (defaults to all namespaces if not specified) * [!] :: optional. prefix each with ! e.g., !wiki!comments:currentyear + * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * @author * @author Andy Webber * @author Federico Ariel Castagnini * @author Cyrille37 + * @author Rik Blok + * @author Christian Paul */ - + if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); -require_once(DOKU_PLUGIN.'syntax.php'); - -require_once(DOKU_INC.'inc/search.php'); - -define('DEBUG', 0); - -//------------------------------------- - -function orph_callback_search_wanted(&$data,$base,$file,$type,$lvl,$opts) { - - if($type == 'd'){ - return true; // recurse all directories, but we don't store namespaces - } - - if(!preg_match("/.*\.txt$/", $file)) { // Ignore everything but TXT - return true; - } - - // search the body of the file for links - // dae mod - // orph_Check_InternalLinks(&$data,$base,$file,$type,$lvl,$opts); - orph_Check_InternalLinks($data,$base,$file,$type,$lvl,$opts); - - // get id of this file - $id = pathID($file); - - //check ACL - if(auth_quickaclcheck($id) < AUTH_READ) { - return false; - } - - // try to avoid making duplicate entries for forms and pages - $item = &$data["$id"]; - if(isset($item)) { - // This item already has a member in the array - // Note that the file search found it - $item['exists'] = true; - } else { - // Create a new entry - $data["$id"]=array('exists' => true, - 'links' => 0); - } - return true; -} - -function orph_handle_link( &$data, $link ) -{ - if( isset($data[$link]) ) - { - // This item already has a member in the array - // Note that the file search found it - $data[$link]['links'] ++ ; // count the link - } else { - // Create a new entry - $data[$link] = array( - 'exists' => false, // Only found a link, not the file - 'links' => 1 - ); - // echo " \n"; - } - if (DEBUG) echo "

-- New count for link " . $link . ": " . $data[$link]['links'] . "

\n"; -} - - -/** - * Search for internal wiki links in page $file - */ -function orph_Check_InternalLinks( &$data, $base, $file, $type, $lvl, $opts ) -{ - global $conf; - define('LINK_PATTERN', '%\[\[([^\]|#]*)(#[^\]|]*)?\|?([^\]]*)]]%'); - - if( ! preg_match("/.*\.txt$/", $file) ) - { - return ; - } - - $currentID = pathID($file); - $currentNS = getNS($currentID); - if(DEBUG) echo sprintf("

%s: %s

\n", $file, $currentID); - - // echo " \n"; - $body = @file_get_contents($conf['datadir'] . $file); - - // ignores entries in , %%, and emails with @ - foreach( array( - '/.*?<\/nowiki>/', - '/%%.*?%%/', - '/.*?<\/code>/' - ) - as $ignored ) - { - $body = preg_replace($ignored, '', $body); - } - - $links = array(); - preg_match_all( LINK_PATTERN, $body, $links ); - - foreach( $links[1] as $link ) - { - if(DEBUG) echo sprintf("--- Checking %s
\n", $link); - - if( (0 < strlen(ltrim($link))) - and ! preg_match('/^[a-zA-Z0-9\.]+>{1}.*$/u',$link) // Interwiki - and ! preg_match('/^\\\\\\\\[\w.:?\-;,]+?\\\\/u',$link) // Windows Share - and ! preg_match('#^([a-z0-9\-\.+]+?)://#i',$link) // external link (accepts all protocols) - and ! preg_match('<'.PREG_PATTERN_VALID_EMAIL.'>',$link) // E-Mail (pattern above is defined in inc/mail.php) - and ! preg_match('!^#.+!',$link) // inside page link (html anchor) - ) { - $pageExists=false; - resolve_pageid($currentNS,$link,$pageExists ); - if (DEBUG) echo sprintf("---- link='%s' %s ", $link, $pageExists?'EXISTS':'MISS'); - - if(((strlen(ltrim($link)) > 0) // there IS an id? - and !auth_quickaclcheck($link) < AUTH_READ)) { // should be visible to user - //echo " \n"; - - if(DEBUG) echo ' A_LINK' ; - - $link= strtolower( $link ); - orph_handle_link($data, $link); - } - else - { - if(DEBUG) echo ' EMPTY_OR_FORBIDDEN' ; - } - } // link is not empty and is a local link? - else - { - if(DEBUG) echo ' NOT_INTERNAL'; - } - - if(DEBUG) echo "
\n"; - } // end of foreach link -} - - - -// -------------------- - /** * All DokuWiki plugins to extend the parser/rendering mechanism * need to inherit from this class */ class syntax_plugin_orphanswanted extends DokuWiki_Syntax_Plugin { - /** - * return some info - */ - function getInfo(){ - return array( - 'author' => 'Doug Edmunds', - 'email' => 'dae@douglasedmunds.com', - 'date' => @file_get_contents(dirname(__FILE__) . '/VERSION'), - 'name' => 'OrphansWanted Plugin', - 'desc' => 'Find orphan pages and wanted pages . - syntax ~~ORPHANSWANTED:[!]~~ . - :: orphans|wanted|valid|all . - are optional, start each namespace with !' , - 'url' => 'http://dokuwiki.org/plugin:orphanswanted', - ); - } - + /** * What kind of syntax are we? */ function getType(){ return 'substition'; } - + /** * What about paragraphs? */ function getPType(){ return 'normal'; } - + /** * Where to sort in? */ function getSort(){ - return 990; //was 990 + return 990; // was 990 } - - + + /** * Connect pattern to lexer */ function connectTo($mode) { - $this->Lexer->addSpecialPattern('~~ORPHANSWANTED:[0-9a-zA-Z_:!]+~~',$mode,'plugin_orphanswanted'); + $this->Lexer->addSpecialPattern('~~ORPHANSWANTED:[\w:@!-]+~~', $mode, 'plugin_orphanswanted'); } - + /** * Handle the match */ - - function handle($match, $state, $pos, &$handler){ + function handle($match, $state, $pos, Doku_Handler $handler){ $match_array = array(); $match = substr($match,16,-2); //strip ~~ORPHANSWANTED: from start and ~~ from end + // Wolfgang 2007-08-29 suggests commenting out the next line // $match = strtolower($match); //create array, using ! as separator - $match_array = explode("!", $match); + // eg: $match = 'all@includens!excludens' + $match_in = explode("@", $match); // eg: $match_array = array(); $match_in = array('all', 'includens!excludens') + $match_ex = explode("!",array_pop($match_in)); // eg: $match_array = array(); $match_in = array('all'); $match_ex = array('includens', 'excludens') + array_push($match_in,array_shift($match_ex)); // eg: $match_array = array(); $match_in = array('all', 'includens'); $match_ex = array('excludens') + $match_array[0] = array_shift($match_in); // eg: $match_array = array('all'); $match_in = array('includens'); $match_ex = array('excludens') + $match_array[1] = $match_in; // eg: $match_array = array('all', array('includens')); $match_ex = array('excludens') + $match_array[2] = $match_ex; // eg: $match_array = array('all', array('includens'), array('excludens')) + // $match_array[0] will be orphan, wanted, valid, all, or syntax error // if there are excluded namespaces, they will be in $match_array[1] .. [x] // this return value appears in render() as the $data param there + return $match_array; } - + /** * Create output */ - function render($format, &$renderer, $data) { + function render($format, Doku_Renderer $renderer, $data) { global $INFO, $conf; - if($format == 'xhtml'){ - - // user needs to add ~~NOCACHE~~ manually to page, to assure ACL rules are followed - // coding here is too late, it doesn't get parsed - // $renderer->doc .= "~~NOCACHE~~"; - + $helper = plugin_load('helper','orphanswanted'); + + if($format == 'xhtml') { + // prevent caching to ensure content is always fresh + $renderer->info['cache'] = false; + // $data is an array // $data[1]..[x] are excluded namespaces, $data[0] is the report type //handle choices - switch ($data[0]){ + + switch ($data[0]) { case 'orphans': - $renderer->doc .= $this->orphan_pages($data); + $renderer->doc .= $helper->orphan_pages($data); break; case 'wanted': - $renderer->doc .= $this->wanted_pages($data); + $renderer->doc .= $helper->wanted_pages($data); break; case 'valid': - $renderer->doc .= $this->valid_pages($data); + $renderer->doc .= $helper->valid_pages($data); break; case 'all': - $renderer->doc .= $this->all_pages($data); + $renderer->doc .= $helper->all_pages($data); break; default: $renderer->doc .= "ORPHANSWANTED syntax error"; - // $renderer->doc .= "syntax ~~ORPHANSWANTED:~~ :: orphans|wanted|valid|all Ex: ~~ORPHANSWANTED:valid~~"; } - - return true; + return true; } + return false; } - - -// three choices -// $params_array used to extract excluded namespaces for report -// orphans = orph_report_table($data, true, false, $params_array); -// wanted = orph_report_table($data, false, true), $params_array; -// valid = orph_report_table($data, true, true, $params_array); - - - function orphan_pages($params_array) { - global $conf; - $result = ''; - $data = array(); - search($data,$conf['datadir'],'orph_callback_search_wanted',array('ns' => $ns)); - $result .= $this->orph_report_table($data, true, false,$params_array); - - return $result; - } - - function wanted_pages($params_array) { - global $conf; - $result = ''; - $data = array(); - search($data,$conf['datadir'],'orph_callback_search_wanted',array('ns' => $ns)); - $result .= $this->orph_report_table($data, false, true,$params_array); - - return $result; - } - - function valid_pages($params_array) { - global $conf; - $result = ''; - $data = array(); - search($data,$conf['datadir'],'orph_callback_search_wanted',array('ns' => $ns)); - $result .= $this->orph_report_table($data, true, true, $params_array); - - return $result; - } - - function all_pages($params_array) { - global $conf; - $result = ''; - $data = array(); - search($data,$conf['datadir'],'orph_callback_search_wanted',array('ns' => $ns)); - - $result .= "

Orphans

"; - $result .= $this->orph_report_table($data, true, false,$params_array); - $result .= "

Wanted

"; - $result .= $this->orph_report_table($data, false, true,$params_array); - $result .= "

Valid

"; - $result .= $this->orph_report_table($data, true, true, $params_array); - - - return $result; - } - - function orph_report_table( $data, $page_exists, $has_links, $params_array ) - { - global $conf; - - $show_heading = ($page_exists && $conf['useheading']) ? true : false ; - - //take off $params_array[0]; - $exclude_array = array_slice($params_array,1); - - $count = 1; - $output = ''; - - // for valid html - need to close the

that is feed before this - $output .= '

'; - $output .= '' - . ($show_heading ? '' : '' ) - . '' - ."\n" ; - - arsort($data); - - foreach($data as $id=>$item) - { - - if( ! (($item['exists'] == $page_exists) and (($item['links'] <> 0)== $has_links)) ) - { - continue ; - } - - // $id is a string, looks like this: page, namespace:page, or namespace::page - $match_array = explode(":", $id); - //remove last item in array, the page identifier - $match_array = array_slice($match_array, 0, -1); - //put it back together - $page_namespace = implode (":", $match_array); - //add a trailing : - $page_namespace = $page_namespace . ':'; - - //set it to show, unless blocked by exclusion list - $show_it = true; - foreach ($exclude_array as $exclude_item) - { - //add a trailing : to each $item too - $exclude_item = $exclude_item . ":"; - // need === to avoid boolean false - // strpos(haystack, needle) - // if exclusion is beginning of page's namespace , block it - if (strpos($page_namespace, $exclude_item) === 0){ - //there is a match, so block it - $show_it = false; - } - } - - if( $show_it ) - { - $output .= "' - . ($show_heading ? '' : '' ) - . '\n"; - - $count++; - } - - } - - $output .= "
# ID TitleLinks
$count" - . $id .'' . hsc(p_get_first_heading($id)) .'' . $item['links'] - . ($has_links - ? " : Show backlinks" - : '' - ) - . "
\n"; - //for valid html = need to reopen a

- $output .= '

'; - - return $output; - } - } - + //Setup VIM: ex: et ts=4 enc=utf-8 : -?>