1#!/usr/bin/php 2<?php 3if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__) . '/../') . '/'); 4define('NOSESSION', 1); 5require_once(DOKU_INC . 'inc/init.php'); 6 7class WantedPagesCLI extends DokuCLI { 8 9 const DIR_CONTINUE = 1; 10 const DIR_NS = 2; 11 const DIR_PAGE = 3; 12 13 /** 14 * Register options and arguments on the given $options object 15 * 16 * @param DokuCLI_Options $options 17 * @return void 18 */ 19 protected function setup(DokuCLI_Options $options) { 20 $options->setHelp( 21 'Outputs a list of wanted pages (pages which have internal links but do not yet exist).' 22 ); 23 $options->registerArgument( 24 'namespace', 25 'The namespace to lookup. Defaults to root namespace', 26 false 27 ); 28 } 29 30 /** 31 * Your main program 32 * 33 * Arguments and options have been parsed when this is run 34 * 35 * @param DokuCLI_Options $options 36 * @return void 37 */ 38 protected function main(DokuCLI_Options $options) { 39 40 if($options->args) { 41 $startdir = dirname(wikiFN($options->args[0] . ':xxx')); 42 } else { 43 $startdir = dirname(wikiFN('xxx')); 44 } 45 46 $this->info("searching $startdir"); 47 48 $wanted_pages = array(); 49 50 foreach($this->get_pages($startdir) as $page) { 51 $wanted_pages = array_merge($wanted_pages, $this->internal_links($page)); 52 } 53 $wanted_pages = array_unique($wanted_pages); 54 sort($wanted_pages); 55 56 foreach($wanted_pages as $page) { 57 print $page . "\n"; 58 } 59 } 60 61 protected function dir_filter($entry, $basepath) { 62 if($entry == '.' || $entry == '..') { 63 return WantedPagesCLI::DIR_CONTINUE; 64 } 65 if(is_dir($basepath . '/' . $entry)) { 66 if(strpos($entry, '_') === 0) { 67 return WantedPagesCLI::DIR_CONTINUE; 68 } 69 return WantedPagesCLI::DIR_NS; 70 } 71 if(preg_match('/\.txt$/', $entry)) { 72 return WantedPagesCLI::DIR_PAGE; 73 } 74 return WantedPagesCLI::DIR_CONTINUE; 75 } 76 77 protected function get_pages($dir) { 78 static $trunclen = null; 79 if(!$trunclen) { 80 global $conf; 81 $trunclen = strlen($conf['datadir'] . ':'); 82 } 83 84 if(!is_dir($dir)) { 85 throw new DokuCLI_Exception("Unable to read directory $dir"); 86 } 87 88 $pages = array(); 89 $dh = opendir($dir); 90 while(false !== ($entry = readdir($dh))) { 91 $status = $this->dir_filter($entry, $dir); 92 if($status == WantedPagesCLI::DIR_CONTINUE) { 93 continue; 94 } else if($status == WantedPagesCLI::DIR_NS) { 95 $pages = array_merge($pages, $this->get_pages($dir . '/' . $entry)); 96 } else { 97 $page = array( 98 'id' => pathID(substr($dir . '/' . $entry, $trunclen)), 99 'file' => $dir . '/' . $entry, 100 ); 101 $pages[] = $page; 102 } 103 } 104 closedir($dh); 105 return $pages; 106 } 107 108 function internal_links($page) { 109 global $conf; 110 $instructions = p_get_instructions(file_get_contents($page['file'])); 111 $links = array(); 112 $cns = getNS($page['id']); 113 $exists = false; 114 foreach($instructions as $ins) { 115 if($ins[0] == 'internallink' || ($conf['camelcase'] && $ins[0] == 'camelcaselink')) { 116 $mid = $ins[1][0]; 117 resolve_pageid($cns, $mid, $exists); 118 if(!$exists) { 119 list($mid) = explode('#', $mid); //record pages without hashs 120 $links[] = $mid; 121 } 122 } 123 } 124 return $links; 125 } 126} 127 128// Main 129$cli = new WantedPagesCLI(); 130$cli->run();