Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parametric page name and other changes #72

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions conf/default.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
$conf['addpage_showroot'] = 1;
$conf['addpage_hide'] = 1;
$conf['addpage_hideACL'] = 0;
$conf['addpage_autopage'] = 0;

1 change: 1 addition & 0 deletions conf/metadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
$meta['addpage_showroot'] = array('onoff');
$meta['addpage_hide'] = array('onoff');
$meta['addpage_hideACL'] = array('onoff');
$meta['addpage_autopage'] = array('onoff');
1 change: 1 addition & 0 deletions lang/en/settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
$lang['addpage_showroot'] = "Show root namespace";
$lang['addpage_hide'] = "When you use {{NEWPAGE>[ns]}} syntax: Hide namespace selection (unchecked: show only subnamespaces)";
$lang['addpage_hideACL'] = "Hide {{NEWPAGE}} if user does not have rights to add pages (show message if unchecked)";
$lang['addpage_autopage'] = "Don't show the input box, the preconfigured namespace is treated as a full page ID. (makes sense with date placeholders)";
4 changes: 2 additions & 2 deletions plugin.info.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# General Plugin Info
base addnewpage
author Benjamin Santalucia, Sam Wilson, Michael Braun, Gerrit Uitslag, Albert Chern
email
date 2015-11-02
email
date 2017-05-29
name Add New Page
desc Adds a "new page form" to any wiki page.
url http://www.dokuwiki.org/plugin:addnewpage
51 changes: 27 additions & 24 deletions script.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,35 @@
jQuery(document).ready(function() {
jQuery(function () {
jQuery(".addnewpage form").each(function () {
var $form = jQuery(this);
var $ns = $form.find("[name='np_cat']");
var $title = $form.find("input[name='title']");
var $id = $form.find("input[name='id']");
var $submit = $form.find(':submit');

// Start with disabled submit button
jQuery(".addnewpage :submit").prop("disabled", true);
// Then enable it when a title is entered
jQuery(".addnewpage input[name='title']").keyup(function(){
var $submit = jQuery(this).parent("form").find(":submit");
if (jQuery(this).val().length > 0) {
$submit.removeAttr("disabled");
} else {
// For when the user deletes the text
$submit.attr("disabled", "disabled");
// disable submit unless something is in input or input is disabled
if ($title.attr('type') === 'text') {
$submit.attr('disabled', 'disabled');
$title.on('input', function () {
if ($title.val().length > 0) {
$submit.removeAttr('disabled');
} else {
$submit.attr('disabled', 'disabled');
}
});
}
}).keyup();

// Change the form's page-ID field on submit
jQuery(".addnewpage form").submit(function(e) {
// Change the form's page-ID field on submit
$form.submit(function () {
// Build the new page ID and save in hidden form field
var id = $ns.val().replace('@INPUT@', $title.val());
$id.val(id);

// Build the new page ID and save in hidden form field
var ns = jQuery(this).find("[name='np_cat']");
var title = jQuery(this).find("input[name='title']");
var id = ns.val()+":"+title.val();
jQuery(this).find("input[name='id']").val(id);
// Clean up the form vars, just to make the resultant URL a bit nicer
$ns.prop("disabled", true);
$title.prop("disabled", true);

// Clean up the form vars, just to make the resultant URL a bit nicer
ns.prop("disabled", true);
title.prop("disabled", true);
return true;
});

return true;
});

});
149 changes: 116 additions & 33 deletions syntax.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
*/
class syntax_plugin_addnewpage extends DokuWiki_Syntax_Plugin {

/** @var array the parsed options */
protected $options;

/**
* Syntax Type
*/
Expand Down Expand Up @@ -50,25 +53,42 @@ public function connectTo($mode) {
* {{NEWPAGE#newtpl1|Title1,newtpl2|Title1}}
* {{NEWPAGE>your:namespace#newtpl1|Title1,newtpl2|Title1}}
*
* @param string $match The text matched by the patterns
* @param int $state The lexer state for the match
* @param int $pos The character position of the matched text
* @param string $match The text matched by the patterns
* @param int $state The lexer state for the match
* @param int $pos The character position of the matched text
* @param Doku_Handler $handler The Doku_Handler object
* @return array Return an array with all data you want to use in render
* @codingStandardsIgnoreStart
*/
public function handle($match, $state, $pos, Doku_Handler $handler) {
/* @codingStandardsIgnoreEnd */
$options = substr($match, 9, -2); // strip markup
$options = explode('#', $options, 2);

$namespace = trim(ltrim($options[0], '>'));
$templates = explode(',', $options[1]);
$templates = array_map('trim', $templates);
return array(
'namespace' => $namespace,
'newpagetemplates' => $templates
$match = substr($match, 9, -2); // strip markup

$data = array(
'namespace' => '',
'newpagetemplates' => array(),
'options' => array(
'exclude' => $this->getConf('addpage_exclude'),
'showroot' => $this->getConf('addpage_showroot'),
'hide' => $this->getConf('addpage_hide'),
'hideacl' => $this->getConf('addpage_hideACL'),
'autopage' => $this->getConf('addpage_autopage'),
)
);

if(preg_match('/>(.*?)(#|\?|$)/', $match, $m)) {
$data['namespace'] = trim($m[1]);
}

if(preg_match('/#(.*?)(\?|$)/', $match, $m)) {
$data['newpagetemplates'] = array_map('trim', explode(',', $m[1]));
}

if(preg_match('/\?(.*?)(#|$)/', $match, $m)) {
$this->_parseOptions($m[1], $data['options']);
}

return $data;
}

/**
Expand All @@ -82,11 +102,14 @@ public function handle($match, $state, $pos, Doku_Handler $handler) {
public function render($mode, Doku_Renderer $renderer, $data) {
global $lang;

// make options available in class
$this->options = $data['options'];

if($mode == 'xhtml') {
$disablecache = null;
$namespaceinput = $this->_htmlNamespaceInput($data['namespace'], $disablecache);
if($namespaceinput === false) {
if($this->getConf('addpage_hideACL')) {
if($this->options['hideacl']) {
$renderer->doc .= '';
} else {
$renderer->doc .= $this->getLang('nooption');
Expand All @@ -97,10 +120,13 @@ public function render($mode, Doku_Renderer $renderer, $data) {

$newpagetemplateinput = $this->_htmlTemplateInput($data['newpagetemplates']);

$input = 'text';
if($this->options['autopage']) $input = 'hidden';

$form = '<div class="addnewpage">' . DOKU_LF
. DOKU_TAB . '<form name="addnewpage" method="get" action="' . DOKU_BASE . DOKU_SCRIPT . '" accept-charset="' . $lang['encoding'] . '">' . DOKU_LF
. DOKU_TAB . DOKU_TAB . $namespaceinput . DOKU_LF
. DOKU_TAB . DOKU_TAB . '<input class="edit" type="text" name="title" size="20" maxlength="255" tabindex="2" />' . DOKU_LF
. DOKU_TAB . DOKU_TAB . '<input class="edit" type="'.$input.'" name="title" size="20" maxlength="255" tabindex="2" />' . DOKU_LF
. $newpagetemplateinput
. DOKU_TAB . DOKU_TAB . '<input type="hidden" name="do" value="edit" />' . DOKU_LF
. DOKU_TAB . DOKU_TAB . '<input type="hidden" name="id" />' . DOKU_LF
Expand All @@ -114,21 +140,78 @@ public function render($mode, Doku_Renderer $renderer, $data) {
return false;
}

/**
* Overwrites the $options with the ones parsed from $optstr
*
* @param string $optstr
* @param array $options
* @author Andreas Gohr <[email protected]>
*/
protected function _parseOptions($optstr, &$options) {
$opts = preg_split('/[,&]/', $optstr);

foreach($opts as $opt) {
$opt = strtolower(trim($opt));
$val = true;
// booleans can be negated with a no prefix
if(substr($opt, 0, 2) == 'no') {
$opt = substr($opt, 2);
$val = false;
}

// not a known option? might be a key=value pair
if(!isset($options[$opt])) {
list($opt, $val) = array_map('trim', explode('=', $opt, 2));
}

// still unknown? skip it
if(!isset($options[$opt])) continue;

// overwrite the current value
$options[$opt] = $val;
}
}

/**
* Parse namespace request
*
* This creates the final ID to be created (still having an @INPUT@ variable
* which is filled in via JavaScript)
*
* @author Samuele Tognini <[email protected]>
* @author Michael Braun <[email protected]>
* @author Andreas Gohr <[email protected]>
* @param string $ns The namespace as given in the syntax
* @return string
*/
protected function _parseNS($ns) {
global $ID;
if(strpos($ns, '@PAGE@') !== false) {
return cleanID(str_replace('@PAGE@', $ID, $ns));
}
if($ns == "@NS@") return getNS($ID);
$ns = preg_replace("/^\.(:|$)/", dirname(str_replace(':', '/', $ID)) . "$1", $ns);
$ns = str_replace("/", ":", $ns);
global $INFO;

$selfid = $INFO['id'];
$selfns = getNS($INFO['id']);
// replace the input variable with something unique that survives cleanID
$keep = sha1(time());

// by default append the input to the namespace (except on autopage)
if(strpos($ns, '@INPUT@') === false && !$this->options['autopage']) $ns .= ":@INPUT@";

// date replacements
$ns = dformat(null, $ns);

// placeholders
$replacements = array(
'/\//' => ':', // forward slashes to colons
'/@PAGE@/' => $selfid,
'/@NS@/' => $selfns,
'/^\.(:|\/|$)/' => "$selfns:",
'/@INPUT@/' => $keep,
);
$ns = preg_replace(array_keys($replacements), array_values($replacements), $ns);

// clean up, then reinsert the input variable
$ns = cleanID($ns);
$ns = str_replace($keep, '@INPUT@', $ns);

return $ns;
}

Expand All @@ -146,7 +229,7 @@ protected function _htmlNamespaceInput($dest_ns, &$disablecache) {

// If a NS has been provided:
// Whether to hide the NS selection (otherwise, show only subnamespaces).
$hide = $this->getConf('addpage_hide');
$hide = $this->options['hide'];

$parsed_dest_ns = $this->_parseNS($dest_ns);
// Whether the user can create pages in the provided NS (or root, if no
Expand All @@ -171,7 +254,7 @@ protected function _htmlNamespaceInput($dest_ns, &$disablecache) {
$someopt = false;

// Show root namespace if requested and allowed
if($this->getConf('addpage_showroot') && $can_create) {
if($this->options['showroot'] && $can_create) {
if(empty($dest_ns)) {
// If no namespace has been provided, add an option for the root NS.
$ret .= '<option ' . (($currentns == '') ? 'selected ' : '') . 'value="">' . $this->getLang('namespaceRoot') . '</option>';
Expand All @@ -187,7 +270,7 @@ protected function _htmlNamespaceInput($dest_ns, &$disablecache) {

// The top of this stack will always be the last printed ancestor namespace
$ancestor_stack = array();
if (!empty($dest_ns)) {
if(!empty($dest_ns)) {
array_push($ancestor_stack, $dest_ns);
}

Expand All @@ -201,14 +284,14 @@ protected function _htmlNamespaceInput($dest_ns, &$disablecache) {
}

$nsparts = explode(':', $ns);
$first_unprinted_depth = empty($ancestor_stack)? 1 : (2 + substr_count($ancestor_stack[count($ancestor_stack) - 1], ':'));
for ($i = $first_unprinted_depth, $end = count($nsparts); $i <= $end; $i++) {
$first_unprinted_depth = empty($ancestor_stack) ? 1 : (2 + substr_count($ancestor_stack[count($ancestor_stack) - 1], ':'));
for($i = $first_unprinted_depth, $end = count($nsparts); $i <= $end; $i++) {
$namespace = implode(':', array_slice($nsparts, 0, $i));
array_push($ancestor_stack, $namespace);
$selectOptionText = str_repeat('&nbsp;&nbsp;', substr_count($namespace, ':')) . $nsparts[$i - 1];
$ret .= '<option ' .
(($currentns == $namespace) ? 'selected ' : '') .
($i == $end? ('value="' . $namespace . '">') : 'disabled>') .
($i == $end ? ('value="' . $namespace . '">') : 'disabled>') .
$selectOptionText .
'</option>';
}
Expand Down Expand Up @@ -237,7 +320,7 @@ protected function _getNamespaceList($topns = '') {

$topns = utf8_encodeFN(str_replace(':', '/', $topns));

$excludes = $this->getConf('addpage_exclude');
$excludes = $this->options['exclude'];
if($excludes == "") {
$excludes = array();
} else {
Expand All @@ -249,7 +332,7 @@ protected function _getNamespaceList($topns = '') {
$namespaces = array();
foreach($searchdata as $ns) {
foreach($excludes as $exclude) {
if( ! empty($exclude) && strpos($ns['id'], $exclude) === 0) {
if(!empty($exclude) && strpos($ns['id'], $exclude) === 0) {
continue 2;
}
}
Expand All @@ -272,7 +355,7 @@ public function _htmlTemplateInput($newpagetemplates) {

} else {
if($cnt == 1) {
list($template, ) = $this->_parseNSTemplatePage($newpagetemplates[0]);
list($template,) = $this->_parseNSTemplatePage($newpagetemplates[0]);
$input = '<input type="hidden" name="newpagetemplate" value="' . formText($template) . '" />';
} else {
$first = true;
Expand All @@ -282,8 +365,8 @@ public function _htmlTemplateInput($newpagetemplates) {
$first = false;

list($template, $name) = $this->_parseNSTemplatePage($template);
$p .= ' value="'.formText($template).'"';
$input .= "<option $p>".formText($name)."</option>";
$p .= ' value="' . formText($template) . '"';
$input .= "<option $p>" . formText($name) . "</option>";
}
$input .= '</select>';
}
Expand All @@ -306,7 +389,7 @@ protected function _parseNSTemplatePage($nstemplate) {
$exist = null;
resolve_pageid(getNS($ID), $template, $exist); //get absolute id

if (is_null($name)) $name = $template;
if(is_null($name)) $name = $template;

return array($template, $name);
}
Expand Down