ajout de la partie slam dans le dossier web

This commit is contained in:
root
2022-03-10 11:56:26 +01:00
parent 31d3052792
commit e375c4f088
4847 changed files with 325719 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
<IfModule !mod_authz_core.c>
Order allow,deny
Deny from all
</IfModule>

322
ap23/web/doku/bin/dwpage.php Executable file
View File

@@ -0,0 +1,322 @@
#!/usr/bin/env php
<?php
use splitbrain\phpcli\CLI;
use splitbrain\phpcli\Options;
if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__) . '/../') . '/');
define('NOSESSION', 1);
require_once(DOKU_INC . 'inc/init.php');
/**
* Checkout and commit pages from the command line while maintaining the history
*/
class PageCLI extends CLI {
protected $force = false;
protected $username = '';
/**
* Register options and arguments on the given $options object
*
* @param Options $options
* @return void
*/
protected function setup(Options $options) {
/* global */
$options->registerOption(
'force',
'force obtaining a lock for the page (generally bad idea)',
'f'
);
$options->registerOption(
'user',
'work as this user. defaults to current CLI user',
'u',
'username'
);
$options->setHelp(
'Utility to help command line Dokuwiki page editing, allow ' .
'pages to be checked out for editing then committed after changes'
);
/* checkout command */
$options->registerCommand(
'checkout',
'Checks out a file from the repository, using the wiki id and obtaining ' .
'a lock for the page. ' . "\n" .
'If a working_file is specified, this is where the page is copied to. ' .
'Otherwise defaults to the same as the wiki page in the current ' .
'working directory.'
);
$options->registerArgument(
'wikipage',
'The wiki page to checkout',
true,
'checkout'
);
$options->registerArgument(
'workingfile',
'How to name the local checkout',
false,
'checkout'
);
/* commit command */
$options->registerCommand(
'commit',
'Checks in the working_file into the repository using the specified ' .
'wiki id, archiving the previous version.'
);
$options->registerArgument(
'workingfile',
'The local file to commit',
true,
'commit'
);
$options->registerArgument(
'wikipage',
'The wiki page to create or update',
true,
'commit'
);
$options->registerOption(
'message',
'Summary describing the change (required)',
'm',
'summary',
'commit'
);
$options->registerOption(
'trivial',
'minor change',
't',
false,
'commit'
);
/* lock command */
$options->registerCommand(
'lock',
'Obtains or updates a lock for a wiki page'
);
$options->registerArgument(
'wikipage',
'The wiki page to lock',
true,
'lock'
);
/* unlock command */
$options->registerCommand(
'unlock',
'Removes a lock for a wiki page.'
);
$options->registerArgument(
'wikipage',
'The wiki page to unlock',
true,
'unlock'
);
}
/**
* Your main program
*
* Arguments and options have been parsed when this is run
*
* @param Options $options
* @return void
*/
protected function main(Options $options) {
$this->force = $options->getOpt('force', false);
$this->username = $options->getOpt('user', $this->getUser());
$command = $options->getCmd();
$args = $options->getArgs();
switch($command) {
case 'checkout':
$wiki_id = array_shift($args);
$localfile = array_shift($args);
$this->commandCheckout($wiki_id, $localfile);
break;
case 'commit':
$localfile = array_shift($args);
$wiki_id = array_shift($args);
$this->commandCommit(
$localfile,
$wiki_id,
$options->getOpt('message', ''),
$options->getOpt('trivial', false)
);
break;
case 'lock':
$wiki_id = array_shift($args);
$this->obtainLock($wiki_id);
$this->success("$wiki_id locked");
break;
case 'unlock':
$wiki_id = array_shift($args);
$this->clearLock($wiki_id);
$this->success("$wiki_id unlocked");
break;
default:
echo $options->help();
}
}
/**
* Check out a file
*
* @param string $wiki_id
* @param string $localfile
*/
protected function commandCheckout($wiki_id, $localfile) {
global $conf;
$wiki_id = cleanID($wiki_id);
$wiki_fn = wikiFN($wiki_id);
if(!file_exists($wiki_fn)) {
$this->fatal("$wiki_id does not yet exist");
}
if(empty($localfile)) {
$localfile = getcwd() . '/' . \dokuwiki\Utf8\PhpString::basename($wiki_fn);
}
if(!file_exists(dirname($localfile))) {
$this->fatal("Directory " . dirname($localfile) . " does not exist");
}
if(stristr(realpath(dirname($localfile)), realpath($conf['datadir'])) !== false) {
$this->fatal("Attempt to check out file into data directory - not allowed");
}
$this->obtainLock($wiki_id);
if(!copy($wiki_fn, $localfile)) {
$this->clearLock($wiki_id);
$this->fatal("Unable to copy $wiki_fn to $localfile");
}
$this->success("$wiki_id > $localfile");
}
/**
* Save a file as a new page revision
*
* @param string $localfile
* @param string $wiki_id
* @param string $message
* @param bool $minor
*/
protected function commandCommit($localfile, $wiki_id, $message, $minor) {
$wiki_id = cleanID($wiki_id);
$message = trim($message);
if(!file_exists($localfile)) {
$this->fatal("$localfile does not exist");
}
if(!is_readable($localfile)) {
$this->fatal("Cannot read from $localfile");
}
if(!$message) {
$this->fatal("Summary message required");
}
$this->obtainLock($wiki_id);
saveWikiText($wiki_id, file_get_contents($localfile), $message, $minor);
$this->clearLock($wiki_id);
$this->success("$localfile > $wiki_id");
}
/**
* Lock the given page or exit
*
* @param string $wiki_id
*/
protected function obtainLock($wiki_id) {
if($this->force) $this->deleteLock($wiki_id);
$_SERVER['REMOTE_USER'] = $this->username;
if(checklock($wiki_id)) {
$this->error("Page $wiki_id is already locked by another user");
exit(1);
}
lock($wiki_id);
if(checklock($wiki_id)) {
$this->error("Unable to obtain lock for $wiki_id ");
var_dump(checklock($wiki_id));
exit(1);
}
}
/**
* Clear the lock on the given page
*
* @param string $wiki_id
*/
protected function clearLock($wiki_id) {
if($this->force) $this->deleteLock($wiki_id);
$_SERVER['REMOTE_USER'] = $this->username;
if(checklock($wiki_id)) {
$this->error("Page $wiki_id is locked by another user");
exit(1);
}
unlock($wiki_id);
if(file_exists(wikiLockFN($wiki_id))) {
$this->error("Unable to clear lock for $wiki_id");
exit(1);
}
}
/**
* Forcefully remove a lock on the page given
*
* @param string $wiki_id
*/
protected function deleteLock($wiki_id) {
$wikiLockFN = wikiLockFN($wiki_id);
if(file_exists($wikiLockFN)) {
if(!unlink($wikiLockFN)) {
$this->error("Unable to delete $wikiLockFN");
exit(1);
}
}
}
/**
* Get the current user's username from the environment
*
* @return string
*/
protected function getUser() {
$user = getenv('USER');
if(empty ($user)) {
$user = getenv('USERNAME');
} else {
return $user;
}
if(empty ($user)) {
$user = 'admin';
}
return $user;
}
}
// Main
$cli = new PageCLI();
$cli->run();

340
ap23/web/doku/bin/gittool.php Executable file
View File

@@ -0,0 +1,340 @@
#!/usr/bin/env php
<?php
use splitbrain\phpcli\CLI;
use splitbrain\phpcli\Options;
if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__) . '/../') . '/');
define('NOSESSION', 1);
require_once(DOKU_INC . 'inc/init.php');
/**
* Easily manage DokuWiki git repositories
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
class GitToolCLI extends CLI {
/**
* Register options and arguments on the given $options object
*
* @param Options $options
* @return void
*/
protected function setup(Options $options) {
$options->setHelp(
"Manage git repositories for DokuWiki and its plugins and templates.\n\n" .
"$> ./bin/gittool.php clone gallery template:ach\n" .
"$> ./bin/gittool.php repos\n" .
"$> ./bin/gittool.php origin -v"
);
$options->registerArgument(
'command',
'Command to execute. See below',
true
);
$options->registerCommand(
'clone',
'Tries to install a known plugin or template (prefix with template:) via git. Uses the DokuWiki.org ' .
'plugin repository to find the proper git repository. Multiple extensions can be given as parameters'
);
$options->registerArgument(
'extension',
'name of the extension to install, prefix with \'template:\' for templates',
true,
'clone'
);
$options->registerCommand(
'install',
'The same as clone, but when no git source repository can be found, the extension is installed via ' .
'download'
);
$options->registerArgument(
'extension',
'name of the extension to install, prefix with \'template:\' for templates',
true,
'install'
);
$options->registerCommand(
'repos',
'Lists all git repositories found in this DokuWiki installation'
);
$options->registerCommand(
'*',
'Any unknown commands are assumed to be arguments to git and will be executed in all repositories ' .
'found within this DokuWiki installation'
);
}
/**
* Your main program
*
* Arguments and options have been parsed when this is run
*
* @param Options $options
* @return void
*/
protected function main(Options $options) {
$command = $options->getCmd();
$args = $options->getArgs();
if(!$command) $command = array_shift($args);
switch($command) {
case '':
echo $options->help();
break;
case 'clone':
$this->cmdClone($args);
break;
case 'install':
$this->cmdInstall($args);
break;
case 'repo':
case 'repos':
$this->cmdRepos();
break;
default:
$this->cmdGit($command, $args);
}
}
/**
* Tries to install the given extensions using git clone
*
* @param array $extensions
*/
public function cmdClone($extensions) {
$errors = array();
$succeeded = array();
foreach($extensions as $ext) {
$repo = $this->getSourceRepo($ext);
if(!$repo) {
$this->error("could not find a repository for $ext");
$errors[] = $ext;
} else {
if($this->cloneExtension($ext, $repo)) {
$succeeded[] = $ext;
} else {
$errors[] = $ext;
}
}
}
echo "\n";
if($succeeded) $this->success('successfully cloned the following extensions: ' . join(', ', $succeeded));
if($errors) $this->error('failed to clone the following extensions: ' . join(', ', $errors));
}
/**
* Tries to install the given extensions using git clone with fallback to install
*
* @param array $extensions
*/
public function cmdInstall($extensions) {
$errors = array();
$succeeded = array();
foreach($extensions as $ext) {
$repo = $this->getSourceRepo($ext);
if(!$repo) {
$this->info("could not find a repository for $ext");
if($this->downloadExtension($ext)) {
$succeeded[] = $ext;
} else {
$errors[] = $ext;
}
} else {
if($this->cloneExtension($ext, $repo)) {
$succeeded[] = $ext;
} else {
$errors[] = $ext;
}
}
}
echo "\n";
if($succeeded) $this->success('successfully installed the following extensions: ' . join(', ', $succeeded));
if($errors) $this->error('failed to install the following extensions: ' . join(', ', $errors));
}
/**
* Executes the given git command in every repository
*
* @param $cmd
* @param $arg
*/
public function cmdGit($cmd, $arg) {
$repos = $this->findRepos();
$shell = array_merge(array('git', $cmd), $arg);
$shell = array_map('escapeshellarg', $shell);
$shell = join(' ', $shell);
foreach($repos as $repo) {
if(!@chdir($repo)) {
$this->error("Could not change into $repo");
continue;
}
$this->info("executing $shell in $repo");
$ret = 0;
system($shell, $ret);
if($ret == 0) {
$this->success("git succeeded in $repo");
} else {
$this->error("git failed in $repo");
}
}
}
/**
* Simply lists the repositories
*/
public function cmdRepos() {
$repos = $this->findRepos();
foreach($repos as $repo) {
echo "$repo\n";
}
}
/**
* Install extension from the given download URL
*
* @param string $ext
* @return bool|null
*/
private function downloadExtension($ext) {
/** @var helper_plugin_extension_extension $plugin */
$plugin = plugin_load('helper', 'extension_extension');
if(!$ext) die("extension plugin not available, can't continue");
$plugin->setExtension($ext);
$url = $plugin->getDownloadURL();
if(!$url) {
$this->error("no download URL for $ext");
return false;
}
$ok = false;
try {
$this->info("installing $ext via download from $url");
$ok = $plugin->installFromURL($url);
} catch(Exception $e) {
$this->error($e->getMessage());
}
if($ok) {
$this->success("installed $ext via download");
return true;
} else {
$this->success("failed to install $ext via download");
return false;
}
}
/**
* Clones the extension from the given repository
*
* @param string $ext
* @param string $repo
* @return bool
*/
private function cloneExtension($ext, $repo) {
if(substr($ext, 0, 9) == 'template:') {
$target = fullpath(tpl_incdir() . '../' . substr($ext, 9));
} else {
$target = DOKU_PLUGIN . $ext;
}
$this->info("cloning $ext from $repo to $target");
$ret = 0;
system("git clone $repo $target", $ret);
if($ret === 0) {
$this->success("cloning of $ext succeeded");
return true;
} else {
$this->error("cloning of $ext failed");
return false;
}
}
/**
* Returns all git repositories in this DokuWiki install
*
* Looks in root, template and plugin directories only.
*
* @return array
*/
private function findRepos() {
$this->info('Looking for .git directories');
$data = array_merge(
glob(DOKU_INC . '.git', GLOB_ONLYDIR),
glob(DOKU_PLUGIN . '*/.git', GLOB_ONLYDIR),
glob(fullpath(tpl_incdir() . '../') . '/*/.git', GLOB_ONLYDIR)
);
if(!$data) {
$this->error('Found no .git directories');
} else {
$this->success('Found ' . count($data) . ' .git directories');
}
$data = array_map('fullpath', array_map('dirname', $data));
return $data;
}
/**
* Returns the repository for the given extension
*
* @param $extension
* @return false|string
*/
private function getSourceRepo($extension) {
/** @var helper_plugin_extension_extension $ext */
$ext = plugin_load('helper', 'extension_extension');
if(!$ext) die("extension plugin not available, can't continue");
$ext->setExtension($extension);
$repourl = $ext->getSourcerepoURL();
if(!$repourl) return false;
// match github repos
if(preg_match('/github\.com\/([^\/]+)\/([^\/]+)/i', $repourl, $m)) {
$user = $m[1];
$repo = $m[2];
return 'https://github.com/' . $user . '/' . $repo . '.git';
}
// match gitorious repos
if(preg_match('/gitorious.org\/([^\/]+)\/([^\/]+)?/i', $repourl, $m)) {
$user = $m[1];
$repo = $m[2];
if(!$repo) $repo = $user;
return 'https://git.gitorious.org/' . $user . '/' . $repo . '.git';
}
// match bitbucket repos - most people seem to use mercurial there though
if(preg_match('/bitbucket\.org\/([^\/]+)\/([^\/]+)/i', $repourl, $m)) {
$user = $m[1];
$repo = $m[2];
return 'https://bitbucket.org/' . $user . '/' . $repo . '.git';
}
return false;
}
}
// Main
$cli = new GitToolCLI();
$cli->run();

107
ap23/web/doku/bin/indexer.php Executable file
View File

@@ -0,0 +1,107 @@
#!/usr/bin/env php
<?php
use splitbrain\phpcli\CLI;
use splitbrain\phpcli\Options;
if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__) . '/../') . '/');
define('NOSESSION', 1);
require_once(DOKU_INC . 'inc/init.php');
/**
* Update the Search Index from command line
*/
class IndexerCLI extends CLI {
private $quiet = false;
private $clear = false;
/**
* Register options and arguments on the given $options object
*
* @param Options $options
* @return void
*/
protected function setup(Options $options) {
$options->setHelp(
'Updates the searchindex by indexing all new or changed pages. When the -c option is ' .
'given the index is cleared first.'
);
$options->registerOption(
'clear',
'clear the index before updating',
'c'
);
$options->registerOption(
'quiet',
'don\'t produce any output',
'q'
);
}
/**
* Your main program
*
* Arguments and options have been parsed when this is run
*
* @param Options $options
* @return void
*/
protected function main(Options $options) {
$this->clear = $options->getOpt('clear');
$this->quiet = $options->getOpt('quiet');
if($this->clear) $this->clearindex();
$this->update();
}
/**
* Update the index
*/
protected function update() {
global $conf;
$data = array();
$this->quietecho("Searching pages... ");
search($data, $conf['datadir'], 'search_allpages', array('skipacl' => true));
$this->quietecho(count($data) . " pages found.\n");
foreach($data as $val) {
$this->index($val['id']);
}
}
/**
* Index the given page
*
* @param string $id
*/
protected function index($id) {
$this->quietecho("$id... ");
idx_addPage($id, !$this->quiet, $this->clear);
$this->quietecho("done.\n");
}
/**
* Clear all index files
*/
protected function clearindex() {
$this->quietecho("Clearing index... ");
idx_get_indexer()->clear();
$this->quietecho("done.\n");
}
/**
* Print message if not supressed
*
* @param string $msg
*/
protected function quietecho($msg) {
if(!$this->quiet) echo $msg;
}
}
// Main
$cli = new IndexerCLI();
$cli->run();

103
ap23/web/doku/bin/plugin.php Executable file
View File

@@ -0,0 +1,103 @@
#!/usr/bin/env php
<?php
use dokuwiki\Extension\PluginController;
use splitbrain\phpcli\CLI;
use splitbrain\phpcli\Colors;
use splitbrain\phpcli\Options;
if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__) . '/../') . '/');
define('NOSESSION', 1);
require_once(DOKU_INC . 'inc/init.php');
class PluginCLI extends CLI {
/**
* Register options and arguments on the given $options object
*
* @param Options $options
* @return void
*/
protected function setup(Options $options) {
$options->setHelp('Excecutes Plugin command line tools');
$options->registerArgument('plugin', 'The plugin CLI you want to run. Leave off to see list', false);
}
/**
* Your main program
*
* Arguments and options have been parsed when this is run
*
* @param Options $options
* @return void
*/
protected function main(Options $options) {
global $argv;
$argv = $options->getArgs();
if($argv) {
$plugin = $this->loadPlugin($argv[0]);
if($plugin !== null) {
$plugin->run();
} else {
$this->fatal('Command {cmd} not found.', ['cmd' => $argv[0]]);
}
} else {
echo $options->help();
$this->listPlugins();
}
}
/**
* List available plugins
*/
protected function listPlugins() {
/** @var PluginController $plugin_controller */
global $plugin_controller;
echo "\n";
echo "\n";
echo $this->colors->wrap('AVAILABLE PLUGINS:', Colors::C_BROWN);
echo "\n";
$list = $plugin_controller->getList('cli');
sort($list);
if(!count($list)) {
echo $this->colors->wrap(" No plugins providing CLI components available\n", Colors::C_RED);
} else {
$tf = new \splitbrain\phpcli\TableFormatter($this->colors);
foreach($list as $name) {
$plugin = $this->loadPlugin($name);
if($plugin === null) continue;
$info = $plugin->getInfo();
echo $tf->format(
[2, '30%', '*'],
['', $name, $info['desc']],
['', Colors::C_CYAN, '']
);
}
}
}
/**
* Instantiate a CLI plugin
*
* @param string $name
* @return \dokuwiki\Extension\CLIPlugin|null
*/
protected function loadPlugin($name) {
// execute the plugin CLI
$class = "cli_plugin_$name";
if(class_exists($class)) {
return new $class();
}
return null;
}
}
// Main
$cli = new PluginCLI();
$cli->run();

64
ap23/web/doku/bin/render.php Executable file
View File

@@ -0,0 +1,64 @@
#!/usr/bin/env php
<?php
use splitbrain\phpcli\CLI;
use splitbrain\phpcli\Options;
if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__) . '/../') . '/');
define('NOSESSION', 1);
require_once(DOKU_INC . 'inc/init.php');
/**
* A simple commandline tool to render some DokuWiki syntax with a given
* renderer.
*
* This may not work for plugins that expect a certain environment to be
* set up before rendering, but should work for most or even all standard
* DokuWiki markup
*
* @license GPL2
* @author Andreas Gohr <andi@splitbrain.org>
*/
class RenderCLI extends CLI {
/**
* Register options and arguments on the given $options object
*
* @param Options $options
* @return void
*/
protected function setup(Options $options) {
$options->setHelp(
'A simple commandline tool to render some DokuWiki syntax with a given renderer.' .
"\n\n" .
'This may not work for plugins that expect a certain environment to be ' .
'set up before rendering, but should work for most or even all standard ' .
'DokuWiki markup'
);
$options->registerOption('renderer', 'The renderer mode to use. Defaults to xhtml', 'r', 'mode');
}
/**
* Your main program
*
* Arguments and options have been parsed when this is run
*
* @param Options $options
* @throws DokuCLI_Exception
* @return void
*/
protected function main(Options $options) {
$renderer = $options->getOpt('renderer', 'xhtml');
// do the action
$source = stream_get_contents(STDIN);
$info = array();
$result = p_render($renderer, p_get_instructions($source), $info);
if(is_null($result)) throw new DokuCLI_Exception("No such renderer $renderer");
echo $result;
}
}
// Main
$cli = new RenderCLI();
$cli->run();

114
ap23/web/doku/bin/striplangs.php Executable file
View File

@@ -0,0 +1,114 @@
#!/usr/bin/env php
<?php
use splitbrain\phpcli\CLI;
use splitbrain\phpcli\Options;
if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__) . '/../') . '/');
define('NOSESSION', 1);
require_once(DOKU_INC . 'inc/init.php');
/**
* Remove unwanted languages from a DokuWiki install
*/
class StripLangsCLI extends CLI {
/**
* Register options and arguments on the given $options object
*
* @param Options $options
* @return void
*/
protected function setup(Options $options) {
$options->setHelp(
'Remove all languages from the installation, besides the ones specified. English language ' .
'is never removed!'
);
$options->registerOption(
'keep',
'Comma separated list of languages to keep in addition to English.',
'k',
'langcodes'
);
$options->registerOption(
'english-only',
'Remove all languages except English',
'e'
);
}
/**
* Your main program
*
* Arguments and options have been parsed when this is run
*
* @param Options $options
* @return void
*/
protected function main(Options $options) {
if($options->getOpt('keep')) {
$keep = explode(',', $options->getOpt('keep'));
if(!in_array('en', $keep)) $keep[] = 'en';
} elseif($options->getOpt('english-only')) {
$keep = array('en');
} else {
echo $options->help();
exit(0);
}
// Kill all language directories in /inc/lang and /lib/plugins besides those in $langs array
$this->stripDirLangs(realpath(dirname(__FILE__) . '/../inc/lang'), $keep);
$this->processExtensions(realpath(dirname(__FILE__) . '/../lib/plugins'), $keep);
$this->processExtensions(realpath(dirname(__FILE__) . '/../lib/tpl'), $keep);
}
/**
* Strip languages from extensions
*
* @param string $path path to plugin or template dir
* @param array $keep_langs languages to keep
*/
protected function processExtensions($path, $keep_langs) {
if(is_dir($path)) {
$entries = scandir($path);
foreach($entries as $entry) {
if($entry != "." && $entry != "..") {
if(is_dir($path . '/' . $entry)) {
$plugin_langs = $path . '/' . $entry . '/lang';
if(is_dir($plugin_langs)) {
$this->stripDirLangs($plugin_langs, $keep_langs);
}
}
}
}
}
}
/**
* Strip languages from path
*
* @param string $path path to lang dir
* @param array $keep_langs languages to keep
*/
protected function stripDirLangs($path, $keep_langs) {
$dir = dir($path);
while(($cur_dir = $dir->read()) !== false) {
if($cur_dir != '.' and $cur_dir != '..' and is_dir($path . '/' . $cur_dir)) {
if(!in_array($cur_dir, $keep_langs, true)) {
io_rmdir($path . '/' . $cur_dir, true);
}
}
}
$dir->close();
}
}
$cli = new StripLangsCLI();
$cli->run();

186
ap23/web/doku/bin/wantedpages.php Executable file
View File

@@ -0,0 +1,186 @@
#!/usr/bin/env php
<?php
use splitbrain\phpcli\CLI;
use splitbrain\phpcli\Options;
if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__) . '/../') . '/');
define('NOSESSION', 1);
require_once(DOKU_INC . 'inc/init.php');
/**
* Find wanted pages
*/
class WantedPagesCLI extends CLI {
const DIR_CONTINUE = 1;
const DIR_NS = 2;
const DIR_PAGE = 3;
private $skip = false;
private $sort = 'wanted';
private $result = array();
/**
* Register options and arguments on the given $options object
*
* @param Options $options
* @return void
*/
protected function setup(Options $options) {
$options->setHelp(
'Outputs a list of wanted pages (pages that do not exist yet) and their origin pages ' .
' (the pages that are linkin to these missing pages).'
);
$options->registerArgument(
'namespace',
'The namespace to lookup. Defaults to root namespace',
false
);
$options->registerOption(
'sort',
'Sort by wanted or origin page',
's',
'(wanted|origin)'
);
$options->registerOption(
'skip',
'Do not show the second dimension',
'k'
);
}
/**
* Your main program
*
* Arguments and options have been parsed when this is run
*
* @param Options $options
* @return void
*/
protected function main(Options $options) {
$args = $options->getArgs();
if($args) {
$startdir = dirname(wikiFN($args[0] . ':xxx'));
} else {
$startdir = dirname(wikiFN('xxx'));
}
$this->skip = $options->getOpt('skip');
$this->sort = $options->getOpt('sort');
$this->info("searching $startdir");
foreach($this->getPages($startdir) as $page) {
$this->internalLinks($page);
}
ksort($this->result);
foreach($this->result as $main => $subs) {
if($this->skip) {
print "$main\n";
} else {
$subs = array_unique($subs);
sort($subs);
foreach($subs as $sub) {
printf("%-40s %s\n", $main, $sub);
}
}
}
}
/**
* Determine directions of the search loop
*
* @param string $entry
* @param string $basepath
* @return int
*/
protected function dirFilter($entry, $basepath) {
if($entry == '.' || $entry == '..') {
return WantedPagesCLI::DIR_CONTINUE;
}
if(is_dir($basepath . '/' . $entry)) {
if(strpos($entry, '_') === 0) {
return WantedPagesCLI::DIR_CONTINUE;
}
return WantedPagesCLI::DIR_NS;
}
if(preg_match('/\.txt$/', $entry)) {
return WantedPagesCLI::DIR_PAGE;
}
return WantedPagesCLI::DIR_CONTINUE;
}
/**
* Collects recursively the pages in a namespace
*
* @param string $dir
* @return array
* @throws DokuCLI_Exception
*/
protected function getPages($dir) {
static $trunclen = null;
if(!$trunclen) {
global $conf;
$trunclen = strlen($conf['datadir'] . ':');
}
if(!is_dir($dir)) {
throw new DokuCLI_Exception("Unable to read directory $dir");
}
$pages = array();
$dh = opendir($dir);
while(false !== ($entry = readdir($dh))) {
$status = $this->dirFilter($entry, $dir);
if($status == WantedPagesCLI::DIR_CONTINUE) {
continue;
} else if($status == WantedPagesCLI::DIR_NS) {
$pages = array_merge($pages, $this->getPages($dir . '/' . $entry));
} else {
$page = array(
'id' => pathID(substr($dir . '/' . $entry, $trunclen)),
'file' => $dir . '/' . $entry,
);
$pages[] = $page;
}
}
closedir($dh);
return $pages;
}
/**
* Parse instructions and add the non-existing links to the result array
*
* @param array $page array with page id and file path
*/
protected function internalLinks($page) {
global $conf;
$instructions = p_get_instructions(file_get_contents($page['file']));
$cns = getNS($page['id']);
$exists = false;
$pid = $page['id'];
foreach($instructions as $ins) {
if($ins[0] == 'internallink' || ($conf['camelcase'] && $ins[0] == 'camelcaselink')) {
$mid = $ins[1][0];
resolve_pageid($cns, $mid, $exists);
if(!$exists) {
list($mid) = explode('#', $mid); //record pages without hashes
if($this->sort == 'origin') {
$this->result[$pid][] = $mid;
} else {
$this->result[$mid][] = $pid;
}
}
}
}
}
}
// Main
$cli = new WantedPagesCLI();
$cli->run();