summaryrefslogtreecommitdiff
path: root/platform/www/lib/plugins/bureaucracy
diff options
context:
space:
mode:
Diffstat (limited to 'platform/www/lib/plugins/bureaucracy')
-rw-r--r--platform/www/lib/plugins/bureaucracy/.github/workflows/phpTestLinux.yml52
-rw-r--r--platform/www/lib/plugins/bureaucracy/README25
-rw-r--r--platform/www/lib/plugins/bureaucracy/_test/BureaucracyTest.php69
-rw-r--r--platform/www/lib/plugins/bureaucracy/_test/actions_template.test.php88
-rw-r--r--platform/www/lib/plugins/bureaucracy/_test/actions_template_noreplace.test.php113
-rw-r--r--platform/www/lib/plugins/bureaucracy/_test/field_date.test.php97
-rw-r--r--platform/www/lib/plugins/bureaucracy/_test/field_email.test.php92
-rw-r--r--platform/www/lib/plugins/bureaucracy/_test/field_file.test.php137
-rw-r--r--platform/www/lib/plugins/bureaucracy/_test/field_hidden.test.php77
-rw-r--r--platform/www/lib/plugins/bureaucracy/_test/field_multiselect.test.php81
-rw-r--r--platform/www/lib/plugins/bureaucracy/_test/field_radio.test.php74
-rw-r--r--platform/www/lib/plugins/bureaucracy/_test/field_time.test.php86
-rw-r--r--platform/www/lib/plugins/bureaucracy/_test/field_user.test.php209
-rw-r--r--platform/www/lib/plugins/bureaucracy/_test/field_users.test.php168
-rw-r--r--platform/www/lib/plugins/bureaucracy/_test/field_yesno.test.php70
-rw-r--r--platform/www/lib/plugins/bureaucracy/_test/general.test.php61
-rw-r--r--platform/www/lib/plugins/bureaucracy/_test/input.txt38
-rw-r--r--platform/www/lib/plugins/bureaucracy/_test/replace_functions.test.php142
-rw-r--r--platform/www/lib/plugins/bureaucracy/_test/syntax.test.php138
-rw-r--r--platform/www/lib/plugins/bureaucracy/action.php60
-rw-r--r--platform/www/lib/plugins/bureaucracy/conf/default.php4
-rw-r--r--platform/www/lib/plugins/bureaucracy/conf/metadata.php5
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/action.php136
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/actionmail.php212
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/actionscript.php62
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/actiontemplate.php459
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/field.php508
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fieldaddpage.php63
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fielddate.php42
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fieldemail.php30
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fieldfieldset.php114
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fieldfile.php75
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fieldhidden.php47
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fieldhiddenautoinc.php35
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fieldmultiselect.php62
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fieldnumber.php119
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fieldonoff.php16
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fieldpassword.php29
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fieldradio.php82
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fieldselect.php61
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fieldstatic.php60
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fieldsubject.php37
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fieldsubmit.php89
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fieldtextarea.php29
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fieldtextbox.php34
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fieldtime.php42
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fieldusemailtemplate.php62
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fielduser.php99
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fieldusers.php96
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fieldwiki.php70
-rw-r--r--platform/www/lib/plugins/bureaucracy/helper/fieldyesno.php98
-rw-r--r--platform/www/lib/plugins/bureaucracy/interfaces/bureaucracy_handler_interface.php19
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/cs/lang.php27
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/cs/settings.php4
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/de/lang.php38
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/de/settings.php8
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/en/lang.php40
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/en/settings.php5
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/es/lang.php38
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/es/settings.php9
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/fa/lang.php38
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/fa/settings.php9
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/fr/lang.php38
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/fr/settings.php9
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/hr/lang.php38
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/hr/settings.php9
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/it/lang.php19
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/ja/lang.php38
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/ja/settings.php9
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/lv/lang.php30
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/nl/lang.php38
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/nl/settings.php9
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/no/lang.php39
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/no/settings.php5
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/pt-br/lang.php34
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/pt/lang.php37
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/pt/settings.php9
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/ru/lang.php38
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/ru/settings.php9
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/zh/lang.php39
-rw-r--r--platform/www/lib/plugins/bureaucracy/lang/zh/settings.php5
-rw-r--r--platform/www/lib/plugins/bureaucracy/plugin.info.txt8
-rw-r--r--platform/www/lib/plugins/bureaucracy/script.js3
-rwxr-xr-xplatform/www/lib/plugins/bureaucracy/script/datepicker.js11
-rw-r--r--platform/www/lib/plugins/bureaucracy/script/fieldsets.js84
-rwxr-xr-xplatform/www/lib/plugins/bureaucracy/script/user.js90
-rw-r--r--platform/www/lib/plugins/bureaucracy/style.css101
-rw-r--r--platform/www/lib/plugins/bureaucracy/syntax.php623
88 files changed, 6361 insertions, 0 deletions
diff --git a/platform/www/lib/plugins/bureaucracy/.github/workflows/phpTestLinux.yml b/platform/www/lib/plugins/bureaucracy/.github/workflows/phpTestLinux.yml
new file mode 100644
index 0000000..194e707
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/.github/workflows/phpTestLinux.yml
@@ -0,0 +1,52 @@
+name: PHP Tests on Linux
+
+on: [push, pull_request]
+
+jobs:
+ run:
+ name: PHP ${{ matrix.php-versions }} DokuWiki ${{ matrix.dokuwiki-branch }}
+ runs-on: ubuntu-latest
+ if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
+
+ strategy:
+ matrix:
+ php-versions: ['7.2', '7.3', '7.4', '8.0']
+ dokuwiki-branch: [ 'master', 'stable']
+ exclude:
+ - dokuwiki-branch: 'stable'
+ php-versions: '8.0'
+ fail-fast: true
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php-versions }}
+ extensions: mbstring, intl, PDO, pdo_sqlite, bz2
+
+ - name: Setup problem matchers
+ run: |
+ echo ::add-matcher::${{ runner.tool_cache }}/php.json
+ echo ::add-matcher::${{ runner.tool_cache }}/phpunit.json
+
+ - name: Download DokuWiki Test-setup
+ run: wget https://raw.github.com/splitbrain/dokuwiki-travis/master/travis.sh
+
+ - name: Run DokuWiki Test-setup
+ env:
+ CI_SERVER: 1
+ DOKUWIKI: ${{ matrix.dokuwiki-branch }}
+ run: sh travis.sh
+
+ - name: Setup PHPUnit
+ run: |
+ php _test/fetchphpunit.php
+ cd _test
+
+ - name: Run PHPUnit
+ run: |
+ cd _test
+ php phpunit.phar --verbose --stderr --group plugin_bureaucracy
diff --git a/platform/www/lib/plugins/bureaucracy/README b/platform/www/lib/plugins/bureaucracy/README
new file mode 100644
index 0000000..ca2bef7
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/README
@@ -0,0 +1,25 @@
+bureaucracy Plugin for DokuWiki
+
+All documentation for this plugin can be found at
+http://www.dokuwiki.org/plugin:bureaucracy
+
+If you install this plugin manually, make sure it is installed in
+lib/plugins/bureaucracy/ - if the folder is called different it
+will not work!
+
+Please refer to http://www.dokuwiki.org/plugins for additional info
+on how to install plugins in DokuWiki.
+
+----
+Copyright (C) Andreas Gohr <andi@splitbrain.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; version 2 of the License
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+See the COPYING file in your DokuWiki folder for details
diff --git a/platform/www/lib/plugins/bureaucracy/_test/BureaucracyTest.php b/platform/www/lib/plugins/bureaucracy/_test/BureaucracyTest.php
new file mode 100644
index 0000000..5a381e6
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/_test/BureaucracyTest.php
@@ -0,0 +1,69 @@
+<?php
+
+namespace dokuwiki\plugin\bureaucracy\test;
+
+
+class BureaucracyTest extends \DokuWikiTest
+{
+
+ const FORM_PREFIX_HTML = '<form class="bureaucracy__plugin" id="bureaucracy__plugin1" enctype="multipart/form-data" method="post" action="" accept-charset="utf-8"><div class="no">
+<input type="hidden" name="sectok" value="" /><input type="hidden" name="bureaucracy[$$id]" value="1" /><fieldset ><legend></legend>';
+ const FORM_SUFFIX_HTML = '</fieldset>
+</div></form>';
+
+ protected $pluginsEnabled = ['bureaucracy'];
+
+ /**
+ * Simulate sending of bureaucracy form
+ *
+ * @param string|array $form_syntax syntax to build a bureaucracy form
+ * @param string $template_syntax syntax used as a page template for the "action template"
+ * @param array & $validation_errors field labels that were invalid
+ * @param string|array ...$values values passed to form handler
+ *
+ * @return string content of newly created page
+ */
+ protected function send_form_action_template($form_syntax, $template_syntax, &$validation_errors, ...$values)
+ {
+ $id = uniqid('page', true);
+ $template_id = uniqid('template', true);
+
+ //create full form syntax
+ if (is_array($form_syntax)) {
+ $form_syntax = implode("\n", $form_syntax);
+ }
+ $form_syntax = "<form>\naction template $template_id $id\n$form_syntax\n</form>";
+
+ saveWikiText($template_id, $template_syntax, 'summary');
+
+ /** @var \syntax_plugin_bureaucracy $syntax_plugin */
+ $syntax_plugin = plugin_load('syntax', 'bureaucracy');
+ $data = $syntax_plugin->handle($form_syntax, 0, 0, new \Doku_Handler());
+
+ $actionData = $data['actions'][0];
+ /** @var \helper_plugin_bureaucracy_action $action */
+ $action = plugin_load('helper', $actionData['actionname']);
+ //this is the only form
+ $form_id = 0;
+
+ /** @var \helper_plugin_bureaucracy_field $field */
+ foreach ($data['fields'] as $i => $field) {
+ if (!isset($values[$i])) {
+ $values[$i] = null;
+ }
+
+ $isValid = $field->handle_post($values[$i], $data['fields'], $i, $form_id);
+ if (!$isValid) {
+ $validation_errors[] = $field->getParam('label');
+ }
+ }
+
+ $action->run(
+ $data['fields'],
+ $data['thanks'],
+ $actionData['argv']
+ );
+
+ return rawWiki($id);
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/_test/actions_template.test.php b/platform/www/lib/plugins/bureaucracy/_test/actions_template.test.php
new file mode 100644
index 0000000..befefc3
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/_test/actions_template.test.php
@@ -0,0 +1,88 @@
+<?php
+/**
+ * @group plugin_bureaucracy
+ * @group plugins
+ */
+class syntax_plugin_bureaucracy_action_template_test extends DokuWikiTest {
+
+ protected $pluginsEnabled = array('bureaucracy');
+
+ public function testPrepareLanguagePlaceholderNoTranslate() {
+ $action = $this->getTemplateClass();
+ $action->prepareLanguagePlaceholder();
+
+ $this->assertEquals('en', $action->values['__lang__']);
+ $this->assertEquals('/@LANG@/', $action->patterns['__lang__']);
+ $this->assertEquals('', $action->values['__trans__']);
+ $this->assertEquals('/@TRANS@/', $action->patterns['__trans__']);
+ }
+
+ public function testPrepareLanguagePlaceholderTranslateDefaultNS() {
+ global $conf;
+ global $ID;
+
+ $conf['plugin']['translation']['translations'] = 'de';
+ $ID = 'bla';
+
+ plugin_enable('translation');
+ if (null === plugin_load('helper', 'translation')) return;
+
+ $action = $this->getTemplateClass();
+ $action->prepareLanguagePlaceholder();
+
+ $this->assertEquals('en', $action->values['__lang__']);
+ $this->assertEquals('/@LANG@/', $action->patterns['__lang__']);
+ $this->assertEquals('', $action->values['__trans__']);
+ $this->assertEquals('/@TRANS@/', $action->patterns['__trans__']);
+ }
+
+ public function testPrepareLanguagePlaceholderTranslateLanguageNS() {
+ global $conf;
+ global $ID;
+
+ $conf['plugin']['translation']['translations'] = 'de';
+ $ID = 'de:bla';
+
+ plugin_enable('translation');
+ $translation = plugin_load('helper', 'translation');
+ if (null === $translation) return;
+
+ $action = $this->getTemplateClass();
+ $action->prepareLanguagePlaceholder();
+
+ $this->assertEquals('en', $action->values['__lang__']);
+ $this->assertEquals('/@LANG@/', $action->patterns['__lang__']);
+ $this->assertEquals('de', $action->values['__trans__']);
+ $this->assertEquals('/@TRANS@/', $action->patterns['__trans__']);
+ }
+
+ public function testProcessFields() {
+ $data = array();
+ /** @var helper_plugin_bureaucracy_fieldstatic $staticfield */
+ $staticfield = plugin_load('helper', 'bureaucracy_fieldstatic');
+ $staticfield->initialize(array('text', 'text1'));
+ $data[] = $staticfield;
+
+ $action = $this->getTemplateClass();
+ $action->prepareFieldReplacements($data, '_', '');
+
+ $this->assertEquals('/(@@|##)text1(?:\|(.*?))\1/si', $action->patterns['text1']);
+ $this->assertEquals('$2', $action->values['text1']);
+ $this->assertEmpty($action->targetpages);
+ }
+
+ /**
+ * @return helper_plugin_bureaucracy_actiontemplate
+ */
+ private function getTemplateClass() {
+ /** @var helper_plugin_bureaucracy_actiontemplate $templateaction */
+ $templateaction = plugin_load('helper', 'bureaucracy_actiontemplate');
+ $templateaction->patterns = array();
+ $templateaction->values = array();
+ $templateaction->targetpages = array();
+ $templateaction->pagename = array();
+ return $templateaction;
+ }
+
+
+}
diff --git a/platform/www/lib/plugins/bureaucracy/_test/actions_template_noreplace.test.php b/platform/www/lib/plugins/bureaucracy/_test/actions_template_noreplace.test.php
new file mode 100644
index 0000000..dc54878
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/_test/actions_template_noreplace.test.php
@@ -0,0 +1,113 @@
+<?php
+
+namespace dokuwiki\plugin\bureaucracy\test;
+
+/**
+ * @group plugin_bureaucracy
+ * @group plugins
+ */
+class bureaucracy_actions_template_test extends BureaucracyTest {
+
+ public function dataProvider()
+ {
+ return [
+ [
+ 'This is <noreplace>test</noreplace>.',
+ '',
+ '',
+ 'This is test.',
+ [],
+ '<noreplace></noreplace> not removed.',
+ ],
+ [
+ '%Y-%m-%d <noreplace>%Y-%m-%d</noreplace>.',
+ '',
+ '',
+ date('Y-m-d') . ' %Y-%m-%d.',
+ [],
+ 'Date replaced inside <noreplace></noreplace>.',
+ ],
+ [
+ '@@test@@ <noreplace>@@test@@</noreplace>.',
+ 'textbox test',
+ 'something',
+ 'something @@test@@.',
+ [],
+ 'Field value replaced inside <noreplace></noreplace>.',
+ ],
+ [
+ '<noreplace>@ID@ @USER@ @MAIL@</noreplace>',
+ '',
+ '',
+ '@ID@ @USER@ @MAIL@',
+ [],
+ 'DokuWiki replacement paterns for templates replaced inside <noreplace></noreplace>.',
+ ],
+ [
+ '<noreplace>@FORMPAGE_ID@ @FORMPAGE_NS@ @FORMPAGE_CURNS@</noreplace>',
+ '',
+ '',
+ '@FORMPAGE_ID@ @FORMPAGE_NS@ @FORMPAGE_CURNS@',
+ [],
+ '@FORMPAGE_*@ replacement paterns replaced inside <noreplace></noreplace>.',
+ ],
+ [
+ '<noreplace><noinclude>TEST</noinclude></noreplace>',
+ '',
+ '',
+ '<noinclude>TEST</noinclude>',
+ [],
+ 'noinclude tag inside <replaced inside <noreplace></noreplace>.',
+ ],
+ [
+ '<noreplace>@NSBASE@</noreplace>',
+ '',
+ '',
+ '@NSBASE@',
+ [],
+ '"@NSBASE@" replaced inside <noreplace></noreplace>.',
+ ],
+ [
+ '<noreplace>%%</noreplace>',
+ '',
+ '',
+ '%%',
+ [],
+ '"%%" replaced inside <noreplace></noreplace>.',
+ ]
+ ];
+ }
+
+ /**
+ * @dataProvider dataProvider
+ *
+ * @param string $templateSyntax
+ * @param string $formSyntax
+ * @param string $postedValue
+ * @param string $expectedWikiText
+ * @param string $msg
+ *
+ */
+ public function test_noreplace_tag(
+ $templateSyntax,
+ $formSyntax,
+ $postedValue,
+ $expectedWikiText,
+ $expectedValidationErrors,
+ $msg
+ ) {
+ $actualValidationErrors = [];
+
+ $actualWikiText = parent::send_form_action_template(
+ $formSyntax,
+ $templateSyntax,
+ $actualValidationErrors,
+ $postedValue
+ );
+
+ if (empty($expectedValidationErrors)) {
+ $this->assertEquals($expectedWikiText, $actualWikiText, $msg);
+ }
+ $this->assertEquals($expectedValidationErrors, $actualValidationErrors, $msg);
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/_test/field_date.test.php b/platform/www/lib/plugins/bureaucracy/_test/field_date.test.php
new file mode 100644
index 0000000..3164630
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/_test/field_date.test.php
@@ -0,0 +1,97 @@
+<?php
+
+namespace dokuwiki\plugin\bureaucracy\test;
+
+use \Doku_Form;
+
+/**
+ * @group plugin_bureaucracy
+ * @group plugins
+ */
+class bureaucracy_field_date_test extends BureaucracyTest
+{
+
+ public function dataProvider()
+ {
+ return [
+ [
+ 'Date:@@dateLabel@@',
+ 'date "dateLabel"',
+ '2018-05-15',
+ 'Date:2018-05-15',
+ [],
+ 'valid date',
+ ],
+ [
+ 'Date:@@dateLabel@@',
+ 'date "dateLabel"',
+ '2018.05.15',
+ null,
+ ['dateLabel'],
+ 'invalid date',
+ ],
+ [
+ 'Date: @DATE(@@dateLabel@@)@',
+ 'date "dateLabel"',
+ '2018-02-15',
+ 'Date: 2018/02/15 00:00',
+ [],
+ 'formatted date with $conf[\'dformat\'] format',
+ ],
+ [
+ 'Month: @DATE(@@dateLabel@@,%%m)@',
+ 'date "dateLabel"',
+ '2018-02-15',
+ 'Month: 02',
+ [],
+ 'formatted date with custom format',
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider dataProvider
+ *
+ * @param string $templateSyntax
+ * @param string $formSyntax
+ * @param string $postedValue
+ * @param string $expectedWikiText
+ * @param string $expectedValidationErrors
+ * @param string $msg
+ *
+ */
+ public function test_field_date_submit(
+ $templateSyntax,
+ $formSyntax,
+ $postedValue,
+ $expectedWikiText,
+ $expectedValidationErrors,
+ $msg
+ ) {
+ $actualValidationErrors = [];
+
+ $actualWikiText = parent::send_form_action_template(
+ $formSyntax,
+ $templateSyntax,
+ $actualValidationErrors,
+ $postedValue
+ );
+
+ if (empty($expectedValidationErrors)) {
+ $this->assertEquals($expectedWikiText, $actualWikiText, $msg);
+ }
+ $this->assertEquals($expectedValidationErrors, $actualValidationErrors, $msg);
+ }
+
+ public function test_field_date_render()
+ {
+ $formSyntax = 'date "dateLabel"';
+ $instr = p_get_instructions("<form>\n$formSyntax\n</form>");
+
+ $actualHTML = p_render('xhtml', $instr, $info);
+
+ $expectedFieldHTML = '<label><span>dateLabel <sup>*</sup></span> <input type="text" name="bureaucracy[0]" class="datepicker edit required" maxlength="10" required="required" /></label>';
+ $expectedHTML = self::FORM_PREFIX_HTML . "\n$expectedFieldHTML\n" . self::FORM_SUFFIX_HTML;
+ $this->assertEquals(trim($expectedHTML), trim($actualHTML));
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/_test/field_email.test.php b/platform/www/lib/plugins/bureaucracy/_test/field_email.test.php
new file mode 100644
index 0000000..c3c522a
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/_test/field_email.test.php
@@ -0,0 +1,92 @@
+<?php
+
+namespace dokuwiki\plugin\bureaucracy\test;
+
+use \Doku_Form;
+
+/**
+ * @group plugin_bureaucracy
+ * @group plugins
+ */
+class bureaucracy_field_email_test extends BureaucracyTest
+{
+
+ public function dataProvider()
+ {
+ return [
+ [
+ 'Mail: @@emailLabel@@',
+ 'valid@example.com',
+ 'Mail: valid@example.com',
+ [],
+ 'valid email',
+ ],
+ [
+ 'Mail: @@emailLabel@@',
+ '@MAIL@',
+ 'Mail: @MAIL@',
+ [],
+ '@MAIL@ placeholder for user\'s email adress',
+ ],
+ [
+ 'Mail: @@emailLabel@@',
+ 'invalid@example',
+ 'Mail: invalid@example',
+ [],
+ 'local email addresses are allowed',
+ ],
+ [
+ 'Mail: @@emailLabel@@',
+ 'invalid[at]example.com',
+ null,
+ ['emailLabel'],
+ 'invalid email',
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider dataProvider
+ *
+ * @param string $templateSyntax
+ * @param $postedValue
+ * @param string $expectedWikiText
+ * @param string $expectedValidationErrors
+ * @param string $msg
+ *
+ */
+ public function test_field_email_submit(
+ $templateSyntax,
+ $postedValue,
+ $expectedWikiText,
+ $expectedValidationErrors,
+ $msg
+ ) {
+ $actualValidationErrors = [];
+
+ $label = 'emailLabel';
+ $actualWikiText = parent::send_form_action_template(
+ "email \"$label\"",
+ $templateSyntax,
+ $actualValidationErrors,
+ $postedValue
+ );
+
+ if (empty($expectedValidationErrors)) {
+ $this->assertEquals($expectedWikiText, $actualWikiText, $msg);
+ }
+ $this->assertEquals($expectedValidationErrors, $actualValidationErrors, $msg);
+ }
+
+ public function test_field_email_render()
+ {
+ $formSyntax = 'email emailLabel';
+ $instr = p_get_instructions("<form>\n$formSyntax\n</form>");
+
+ $actualHTML = p_render('xhtml', $instr, $info);
+
+ $expectedFieldHTML = '<label><span>emailLabel <sup>*</sup></span> <input type="text" name="bureaucracy[0]" class="edit required" required="required" /></label>';
+ $expectedHTML = self::FORM_PREFIX_HTML . "\n$expectedFieldHTML\n" . self::FORM_SUFFIX_HTML;
+ $this->assertEquals(trim($expectedHTML), trim($actualHTML));
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/_test/field_file.test.php b/platform/www/lib/plugins/bureaucracy/_test/field_file.test.php
new file mode 100644
index 0000000..628bff4
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/_test/field_file.test.php
@@ -0,0 +1,137 @@
+<?php
+/**
+ * @group plugin_bureaucracy
+ * @group plugins
+ */
+class syntax_plugin_bureaucracy_fieldfile_test extends DokuWikiTest {
+
+ protected $pluginsEnabled = array('bureaucracy');
+
+ /**
+ * Parse doku $syntax and check if any resulting xhtml element can be selected by $pqSelector
+ *
+ * @param $syntax
+ * @param $pqSelector
+ */
+ protected function assertPqSelector($syntax, $pqSelector) {
+ $xhtml = p_render('xhtml', p_get_instructions($syntax), $info);
+ $doc = phpQuery::newDocument($xhtml);
+ $result = pq($pqSelector, $doc);
+ $this->assertEquals(1, $result->length, "selector: \"$pqSelector\" not found in\n$xhtml\n");
+ }
+
+ /**
+ * Chceck if defined namespace doesn't violate $standardArgs
+ */
+ function test_syntax() {
+ $standardArgs = array(
+ '!' => 'input[type=file].edit',
+ '^' => 'input[type=file][required].edit.required',
+ '@' => 'input[type=file][required].edit.required',
+ '! /regex/' => 'input[type=file].edit',
+ '@ /regex/ "**Example error"' => 'input[type=file][required].edit.required'
+ );
+
+ //upload namespace not defined
+ foreach ($standardArgs as $arg => $pqSelector) {
+ $input = "<form>\nfile \"Some label\" $arg\n</form>";
+ $this->assertPqSelector($input, $pqSelector);
+ }
+
+ //upload namespace defined, nothing shoud change in syntax
+ foreach ($standardArgs as $arg => $pqSelector) {
+ $input = "<form>\nfile \"Some label\" upload:here $arg\n</form>";
+ $this->assertPqSelector($input, $pqSelector);
+ }
+
+ //upload namespace in ""
+ foreach ($standardArgs as $arg => $pqSelector) {
+ $input = "<form>\nfile \"Some label\" \"upload:here\" $arg\n</form>";
+ $this->assertPqSelector($input, $pqSelector);
+ }
+ }
+
+ /**
+ * Parse the bureaucracy form syntax and simulate a file upload
+ *
+ * @param $form_syntax bureaucracy form syntax containg only one file field
+ * @return string a name of the uploaded file
+ */
+ protected function simulate_file_upload($form_syntax) {
+ $media = 'img.png';
+ $media_src = mediaFN('wiki:dokuwiki-128.png');
+
+ $syntax_plugin = new syntax_plugin_bureaucracy();
+ $data = $syntax_plugin->handle($form_syntax, 0, 0, new Doku_Handler());
+
+ $actionData = $data['actions'][0];
+ $action = plugin_load('helper', $actionData['actionname']);
+
+ $fileField = $data['fields'][0];
+
+ //mock file upload
+ $file = array(
+ 'name' => $media,
+ 'type' => 'image/png',
+ 'size' => filesize($media_src),
+ 'tmp_name' => $media_src
+ );
+ //this is the only field
+ $index = 0;
+ //this is the only form
+ $form_id = 0;
+ $fileField->handle_post($file, $data['fields'], $index, $form_id);
+
+ //upload file
+ $action->run(
+ $data['fields'],
+ $data['thanks'],
+ $actionData['argv']
+ );
+
+ return $media;
+ }
+
+ function test_action_template_upload_default() {
+ $template_id = 'template_upload_default';
+ $id = 'upload_default';
+
+ saveWikiText($template_id, 'Value:@@Some label@@', 'summary');
+
+ $form_syntax = "<form>action template $template_id $id\nfile \"Some label\"\n</form>";
+ $media = $this->simulate_file_upload($form_syntax);
+
+ //check if file exists where we suspect it to be
+ $this->assertTrue(file_exists(mediaFN("$id:$media")));
+ }
+
+ function test_action_template_upload_absolute() {
+ $template_id = 'template_upload_absolute';
+ $id = 'upload_absolute';
+ $upload_ns = 'upload:ns';
+
+ saveWikiText($template_id, 'Value:@@Some label@@', 'summary');
+
+ $form_syntax = "<form>action template $template_id $id\nfile \"Some label\" $upload_ns\n</form>";
+ $media = $this->simulate_file_upload($form_syntax);
+
+ //check if file exists where we suspect it to be
+ $this->assertTrue(file_exists(mediaFN("$upload_ns:$media")));
+ }
+
+ function test_action_template_upload_relative() {
+ $template_id = 'template_upload_relative';
+ $id = 'upload_relative';
+ $upload_ns_rel = 'upload:ns';
+ $upload_ns = ".:$upload_ns_rel";
+
+ saveWikiText($template_id, 'Value:@@Some label@@', 'summary');
+
+ $form_syntax = "<form>action template $template_id $id\nfile \"Some label\" \"$upload_ns\"\n</form>";
+ $media = $this->simulate_file_upload($form_syntax);
+
+ //check if file exists where we suspect it to be
+ $this->assertTrue(file_exists(mediaFN("$id:$upload_ns:$media")));
+ }
+
+}
diff --git a/platform/www/lib/plugins/bureaucracy/_test/field_hidden.test.php b/platform/www/lib/plugins/bureaucracy/_test/field_hidden.test.php
new file mode 100644
index 0000000..386b28b
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/_test/field_hidden.test.php
@@ -0,0 +1,77 @@
+<?php
+
+namespace dokuwiki\plugin\bureaucracy\test;
+
+use \Doku_Form;
+
+/**
+ * @group plugin_bureaucracy
+ * @group plugins
+ */
+class bureaucracy_field_hidden_test extends BureaucracyTest
+{
+
+ public function dataProvider()
+ {
+ return [
+ [
+ 'hidden:@@hiddenLabel@@',
+ 'default value of the hidden field',
+ 'default value of the hidden field',
+ 'hidden:default value of the hidden field',
+ [],
+ 'valid hidden',
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider dataProvider
+ *
+ * @param string $templateSyntax
+ * @param $postedValue
+ * @param string $expectedWikiText
+ * @param string $expectedValidationErrors
+ * @param string $msg
+ *
+ */
+ public function test_field_hidden_submit(
+ $templateSyntax,
+ $defaultValue,
+ $postedValue,
+ $expectedWikiText,
+ $expectedValidationErrors,
+ $msg
+ ) {
+ $actualValidationErrors = [];
+
+ $label = 'hiddenLabel';
+ $actualWikiText = parent::send_form_action_template(
+ "hidden \"$label\" \"=$defaultValue\"",
+ $templateSyntax,
+ $actualValidationErrors,
+ $postedValue
+ );
+
+ if (empty($expectedValidationErrors)) {
+ $this->assertEquals($expectedWikiText, $actualWikiText, $msg);
+ }
+ $this->assertEquals($expectedValidationErrors, $actualValidationErrors, $msg);
+ }
+
+ public function test_field_time_render()
+ {
+ $formSyntax = 'hidden hiddenLabel "=default value of the hidden field"';
+ $instr = p_get_instructions("<form>\n$formSyntax\n</form>");
+
+ $actualHTML = p_render('xhtml', $instr, $info);
+
+ $hiddenFormPrefix = '<form class="bureaucracy__plugin" id="bureaucracy__plugin1" enctype="multipart/form-data" method="post" action="" accept-charset="utf-8"><div class="no">
+<input type="hidden" name="sectok" value="" /><input type="hidden" name="bureaucracy[$$id]" value="1" />';
+ $expectedFieldHTML = '<input type="hidden" name="bureaucracy[0]" value="default value of the hidden field" />';
+ $hiddenFormSuffix = '</div></form>';
+ $expectedHTML = "$hiddenFormPrefix$expectedFieldHTML$hiddenFormSuffix";
+
+ $this->assertEquals(trim($expectedHTML), trim($actualHTML));
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/_test/field_multiselect.test.php b/platform/www/lib/plugins/bureaucracy/_test/field_multiselect.test.php
new file mode 100644
index 0000000..9445dc2
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/_test/field_multiselect.test.php
@@ -0,0 +1,81 @@
+<?php
+
+namespace dokuwiki\plugin\bureaucracy\test;
+
+use Doku_Form;
+
+/**
+ * @group plugin_bureaucracy
+ * @group plugins
+ */
+class bureaucracy_field_multiselect_test extends BureaucracyTest
+{
+
+ public function dataProvider()
+ {
+ return [
+ [
+ 'fruits: @@multiSelectLabel@@',
+ 'multiselect "multiSelectLabel" "Peaches|Apples|Oranges" =Peaches,Oranges',
+ ['Peaches','Apples'],
+ 'fruits: Peaches, Apples',
+ [],
+ 'default separator',
+ ],
+ [
+ 'fruits: @@multiSelectLabel(;)@@',
+ 'multiselect "multiSelectLabel" "Peaches|Apples|Oranges" =Peaches,Oranges',
+ ['Peaches','Apples'],
+ 'fruits: Peaches;Apples',
+ [],
+ 'custom separator',
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider dataProvider
+ *
+ * @param string $templateSyntax
+ * @param string $formSyntax
+ * @param $postedValue
+ * @param string $expectedWikiText
+ * @param string $expectedValidationErrors
+ * @param string $msg
+ *
+ */
+ public function test_field_multiselect_submit(
+ $templateSyntax,
+ $formSyntax,
+ $postedValue,
+ $expectedWikiText,
+ $expectedValidationErrors,
+ $msg
+ ) {
+ $actualValidationErrors = [];
+
+ $actualWikiText = parent::send_form_action_template(
+ $formSyntax,
+ $templateSyntax,
+ $actualValidationErrors,
+ $postedValue
+ );
+
+ $this->assertEquals($expectedWikiText, $actualWikiText, $msg);
+ $this->assertEquals($expectedValidationErrors, $actualValidationErrors, $msg);
+ }
+
+ public function test_field_multiselect_render()
+ {
+ $formSyntax = 'multiselect "multiSelectLabel" "Peaches|Apples|Oranges" =Peaches,Oranges';
+ $instr = p_get_instructions("<form>\n$formSyntax\n</form>");
+
+ $actualHTML = p_render('xhtml', $instr, $info);
+
+ $expectedFieldHTML = '<label><span>multiSelectLabel <sup>*</sup></span> <select name="bureaucracy[0][]" multiple="multiple">
+<option value="Peaches" selected="selected">Peaches</option><option value="Apples">Apples</option><option value="Oranges" selected="selected">Oranges</option>
+</select></label>';
+ $expectedHTML = self::FORM_PREFIX_HTML . "\n$expectedFieldHTML\n" . self::FORM_SUFFIX_HTML;
+ $this->assertEquals(trim($expectedHTML), trim($actualHTML));
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/_test/field_radio.test.php b/platform/www/lib/plugins/bureaucracy/_test/field_radio.test.php
new file mode 100644
index 0000000..34839f6
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/_test/field_radio.test.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace dokuwiki\plugin\bureaucracy\test;
+
+use Doku_Form;
+
+/**
+ * @group plugin_bureaucracy
+ * @group plugins
+ */
+class bureaucracy_field_radio_test extends BureaucracyTest
+{
+
+ public function dataProvider()
+ {
+ return [
+ [
+ 'fruits:@@radioLabel@@',
+ 'radio "radioLabel" "Peaches|Apples|Oranges"',
+ 'Peaches',
+ 'fruits:Peaches',
+ [],
+ 'first option chosen',
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider dataProvider
+ *
+ * @param string $templateSyntax
+ * @param string $formSyntax
+ * @param $postedValue
+ * @param string $expectedWikiText
+ * @param string $expectedValidationErrors
+ * @param string $msg
+ *
+ */
+ public function test_field_radio_submit(
+ $templateSyntax,
+ $formSyntax,
+ $postedValue,
+ $expectedWikiText,
+ $expectedValidationErrors,
+ $msg
+ ) {
+ $actualValidationErrors = [];
+
+ $label = 'radio';
+ $actualWikiText = parent::send_form_action_template(
+ $formSyntax,
+ $templateSyntax,
+ $actualValidationErrors,
+ $postedValue
+ );
+
+ $this->assertEquals($expectedWikiText, $actualWikiText, $msg);
+ $this->assertEquals($expectedValidationErrors, $actualValidationErrors, $msg);
+ }
+
+ public function test_field_date_render()
+ {
+ $formSyntax = 'radio "radioLabel" "Peaches|Apples|Oranges"';
+ $instr = p_get_instructions("<form>\n$formSyntax\n</form>");
+
+ $actualHTML = p_render('xhtml', $instr, $info);
+
+ $expectedFieldHTML = '<label class="radiolabel "><span>radioLabel <sup>*</sup></span></label><label><input type="radio" name="bureaucracy[0]" value="Peaches" /> <span>Peaches</span></label>
+<label><input type="radio" name="bureaucracy[0]" value="Apples" /> <span>Apples</span></label>
+<label><input type="radio" name="bureaucracy[0]" value="Oranges" /> <span>Oranges</span></label>';
+ $expectedHTML = self::FORM_PREFIX_HTML . "\n$expectedFieldHTML\n" . self::FORM_SUFFIX_HTML;
+ $this->assertEquals(trim($expectedHTML), trim($actualHTML));
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/_test/field_time.test.php b/platform/www/lib/plugins/bureaucracy/_test/field_time.test.php
new file mode 100644
index 0000000..b027d8c
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/_test/field_time.test.php
@@ -0,0 +1,86 @@
+<?php
+
+namespace dokuwiki\plugin\bureaucracy\test;
+
+/**
+ * @group plugin_bureaucracy
+ * @group plugins
+ */
+class bureaucracy_field_time_test extends BureaucracyTest
+{
+
+ public function dataProvider()
+ {
+ return [
+ [
+ 'time:@@timeLabel@@',
+ 'time timeLabel',
+ '10:32',
+ 'time:10:32',
+ [],
+ 'valid time without seconds',
+ ],
+ [
+ 'time:@@timeLabel@@',
+ 'time timeLabel',
+ '10:32:44',
+ 'time:10:32:44',
+ [],
+ 'valid time with seconds',
+ ],
+ [
+ 'time:@@timeLabel@@',
+ 'time timeLabel',
+ '1032',
+ null,
+ ['timeLabel'],
+ 'invalid time',
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider dataProvider
+ *
+ * @param string $templateSyntax
+ * @param string $formSyntax
+ * @param string $postedValue
+ * @param string $expectedWikiText
+ * @param string[] $expectedValidationErrors
+ * @param string $msg
+ */
+ public function test_field_time_submit(
+ $templateSyntax,
+ $formSyntax,
+ $postedValue,
+ $expectedWikiText,
+ $expectedValidationErrors,
+ $msg
+ ) {
+ $actualValidationErrors = [];
+
+ $actualWikiText = parent::send_form_action_template(
+ $formSyntax,
+ $templateSyntax,
+ $actualValidationErrors,
+ $postedValue
+ );
+
+ if (empty($expectedValidationErrors)) {
+ $this->assertEquals($expectedWikiText, $actualWikiText, $msg);
+ }
+ $this->assertEquals($expectedValidationErrors, $actualValidationErrors, $msg);
+ }
+
+ public function test_field_time_render()
+ {
+ $formSyntax = 'time "timeLabel"';
+ $instr = p_get_instructions("<form>\n$formSyntax\n</form>");
+
+ $actualHTML = p_render('xhtml', $instr, $info);
+
+ $expectedFieldHTML = '<label><span>timeLabel <sup>*</sup></span> <input type="text" name="bureaucracy[0]" class="timefield edit required" maxlength="8" required="required" /></label>';
+ $expectedHTML = self::FORM_PREFIX_HTML . "\n$expectedFieldHTML\n" . self::FORM_SUFFIX_HTML;
+ $this->assertEquals(trim($expectedHTML), trim($actualHTML));
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/_test/field_user.test.php b/platform/www/lib/plugins/bureaucracy/_test/field_user.test.php
new file mode 100644
index 0000000..a7ade9b
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/_test/field_user.test.php
@@ -0,0 +1,209 @@
+<?php
+
+namespace dokuwiki\plugin\bureaucracy\test;
+
+/**
+ * @group plugin_bureaucracy
+ * @group plugins
+ */
+class syntax_plugin_bureaucracy_fielduser_test extends BureaucracyTest
+{
+
+ /**
+ * Create some users
+ */
+ public function setUp(): void
+ {
+ parent::setUp();
+
+ /** @var \DokuWiki_Auth_Plugin $auth */
+ global $auth;
+
+ $auth->createUser("user1", "54321", "user1Name", "user1@example.com");
+ $auth->createUser("user2", "543210", "user2Name", "user2@example.com");
+ $auth->createUser("mwuser", "12345", "Wiki User", "wikiuser@example.com", ['group1', 'group2']);
+ }
+
+ public function dataProvider()
+ {
+ return [
+ [
+ 'user:@@user@@',
+ 'user user',
+ 'mwuser',
+ 'user:mwuser',
+ [],
+ 'default substitution',
+ ],
+ [
+ 'user:@@user@@',
+ 'user user',
+ '',
+ 'user:',
+ ['user'],
+ 'error for empty substitution',
+ ],
+ [
+ 'user:@@user@@',
+ 'user user !',
+ '',
+ 'user:',
+ [],
+ 'ok for empty substitution in optional field',
+ ],
+ [
+ 'user:@@user.name@@',
+ 'user user',
+ 'mwuser',
+ 'user:Wiki User',
+ [],
+ 'name substitution',
+ ],
+ [
+ 'user:@@user.mail@@',
+ 'user user',
+ 'mwuser',
+ 'user:wikiuser@example.com',
+ [],
+ 'mail substitution',
+ ],
+ [
+ 'user:@@user.grps@@',
+ 'user user',
+ 'mwuser',
+ 'user:group1, group2',
+ [],
+ 'groups substitution',
+ ],
+ [
+ 'user:@@user.grps(;)@@',
+ 'user user',
+ 'mwuser',
+ 'user:group1;group2',
+ [],
+ 'groups substitution custom delimiter',
+ ],
+ [
+ 'user:@@user.grps())@@',
+ 'user user',
+ 'mwuser',
+ 'user:group1)group2',
+ [],
+ 'groups substitution custom delimiter with brackets',
+ ],
+ [
+ 'user:@@user.no_sutch_attribute@@',
+ 'user user',
+ 'mwuser',
+ 'user:@@user.no_sutch_attribute@@',
+ [],
+ 'template unknown attribute substitution',
+ ],
+ [
+ 'user:##user##',
+ 'user user',
+ 'mwuser',
+ 'user:mwuser',
+ [],
+ 'hash substitution',
+ ],
+ [
+ 'user:##user.mail##',
+ 'user user',
+ 'mwuser',
+ 'user:wikiuser@example.com',
+ [],
+ 'hash substitution with attribute',
+ ],
+ [
+ 'user:##user@@',
+ 'user user',
+ 'mwuser',
+ 'user:##user@@',
+ [],
+ 'hash substitution sign mismatch',
+ ],
+ [
+ "user:@@user@@\n\nmail:@@user.mail@@\n\ngrps:@@user.grps(\n)@@",
+ 'user user',
+ 'mwuser',
+ "user:mwuser\n\nmail:wikiuser@example.com\n\ngrps:group1\ngroup2",
+ [],
+ 'multiple replacements',
+ ],
+ [
+ "grps1:@@user.grps(\n)@@\n\ngrps2:@@user.grps(())@@",
+ 'user user',
+ 'mwuser',
+ "grps1:group1\ngroup2\n\ngrps2:group1()group2",
+ [],
+ 'groups twice',
+ ],
+ [
+ 'grps:@@user.grps(end))@@',
+ 'user user',
+ 'mwuser',
+ 'grps:group1end)group2',
+ [],
+ 'groups special glue',
+ ],
+ [
+ 'grps:@@user.grps()@@',
+ 'user user',
+ 'mwuser',
+ 'grps:group1group2',
+ [],
+ 'groups with empty delimiter',
+ ],
+ [
+ 'user:@@user@@',
+ 'user user',
+ 'non_existant_user',
+ 'user:non_existant_user',
+ ['user'],
+ 'error for non existant user',
+ ],
+ [
+ 'user:@@user.name@@',
+ 'user user',
+ 'non_existant_user',
+ 'user:@@user.name@@',
+ ['user'],
+ 'error for non existant user with attribute',
+ ],
+ ];
+ }
+
+
+ /**
+ * @dataProvider dataProvider
+ *
+ * @param string $templateSyntax
+ * @param string $formSyntax
+ * @param string $postedValue value of 'user' field
+ * @param string $expectedWikiText
+ * @param string $expectedValidationErrors
+ * @param string $msg
+ *
+ */
+ public function test_field_user(
+ $templateSyntax,
+ $formSyntax,
+ $postedValue,
+ $expectedWikiText,
+ $expectedValidationErrors,
+ $msg
+ ) {
+ $actualValidationErrors = [];
+
+ $actualWikiText = parent::send_form_action_template(
+ $formSyntax,
+ $templateSyntax,
+ $actualValidationErrors,
+ $postedValue
+ );
+
+ $this->assertEquals($expectedValidationErrors, $actualValidationErrors, $msg);
+ $this->assertEquals($expectedWikiText, $actualWikiText, $msg);
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/_test/field_users.test.php b/platform/www/lib/plugins/bureaucracy/_test/field_users.test.php
new file mode 100644
index 0000000..633be20
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/_test/field_users.test.php
@@ -0,0 +1,168 @@
+<?php
+
+namespace dokuwiki\plugin\bureaucracy\test;
+
+/**
+ * @group plugin_bureaucracy
+ * @group plugins
+ */
+class syntax_plugin_bureaucracy_fieldusers_test extends BureaucracyTest
+{
+
+ /**
+ * Create some users
+ */
+ public function setUp(): void
+ {
+ parent::setUp();
+
+ /** @var \DokuWiki_Auth_Plugin $auth */
+ global $auth;
+
+ $auth->createUser('user1', '54321', 'user1Name', 'user1@example.com');
+ $auth->createUser('user2', '543210', 'user2Name', 'user2@example.com');
+ $auth->createUser('mwuser', '12345', 'Wiki User', 'me@example.com', ['group1', 'group2']);
+ }
+
+ public function dataProvider()
+ {
+ return [
+ [
+ 'users:@@users@@',
+ 'users users',
+ 'user1, user2',
+ 'users:user1, user2',
+ [],
+ 'default substitution',
+ ],
+ [
+ 'users:@@users@@',
+ 'users users',
+ '',
+ 'users:',
+ ['users'],
+ 'error for empty substitution',
+ ],
+ [
+ 'users:@@users(;)@@',
+ 'users users',
+ 'user1, user2',
+ 'users:user1;user2',
+ [],
+ 'custom delimiter',
+ ],
+ [
+ "users:@@users(\n)@@",
+ 'users users',
+ 'user1, user2',
+ "users:user1\nuser2",
+ [],
+ 'newline delimiter',
+ ],
+ [
+ 'users:@@users()@@',
+ 'users users',
+ 'user1, user2',
+ 'users:user1user2',
+ [],
+ 'empty delimiter',
+ ],
+ [
+ 'users:@@users.name@@',
+ 'users users',
+ 'user1, user2',
+ 'users:user1Name, user2Name',
+ [],
+ 'names substitution default delitmiter',
+ ],
+ [
+ 'users:@@users(;).name@@',
+ 'users users',
+ 'user1, user2',
+ 'users:user1Name;user2Name',
+ [],
+ 'names substitution custom delitmiter',
+ ],
+ [
+ 'users:@@users.mail@@',
+ 'users users',
+ 'user1, user2',
+ 'users:user1@example.com, user2@example.com',
+ [],
+ 'mail substitution default delitmiter',
+ ],
+ [
+ "mails:@@users.mail@@\n\nnames:@@users(\n).name@@",
+ 'users users',
+ 'user1, user2',
+ "mails:user1@example.com, user2@example.com\n\nnames:user1Name\nuser2Name",
+ [],
+ 'multiple replacements',
+ ],
+ [
+ 'users:@@users@@',
+ 'users users',
+ 'not_existing1, not_existing2',
+ 'users:not_existing1, not_existing2',
+ ['users'],
+ 'unknown users should cause errors',
+ ],
+ [
+ 'users:@@users.unknown_attribute@@',
+ 'users users',
+ 'user1, user2',
+ 'users:@@users.unknown_attribute@@',
+ [],
+ 'non existant attribute is not replaced',
+ ],
+ [
+ 'users:@@*]]@@', // the label must be something to break a regex when not properly quoted
+ 'users "*]]"',
+ 'user1, user2',
+ 'users:user1, user2',
+ [],
+ 'ensure label desn\'t break regex',
+ ],
+ [
+ 'users:@@tHis Is UsEr@@',
+ 'users "tHis Is UsEr"',
+ 'user1, user2',
+ 'users:user1, user2',
+ [],
+ 'label with spaces and mixed case',
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider dataProvider
+ *
+ * @param string $templateSyntax
+ * @param string $formSyntax
+ * @param string $postedValue value of 'users' field
+ * @param string $expectedWikiText
+ * @param string $expectedValidationErrors
+ * @param string $msg
+ *
+ */
+ public function test_field_users(
+ $templateSyntax,
+ $formSyntax,
+ $postedValue,
+ $expectedWikiText,
+ $expectedValidationErrors,
+ $msg
+ ) {
+ $actualValidationErrors = [];
+
+ $actualWikiText = parent::send_form_action_template(
+ $formSyntax,
+ $templateSyntax,
+ $actualValidationErrors,
+ $postedValue
+ );
+
+ $this->assertEquals($expectedWikiText, $actualWikiText, $msg);
+ $this->assertEquals($expectedValidationErrors, $actualValidationErrors, $msg);
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/_test/field_yesno.test.php b/platform/www/lib/plugins/bureaucracy/_test/field_yesno.test.php
new file mode 100644
index 0000000..26bd785
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/_test/field_yesno.test.php
@@ -0,0 +1,70 @@
+<?php
+
+namespace dokuwiki\plugin\bureaucracy\test;
+
+/**
+ * @group plugin_bureaucracy
+ * @group plugins
+ */
+class bureaucracy_field_yesno_test extends BureaucracyTest
+{
+
+ public function dataProvider()
+ {
+ return [
+ [
+ 'cb:@@checkbox@@',
+ '"=Yes"',
+ '"!No"',
+ '1',
+ 'cb:Yes',
+ [],
+ 'default checked substitution',
+ ],
+ [
+ 'cb:@@checkbox@@',
+ '"=Yes"',
+ '"!No"',
+ '0',
+ 'cb:No',
+ [],
+ 'default unchecked substitution',
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider dataProvider
+ *
+ * @param string $templateSyntax
+ * @param $YesValue
+ * @param $NoValue
+ * @param $isChecked
+ * @param string $expectedWikiText
+ * @param string $expectedValidationErrors
+ * @param string $msg
+ *
+ */
+ public function test_field_yesno(
+ $templateSyntax,
+ $YesValue,
+ $NoValue,
+ $isChecked,
+ $expectedWikiText,
+ $expectedValidationErrors,
+ $msg
+ ) {
+ $actualValidationErrors = [];
+
+ $label = 'checkbox';
+ $actualWikiText = parent::send_form_action_template(
+ "yesno \"$label\" $YesValue $NoValue",
+ $templateSyntax,
+ $actualValidationErrors,
+ $isChecked
+ );
+
+ $this->assertEquals($expectedWikiText, $actualWikiText, $msg);
+ $this->assertEquals($expectedValidationErrors, $actualValidationErrors, $msg);
+ }
+} \ No newline at end of file
diff --git a/platform/www/lib/plugins/bureaucracy/_test/general.test.php b/platform/www/lib/plugins/bureaucracy/_test/general.test.php
new file mode 100644
index 0000000..0b3e0cf
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/_test/general.test.php
@@ -0,0 +1,61 @@
+<?php
+/**
+ * General tests for the bureaucracy plugin
+ *
+ * @group plugin_bureaucracy
+ * @group plugins
+ */
+class general_plugin_bureaucracy_test extends DokuWikiTest {
+
+ /**
+ * Simple test to make sure the plugin.info.txt is in correct format
+ */
+ public function test_plugininfo() {
+ $file = __DIR__.'/../plugin.info.txt';
+ $this->assertFileExists($file);
+
+ $info = confToHash($file);
+
+ $this->assertArrayHasKey('base', $info);
+ $this->assertArrayHasKey('author', $info);
+ $this->assertArrayHasKey('email', $info);
+ $this->assertArrayHasKey('date', $info);
+ $this->assertArrayHasKey('name', $info);
+ $this->assertArrayHasKey('desc', $info);
+ $this->assertArrayHasKey('url', $info);
+
+ $this->assertEquals('bureaucracy', $info['base']);
+ $this->assertRegExp('/^https?:\/\//', $info['url']);
+ $this->assertTrue(mail_isvalid($info['email']));
+ $this->assertRegExp('/^\d\d\d\d-\d\d-\d\d$/', $info['date']);
+ $this->assertTrue(false !== strtotime($info['date']));
+ }
+
+ /**
+ * Test to ensure that every conf['...'] entry in conf/default.php has a corresponding meta['...'] entry in
+ * conf/metadata.php.
+ */
+ public function test_plugin_conf() {
+ $conf_file = __DIR__.'/../conf/default.php';
+ if (file_exists($conf_file)){
+ include($conf_file);
+ }
+ $meta_file = __DIR__.'/../conf/metadata.php';
+ if (file_exists($meta_file)) {
+ include($meta_file);
+ }
+
+ $this->assertEquals(gettype($conf), gettype($meta),'Both ' . DOKU_PLUGIN . 'bureaucracy/conf/default.php and ' . DOKU_PLUGIN . 'bureaucracy/conf/metadata.php have to exist and contain the same keys.');
+
+ if (gettype($conf) != 'NULL' && gettype($meta) != 'NULL') {
+ foreach($conf as $key => $value) {
+ $this->assertArrayHasKey($key, $meta, 'Key $meta[\'' . $key . '\'] missing in ' . DOKU_PLUGIN . 'bureaucracy/conf/metadata.php');
+ }
+
+ foreach($meta as $key => $value) {
+ $this->assertArrayHasKey($key, $conf, 'Key $conf[\'' . $key . '\'] missing in ' . DOKU_PLUGIN . 'bureaucracy/conf/default.php');
+ }
+ }
+
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/_test/input.txt b/platform/www/lib/plugins/bureaucracy/_test/input.txt
new file mode 100644
index 0000000..6b395ed
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/_test/input.txt
@@ -0,0 +1,38 @@
+<form>
+action template userstpl users:%Y:@@What's your Name?@@:start
+
+Fieldset "A set of fields"
+Textbox "Employee Name" "=Your Name"
+number "Your Age" >13 <99
+email "Your E-Mail Address"
+textbox "Occupation (optional)" !
+password "Some password"
+file "File1"
+
+fieldset "HTML Checks <bold>bang</bold>" "<bold>bang</bold>" "<bold>bang</bold>"
+textbox "HTML check 1 <bold>bang</bold>" "=<bold>bang</bold>"
+password "HTML check 2 <bold>bang</bold>" "=<bold>bang</bold>"
+textarea "HTML check 3 <bold>bang</bold>" "=<bold>bang</bold>"
+static "HTML check 4 <bold>bang</bold>"
+wiki "HTML check 5 <bold>bang</bold>"
+
+fieldset "even more fields"
+select "Please select an option" "Peaches|Apples|Oranges"
+static "Some static text that could be an agreement"
+yesno "Read the agreement?"
+textarea "Tell me about your self"
+textbox "You need to write 'agree' here" /^agree$/
+
+fieldset "Create Your User Page"
+select "What's your Continent?" "Europe|N. America|S. America|Asia|Australia"
+textbox "What's your Name?"
+textarea "Enter a short bio" !
+yesno "Do have publication?"
+
+fieldset "Add your publications" "Do have publication?"
+textarea "Publications:"
+addpage users:publicationtemplate publications
+
+fieldset "Finish"
+submit "Submit Query"
+</form> \ No newline at end of file
diff --git a/platform/www/lib/plugins/bureaucracy/_test/replace_functions.test.php b/platform/www/lib/plugins/bureaucracy/_test/replace_functions.test.php
new file mode 100644
index 0000000..d4104de
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/_test/replace_functions.test.php
@@ -0,0 +1,142 @@
+<?php
+
+namespace dokuwiki\plugin\bureaucracy\test;
+
+use \Doku_Form;
+
+/**
+ * @group plugin_bureaucracy
+ * @group plugins
+ */
+class bureaucracy_replace_functions_test extends BureaucracyTest
+{
+
+ public function dataProvider()
+ {
+ return [
+ [
+ '@curNS@',
+ '',
+ '',
+ '@curNS@',
+ [],
+ '"@function@" shouldn\'t be replaced.',
+ ],
+ [
+ '@curNS()@',
+ '',
+ '',
+ '',
+ [],
+ '"@function()@" should return empty string.',
+ ],
+ [
+ '(@noNS(test):page)@)', //test doubled bracket
+ '',
+ '',
+ '(page)',
+ [],
+ '"@curNS(test:page))@" should return empty string.',
+ ],
+ [
+ '@curNS(test:static:value)@',
+ '',
+ '',
+ 'static',
+ [],
+ '@curNS()@ doesn\'t work.',
+ ],
+ [
+ '@curNS(@@page@@)@',
+ 'textbox page',
+ 'some:test:page',
+ 'test',
+ [],
+ '@curNS()@ doesn\'t work.',
+ ],
+ [
+ '@getNS(@@page@@)@',
+ 'textbox page',
+ 'some:test:page',
+ 'some:test',
+ [],
+ '@getNS()@ doesn\'t work.',
+ ],
+ [
+ '@getNS(test:static:value)@',
+ '',
+ '',
+ 'test:static',
+ [],
+ '@getNS()@ doesn\'t work.',
+ ],
+ [
+ '@noNS(test:static:value)@',
+ '',
+ '',
+ 'value',
+ [],
+ '@noNS()@ doesn\'t work.',
+ ],
+ [
+ '@noNS(@@page@@)@',
+ 'textbox page',
+ 'some:test:page',
+ 'page',
+ [],
+ '@noNS()@ doesn\'t work.',
+ ]
+ ];
+ }
+
+ /**
+ * @dataProvider dataProvider
+ *
+ * @param string $templateSyntax
+ * @param string $formSyntax
+ * @param string $postedValue
+ * @param string $expectedWikiText
+ * @param string $expectedValidationErrors
+ * @param string $msg
+ *
+ */
+ public function test_NS_functions(
+ $templateSyntax,
+ $formSyntax,
+ $postedValue,
+ $expectedWikiText,
+ $expectedValidationErrors,
+ $msg
+ ) {
+ $actualValidationErrors = [];
+
+ $actualWikiText = parent::send_form_action_template(
+ $formSyntax,
+ $templateSyntax,
+ $actualValidationErrors,
+ $postedValue
+ );
+
+ if (empty($expectedValidationErrors)) {
+ $this->assertEquals($expectedWikiText, $actualWikiText, $msg);
+ }
+ $this->assertEquals($expectedValidationErrors, $actualValidationErrors, $msg);
+ }
+
+ public function test_p_get_first_heading_function() {
+ //create page with heading
+ $wikitext = "====== Header 1 ======\n";
+ $page = 'some:test:page';
+ saveWikiText($page, $wikitext, 'summary');
+
+ $actualValidationErrors = [];
+ $actualWikiText = parent::send_form_action_template(
+ 'textbox page',
+ '@p_get_first_heading(@@page@@)@',
+ $actualValidationErrors,
+ $page
+ );
+
+ $this->assertEquals('Header 1', $actualWikiText);
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/_test/syntax.test.php b/platform/www/lib/plugins/bureaucracy/_test/syntax.test.php
new file mode 100644
index 0000000..9b552e0
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/_test/syntax.test.php
@@ -0,0 +1,138 @@
+<?php
+/**
+ * @group plugin_bureaucracy
+ * @group plugins
+ */
+class syntax_plugin_bureaucracy_test extends DokuWikiTest {
+
+ protected $pluginsEnabled = array('bureaucracy');
+
+ public function test_generalFormOutput() {
+ $input = file_get_contents(dirname(__FILE__) . '/input.txt');
+ $xhtml = p_render('xhtml', p_get_instructions($input), $info);
+
+ $doc = phpQuery::newDocument($xhtml);
+
+ $this->assertEquals(1, pq('form.bureaucracy__plugin', $doc)->length);
+ $this->assertEquals(6, pq('form.bureaucracy__plugin fieldset', $doc)->length);
+
+ // standard input types
+ $this->checkField($doc, 'Employee Name', 'input[type=text][value=Your Name].edit', true);
+ $this->checkField($doc, 'Your Age', 'input[type=text].edit', true);
+ $this->checkField($doc, 'Your E-Mail Address', 'input[type=text].edit', true);
+ $this->checkField($doc, 'Occupation (optional)', 'input[type=text].edit');
+ $this->checkField($doc, 'Some password', 'input[type=password].edit', true);
+
+ // select field
+ $select = $this->checkField($doc, 'Please select an option', 'select');
+ $this->assertEquals(3, pq('option', $select)->length);
+ $this->assertEquals(1, pq('option:selected', $select)->length);
+ $this->assertEquals('Peaches', pq('option:selected', $select)->val());
+
+ // static text
+ $this->assertEquals(1, pq('p:contains(Some static text)', $doc)->length);
+
+ // checkbox
+ $cb = $this->checkField($doc, 'Read the agreement?', 'input[type=checkbox][value=1]');
+ $this->assertEquals('1', pq('input[type=hidden][value=0]', $cb->parent())->length);
+
+ // text area
+ $this->checkField($doc, 'Tell me about your self', 'textarea.edit', true);
+
+ // file field
+ $this->checkField($doc, 'File1', 'input[type=file].edit', true);
+
+ // submit button
+ $this->assertEquals(1, pq('button[type=submit]:contains(Submit Query)')->length);
+
+ }
+
+ public function test_HTMLinclusion() {
+ $input = file_get_contents(dirname(__FILE__) . '/input.txt');
+ $xhtml = p_render('xhtml', p_get_instructions($input), $info);
+
+ $doc = phpQuery::newDocument($xhtml);
+
+ // HTML Check - there should be no bold tag anywhere
+ $this->assertEquals(0, pq('bold', $doc)->length);
+ }
+
+ private function checkField($doc, $name, $check, $required=false) {
+
+ $field = pq('form.bureaucracy__plugin label span:contains(' . $name . ')', $doc);
+ $this->assertEquals(1, $field->length, "find span of $name");
+
+ if($required){
+ $this->assertEquals(1, pq('sup', $field)->length, "is mandatory of $name");
+ }
+
+ $label = $field->parent();
+ $this->assertTrue($label->is('label'), "find label of $name");
+
+ $input = pq($check, $label);
+ $this->assertEquals(1, $input->length, "find check of $name");
+
+ return $input;
+ }
+
+ public function test_parseline() {
+ $match = 'textbox label0 "Test with spaces"
+textbox LabelWithoutSpaces
+textbox Label Without Spaces
+textbox "Label with spaces" "Text with a quote""in text"
+textbox Label2 " "
+textbox Label3 """"
+textbox Label4 " """ " """ " """
+textbox Label5 """ "
+textbox Label6 "" " "
+textbox Label7 " "" "
+textbox Label7 " ""
+ "" ss"
+textbox Label8';
+
+ $expected = array(
+ array('textbox', 'label0', 'Test with spaces'),
+ array('textbox', 'LabelWithoutSpaces'),
+ array('textbox', 'Label', 'Without', 'Spaces'),
+ array('textbox', 'Label with spaces', 'Text with a quote"in text'),
+ array('textbox', 'Label2', ' '),
+ array('textbox', 'Label3', '"'),
+ array('textbox', 'Label4', ' "', ' "', ' "'),
+ array('textbox', 'Label5', '" '),
+ array('textbox', 'Label6', '', ' '),
+ array('textbox', 'Label7', ' " '),
+ array('textbox', 'Label7', ' "
+ " ss'),
+ array('textbox', 'Label8')
+ );
+
+ $lines = explode("\n", $match);
+ $i = 0;
+ while(count($lines) > 0) {
+ $line = trim(array_shift($lines));
+
+ $syntaxcomponent = new syntax_plugin_bureaucracy();
+ $actual = $this->callNonaccessibleMethod($syntaxcomponent, '_parse_line', array($line, &$lines));
+
+ $this->assertEquals($expected[$i], $actual);
+ $i++;
+ }
+
+ }
+
+ /**
+ * Test not accessible methods..
+ *
+ * @param string|object $obj
+ * @param string $name
+ * @param array $args
+ * @return mixed
+ */
+ protected function callNonaccessibleMethod($obj, $name, array $args) {
+ $class = new ReflectionClass($obj);
+ $method = $class->getMethod($name);
+ $method->setAccessible(true);
+ return $method->invokeArgs($obj, $args);
+ }
+
+}
diff --git a/platform/www/lib/plugins/bureaucracy/action.php b/platform/www/lib/plugins/bureaucracy/action.php
new file mode 100644
index 0000000..a4a7a4e
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/action.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Bureaucracy Plugin: Allows flexible creation of forms
+ *
+ * This plugin allows definition of forms in wiki pages. The forms can be
+ * submitted via email or used to create new pages from templates.
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @author Adrian Lang <dokuwiki@cosmocode.de>
+ */
+// must be run within Dokuwiki
+if (!defined('DOKU_INC')) die();
+
+/**
+ * Class action_plugin_bureaucracy
+ */
+class action_plugin_bureaucracy extends DokuWiki_Action_Plugin {
+
+ /**
+ * Registers a callback function for a given event
+ */
+ public function register(Doku_Event_Handler $controller) {
+ $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'ajax');
+ }
+
+ /**
+ * @param Doku_Event$event
+ * @param $param
+ */
+ public function ajax(Doku_Event $event, $param) {
+ if ($event->data !== 'bureaucracy_user_field') {
+ return;
+ }
+ $event->stopPropagation();
+ $event->preventDefault();
+
+ $search = $_REQUEST['search'];
+
+ /** @var DokuWiki_Auth_Plugin $auth */
+ global $auth;
+ $users = array();
+ foreach($auth->retrieveUsers() as $username => $data) {
+ if ($search === '' || // No search
+ stripos($username, $search) === 0 || // Username (prefix)
+ stripos($data['name'], $search) !== false) { // Full name
+ $users[$username] = $data['name'];
+ }
+ if (count($users) === 10) {
+ break;
+ }
+ }
+
+ if (count($users) === 1 && key($users) === $search) {
+ $users = array();
+ }
+
+ echo json_encode($users);
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/conf/default.php b/platform/www/lib/plugins/bureaucracy/conf/default.php
new file mode 100644
index 0000000..ed0463f
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/conf/default.php
@@ -0,0 +1,4 @@
+<?php
+
+$conf['runas'] = '';
+$conf['maxEmailAttachmentSize'] = 3*1024*1024; //3MB \ No newline at end of file
diff --git a/platform/www/lib/plugins/bureaucracy/conf/metadata.php b/platform/www/lib/plugins/bureaucracy/conf/metadata.php
new file mode 100644
index 0000000..7119b98
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/conf/metadata.php
@@ -0,0 +1,5 @@
+<?php
+
+$meta['runas'] = array('string');
+$meta['maxEmailAttachmentSize'] = array('numeric');
+
diff --git a/platform/www/lib/plugins/bureaucracy/helper/action.php b/platform/www/lib/plugins/bureaucracy/helper/action.php
new file mode 100644
index 0000000..5c6dd08
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/action.php
@@ -0,0 +1,136 @@
+<?php
+/**
+ * Base class for bureaucracy actions.
+ *
+ * All bureaucracy actions have to inherit from this class.
+ *
+ * ATM this class is pretty empty but, in the future it could be used to add
+ * helper functions which can be utilized by the different actions.
+ *
+ * @author Michael Klier <chi@chimeric.de>
+ */
+class helper_plugin_bureaucracy_action extends syntax_plugin_bureaucracy {
+
+ /**
+ * Return false to prevent DokuWiki reusing instances of the plugin
+ *
+ * @return bool
+ */
+ public function isSingleton() {
+ return false;
+ }
+
+ /**
+ * Handle the user input [required]
+ *
+ * This function needs to be implemented to accept the user data collected
+ * from the form. Data has to be grabbed from $_POST['bureaucracy'] using
+ * the indicies in the 'idx' members of the $data items.
+ *
+ * @param helper_plugin_bureaucracy_field[] $fields the list of fields in the form
+ * @param string $thanks the thank you message as defined in the form
+ * or default one. Might be modified by the action
+ * before returned
+ * @param array $argv additional arguments passed to the action
+ * @return bool|string false on error, $thanks on success
+ */
+ public function run($fields, $thanks, $argv){
+ msg('ERROR: called action %s did not implement a run() function');
+ return false;
+ }
+
+ /**
+ * Adds some language related replacement patterns
+ */
+ function prepareLanguagePlaceholder() {
+ global $ID;
+ global $conf;
+
+ $this->patterns['__lang__'] = '/@LANG@/';
+ $this->values['__lang__'] = $conf['lang'];
+
+ $this->patterns['__trans__'] = '/@TRANS@/';
+ $this->values['__trans__'] = '';
+
+ /** @var helper_plugin_translation $trans */
+ $trans = plugin_load('helper', 'translation');
+ if (!$trans) return;
+
+ $this->values['__trans__'] = $trans->getLangPart($ID);
+ $this->values['__lang__'] = $trans->realLC('');
+ }
+
+ /**
+ * Adds replacement pattern for fieldlabels (e.g @@Label@@)
+ *
+ * @param helper_plugin_bureaucracy_field $field
+ */
+ function prepareFieldReplacement($field) {
+ $label = $field->getParam('label');
+
+ if(!is_null($label)) {
+ $this->patterns[$label] = $field->getReplacementPattern();
+ $this->values[$label] = $field->getReplacementValue();
+ }
+ }
+
+ /**
+ * Adds <noinclude></noinclude> to replacement patterns
+ */
+ function prepareNoincludeReplacement() {
+ $this->patterns['__noinclude__'] = '/<noinclude>(.*?)<\/noinclude>/is';
+ $this->values['__noinclude__'] = '';
+ }
+
+ /**
+ * Generate field replacements
+ *
+ * @param helper_plugin_bureaucracy_field[] $fields List of field objects
+ * @return array
+ */
+ function prepareFieldReplacements($fields) {
+ foreach ($fields as $field) {
+ //field replacements
+ $this->prepareFieldReplacement($field);
+ }
+ }
+
+ /**
+ * Returns ACL access level of the user or the (virtual) 'runas' user
+ *
+ * @param string $id pageid
+ * @return int
+ */
+ protected function aclcheck($id) {
+ $runas = $this->getConf('runas');
+
+ if($runas) {
+ $auth = auth_aclcheck($id, $runas, array());
+ } else {
+ $auth = auth_quickaclcheck($id);
+ }
+ return $auth;
+
+ }
+
+ /**
+ * Available methods
+ *
+ * @return array
+ */
+ public function getMethods() {
+ $result = array();
+ $result[] = array(
+ 'name' => 'run',
+ 'desc' => 'Handle the user input',
+ 'params' => array(
+ 'fields' => 'helper_plugin_bureaucracy_field[]',
+ 'thanks' => 'string',
+ 'argv' => 'array'
+ ),
+ 'return' => array('false on error, thanks message on success' => 'bool|string')
+ );
+ return $result;
+ }
+
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/actionmail.php b/platform/www/lib/plugins/bureaucracy/helper/actionmail.php
new file mode 100644
index 0000000..698e6c0
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/actionmail.php
@@ -0,0 +1,212 @@
+<?php
+/**
+ * Action sendemail for DokuWiki plugin bureaucracy
+ */
+
+class helper_plugin_bureaucracy_actionmail extends helper_plugin_bureaucracy_action {
+
+ protected $_mail_html = '';
+ protected $_mail_text = '';
+ protected $subject = '';
+ protected $replyto = array();
+ protected $mailtemplate = '';
+
+ /**
+ * Build a nice email from the submitted data and send it
+ *
+ * @param helper_plugin_bureaucracy_field[] $fields
+ * @param string $thanks
+ * @param array $argv
+ * @return string thanks message
+ * @throws Exception mailing failed
+ */
+ public function run($fields, $thanks, $argv) {
+ global $ID;
+ global $conf;
+
+ $mail = new Mailer();
+
+ $this->prepareNamespacetemplateReplacements();
+ $this->prepareDateTimereplacements();
+ $this->prepareLanguagePlaceholder();
+ $this->prepareNoincludeReplacement();
+ $this->prepareFieldReplacements($fields);
+
+ $evdata = [
+ 'fields' => $fields,
+ 'values' => &$this->values
+ ];
+ $event = new Doku_Event('PLUGIN_BUREAUCRACY_EMAIL_SEND', $evdata);
+ if($event->advise_before()) {
+ //set default subject
+ $this->subject = sprintf($this->getLang('mailsubject'), $ID);
+
+ //build html&text table, collect replyto and subject
+ list($table_html, $table_text) = $this->processFieldsBuildTable($fields, $mail);
+
+ //Body
+ if($this->mailtemplate) {
+ //show template
+ $this->patterns['__tablehtml__'] = '/@TABLEHTML@/';
+ $this->patterns['__tabletext__'] = '/@TABLETEXT@/';
+ $this->values['__tablehtml__'] = $table_html;
+ $this->values['__tabletext__'] = $table_text;
+
+ list($this->_mail_html, $this->_mail_text) = $this->getContent();
+
+ } else {
+ //show simpel listing
+ $this->_mail_html .= sprintf($this->getLang('mailintro')."<br><br>", dformat());
+ $this->_mail_html .= $table_html;
+
+ $this->_mail_text .= sprintf($this->getLang('mailintro')."\n\n", dformat());
+ $this->_mail_text .= $table_text;
+ }
+ $mail->setBody($this->_mail_text,null,null,$this->_mail_html);
+
+ // Reply-to
+ if(!empty($this->replyto)) {
+ $replyto = $mail->cleanAddress($this->replyto);
+ $mail->setHeader('Reply-To', $replyto, false);
+ }
+
+ // To
+ $to = $this->replace(implode(',',$argv)); // get recipient address(es)
+ $to = $mail->cleanAddress($to);
+ $mail->to($to);
+
+ // From
+ $mail->from($conf['mailfrom']);
+
+ // Subject
+ $this->subject = $this->replace($this->subject);
+ $mail->subject($this->subject);
+
+ if(!$mail->send()) {
+ throw new Exception($this->getLang('e_mail'));
+ }
+ }
+ $event->advise_after();
+
+ return '<p>' . $thanks . '</p>';
+ }
+
+ /**
+ * Create html and plain table of the field
+ * and collect values for subject and replyto
+ *
+ * @param helper_plugin_bureaucracy_field[] $fields
+ * @param Mailer $mail
+ * @return array of html and text table
+ */
+ protected function processFieldsBuildTable($fields, $mail) {
+ global $ID;
+
+ $table_html = '<table>';
+ $table_text = '';
+
+ foreach($fields as $field) {
+ $html = $text = '';
+ $value = $field->getParam('value');
+ $label = $field->getParam('label');
+
+ switch($field->getFieldType()) {
+ case 'fieldset':
+ if(!empty($field->depends_on)) {
+ //print fieldset only if depend condition is true
+ foreach($fields as $field_tmp) {
+ if($field_tmp->getParam('label') === $field->depends_on[0] && $field_tmp->getParam('value') === $field->depends_on[1] ) {
+ list($html, $text) = $this->mail_buildRow($label);
+ }
+ }
+ } else {
+ list($html, $text) = $this->mail_buildRow($label);
+ }
+ break;
+ case 'file':
+ if($value === null || $label === null) break; //print attachment only if field was visible
+ $file = $field->getParam('file');
+ if(!$file['size']) {
+ $message = $this->getLang('attachmentMailEmpty');
+ } else if($file['size'] > $this->getConf('maxEmailAttachmentSize')) {
+ $message = $file['name'] . ' ' . $this->getLang('attachmentMailToLarge');
+ msg(sprintf($this->getLang('attachmentMailToLarge_userinfo'), hsc($file['name']), filesize_h($this->getConf('maxEmailAttachmentSize'))), 2);
+ } else {
+ $message = $file['name'];
+ $mail->attachFile($file['tmp_name'], $file['type'], $file['name']);
+ }
+ list($html, $text) = $this->mail_buildRow($label, $message);
+ break;
+ case 'subject':
+ $this->subject = $label;
+ break;
+ case 'usemailtemplate':
+ if (!is_null($field->getParam('template')) ) {
+ $this->mailtemplate = $this->replace($field->getParam('template'));
+ resolve_pageid(getNS($ID), $this->mailtemplate, $ignored);
+ }
+ break;
+
+ default:
+ if($value === null || $label === null) break;
+ if(is_array($value)) $value = implode(', ', $value);
+ list($html, $text) = $this->mail_buildRow($label, $value);
+
+ if(!is_null($field->getParam('replyto'))) {
+ $this->replyto[] = $value;
+ }
+ }
+ $table_html .= $html;
+ $table_text .= $text;
+ }
+ $table_html .= '</table>';
+
+ return array($table_html, $table_text);
+ }
+
+ /**
+ * Build a row
+ *
+ * @param $column1
+ * @param null $column2
+ * @return array of html and text row
+ */
+ protected function mail_buildRow($column1,$column2=null) {
+ if($column2 === null) {
+ $html = '<tr><td colspan="2"><u>'.hsc($column1).'<u></td></tr>';
+ $text = "\n=====".$column1.'=====';
+ } else {
+ $html = '<tr><td><b>'.hsc($column1).'<b></td><td>'.hsc($column2).'</td></tr>';
+ $text = "\n $column1 \t\t $column2";
+ }
+ return array($html, $text);
+ }
+
+ /**
+ * Parse mail template in html and text, and perform replacements
+ *
+ * @return array html and text content
+ */
+ protected function getContent() {
+ $content = rawWiki($this->mailtemplate);
+ $html = '';
+ $text = '';
+
+ if(preg_match_all('#<code\b(.*?)>(.*?)</code>#is', $content, $matches)) {
+ foreach($matches[1] as $index => $codeoptions) {
+ list($syntax,) = explode(' ', trim($codeoptions), 2);
+ if($syntax == 'html') {
+ $html = $matches[2][$index];
+ }
+ if($syntax == 'text' || $syntax == '') {
+ $text = $matches[2][$index];
+ }
+ }
+ }
+ return array(
+ $this->replace($html),
+ $this->replace($text)
+ );
+ }
+}
+// vim:ts=4:sw=4:et:enc=utf-8:
diff --git a/platform/www/lib/plugins/bureaucracy/helper/actionscript.php b/platform/www/lib/plugins/bureaucracy/helper/actionscript.php
new file mode 100644
index 0000000..f308721
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/actionscript.php
@@ -0,0 +1,62 @@
+<?php
+
+class helper_plugin_bureaucracy_actionscript extends helper_plugin_bureaucracy_action {
+
+ protected $scriptNamePattern = '/^[_a-zA-Z0-9]+\.php$/';
+
+ /**
+ * @inheritDoc
+ * @throws \InvalidArgumentException
+ */
+ public function run($fields, $thanks, $argv) {
+ if (count($argv) < 1) {
+ throw new InvalidArgumentException('The "script"-action expects exactly 1 argument: the script name.');
+ }
+
+ $scriptName = $argv[0];
+
+ if (!$this->validateScriptName($scriptName)) {
+ $cleanedScriptName = hsc($scriptName);
+ throw new InvalidArgumentException("The supplied scriptname \"<code>$cleanedScriptName</code>\" is invalid! It must conform to <code>{hsc($this->scriptNamePattern)}</code>!");
+ }
+
+ $path = DOKU_CONF . 'plugin/bureaucracy/' . $scriptName;
+
+ if (!file_exists($path)) {
+ $shortPath = 'conf/plugin/bureaucracy/' . $scriptName;
+ throw new InvalidArgumentException("Script <code>$shortPath</code> doesn't exist!");
+ }
+
+ require $path;
+
+ $classFragment = substr($scriptName, 0, strpos($scriptName, '.'));
+ $className = 'helper_plugin_bureaucracy_handler_' . $classFragment;
+
+ $deprecatedClassName = 'bureaucracy_handler_' . $classFragment;
+ if (!class_exists($className) && class_exists($deprecatedClassName)) {
+ msg("Please change this script's class-name to <code>$className</code>.
+Your current scheme <code>$deprecatedClassName</code> is deprecated and will stop working in the future.", 2);
+ $className = $deprecatedClassName;
+ }
+
+ /** @var dokuwiki\plugin\bureaucracy\interfaces\bureaucracy_handler_interface $handler */
+ $handler = new $className;
+
+ if (!is_a($handler, dokuwiki\plugin\bureaucracy\interfaces\bureaucracy_handler_interface::class)) {
+ throw new InvalidArgumentException('The handler must implement the interface <code>dokuwiki\\plugin\\bureaucracy\\interfaces\\bureaucracy_handler_interface</code> !');
+ }
+
+ return $handler->handleData($fields, $thanks);
+ }
+
+ /**
+ * @param $scriptName
+ *
+ * @return bool
+ */
+ protected function validateScriptName($scriptName) {
+ $valid = preg_match($this->scriptNamePattern, $scriptName);
+ return $valid === 1;
+ }
+
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/actiontemplate.php b/platform/www/lib/plugins/bureaucracy/helper/actiontemplate.php
new file mode 100644
index 0000000..04714d8
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/actiontemplate.php
@@ -0,0 +1,459 @@
+<?php
+/**
+ * Simple template replacement action for the bureaucracy plugin
+ *
+ * @author Michael Klier <chi@chimeric.de>
+ */
+
+class helper_plugin_bureaucracy_actiontemplate extends helper_plugin_bureaucracy_action {
+
+ var $targetpages;
+ var $pagename;
+
+ /**
+ * Performs template action
+ *
+ * @param helper_plugin_bureaucracy_field[] $fields array with form fields
+ * @param string $thanks thanks message
+ * @param array $argv array with entries: template, pagename, separator
+ * @return array|mixed
+ *
+ * @throws Exception
+ */
+ public function run($fields, $thanks, $argv) {
+ global $conf;
+
+ [$tpl, $this->pagename] = $argv;
+ $sep = $argv[2] ?? $conf['sepchar'];
+
+ $this->patterns = array();
+ $this->values = array();
+ $this->targetpages = array();
+
+ $this->prepareNamespacetemplateReplacements();
+ $this->prepareDateTimereplacements();
+ $this->prepareLanguagePlaceholder();
+ $this->prepareNoincludeReplacement();
+ $this->prepareFieldReplacements($fields);
+
+ $evdata = array(
+ 'patterns' => &$this->patterns,
+ 'values' => &$this->values,
+ 'fields' => $fields,
+ 'action' => $this
+ );
+
+ $event = new Doku_Event('PLUGIN_BUREAUCRACY_PAGENAME', $evdata);
+ if ($event->advise_before()) {
+ $this->buildTargetPagename($fields, $sep);
+ }
+ $event->advise_after();
+
+ //target&template(s) from addpage fields
+ $this->getAdditionalTargetpages($fields);
+ //target&template(s) from action field
+ $tpl = $this->getActionTargetpages($tpl);
+
+ if(empty($this->targetpages)) {
+ throw new Exception(sprintf($this->getLang('e_template'), $tpl));
+ }
+
+ $this->checkTargetPageNames();
+
+ $this->processUploads($fields);
+ $this->replaceAndSavePages($fields);
+
+ $ret = $this->buildThankYouPage($thanks);
+
+ return $ret;
+ }
+
+ /**
+ * Prepare and resolve target page
+ *
+ * @param helper_plugin_bureaucracy_field[] $fields List of field objects
+ * @param string $sep Separator between fields for page id
+ * @throws Exception missing pagename
+ */
+ protected function buildTargetPagename($fields, $sep) {
+ global $ID;
+
+ foreach ($fields as $field) {
+ $pname = $field->getParam('pagename');
+ if (!is_null($pname)) {
+ if (is_array($pname)) $pname = implode($sep, $pname);
+ $this->pagename .= $sep . $pname;
+ }
+ }
+
+ $this->pagename = $this->replace($this->pagename);
+
+ $myns = getNS($ID);
+ resolve_pageid($myns, $this->pagename, $ignored); // resolve relatives
+
+ if ($this->pagename === '') {
+ throw new Exception($this->getLang('e_pagename'));
+ }
+ }
+
+ /**
+ * Handle templates from addpage field
+ *
+ * @param helper_plugin_bureaucracy_field[] $fields List of field objects
+ * @return array
+ */
+ function getAdditionalTargetpages($fields) {
+ global $ID;
+ $ns = getNS($ID);
+
+ foreach ($fields as $field) {
+ if (!is_null($field->getParam('page_tpl')) && !is_null($field->getParam('page_tgt')) ) {
+ //template
+ $templatepage = $this->replace($field->getParam('page_tpl'));
+ resolve_pageid(getNS($ID), $templatepage, $ignored);
+
+ //target
+ $relativetargetpage = $field->getParam('page_tgt');
+ resolve_pageid($ns, $relativeTargetPageid, $ignored);
+ $targetpage = "$this->pagename:$relativetargetpage";
+
+ $auth = $this->aclcheck($templatepage); // runas
+ if ($auth >= AUTH_READ ) {
+ $this->addParsedTargetpage($targetpage, $templatepage);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns raw pagetemplate contents for the ID's namespace
+ *
+ * @param string $id the id of the page to be created
+ * @return string raw pagetemplate content
+ */
+ protected function rawPageTemplate($id) {
+ global $conf;
+
+ $path = dirname(wikiFN($id));
+ if(file_exists($path.'/_template.txt')) {
+ $tplfile = $path.'/_template.txt';
+ } else {
+ // search upper namespaces for templates
+ $len = strlen(rtrim($conf['datadir'], '/'));
+ while(strlen($path) >= $len) {
+ if(file_exists($path.'/__template.txt')) {
+ $tplfile = $path.'/__template.txt';
+ break;
+ }
+ $path = substr($path, 0, strrpos($path, '/'));
+ }
+ }
+
+ $tpl = io_readFile($tplfile);
+ return $tpl;
+ }
+
+ /**
+ * Load template(s) for targetpage as given via action field
+ *
+ * @param string $tpl template name as given in form
+ * @return string parsed templatename
+ */
+ protected function getActionTargetpages($tpl) {
+ global $USERINFO;
+ global $conf;
+ global $ID;
+ $runas = $this->getConf('runas');
+
+ if ($tpl == '_') {
+ // use namespace template
+ if (!isset($this->targetpages[$this->pagename])) {
+ $raw = $this->rawPageTemplate($this->pagename);
+ $this->noreplace_save($raw);
+ $this->targetpages[$this->pagename] = pageTemplate(array($this->pagename));
+ }
+ } elseif ($tpl !== '!') {
+ $tpl = $this->replace($tpl);
+
+ // resolve templates, but keep references to whole namespaces intact (ending in a colon)
+ if(substr($tpl, -1) == ':') {
+ $tpl = $tpl.'xxx'; // append a fake page name
+ resolve_pageid(getNS($ID), $tpl, $ignored);
+ $tpl = substr($tpl, 0, -3); // cut off fake page name again
+ } else {
+ resolve_pageid(getNS($ID), $tpl, $ignored);
+ }
+
+ $backup = array();
+ if ($runas) {
+ // Hack user credentials.
+ $backup = array($_SERVER['REMOTE_USER'], $USERINFO['grps']);
+ $_SERVER['REMOTE_USER'] = $runas;
+ $USERINFO['grps'] = array();
+ }
+
+ $template_pages = array();
+ //search checks acl (as runas)
+ $opts = array(
+ 'depth' => 0,
+ 'listfiles' => true,
+ 'showhidden' => true
+ );
+ search($template_pages, $conf['datadir'], 'search_universal', $opts, str_replace(':', '/', getNS($tpl)));
+
+ foreach ($template_pages as $template_page) {
+ $templatepageid = cleanID($template_page['id']);
+ // try to replace $tpl path with $this->pagename path in the founded $templatepageid
+ // - a single-page template will only match on itself and will be replaced,
+ // other newtargets are pages in same namespace, so aren't changed
+ // - a namespace as template will match at the namespaces-part of the path of pages in this namespace
+ // so these newtargets are changed
+ // if there exist a single-page and a namespace with name $tpl, both are selected
+ $newTargetpageid = preg_replace('/^' . preg_quote_cb(cleanID($tpl)) . '($|:)/', $this->pagename . '$1', $templatepageid);
+
+ if ($newTargetpageid === $templatepageid) {
+ // only a single-page template or page in the namespace template
+ // which matches the $tpl path are changed
+ continue;
+ }
+
+ if (!isset($this->targetpages[$newTargetpageid])) {
+ $this->addParsedTargetpage($newTargetpageid, $templatepageid);
+ }
+ }
+
+ if ($runas) {
+ /* Restore user credentials. */
+ list($_SERVER['REMOTE_USER'], $USERINFO['grps']) = $backup;
+ }
+ }
+ return $tpl;
+ }
+
+ /**
+ * Checks for existance and access of target pages
+ *
+ * @return mixed
+ * @throws Exception
+ */
+ protected function checkTargetPageNames() {
+ foreach (array_keys($this->targetpages) as $pname) {
+ // prevent overriding already existing pages
+ if (page_exists($pname)) {
+ throw new Exception(sprintf($this->getLang('e_pageexists'), html_wikilink($pname)));
+ }
+
+ $auth = $this->aclcheck($pname);
+ if ($auth < AUTH_CREATE) {
+ throw new Exception($this->getLang('e_denied'));
+ }
+ }
+ }
+
+ /**
+ * Perform replacements on the collected templates, and save the pages.
+ *
+ * Note: wrt runas, for changelog are used:
+ * - $INFO['userinfo']['name']
+ * - $INPUT->server->str('REMOTE_USER')
+ */
+ protected function replaceAndSavePages($fields) {
+ global $ID;
+ foreach ($this->targetpages as $pageName => $template) {
+ // set NSBASE var to make certain dataplugin constructs easier
+ $this->patterns['__nsbase__'] = '/@NSBASE@/';
+ $this->values['__nsbase__'] = noNS(getNS($pageName));
+
+ $evdata = array(
+ 'patterns' => &$this->patterns,
+ 'values' => &$this->values,
+ 'id' => $pageName,
+ 'template' => $template,
+ 'form' => $ID,
+ 'fields' => $fields
+ );
+
+ $event = new Doku_Event('PLUGIN_BUREAUCRACY_TEMPLATE_SAVE', $evdata);
+ if($event->advise_before()) {
+ // save page
+ saveWikiText(
+ $evdata['id'],
+ cleanText($this->replace($evdata['template'], false)),
+ sprintf($this->getLang('summary'), $ID)
+ );
+ }
+ $event->advise_after();
+ }
+ }
+
+ /**
+ * (Callback) Sorts first by namespace depth, next by page ids
+ *
+ * @param string $a
+ * @param string $b
+ * @return int positive if $b is in deeper namespace than $a, negative higher.
+ * further sorted by pageids
+ *
+ * return an integer less than, equal to, or
+ * greater than zero if the first argument is considered to be
+ * respectively less than, equal to, or greater than the second.
+ */
+ public function _sorttargetpages($a, $b) {
+ $ns_diff = substr_count($a, ':') - substr_count($b, ':');
+ return ($ns_diff === 0) ? strcmp($a, $b) : ($ns_diff > 0 ? -1 : 1);
+ }
+
+ /**
+ * (Callback) Build content of item
+ *
+ * @param array $item
+ * @return string
+ */
+ public function html_list_index($item){
+ $ret = '';
+ if($item['type']=='f'){
+ $ret .= html_wikilink(':'.$item['id']);
+ } else {
+ $ret .= '<strong>' . trim(substr($item['id'], strrpos($item['id'], ':', -2)), ':') . '</strong>';
+ }
+ return $ret;
+ }
+
+ /**
+ * Build thanks message, trigger indexing and rendering of new pages.
+ *
+ * @param string $thanks
+ * @return string html of thanks message or when redirect the first page id of created pages
+ */
+ protected function buildThankYouPage($thanks) {
+ global $ID;
+ $backupID = $ID;
+
+ $html = "<p>$thanks</p>";
+
+ // Build result tree
+ $pages = array_keys($this->targetpages);
+ usort($pages, array($this, '_sorttargetpages'));
+
+ $data = array();
+ $last_folder = array();
+ foreach ($pages as $ID) {
+ $lvl = substr_count($ID, ':');
+ for ($n = 0; $n < $lvl; ++$n) {
+ if (!isset($last_folder[$n]) || strpos($ID, $last_folder[$n]['id']) !== 0) {
+ $last_folder[$n] = array(
+ 'id' => substr($ID, 0, strpos($ID, ':', ($n > 0 ? strlen($last_folder[$n - 1]['id']) : 0) + 1) + 1),
+ 'level' => $n + 1,
+ 'open' => 1
+ );
+ $data[] = $last_folder[$n];
+ }
+ }
+ $data[] = array('id' => $ID, 'level' => 1 + substr_count($ID, ':'), 'type' => 'f');
+ }
+ $html .= html_buildlist($data, 'idx', array($this, 'html_list_index'), 'html_li_index');
+
+ // Add indexer bugs for every just-created page
+ $html .= '<div class="no">';
+ ob_start();
+ foreach ($pages as $ID) {
+ // indexerWebBug uses ID and INFO[exists], but the bureaucracy form
+ // page always exists, as does the just-saved page, so INFO[exists]
+ // is correct in any case
+ tpl_indexerWebBug();
+
+ // the iframe will trigger real rendering of the pages to make sure
+ // any used plugins are initialized (eg. the do plugin)
+ echo '<iframe src="' . wl($ID, array('do' => 'export_html')) . '" width="1" height="1" style="visibility:hidden"></iframe>';
+ }
+ $html .= ob_get_contents();
+ ob_end_clean();
+ $html .= '</div>';
+
+ $ID = $backupID;
+ return $html;
+ }
+
+ /**
+ * move the uploaded files to <pagename>:FILENAME
+ *
+ *
+ * @param helper_plugin_bureaucracy_field[] $fields
+ * @throws Exception
+ */
+ protected function processUploads($fields) {
+ foreach($fields as $field) {
+
+ if($field->getFieldType() !== 'file') continue;
+
+ $label = $field->getParam('label');
+ $file = $field->getParam('file');
+ $ns = $field->getParam('namespace');
+
+ //skip empty files
+ if(!$file['size']) {
+ $this->values[$label] = '';
+ continue;
+ }
+
+ $id = $ns.':'.$file['name'];
+ resolve_mediaid($this->pagename, $id, $ignored); // resolve relatives
+
+ $auth = $this->aclcheck($id); // runas
+ $move = 'copy_uploaded_file';
+ //prevent from is_uploaded_file() check
+ if(defined('DOKU_UNITTEST')) {
+ $move = 'copy';
+ }
+ $res = media_save(
+ array('name' => $file['tmp_name']),
+ $id,
+ false,
+ $auth,
+ $move);
+
+ if(is_array($res)) throw new Exception($res[0]);
+
+ $this->values[$label] = $res;
+
+ }
+ }
+
+ /**
+ * Load page data and do default pattern replacements like namespace templates do
+ * and add it to list of targetpages
+ *
+ * Note: for runas the values of the real user are used for the placeholders
+ * @NAME@ => $USERINFO['name']
+ * @MAIL@ => $USERINFO['mail']
+ * and the replaced value:
+ * @USER@ => $INPUT->server->str('REMOTE_USER')
+ *
+ * @param string $targetpageid pageid of destination
+ * @param string $templatepageid pageid of template for this targetpage
+ */
+ protected function addParsedTargetpage($targetpageid, $templatepageid) {
+ $tpl = rawWiki($templatepageid);
+ $this->noreplace_save($tpl);
+
+ $data = array(
+ 'id' => $targetpageid,
+ 'tpl' => $tpl,
+ 'doreplace' => true,
+ );
+ parsePageTemplate($data);
+
+ //collect and apply some other replacements
+ $patterns = array();
+ $values = array();
+ $keys = array('__lang__', '__trans__', '__year__', '__month__', '__day__', '__time__');
+ foreach($keys as $key) {
+ $patterns[$key] = $this->patterns[$key];
+ $values[$key] = $this->values[$key];
+ }
+
+ $this->targetpages[$targetpageid] = preg_replace($patterns, $values, $data['tpl']);
+ }
+
+}
+// vim:ts=4:sw=4:et:enc=utf-8:
diff --git a/platform/www/lib/plugins/bureaucracy/helper/field.php b/platform/www/lib/plugins/bureaucracy/helper/field.php
new file mode 100644
index 0000000..070e331
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/field.php
@@ -0,0 +1,508 @@
+<?php
+
+/**
+ * Base class for form fields
+ *
+ * This class provides basic functionality for many form fields. It supports
+ * labels, basic validation and template-based XHTML output.
+ *
+ * @author Adrian Lang <lang@cosmocode.de>
+ **/
+
+/**
+ * Class helper_plugin_bureaucracy_field
+ *
+ * base class for all the form fields
+ */
+class helper_plugin_bureaucracy_field extends syntax_plugin_bureaucracy {
+
+ protected $mandatory_args = 2;
+ public $opt = array();
+ /** @var string|array */
+ protected $tpl;
+ protected $checks = array();
+ public $hidden = false;
+ protected $error = false;
+ protected $checktypes = array(
+ '/' => 'match',
+ '<' => 'max',
+ '>' => 'min'
+ );
+
+ /**
+ * Construct a helper_plugin_bureaucracy_field object
+ *
+ * This constructor initializes a helper_plugin_bureaucracy_field object
+ * based on a given definition.
+ *
+ * The first two items represent:
+ * * the type of the field
+ * * and the label the field has been given.
+ * Additional arguments are type-specific mandatory extra arguments and optional arguments.
+ *
+ * The optional arguments may add constraints to the field value, provide a
+ * default value, mark the field as optional or define that the field is
+ * part of a pagename (when using the template action).
+ *
+ * Since the field objects are cached, this constructor may not reference
+ * request data.
+ *
+ * @param array $args The tokenized definition, only split at spaces
+ */
+ public function initialize($args) {
+ $this->init($args);
+ $this->standardArgs($args);
+ }
+
+ /**
+ * Return false to prevent DokuWiki reusing instances of the plugin
+ *
+ * @return bool
+ */
+ public function isSingleton() {
+ return false;
+ }
+
+ /**
+ * Checks number of arguments and store 'cmd', 'label' and 'display' values
+ *
+ * @param array $args array with the definition
+ */
+ protected function init(&$args) {
+ if(count($args) < $this->mandatory_args){
+ msg(sprintf($this->getLang('e_missingargs'), hsc($args[0]),
+ hsc($args[1])), -1);
+ return;
+ }
+
+ // get standard arguments
+ $this->opt = array();
+ foreach (array('cmd', 'label') as $key) {
+ if (count($args) === 0) break;
+ $this->opt[$key] = array_shift($args);
+ }
+ $this->opt['display'] = $this->opt['label']; // allow to modify display value independently
+ }
+
+ /**
+ * Check for additional arguments and store their values
+ *
+ * @param array $args array with remaining definition arguments
+ */
+ protected function standardArgs($args) {
+ // parse additional arguments
+ foreach($args as $arg){
+ if ($arg[0] == '=') {
+ $this->setVal(substr($arg,1));
+ } elseif ($arg == '!') {
+ $this->opt['optional'] = true;
+ } elseif ($arg == '^') {
+ //only one field has focus
+ if (helper_plugin_bureaucracy_field::hasFocus()) {
+ $this->opt['id'] = 'focus__this';
+ }
+ } elseif($arg == '@') {
+ $this->opt['pagename'] = true;
+ } elseif($arg == '@@') {
+ $this->opt['replyto'] = true;
+ } elseif(preg_match('/x\d/', $arg)) {
+ $this->opt['rows'] = substr($arg,1);
+ } elseif($arg[0] == '.') {
+ $this->opt['class'] = substr($arg, 1);
+ } elseif(preg_match('/^0{2,}$/', $arg)) {
+ $this->opt['leadingzeros'] = strlen($arg);
+ } elseif($arg[0].$arg[1] == '**') {
+ $this->opt['matchexplanation'] = substr($arg,2);
+ } else {
+ $t = $arg[0];
+ $d = substr($arg,1);
+ if (in_array($t, array('>', '<')) && !is_numeric($d)) {
+ break;
+ }
+ if ($t == '/') {
+ if (substr($d, -1) !== '/') {
+ break;
+ }
+ $d = substr($d, 0, -1);
+ }
+ if (!isset($this->checktypes[$t]) || !method_exists($this, 'validate_' . $this->checktypes[$t])) {
+ msg(sprintf($this->getLang('e_unknownconstraint'), hsc($t).' ('.hsc($arg).')'), -1);
+ return;
+ }
+ $this->checks[] = array('t' => $t, 'd' => $d);
+ }
+ }
+ }
+
+ /**
+ * Add parsed element to Form which generates XHTML
+ *
+ * Outputs the represented field using the passed Doku_Form object.
+ * Additional parameters (CSS class & HTML name) are passed in $params.
+ * HTML output is created by passing the template $this->tpl to the simple
+ * template engine _parse_tpl.
+ *
+ * @param array $params Additional HTML specific parameters
+ * @param Doku_Form $form The target Doku_Form object
+ * @param int $formid unique identifier of the form which contains this field
+ */
+ public function renderfield($params, Doku_Form $form, $formid) {
+ $this->_handlePreload();
+ if(!$form->_infieldset){
+ $form->startFieldset('');
+ }
+ if ($this->error) {
+ $params['class'] = 'bureaucracy_error';
+ }
+
+ $params = array_merge($this->opt, $params);
+ $form->addElement($this->_parse_tpl($this->tpl, $params));
+ }
+
+ /**
+ * Only the first use get the focus, next calls not
+ *
+ * @return bool
+ */
+ protected static function hasFocus(){
+ static $focus = true;
+ if($focus) {
+ $focus = false;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+
+ /**
+ * Check for preload value in the request url
+ */
+ protected function _handlePreload() {
+ $preload_name = '@' . strtr($this->getParam('label'),' .','__') . '@';
+ if (isset($_GET[$preload_name])) {
+ $this->setVal($_GET[$preload_name]);
+ }
+ }
+
+ /**
+ * Handle a post to the field
+ *
+ * Accepts and validates a posted value.
+ *
+ * (Overridden by fieldset, which has as argument an array with the form array by reference)
+ *
+ * @param string $value The passed value or array or null if none given
+ * @param helper_plugin_bureaucracy_field[] $fields (reference) form fields (POST handled upto $this field)
+ * @param int $index index number of field in form
+ * @param int $formid unique identifier of the form which contains this field
+ * @return bool Whether the passed value is valid
+ */
+ public function handle_post($value, &$fields, $index, $formid) {
+ return $this->hidden || $this->setVal($value);
+ }
+
+ /**
+ * Get the field type
+ *
+ * @return string
+ **/
+ public function getFieldType() {
+ return $this->opt['cmd'];
+ }
+
+ /**
+ * Get the replacement pattern used by action
+ *
+ * @return string
+ */
+ public function getReplacementPattern() {
+ $label = $this->getParam('label');
+ $value = $this->getParam('value');
+
+ if (is_array($value)) {
+ return '/(@@|##)' . preg_quote($label, '/') .
+ '(?:\((?P<delimiter>.*?)\))?' .//delimiter
+ '(?:\|(?P<default>.*?))' . (count($value) == 0 ? '' : '?') .
+ '\1/si';
+ }
+
+ return '/(@@|##)' . preg_quote($label, '/') .
+ '(?:\|(.*?))' . (is_null($value) ? '' : '?') .
+ '\1/si';
+ }
+
+ /**
+ * Used as an callback for preg_replace_callback
+ *
+ * @param $matches
+ * @return string
+ */
+ public function replacementMultiValueCallback($matches) {
+ $value = $this->opt['value'];
+
+ //default value
+ if (is_null($value) || $value === false) {
+ if (isset($matches['default']) && $matches['default'] != '') {
+ return $matches['default'];
+ }
+ return $matches[0];
+ }
+
+ //check if matched string containts a pair of brackets
+ $delimiter = preg_match('/\(.*\)/s', $matches[0]) ? $matches['delimiter'] : ', ';
+
+ return implode($delimiter, $value);
+ }
+
+ /**
+ * Get the value used by action
+ * If value is a callback preg_replace_callback is called instead preg_replace
+ *
+ * @return mixed|string
+ */
+ public function getReplacementValue() {
+ $value = $this->getParam('value');
+
+ if (is_array($value)) {
+ return array($this, 'replacementMultiValueCallback');
+ }
+
+ return is_null($value) || $value === false ? '$2' : $value;
+ }
+
+ /**
+ * Validate value and stores it
+ *
+ * @param mixed $value value entered into field
+ * @return bool whether the passed value is valid
+ */
+ protected function setVal($value) {
+ if ($value === '') {
+ $value = null;
+ }
+ $this->opt['value'] = $value;
+ try {
+ $this->_validate();
+ $this->error = false;
+ } catch (Exception $e) {
+ msg($e->getMessage(), -1);
+ $this->error = true;
+ }
+ return !$this->error;
+ }
+
+ /**
+ * Whether the field is true (used for depending fieldsets)
+ *
+ * @return bool whether field is set
+ */
+ public function isSet_() {
+ return !is_null($this->getParam('value'));
+ }
+
+ /**
+ * Validate value of field and throws exceptions for bad values.
+ *
+ * @throws Exception when field didn't validate.
+ */
+ protected function _validate() {
+ $value = $this->getParam('value');
+ if (is_null($value)) {
+ if(!isset($this->opt['optional'])) {
+ throw new Exception(sprintf($this->getLang('e_required'),hsc($this->opt['label'])));
+ }
+ return;
+ }
+
+ foreach ($this->checks as $check) {
+ $checktype = $this->checktypes[$check['t']];
+ if (!call_user_func(array($this, 'validate_' . $checktype), $check['d'], $value)) {
+ //replacement is custom explanation or just the regexp or the requested value
+ if(isset($this->opt['matchexplanation'])) {
+ $replacement = hsc($this->opt['matchexplanation']);
+ } elseif($checktype == 'match') {
+ $replacement = sprintf($this->getLang('checkagainst'), hsc($check['d']));
+ } else {
+ $replacement = hsc($check['d']);
+ }
+
+ throw new Exception(sprintf($this->getLang('e_' . $checktype), hsc($this->opt['label']), $replacement));
+ }
+ }
+ }
+
+ /**
+ * Get an arbitrary parameter
+ *
+ * @param string $name
+ * @return mixed|null
+ */
+ public function getParam($name) {
+ if (!isset($this->opt[$name]) || $name === 'value' && $this->hidden) {
+ return null;
+ }
+ if ($name === 'pagename') {
+ // If $this->opt['pagename'] is set, return the escaped value of the field.
+ $value = $this->getParam('value');
+ if (is_null($value)) {
+ return null;
+ }
+ global $conf;
+ if($conf['useslash']) $value = str_replace('/',' ',$value);
+ return str_replace(':',' ',$value);
+ }
+ return $this->opt[$name];
+ }
+
+ /**
+ * Parse a template with given parameters
+ *
+ * Replaces variables specified like @@VARNAME|default@@ using the passed
+ * value map.
+ *
+ * @param string|array $tpl The template as string or array
+ * @param array $params A hash mapping parameters to values
+ *
+ * @return string|array The parsed template
+ */
+ protected function _parse_tpl($tpl, $params) {
+ // addElement supports a special array format as well. In this case
+ // not all elements should be escaped.
+ $is_simple = !is_array($tpl);
+ if ($is_simple) $tpl = array($tpl);
+
+ foreach ($tpl as &$val) {
+ // Select box passes options as an array. We do not escape those.
+ if (is_array($val)) continue;
+
+ // find all variables and their defaults or param values
+ preg_match_all('/@@([A-Z]+)(?:\|((?:[^@]|@$|@[^@])*))?@@/', $val, $pregs);
+ for ($i = 0 ; $i < count($pregs[2]) ; ++$i) {
+ if (isset($params[strtolower($pregs[1][$i])])) {
+ $pregs[2][$i] = $params[strtolower($pregs[1][$i])];
+ }
+ }
+ // we now have placeholders in $pregs[0] and their values in $pregs[2]
+ $replacements = array(); // check if empty to prevent php 5.3 warning
+ if (!empty($pregs[0])) {
+ $replacements = array_combine($pregs[0], $pregs[2]);
+ }
+
+ if($is_simple){
+ // for simple string templates, we escape all replacements
+ $replacements = array_map('hsc', $replacements);
+ }else{
+ // for the array ones, we escape the label and display only
+ if(isset($replacements['@@LABEL@@'])) $replacements['@@LABEL@@'] = hsc($replacements['@@LABEL@@']);
+ if(isset($replacements['@@DISPLAY@@'])) $replacements['@@DISPLAY@@'] = hsc($replacements['@@DISPLAY@@']);
+ }
+
+ // we attach a mandatory marker to the display
+ if(isset($replacements['@@DISPLAY@@']) && !isset($params['optional'])){
+ $replacements['@@DISPLAY@@'] .= ' <sup>*</sup>';
+ }
+ $val = str_replace(array_keys($replacements), array_values($replacements), $val);
+ }
+ return $is_simple ? $tpl[0] : $tpl;
+ }
+
+ /**
+ * Executed after performing the action hooks
+ */
+ public function after_action() {
+ }
+
+ /**
+ * Constraint function: value of field should match this regexp
+ *
+ * @param string $d regexp
+ * @param mixed $value
+ * @return int|bool
+ */
+ protected function validate_match($d, $value) {
+ return @preg_match('/' . $d . '/i', $value);
+ }
+
+ /**
+ * Constraint function: value of field should be bigger
+ *
+ * @param int|number $d lower bound
+ * @param mixed $value of field
+ * @return bool
+ */
+ protected function validate_min($d, $value) {
+ return $value > $d;
+ }
+
+ /**
+ * Constraint function: value of field should be smaller
+ *
+ * @param int|number $d upper bound
+ * @param mixed $value of field
+ * @return bool
+ */
+ protected function validate_max($d, $value) {
+ return $value < $d;
+ }
+
+ /**
+ * Available methods
+ *
+ * @return array
+ */
+ public function getMethods() {
+ $result = array();
+ $result[] = array(
+ 'name' => 'initialize',
+ 'desc' => 'Initiate object, first parameters are at least cmd and label',
+ 'params' => array(
+ 'params' => 'array'
+ )
+ );
+ $result[] = array(
+ 'name' => 'renderfield',
+ 'desc' => 'Add parsed element to Form which generates XHTML',
+ 'params' => array(
+ 'params' => 'array',
+ 'form' => 'Doku_Form',
+ 'formid' => 'integer'
+ )
+ );
+ $result[] = array(
+ 'name' => 'handle_post',
+ 'desc' => 'Handle a post to the field',
+ 'params' => array(
+ 'value' => 'array',
+ 'fields' => 'helper_plugin_bureaucracy_field[]',
+ 'index' => 'Doku_Form',
+ 'formid' => 'integer'
+ ),
+ 'return' => array('isvalid' => 'bool')
+ );
+ $result[] = array(
+ 'name' => 'getFieldType',
+ 'desc' => 'Get the field type',
+ 'return' => array('fieldtype' => 'string')
+ );
+ $result[] = array(
+ 'name' => 'isSet_',
+ 'desc' => 'Whether the field is true (used for depending fieldsets) ',
+ 'return' => array('isset' => 'bool')
+ );
+ $result[] = array(
+ 'name' => 'getParam',
+ 'desc' => 'Get an arbitrary parameter',
+ 'params' => array(
+ 'name' => 'string'
+ ),
+ 'return' => array('Parameter value' => 'mixed|null')
+ );
+ $result[] = array(
+ 'name' => 'after_action',
+ 'desc' => 'Executed after performing the action hooks'
+ );
+ return $result;
+ }
+
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fieldaddpage.php b/platform/www/lib/plugins/bureaucracy/helper/fieldaddpage.php
new file mode 100644
index 0000000..0c024fd
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fieldaddpage.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * Class helper_plugin_bureaucracy_fieldaddpage
+ *
+ * Adds another page page_tgt based on a template page page_tpl only for use with the template action
+ */
+class helper_plugin_bureaucracy_fieldaddpage extends helper_plugin_bureaucracy_field {
+
+ /**
+ * Arguments:
+ * - cmd
+ * - page_tpl
+ * - page_tgt
+ *
+ * @param array $args The tokenized definition, only split at spaces
+ */
+ function initialize($args) {
+ if(count($args) < 3){
+ msg(sprintf($this->getLang('e_missingargs'), hsc($args[0]),
+ hsc($args[1])), -1);
+ return;
+ }
+
+ // get standard arguments
+ $this->opt = array_combine(array('cmd', 'page_tpl', 'page_tgt'), $args);
+ }
+
+ /**
+ * Nothing displayed
+ *
+ * @params array $params Additional HTML specific parameters
+ * @params Doku_Form $form The target Doku_Form object
+ * @params int $formid unique identifier of the form which contains this field
+ */
+ function renderfield($params, Doku_Form $form, $formid) {
+ }
+
+ /**
+ * Handle a post to the field
+ *
+ * @param string $value null
+ * @param helper_plugin_bureaucracy_field[] $fields (reference) form fields (POST handled upto $this field)
+ * @param int $index index number of field in form
+ * @param int $formid unique identifier of the form which contains this field
+ * @return bool Whether the passed value is valid
+ */
+ function handle_post($value, &$fields, $index, $formid) {
+ return true;
+ }
+
+ /**
+ * Get an arbitrary parameter
+ *
+ * @param string $name
+ * @return mixed|null
+ */
+ function getParam($name) {
+ return ($name === 'value' ||
+ (in_array($name, array('page_tpl', 'page_tgt')) && $this->hidden)) ?
+ null :
+ parent::getParam($name);
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fielddate.php b/platform/www/lib/plugins/bureaucracy/helper/fielddate.php
new file mode 100644
index 0000000..6feae1c
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fielddate.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * Class helper_plugin_bureaucracy_fielddate
+ *
+ * A date in the format YYYY-MM-DD, provides a date picker
+ */
+class helper_plugin_bureaucracy_fielddate extends helper_plugin_bureaucracy_fieldtextbox {
+ /**
+ * Arguments:
+ * - cmd
+ * - label
+ * - ^ (optional)
+ *
+ * @param array $args The tokenized definition, only split at spaces
+ */
+ public function initialize($args) {
+ parent::initialize($args);
+ $attr = array(
+ 'class' => 'datepicker edit',
+ 'maxlength'=>'10'
+ );
+ if(!isset($this->opt['optional'])) {
+ $attr['required'] = 'required';
+ $attr['class'] .= ' required';
+ }
+ $this->tpl = form_makeTextField('@@NAME@@', '@@VALUE@@', '@@DISPLAY@@', '@@ID@@', '@@CLASS@@', $attr);
+ }
+
+ /**
+ * Validate field input
+ *
+ * @throws Exception when empty or wrong date format
+ */
+ protected function _validate() {
+ parent::_validate();
+
+ $value = $this->getParam('value');
+ if (!is_null($value) && !preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) {
+ throw new Exception(sprintf($this->getLang('e_date'),hsc($this->getParam('display'))));
+ }
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fieldemail.php b/platform/www/lib/plugins/bureaucracy/helper/fieldemail.php
new file mode 100644
index 0000000..7857bd7
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fieldemail.php
@@ -0,0 +1,30 @@
+<?php
+/**
+ * Class helper_plugin_bureaucracy_fieldemail
+ *
+ * Creates a single line input field where the input is validated to be a valid email address
+ */
+class helper_plugin_bureaucracy_fieldemail extends helper_plugin_bureaucracy_fieldtextbox {
+
+ /**
+ * Arguments:
+ * - cmd
+ * - label
+ * - @@ (optional)
+ * - ^ (optional)
+ */
+
+ /**
+ * Validate field value
+ *
+ * @throws Exception when empty or not valid email address
+ */
+ function _validate() {
+ parent::_validate();
+
+ $value = $this->getParam('value');
+ if(!is_null($value) && $value !== '@MAIL@' && !mail_isvalid($value)){
+ throw new Exception(sprintf($this->getLang('e_email'),hsc($this->getParam('display'))));
+ }
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fieldfieldset.php b/platform/www/lib/plugins/bureaucracy/helper/fieldfieldset.php
new file mode 100644
index 0000000..ddce2b6
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fieldfieldset.php
@@ -0,0 +1,114 @@
+<?php
+/**
+ * Class helper_plugin_bureaucracy_fieldfieldset
+ *
+ * Creates a new set of fields, which optional can be shown/hidden depending on the value of another field above it.
+ */
+class helper_plugin_bureaucracy_fieldfieldset extends helper_plugin_bureaucracy_field {
+ protected $mandatory_args = 1;
+ /** @var array with zero, one entry (fieldname) or two entries (fieldname and match value) */
+ public $depends_on = array();
+
+ /**
+ * Arguments:
+ * - cmd
+ * - label (optional)
+ * - field name where switching depends on (optional)
+ * - match value (optional)
+ *
+ * @param array $args The tokenized definition, only split at spaces
+ */
+ public function initialize($args) {
+ // get standard arguments
+ $this->opt = array('cmd' => array_shift($args));
+
+ if (count($args) > 0) {
+ $this->opt['label'] = array_shift($args);
+ $this->opt['display'] = $this->opt['label'];
+
+ $this->depends_on = $args;
+ }
+ }
+
+ /**
+ * Render the top of the fieldset as XHTML
+ *
+ * @param array $params Additional HTML specific parameters
+ * @param Doku_Form $form The target Doku_Form object
+ * @param int $formid unique identifier of the form which contains this field
+ */
+ function renderfield($params, Doku_Form $form, $formid) {
+ $form->startFieldset(hsc($this->getParam('display')));
+ if (!empty($this->depends_on)) {
+ $dependencies = array_map('hsc',(array) $this->depends_on);
+ if (count($this->depends_on) > 1) {
+ $msg = 'Only edit this fieldset if ' .
+ '“<span class="bureaucracy_depends_fname">%s</span>” '.
+ 'is set to “<span class="bureaucracy_depends_fvalue">%s</span>”.';
+ } else {
+ $msg = 'Only edit this fieldset if ' .
+ '“<span class="bureaucracy_depends_fname">%s</span>” is set.';
+ }
+
+ $form->addElement('<p class="bureaucracy_depends">' . vsprintf($msg, $dependencies) . '</p>');
+ }
+ }
+
+ /**
+ * Handle a post to the fieldset
+ *
+ * When fieldset is closed, set containing fields to hidden
+ *
+ * @param null $value field value of fieldset always empty
+ * @param helper_plugin_bureaucracy_field[] $fields (reference) form fields (POST handled upto $this field)
+ * @param int $index index number of field in form
+ * @param int $formid unique identifier of the form which contains this field
+ * @return bool Whether the passed value is valid
+ */
+ public function handle_post($value, &$fields, $index, $formid) {
+ if(empty($this->depends_on)) {
+ return true;
+ }
+
+ // search the field where fieldset depends on in fields before fieldset
+ $hidden = false;
+ for ($n = 0 ; $n < $index; ++$n) {
+ $field = $fields[$n];
+ if ($field->getParam('label') != $this->depends_on[0]) {
+ continue;
+ }
+ if(count($this->depends_on) > 1) {
+ $hidden = $field->getParam('value') != $this->depends_on[1];
+ } else {
+ $hidden = !$field->isSet_();
+ }
+ break;
+ }
+ // mark fields after this fieldset as hidden
+ if ($hidden) {
+ $this->hidden = true;
+ for ($n = $index + 1 ; $n < count($fields) ; ++$n) {
+ $field = $fields[$n];
+ if ($field->getFieldType() === 'fieldset') {
+ break;
+ }
+ $field->hidden = true;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Get an arbitrary parameter
+ *
+ * @param string $name
+ * @return mixed|null
+ */
+ function getParam($name) {
+ if($name === 'value') {
+ return null;
+ } else {
+ return parent::getParam($name);
+ }
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fieldfile.php b/platform/www/lib/plugins/bureaucracy/helper/fieldfile.php
new file mode 100644
index 0000000..285308e
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fieldfile.php
@@ -0,0 +1,75 @@
+<?php
+
+/**
+ * File upload field
+ */
+class helper_plugin_bureaucracy_fieldfile extends helper_plugin_bureaucracy_field {
+
+ /**
+ * Arguments:
+ * - cmd
+ * - label
+ * - ^ (optional)
+ *
+ * @param array $args The tokenized definition, only split at spaces
+ */
+ function initialize($args) {
+ $this->init($args);
+
+ //default namespace for file upload (pagepath:file_name)
+ $this->opt['namespace'] = '.';
+
+ //check whenever the first argument is an upload namespace
+ if (isset($args[0]) && preg_match('/^[a-z.\-_:]+$/', $args[0])) {
+ $this->opt['namespace'] = array_shift($args);
+ }
+ $this->standardArgs($args);
+
+ $attr = array();
+ if(!isset($this->opt['optional'])) {
+ $attr['required'] = 'required';
+ }
+
+ $this->tpl = form_makeFileField('@@NAME@@', '@@DISPLAY@@', '@@ID@@', '@@CLASS@@', $attr);
+
+ if(!isset($this->opt['optional'])){
+ $this->tpl['class'] .= ' required';
+ }
+ }
+
+ /**
+ * Handle a post to the field
+ *
+ * Accepts and validates a posted value.
+ *
+ * @param array $value The passed value or array or null if none given
+ * @param helper_plugin_bureaucracy_field[] $fields (reference) form fields (POST handled upto $this field)
+ * @param int $index index number of field in form
+ * @param int $formid unique identifier of the form which contains this field
+ * @return bool Whether the passed filename is valid
+ */
+ public function handle_post($value, &$fields, $index, $formid) {
+ $this->opt['file'] = $value;
+
+ return parent::handle_post($value['name'], $fields, $index, $formid);
+ }
+
+ /**
+ * @throws Exception max size, required or upload error
+ */
+ protected function _validate() {
+ global $lang;
+ parent::_validate();
+
+ $file = $this->getParam('file');
+ if($file['error'] == 1 || $file['error'] == 2) {
+ throw new Exception(sprintf($lang['uploadsize'],filesize_h(php_to_byte(ini_get('upload_max_filesize')))));
+ } else if($file['error'] == 4) {
+ if(!isset($this->opt['optional'])) {
+ throw new Exception(sprintf($this->getLang('e_required'),hsc($this->opt['label'])));
+ }
+ } else if( $file['error'] || !is_uploaded_file($file['tmp_name'])) {
+ throw new Exception(hsc($this->opt['label']) .' '. $lang['uploadfail'] . ' (' .$file['error'] . ')' );
+ }
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fieldhidden.php b/platform/www/lib/plugins/bureaucracy/helper/fieldhidden.php
new file mode 100644
index 0000000..dd63753
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fieldhidden.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Class helper_plugin_bureaucracy_fieldhidden
+ *
+ * Creates an invisible field with static data
+ */
+class helper_plugin_bureaucracy_fieldhidden extends helper_plugin_bureaucracy_field {
+
+ /**
+ * Arguments:
+ * - cmd
+ * - label
+ * - =default value
+ */
+
+ /**
+ * Render the field as XHTML
+ *
+ * Outputs the represented field using the passed Doku_Form object.
+ *
+ * @param array $params Additional HTML specific parameters
+ * @param Doku_Form $form The target Doku_Form object
+ * @param int $formid unique identifier of the form which contains this field
+ */
+ function renderfield($params, Doku_Form $form, $formid) {
+ $this->_handlePreload();
+ $form->addHidden($params['name'], $this->getParam('value') . '');
+ }
+
+ /**
+ * Get an arbitrary parameter
+ *
+ * @param string $name
+ * @return mixed|null
+ */
+ function getParam($name) {
+ if (!isset($this->opt[$name]) || in_array($name, array('pagename', 'value')) && $this->hidden) {
+ return null;
+ }
+ if ($name === 'pagename') {
+ // If $this->opt['pagename'] is set, return the value of the field,
+ // UNESCAPED.
+ $name = 'value';
+ }
+ return $this->opt[$name];
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fieldhiddenautoinc.php b/platform/www/lib/plugins/bureaucracy/helper/fieldhiddenautoinc.php
new file mode 100644
index 0000000..787e081
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fieldhiddenautoinc.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Class helper_plugin_bureaucracy_fieldhiddenautoinc
+ *
+ * Creates an invisible field with a number that increases by 1 on each form submit
+ */
+class helper_plugin_bureaucracy_fieldhiddenautoinc extends helper_plugin_bureaucracy_fieldnumber {
+
+ /**
+ * Arguments:
+ * - cmd
+ * - label
+ *
+ * @param array $args The tokenized definition, only split at spaces
+ */
+ function initialize($args) {
+ $args[] = '++';
+ parent::initialize($args);
+ }
+
+ /**
+ * Render the field as XHTML
+ *
+ * Outputs the represented field using the passed Doku_Form object.
+ *
+ * @param array $params Additional HTML specific parameters
+ * @param Doku_Form $form The target Doku_Form object
+ * @param $formid
+ */
+ function renderfield($params, Doku_Form $form, $formid) {
+ $this->_handlePreload();
+ $form->addHidden($params['name'], $this->getParam('value') . '');
+ }
+
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fieldmultiselect.php b/platform/www/lib/plugins/bureaucracy/helper/fieldmultiselect.php
new file mode 100644
index 0000000..5311d90
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fieldmultiselect.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * Class helper_plugin_bureaucracy_fieldmultiselect
+ *
+ * Creates a multiselect box
+ */
+class helper_plugin_bureaucracy_fieldmultiselect extends helper_plugin_bureaucracy_fieldselect {
+
+ /**
+ * Arguments:
+ * - cmd
+ * - label
+ * - option1|option2|etc
+ * - ^ (optional)
+ *
+ * @param array $args The tokenized definition, only split at spaces
+ */
+ public function initialize($args) {
+ $this->init($args);
+ $this->opt['args'] = array_map('trim', explode('|',array_shift($args)));
+ $this->standardArgs($args);
+ if (isset($this->opt['value'])) {
+ $this->opt['value'] = array_map('trim', explode(',', $this->opt['value']));
+ } else {
+ $this->opt['value'] = array();
+ }
+ }
+
+ /**
+ * Render the field as XHTML
+ *
+ * Outputs the represented field using the passed Doku_Form object.
+ * Additional parameters (CSS class & HTML name) are passed in $params.
+ *
+ * @params array $params Additional HTML specific parameters
+ * @params Doku_Form $form The target Doku_Form object
+ * @params int $formid unique identifier of the form which contains this field
+ */
+ public function renderfield($params, Doku_Form $form, $formid) {
+ $this->_handlePreload();
+ if(!$form->_infieldset){
+ $form->startFieldset('');
+ }
+ if ($this->error) {
+ $params['class'] = 'bureaucracy_error';
+ }
+ $params = array_merge($this->opt, $params);
+ $form->addElement(call_user_func_array('form_makeListboxField',
+ $this->_parse_tpl(
+ array(
+ '@@NAME@@[]',
+ $params['args'],
+ $this->opt['value'],
+ '@@DISPLAY@@',
+ '@@ID@@',
+ '@@CLASS@@',
+ array('multiple' => 'multiple')
+ ),
+ $params
+ )));
+ }
+} \ No newline at end of file
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fieldnumber.php b/platform/www/lib/plugins/bureaucracy/helper/fieldnumber.php
new file mode 100644
index 0000000..93a2242
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fieldnumber.php
@@ -0,0 +1,119 @@
+<?php
+/**
+ * Class helper_plugin_bureaucracy_fieldnumber
+ *
+ * Creates a single line input field, where input is validated to be numeric
+ */
+class helper_plugin_bureaucracy_fieldnumber extends helper_plugin_bureaucracy_fieldtextbox {
+
+ private $autoinc = false;
+
+ /**
+ * Arguments:
+ * - cmd
+ * - label
+ * - ++ (optional)
+ * - 0000 (optional)
+ * - ^ (optional)
+ *
+ * @param array $args The tokenized definition, only split at spaces
+ */
+ public function initialize($args) {
+ $pp = array_search('++', $args, true);
+ if ($pp !== false) {
+ unset($args[$pp]);
+ $this->autoinc = true;
+ }
+
+ parent::initialize($args);
+
+ if ($this->autoinc) {
+ global $ID;
+ $key = $this->get_key();
+ $c_val = p_get_metadata($ID, 'bureaucracy ' . $key);
+ if (is_null($c_val)) {
+ if (!isset($this->opt['value'])) {
+ $this->opt['value'] = 0;
+ }
+ p_set_metadata($ID, array('bureaucracy' => array($key => $this->opt['value'])));
+ } else {
+ $this->opt['value'] = $c_val;
+ }
+ }
+ $this->opt['value'] = $this->addLeadingzeros($this->opt['value']);
+ }
+
+ /**
+ * Validate field value
+ *
+ * @throws Exception when not a number
+ */
+ protected function _validate() {
+ $value = $this->getParam('value');
+ if (!is_null($value) && !is_numeric($value)){
+ throw new Exception(sprintf($this->getLang('e_numeric'),hsc($this->getParam('display'))));
+ }
+
+ parent::_validate();
+ }
+
+ /**
+ * Handle a post to the field
+ *
+ * Accepts and validates a posted value.
+ *
+ * @param string $value The passed value or array or null if none given
+ * @param array $fields (reference) form fields (POST handled upto $this field)
+ * @param int $index index number of field in form
+ * @param int $formid unique identifier of the form which contains this field
+ * @return bool Whether the passed value is valid
+ */
+ public function handle_post($value, &$fields, $index, $formid) {
+ $value = $this->addLeadingzeros($value);
+
+ return parent::handle_post($value, $fields, $index, $formid);
+ }
+
+ /**
+ * Returns the cleaned key for this field required for metadata
+ *
+ * @return string key
+ */
+ private function get_key() {
+ return preg_replace('/\W/', '', $this->opt['label']) . '_autoinc';
+ }
+
+ /**
+ * Executed after performing the action hooks
+ *
+ * Increases counter and purge cache
+ */
+ public function after_action() {
+ if ($this->autoinc) {
+ global $ID;
+ p_set_metadata($ID, array('bureaucracy' => array($this->get_key() => $this->opt['value'] + 1)));
+ // Force rerendering by removing the instructions cache file
+ $cache_fn = getCacheName(wikiFN($ID).$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT'],'.'.'i');
+ if (file_exists($cache_fn)) {
+ unlink($cache_fn);
+ }
+ }
+ }
+
+ /**
+ * Add leading zeros, depending on the corresponding field option
+ *
+ * @param int|string $value number
+ * @return string
+ */
+ protected function addLeadingzeros(&$value) {
+ if (isset($this->opt['leadingzeros'])) {
+ $length = strlen($value);
+ for($i = $length; $i < $this->opt['leadingzeros']; $i++) {
+ $value = '0' . $value;
+ }
+ return $value;
+ }
+ return $value;
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fieldonoff.php b/platform/www/lib/plugins/bureaucracy/helper/fieldonoff.php
new file mode 100644
index 0000000..d73177b
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fieldonoff.php
@@ -0,0 +1,16 @@
+<?php
+/**
+ * Class helper_plugin_bureaucracy_fieldonoff
+ *
+ * Creates a checkbox
+ */
+class helper_plugin_bureaucracy_fieldonoff extends helper_plugin_bureaucracy_fieldyesno {
+ /**
+ * Arguments:
+ * - cmd
+ * - label
+ * - =yesvalue
+ * - !falsevalue
+ * - ^ (optional)
+ */
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fieldpassword.php b/platform/www/lib/plugins/bureaucracy/helper/fieldpassword.php
new file mode 100644
index 0000000..e4e20f4
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fieldpassword.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Class helper_plugin_bureaucracy_fieldpassword
+ *
+ * Creates a single line password input field
+ */
+class helper_plugin_bureaucracy_fieldpassword extends helper_plugin_bureaucracy_field {
+ /**
+ * Arguments:
+ * - cmd
+ * - label
+ * - ^ (optional)
+ *
+ * @param array $args The tokenized definition, only split at spaces
+ */
+ function initialize($args) {
+ parent::initialize($args);
+
+ $attr = array();
+ if(!isset($this->opt['optional'])) {
+ $attr['required'] = 'required';
+ }
+ $this->tpl = form_makePasswordField('@@NAME@@', '@@DISPLAY@@', '@@ID@@', '@@CLASS@@', $attr);
+
+ if(!isset($this->opt['optional'])){
+ $this->tpl['class'] .= ' required';
+ }
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fieldradio.php b/platform/www/lib/plugins/bureaucracy/helper/fieldradio.php
new file mode 100644
index 0000000..e2b466d
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fieldradio.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Class helper_plugin_bureaucracy_fieldselect
+ *
+ * Creates a dropdown list
+ */
+class helper_plugin_bureaucracy_fieldradio extends helper_plugin_bureaucracy_field {
+
+ protected $mandatory_args = 3;
+
+ /**
+ * Arguments:
+ * - cmd
+ * - label
+ * - option1|option2|etc
+ * - ^ (optional)
+ *
+ * @param array $args The tokenized definition, only split at spaces
+ */
+ public function initialize($args) {
+ $this->init($args);
+ $this->opt['args'] = array_filter(array_map('trim', explode('|',array_shift($args))));
+ $this->standardArgs($args);
+ }
+
+ /**
+ * Render the field as XHTML
+ *
+ * Outputs the represented field using the passed Doku_Form object.
+ * Additional parameters (CSS class & HTML name) are passed in $params.
+ *
+ * @params array $params Additional HTML specific parameters
+ * @params Doku_Form $form The target Doku_Form object
+ * @params int $formid unique identifier of the form which contains this field
+ */
+ public function renderfield($params, Doku_Form $form, $formid) {
+ $this->_handlePreload();
+ if(!$form->_infieldset){
+ $form->startFieldset('');
+ }
+ if ($this->error) {
+ $params['class'] = 'bureaucracy_error';
+ }
+ $params = array_merge($this->opt, $params);
+
+ list($name, $entries, $value, $label, $id, $class) = $this->_parse_tpl(
+ array(
+ '@@NAME@@',
+ $params['args'],
+ '@@VALUE@@',
+ '@@DISPLAY@@',
+ '@@ID@@',
+ '@@CLASS@@'
+ ),
+ $params
+ );
+
+ $value = (in_array($value, $entries) ? $value : null);
+ $valueoffieldwithid = ($value !== null ? $value : current($entries));
+ // label
+ $s = '<label';
+ $s .= ' class="radiolabel '.$class.'"';
+ $s .= '><span>' . $label . '</span>';
+ $s .= '</label>';
+ $form->addElement($s);
+
+ // radio fields
+ foreach($entries as $val) {
+ if($value === $val) {
+ $attrs = array('checked' => 'checked');
+ } else {
+ $attrs = array();
+ }
+ if($valueoffieldwithid === $val) {
+ $_id = $id; //e.g. autofocus with 'focus__this' id
+ } else {
+ $_id = '';
+ }
+ $form->addElement(form_makeRadioField($name, $val, $val, $_id, $class, $attrs));
+ }
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fieldselect.php b/platform/www/lib/plugins/bureaucracy/helper/fieldselect.php
new file mode 100644
index 0000000..391e562
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fieldselect.php
@@ -0,0 +1,61 @@
+<?php
+/**
+ * Class helper_plugin_bureaucracy_fieldselect
+ *
+ * Creates a dropdown list
+ */
+class helper_plugin_bureaucracy_fieldselect extends helper_plugin_bureaucracy_field {
+
+ protected $mandatory_args = 3;
+
+ /**
+ * Arguments:
+ * - cmd
+ * - label
+ * - option1|option2|etc
+ * - ^ (optional)
+ *
+ * @param array $args The tokenized definition, only split at spaces
+ */
+ public function initialize($args) {
+ $this->init($args);
+ $this->opt['args'] = array_map('trim', explode('|',array_shift($args)));
+ $this->standardArgs($args);
+ if (!isset($this->opt['value']) && isset($this->opt['optional'])) {
+ array_unshift($this->opt['args'],' ');
+ }
+ }
+
+ /**
+ * Render the field as XHTML
+ *
+ * Outputs the represented field using the passed Doku_Form object.
+ * Additional parameters (CSS class & HTML name) are passed in $params.
+ *
+ * @params array $params Additional HTML specific parameters
+ * @params Doku_Form $form The target Doku_Form object
+ * @params int $formid unique identifier of the form which contains this field
+ */
+ public function renderfield($params, Doku_Form $form, $formid) {
+ $this->_handlePreload();
+ if(!$form->_infieldset){
+ $form->startFieldset('');
+ }
+ if ($this->error) {
+ $params['class'] = 'bureaucracy_error';
+ }
+ $params = array_merge($this->opt, $params);
+ $form->addElement(call_user_func_array('form_makeListboxField',
+ $this->_parse_tpl(
+ array(
+ '@@NAME@@',
+ $params['args'],
+ '@@VALUE|' . $params['args'][0] . '@@',
+ '@@DISPLAY@@',
+ '@@ID@@',
+ '@@CLASS@@'
+ ),
+ $params
+ )));
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fieldstatic.php b/platform/www/lib/plugins/bureaucracy/helper/fieldstatic.php
new file mode 100644
index 0000000..191be72
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fieldstatic.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Class helper_plugin_bureaucracy_fieldstatic
+ *
+ * Adds some static text to the form
+ */
+class helper_plugin_bureaucracy_fieldstatic extends helper_plugin_bureaucracy_field {
+ protected $tpl = '<p>@@DISPLAY@@</p>';
+
+ /**
+ * Arguments:
+ * - cmd
+ * - text
+ *
+ * @param array $args The tokenized definition, only split at spaces
+ */
+ public function initialize($args) {
+ parent::initialize($args);
+ // make always optional to prevent being marked as required
+ $this->opt['optional'] = true;
+ }
+
+ /**
+ * Handle a post to the field
+ *
+ * @param string $value The passed value
+ * @param helper_plugin_bureaucracy_field[] $fields (reference) form fields (POST handled upto $this field)
+ * @param int $index index number of field in form
+ * @param int $formid unique identifier of the form which contains this field
+ * @return bool Whether the passed value is valid
+ */
+ public function handle_post($value, &$fields, $index, $formid) {
+ return true;
+ }
+
+ /**
+ * Get an arbitrary parameter
+ *
+ * @param string $name
+ * @return mixed|null
+ */
+ public function getParam($name) {
+ return ($name === 'value') ? null : parent::getParam($name);
+ }
+
+ /**
+ * Render the field as XHTML
+ *
+ * @params array $params Additional HTML specific parameters
+ * @params Doku_Form $form The target Doku_Form object
+ * @params int $formid unique identifier of the form which contains this field
+ */
+ public function renderfield($params, Doku_Form $form, $formid) {
+ if (!isset($this->opt['display'])) {
+ $this->opt['display'] = $this->opt['label'];
+ }
+ parent::renderfield($params, $form, $formid);
+ }
+
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fieldsubject.php b/platform/www/lib/plugins/bureaucracy/helper/fieldsubject.php
new file mode 100644
index 0000000..f49c2b7
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fieldsubject.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Class helper_plugin_bureaucracy_fieldsubject
+ *
+ * Defines own subject for mail action from this form
+ */
+class helper_plugin_bureaucracy_fieldsubject extends helper_plugin_bureaucracy_field {
+ /**
+ * Arguments:
+ * - cmd
+ * - subjecttext
+ */
+
+ /**
+ * Render the field as XHTML
+ *
+ * @params array $params Additional HTML specific parameters
+ * @params Doku_Form $form The target Doku_Form object
+ * @params int $formid unique identifier of the form which contains this field
+ */
+ public function renderfield($params, Doku_Form $form, $formid) {
+ $this->_handlePreload();
+ }
+
+ /**
+ * Handle a post to the field
+ *
+ * @param string $value null
+ * @param helper_plugin_bureaucracy_field[] $fields (reference) form fields (POST handled upto $this field)
+ * @param int $index index number of field in form
+ * @param int $formid unique identifier of the form which contains this field
+ * @return bool Whether the passed value is valid
+ */
+ function handle_post($value, &$fields, $index, $formid) {
+ return true;
+ }
+} \ No newline at end of file
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fieldsubmit.php b/platform/www/lib/plugins/bureaucracy/helper/fieldsubmit.php
new file mode 100644
index 0000000..b9f2e45
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fieldsubmit.php
@@ -0,0 +1,89 @@
+<?php
+/**
+ * Class helper_plugin_bureaucracy_fieldsubmit
+ *
+ * Creates a submit button
+ */
+class helper_plugin_bureaucracy_fieldsubmit extends helper_plugin_bureaucracy_field {
+ protected $mandatory_args = 1;
+ static $captcha_displayed = array();
+ static $captcha_checked = array();
+
+ /**
+ * Arguments:
+ * - cmd
+ * - label (optional)
+ * - ^ (optional)
+ *
+ * @param array $args The tokenized definition, only split at spaces
+ */
+ public function initialize($args) {
+ parent::initialize($args);
+ // make always optional to prevent being marked as required
+ $this->opt['optional'] = true;
+ }
+
+ /**
+ * Render the field as XHTML
+ *
+ * @params array $params Additional HTML specific parameters
+ * @params Doku_Form $form The target Doku_Form object
+ * @params int $formid unique identifier of the form which contains this field
+ */
+ public function renderfield($params, Doku_Form $form, $formid) {
+ if(!isset(helper_plugin_bureaucracy_fieldsubmit::$captcha_displayed[$formid])) {
+ helper_plugin_bureaucracy_fieldsubmit::$captcha_displayed[$formid] = true;
+ /** @var helper_plugin_captcha $helper */
+ $helper = null;
+ if(@is_dir(DOKU_PLUGIN.'captcha')) $helper = plugin_load('helper','captcha');
+ if(!is_null($helper) && $helper->isEnabled()){
+ $form->addElement($helper->getHTML());
+ }
+ }
+ $attr = array();
+ if(isset($this->opt['id'])) {
+ $attr['id'] = $this->opt['id'];
+ }
+ $this->tpl = form_makeButton('submit','', '@@DISPLAY|' . $this->getLang('submit') . '@@', $attr);
+ parent::renderfield($params, $form, $formid);
+ }
+
+ /**
+ * Handle a post to the field
+ *
+ * Accepts and validates a posted captcha value.
+ *
+ * @param string $value The passed value
+ * @param helper_plugin_bureaucracy_field[] $fields (reference) form fields (POST handled upto $this field)
+ * @param int $index index number of field in form
+ * @param int $formid unique identifier of the form which contains this field
+ * @return bool Whether the posted form has a valid captcha
+ */
+ public function handle_post($value, &$fields, $index, $formid) {
+ if ($this->hidden) {
+ return true;
+ }
+ if(!isset(helper_plugin_bureaucracy_fieldsubmit::$captcha_checked[$formid])) {
+ helper_plugin_bureaucracy_fieldsubmit::$captcha_checked[$formid] = true;
+ // check CAPTCHA
+ /** @var helper_plugin_captcha $helper */
+ $helper = null;
+ if(@is_dir(DOKU_PLUGIN.'captcha')) $helper = plugin_load('helper','captcha');
+ if(!is_null($helper) && $helper->isEnabled()){
+ return $helper->check();
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Get an arbitrary parameter
+ *
+ * @param string $name
+ * @return mixed|null
+ */
+ public function getParam($name) {
+ return ($name === 'value') ? null : parent::getParam($name);
+ }
+
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fieldtextarea.php b/platform/www/lib/plugins/bureaucracy/helper/fieldtextarea.php
new file mode 100644
index 0000000..0dfcce2
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fieldtextarea.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Class helper_plugin_bureaucracy_fieldtextarea
+ *
+ * Creates a multi-line input field
+ */
+class helper_plugin_bureaucracy_fieldtextarea extends helper_plugin_bureaucracy_field {
+ /**
+ * Arguments:
+ * - cmd
+ * - label
+ * - x123 (optional) as number of lines
+ * - ^ (optional)
+ */
+ public function initialize($args) {
+ parent::initialize($args);
+ if (!isset($this->opt['class'])) {
+ $this->opt['class'] = '';
+ }
+ $this->opt['class'] .= ' textareafield';
+ }
+
+ protected $tpl =
+'<label class="@@CLASS@@">
+ <span>@@DISPLAY@@</span>
+ <textarea name="@@NAME@@" id="@@ID@@" rows="@@ROWS|10@@" cols="10" class="edit @@OPTIONAL|required" required="required@@">@@VALUE@@</textarea>
+</label>';
+
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fieldtextbox.php b/platform/www/lib/plugins/bureaucracy/helper/fieldtextbox.php
new file mode 100644
index 0000000..430cc2d
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fieldtextbox.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Class helper_plugin_bureaucracy_fieldtextbox
+ *
+ * Creates a single line input field
+ */
+class helper_plugin_bureaucracy_fieldtextbox extends helper_plugin_bureaucracy_field {
+
+ /**
+ * Arguments:
+ * - cmd
+ * - label
+ * - =default (optional)
+ * - ^ (optional)
+ *
+ * @param array $args The tokenized definition, only split at spaces
+ */
+ function initialize($args) {
+ parent::initialize($args);
+
+ $attr = array();
+ if(!isset($this->opt['optional'])) {
+ $attr['required'] = 'required';
+ }
+
+ $this->tpl = form_makeTextField('@@NAME@@', '@@VALUE@@', '@@DISPLAY@@', '@@ID@@', '@@CLASS@@', $attr);
+ if(isset($this->opt['class'])){
+ $this->tpl['class'] .= ' '.$this->opt['class'];
+ }
+ if(!isset($this->opt['optional'])){
+ $this->tpl['class'] .= ' required';
+ }
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fieldtime.php b/platform/www/lib/plugins/bureaucracy/helper/fieldtime.php
new file mode 100644
index 0000000..164e71f
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fieldtime.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * Class helper_plugin_bureaucracy_fieldtime
+ *
+ * A time in the format (h)h:mm(:ss)
+ */
+class helper_plugin_bureaucracy_fieldtime extends helper_plugin_bureaucracy_fieldtextbox {
+ /**
+ * Arguments:
+ * - cmd
+ * - label
+ * - ^ (optional)
+ *
+ * @param array $args The tokenized definition, only split at spaces
+ */
+ public function initialize($args) {
+ parent::initialize($args);
+ $attr = array(
+ 'class' => 'timefield edit',
+ 'maxlength'=>'8'
+ );
+ if(!isset($this->opt['optional'])) {
+ $attr['required'] = 'required';
+ $attr['class'] .= ' required';
+ }
+ $this->tpl = form_makeTextField('@@NAME@@', '@@VALUE@@', '@@DISPLAY@@', '@@ID@@', '@@CLASS@@', $attr);
+ }
+
+ /**
+ * Validate field input
+ *
+ * @throws Exception when empty or wrong time format
+ */
+ protected function _validate() {
+ parent::_validate();
+
+ $value = $this->getParam('value');
+ if (!is_null($value) && !preg_match('/^\d{1,2}:\d{2}(?::\d{2})?$/', $value)) {
+ throw new Exception(sprintf($this->getLang('e_time'),hsc($this->getParam('display'))));
+ }
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fieldusemailtemplate.php b/platform/www/lib/plugins/bureaucracy/helper/fieldusemailtemplate.php
new file mode 100644
index 0000000..775f87b
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fieldusemailtemplate.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * Class helper_plugin_bureaucracy_fieldusemailtemplate
+ *
+ * Adds a template only for use with the mail action
+ */
+class helper_plugin_bureaucracy_fieldusemailtemplate extends helper_plugin_bureaucracy_field {
+
+ /**
+ * Arguments:
+ * - cmd
+ * - template
+ *
+ * @param array $args The tokenized definition, only split at spaces
+ */
+ function initialize($args) {
+ if(count($args) < 2){
+ msg(sprintf($this->getLang('e_missingargs'), hsc($args[0]),
+ hsc($args[1])), -1);
+ return;
+ }
+
+ // get standard arguments
+ $this->opt = array_combine(array('cmd', 'template'), $args);
+ }
+
+ /**
+ * Nothing displayed
+ *
+ * @params array $params Additional HTML specific parameters
+ * @params Doku_Form $form The target Doku_Form object
+ * @params int $formid unique identifier of the form which contains this field
+ */
+ function renderfield($params, Doku_Form $form, $formid) {
+ }
+
+ /**
+ * Handle a post to the field
+ *
+ * @param string $value null
+ * @param helper_plugin_bureaucracy_field[] $fields (reference) form fields (POST handled upto $this field)
+ * @param int $index index number of field in form
+ * @param int $formid unique identifier of the form which contains this field
+ * @return bool Whether the passed value is valid
+ */
+ function handle_post($value, &$fields, $index, $formid) {
+ return true;
+ }
+
+ /**
+ * Get an arbitrary parameter
+ *
+ * @param string $name
+ * @return mixed|null
+ */
+ function getParam($name) {
+ return ($name === 'value' ||
+ (in_array($name, array('template')) && $this->hidden)) ?
+ null :
+ parent::getParam($name);
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fielduser.php b/platform/www/lib/plugins/bureaucracy/helper/fielduser.php
new file mode 100644
index 0000000..49608e1
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fielduser.php
@@ -0,0 +1,99 @@
+<?php
+/**
+ * Class helper_plugin_bureaucracy_fielduser
+ *
+ * Create single user input, with autocompletion
+ */
+class helper_plugin_bureaucracy_fielduser extends helper_plugin_bureaucracy_fieldtextbox {
+
+ /**
+ * Arguments:
+ * - cmd
+ * - label
+ * - ^ (optional)
+ *
+ * @param array $args The tokenized definition, only split at spaces
+ */
+ public function initialize($args) {
+ parent::initialize($args);
+ $this->tpl['class'] .= ' userpicker';
+ }
+
+ /**
+ * Allow receiving user attributes by ".". Ex. user.name
+ * You can pass an optional argument to user.grps enclosed in brackets, used as an groups delimiter Ex. user.grps(, )
+ *
+ * @return string
+ */
+ public function getReplacementPattern() {
+ $label = $this->opt['label'];
+
+ return '/(@@|##)' . preg_quote($label, '/') .
+ '(?:\.(.*?))?' . //match attribute after "."
+ '(?:\((.*?)\))?' . //match parameter enclosed in "()". Used for grps separator
+ '\1/si';
+ }
+
+ /**
+ * Used as an callback for preg_replace_callback
+ *
+ * @param $matches
+ * @return string
+ */
+ public function replacementValueCallback($matches) {
+ /** @var DokuWiki_Auth_Plugin $auth */
+ global $auth;
+
+ $value = $this->opt['value'];
+ //attr doesn't exists
+ if (!isset($matches[2])) {
+ return is_null($value) || $value === false ? '' : $value;
+ }
+ $attr = $matches[2];
+
+ $udata = $auth->getUserData($value);
+ //no such user
+ if ($udata === false) {
+ return $matches[0];
+ }
+
+ switch($attr) {
+ case 'name':
+ case 'mail':
+ return $udata[$attr];
+ case 'grps':
+ $delitmiter = ', ';
+ if (isset($matches[3])) {
+ $delitmiter = $matches[3];
+ }
+ return implode($delitmiter, $udata['grps']);
+ default:
+ return $matches[0];
+ }
+ }
+
+ /**
+ * Return the callback for user replacement
+ *
+ * @return array
+ */
+ public function getReplacementValue() {
+ return array($this, 'replacementValueCallback');
+ }
+
+ /**
+ * Validate value of field
+ *
+ * @throws Exception when user not exists
+ */
+ protected function _validate() {
+ parent::_validate();
+
+ /** @var DokuWiki_Auth_Plugin $auth */
+ global $auth;
+ $value = $this->getParam('value');
+ if (!is_null($value) && $auth->getUserData($value) === false) {
+ throw new Exception(sprintf($this->getLang('e_user'),hsc($this->getParam('display'))));
+ }
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fieldusers.php b/platform/www/lib/plugins/bureaucracy/helper/fieldusers.php
new file mode 100644
index 0000000..bd5dce7
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fieldusers.php
@@ -0,0 +1,96 @@
+<?php
+/**
+ * Class helper_plugin_bureaucracy_fieldusers
+ *
+ * Create multi-user input, with autocompletion
+ */
+class helper_plugin_bureaucracy_fieldusers extends helper_plugin_bureaucracy_fieldtextbox {
+
+ /**
+ * Arguments:
+ * - cmd
+ * - label
+ * - ^ (optional)
+ *
+ * @param array $args The tokenized definition, only split at spaces
+ */
+ public function initialize($args) {
+ parent::initialize($args);
+ $this->tpl['class'] .= ' userspicker';
+ }
+
+ /**
+ * Allow receiving user attributes by ".". Ex. user.name
+ * You can pass an optional argument to user.grps enclosed in brackets, used as an groups delimiter Ex. user.grps(, )
+ *
+ * @return string
+ */
+ public function getReplacementPattern() {
+ $label = $this->opt['label'];
+ return '/(@@|##)' . preg_quote($label, '/') .
+ '(?:\((?P<delimiter>.*?)\))?' .//delimiter
+ '(?:\.(?P<attribute>.*?))?' . //match attribute after "."
+ '\1/si';
+ }
+
+ /**
+ * Used as an callback for preg_replace_callback
+ *
+ * @param $matches
+ * @return string
+ */
+ public function replacementValueCallback($matches) {
+ /** @var DokuWiki_Auth_Plugin $auth */
+ global $auth;
+
+ $value = $this->opt['value'];
+ //copy the value by default
+ if (isset($matches[2]) && is_array($matches[2]) && count($matches[2]) == 2) {
+ return is_null($value) || $value === false ? $matches[0] : $value;
+ }
+
+ $attribute = isset($matches['attribute']) ? $matches['attribute'] : '';
+ //check if matched string containts a pair of brackets
+ $delimiter = preg_match('/\(.*\)/s', $matches[0]) ? $matches['delimiter'] : ', ';
+ $users = array_map('trim', explode(',', $value));
+
+ switch($attribute) {
+ case '':
+ return implode($delimiter, $users);
+ case 'name':
+ case 'mail':
+ return implode($delimiter, array_map(function ($user) use ($auth, $attribute) {
+ return $auth->getUserData($user)[$attribute];
+ }, $users));
+ default:
+ return $matches[0];
+ }
+ }
+
+ /**
+ * Return the callback for user replacement
+ *
+ * @return array
+ */
+ public function getReplacementValue() {
+ return array($this, 'replacementValueCallback');
+ }
+
+ /**
+ * Validate value of field
+ *
+ * @throws Exception when user not exists
+ */
+ protected function _validate() {
+ parent::_validate();
+
+ /** @var DokuWiki_Auth_Plugin $auth */
+ global $auth;
+ $users = array_filter(preg_split('/\s*,\s*/', $this->getParam('value')));
+ foreach ($users as $user) {
+ if ($auth->getUserData($user) === false) {
+ throw new Exception(sprintf($this->getLang('e_users'), hsc($this->getParam('display'))));
+ }
+ }
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fieldwiki.php b/platform/www/lib/plugins/bureaucracy/helper/fieldwiki.php
new file mode 100644
index 0000000..dada855
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fieldwiki.php
@@ -0,0 +1,70 @@
+<?php
+/**
+ * Class helper_plugin_bureaucracy_fieldwiki
+ *
+ * Adds some static text to the form, but parses the input as Wiki syntax (computationally expensive)
+ */
+class helper_plugin_bureaucracy_fieldwiki extends helper_plugin_bureaucracy_field {
+
+ protected $tpl = '<p>@@LABEL@@</p>';
+
+ /**
+ * Arguments:
+ * - cmd
+ * - wiki text
+ *
+ * @param array $args The tokenized definition, only split at spaces
+ */
+ public function initialize($args) {
+ parent::initialize($args);
+ // make always optional to prevent being marked as required
+ $this->opt['optional'] = true;
+ }
+
+ /**
+ * Handle a post to the field
+ *
+ * @param null $value empty
+ * @param helper_plugin_bureaucracy_field[] $fields (reference) form fields (POST handled upto $this field)
+ * @param int $index index number of field in form
+ * @param int $formid unique identifier of the form which contains this field
+ * @return bool Whether the passed value is valid
+ */
+ public function handle_post($value, &$fields, $index, $formid) {
+ return true;
+ }
+
+ /**
+ * Get an arbitrary parameter
+ *
+ * @param string $name
+ * @return mixed|null
+ */
+ public function getParam($name) {
+ return ($name === 'value') ? null : parent::getParam($name);
+ }
+
+ /**
+ * Returns parsed wiki instructions
+ *
+ * @param string|array $tpl The template as string
+ * @param array $params A hash mapping parameters to values
+ *
+ * @return string The parsed template
+ */
+ protected function _parse_tpl($tpl, $params) {
+ $ins = p_get_instructions($params['display']);
+ // remove document and p instructions (opening and closing)
+ $start = 2;
+ $end = 2;
+ // check if struct instructions have to be removed as well from the beginning or end
+ if (isset($ins[1][1][0]) && $ins[1][1][0] === 'struct_output') {
+ $start = 3;
+ } elseif (isset($ins[count($ins) - 2][1][0]) && $ins[count($ins) - 2][1][0] === 'struct_output') {
+ $end = 3;
+ }
+ $ins = array_slice($ins, $start, -$end);
+ $tpl = p_render('xhtml', $ins, $byref_ignore);
+ return '<p>'.$tpl.'</p>';
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/helper/fieldyesno.php b/platform/www/lib/plugins/bureaucracy/helper/fieldyesno.php
new file mode 100644
index 0000000..77b83de
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/helper/fieldyesno.php
@@ -0,0 +1,98 @@
+<?php
+/**
+ * Class helper_plugin_bureaucracy_fieldyesno
+ *
+ * Creates a checkbox
+ */
+class helper_plugin_bureaucracy_fieldyesno extends helper_plugin_bureaucracy_field {
+
+ /**
+ * Arguments:
+ * - cmd
+ * - label
+ * - =yesvalue
+ * - !falsevalue
+ * - ^ (optional)
+ *
+ * @param array $args The tokenized definition, only split at spaces
+ */
+ public function initialize($args) {
+ $this->init($args);
+ $newargs = array();
+ foreach ($args as $arg) {
+ switch ($arg[0]) {
+ case '=':
+ if($arg == '==1') {
+ $this->opt['value'] = '1';
+ }elseif($arg == '==0') {
+ $this->opt['value'] = '0';
+ }else{
+ $this->opt['true_value'] = substr($arg, 1);
+ }
+ break;
+ case '!':
+ $this->opt['false_value'] = substr($arg, 1);
+ break;
+ default:
+ $newargs[] = $arg;
+ }
+ }
+ $this->standardArgs($newargs);
+ $this->opt['optional'] = true;
+ }
+
+ /**
+ * Get an arbitrary parameter
+ *
+ * @param string $key
+ * @return mixed|null
+ */
+ public function getParam($key) {
+ if ($key === 'value') {
+ if ($this->opt['value'] === '1') {
+ return isset($this->opt['true_value']) ?
+ $this->opt['true_value'] :
+ null;
+ } elseif ($this->opt['value'] === '0') {
+ return isset($this->opt['false_value']) ?
+ $this->opt['false_value'] :
+ null;
+ }
+ }
+ return parent::getParam($key);
+ }
+
+ /**
+ * Whether the field is true (used for depending fieldsets)
+ *
+ * @return bool whether field is set
+ */
+ public function isSet_() {
+ return $this->opt['value'] === '1';
+ }
+
+ /**
+ * Render the field as XHTML
+ *
+ * @params array $params Additional HTML specific parameters
+ * @params Doku_Form $form The target Doku_Form object
+ * @params int $formid unique identifier of the form which contains this field
+ */
+ public function renderfield($params, Doku_Form $form, $formid) {
+ $id = 'bureaucracy__'.md5(rand());
+ if(isset($this->opt['id'])) {
+ $id = $this->opt['id'];
+ }
+ $params = array_merge(
+ array('value' => false),
+ $this->opt,
+ $params
+ );
+ $check = $params['value'] ? 'checked="checked"' : '';
+ $this->tpl = '<label class="@@CLASS@@" for="'.$id.'"><span>@@DISPLAY@@</span>'.
+ '<input type="hidden" name="@@NAME@@" value="0" />' .
+ '<input type="checkbox" name="@@NAME@@" value="1" id="'.$id.'" ' . $check . ' />' .
+ '</label>';
+ parent::renderfield($params, $form, $formid);
+ }
+}
diff --git a/platform/www/lib/plugins/bureaucracy/interfaces/bureaucracy_handler_interface.php b/platform/www/lib/plugins/bureaucracy/interfaces/bureaucracy_handler_interface.php
new file mode 100644
index 0000000..41c461f
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/interfaces/bureaucracy_handler_interface.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace dokuwiki\plugin\bureaucracy\interfaces;
+
+interface bureaucracy_handler_interface {
+
+ /**
+ * Handle the data incoming from the form.
+ *
+ * @param \helper_plugin_bureaucracy_field[] $fields the list of fields in the form
+ * @param string $thanks the thank you message as defined in the form
+ * or default one. Might be modified by the action
+ * before returned
+ *
+ * @return bool|string false on error, $thanks on success
+ *
+ */
+ public function handleData($fields, $thanks);
+}
diff --git a/platform/www/lib/plugins/bureaucracy/lang/cs/lang.php b/platform/www/lib/plugins/bureaucracy/lang/cs/lang.php
new file mode 100644
index 0000000..38d717e
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/cs/lang.php
@@ -0,0 +1,27 @@
+<?php
+
+$lang['e_unknowntype'] = 'Neznámý typ "%s"';
+$lang['e_missingargs'] = 'Příliš málo argumentů pro %s %s';
+$lang['e_noaction'] = 'Žádná akce nebyla nastavena';
+$lang['e_mail'] = 'Nastala chyba při odesílání';
+
+$lang['e_required'] = '"%s" je povinný';
+$lang['e_match'] = '"%s" nemá požadovaný formát. %s)';
+$lang['checkagainst'] = '(regulární výraz: /%s/i)';
+$lang['e_email'] = '"%s" není platná emailová adresa.';
+$lang['e_numeric'] = '"%s" není číslo.';
+$lang['e_min'] = '"%s" musí být větší než %s.';
+$lang['e_max'] = '"%s" musí být menší než %s.';
+
+$lang['e_pagename'] = 'Chybí jméno stránky.';
+$lang['e_pageexists'] = 'Stránka "%s" již existuje. Vyberte, prosím, jiné jméno.';
+$lang['e_template'] = 'Šablona "%s" nebyla nalezena. Je možné, že nemáte práva pro čtení.';
+$lang['e_denied'] = 'Nemáte práva pro vytvoření stránky, možná nejste přihlášen.';
+
+$lang['mailsubject'] = 'Formulář odeslán jako %s';
+$lang['mailintro'] = 'Následující data byla odeslánan na %s.';
+
+$lang['mail_thanks'] = 'Data byla odeslána. Děkujeme.';
+$lang['template_thanks'] = 'Stránka byla vytvořena, pokračujte na ni následujícím odkazem.';
+
+$lang['summary'] = 'Vytvořeno z formuláře na %s';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/cs/settings.php b/platform/www/lib/plugins/bureaucracy/lang/cs/settings.php
new file mode 100644
index 0000000..453901d
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/cs/settings.php
@@ -0,0 +1,4 @@
+<?php
+
+$lang['runas'] = 'Ovlivňuje "template mode". Použijte práva (virtuálníh)o uživatele pro kontrolu ACL (přístupová práva) při čtení a vytváření stránek.';
+
diff --git a/platform/www/lib/plugins/bureaucracy/lang/de/lang.php b/platform/www/lib/plugins/bureaucracy/lang/de/lang.php
new file mode 100644
index 0000000..5dbfe0c
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/de/lang.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Thorsten Niederkrome <dralli@gmx.net>
+ */
+$lang['e_unknowntype'] = 'Unbekannter Typ "%s"';
+$lang['e_unknownaction'] = 'Unbekannte Aktion "%s"';
+$lang['e_missingargs'] = 'Nicht genug Argumente für %s %s';
+$lang['e_noaction'] = 'Keine Aktion definiert - wohin sollen die Daten gesendet werden?';
+$lang['e_mail'] = 'Beim Versenden der Daten ist ein Fehler aufgetreten';
+$lang['e_unknownconstraint'] = 'Unbekannter Feld-Parameter %s';
+$lang['e_labelpage'] = 'Seite mit Feldnamen %s nicht gefunden';
+$lang['e_required'] = '"%s" muss ausgefüllt werden.';
+$lang['e_match'] = '"%s" wurde nicht korrekt ausgefüllt. %s';
+$lang['checkagainst'] = '(überprüft gegen /%s/)';
+$lang['e_email'] = '"%s" muss eine gültige E-Mail Adresse sein.';
+$lang['e_numeric'] = '"%s" muss eine Nummer sein.';
+$lang['e_date'] = '"%s" muss ein gültiges Datum im Format jjjj-mm-tt sein.';
+$lang['e_time'] = '"%s" muss eine gültige Zeit im Format (h)h:mm(:ss) sein.';
+$lang['e_user'] = '"%s" muss der Name eines existierenden Benutzers sein.';
+$lang['e_users'] = '"%s" muss eine komma-separierte Liste existierender Benutzer sein.';
+$lang['e_min'] = '"%s" muss größer sein als %s.';
+$lang['e_max'] = '"%s" muss kleiner sein als %s.';
+$lang['e_pagename'] = 'Seitenname nicht angegeben.';
+$lang['e_pageexists'] = 'Die Seite "%s" exisistiert bereits. Bitte wählen Sie einen anderen Namen.';
+$lang['e_template'] = 'Das Template "%s" konnte nicht geladen werden. Möglicherweise existiert es nicht oder Sie verfügen nicht über die benötigten Rechte.';
+$lang['e_denied'] = 'Sie sind nicht berechtigt diese Seite anzulegen. Haben Sie vielleicht vergessen sich anzumelden?';
+$lang['mailsubject'] = 'Formulardaten übermittelt von %s';
+$lang['mailintro'] = 'Die folgenden Daten wurden am %s abgeschickt.';
+$lang['mail_thanks'] = 'Ihre Daten wurden erfolgreich versandt. Vielen Dank.';
+$lang['template_thanks'] = 'Die Seite wurde angelegt, folgen Sie dem Link um die neue Seite aufzurufen.';
+$lang['summary'] = 'Erstellt mit dem Formular %s';
+$lang['attachmentMailEmpty'] = '(Datei nicht angegeben)';
+$lang['attachmentMailToLarge'] = '(Datei zu groß für Mail-Anhang)';
+$lang['attachmentMailToLarge_userinfo'] = 'Die Datei "%s" ist zu groß als Mail-Anhang (>%s) (E-Mail ohne Datei gesendet)';
+$lang['submit'] = 'Absenden';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/de/settings.php b/platform/www/lib/plugins/bureaucracy/lang/de/settings.php
new file mode 100644
index 0000000..f81c634
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/de/settings.php
@@ -0,0 +1,8 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ */
+$lang['runas'] = 'Affects the template mode. Use this (virtual) user\'s permissions when checking ACLs for reading templates and creating pages.';
+$lang['maxEmailAttachmentSize'] = 'Maximale größe eines Mail-Anhangs in Bytes (pro Datei).';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/en/lang.php b/platform/www/lib/plugins/bureaucracy/lang/en/lang.php
new file mode 100644
index 0000000..3ccd2ff
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/en/lang.php
@@ -0,0 +1,40 @@
+<?php
+
+$lang['e_unknowntype'] = 'Unknown type "%s"';
+$lang['e_unknownaction'] = 'Unknown action "%s"';
+$lang['e_missingargs'] = 'Not enough arguments for %s %s';
+$lang['e_noaction'] = 'No action defined - where should the data be sent to?';
+$lang['e_mail'] = 'Something went wrong with sending that data';
+$lang['e_unknownconstraint'] = 'Unknown field constraint %s';
+$lang['e_labelpage'] = 'Labelpage %s not found';
+
+$lang['e_required'] = '"%s" is required';
+$lang['e_match'] = '"%s" wasn\'t filled in correctly. %s';
+$lang['checkagainst'] = '(Checked against /%s/i)';
+$lang['e_email'] = '"%s" needs to be a valid email address.';
+$lang['e_numeric'] = '"%s" needs to be a number.';
+$lang['e_date'] = '"%s" needs to be a valid date in the format yyyy-mm-dd.';
+$lang['e_time'] = '"%s" needs to be a valid time in the format (h)h:mm(:ss).';
+$lang['e_user'] = '"%s" needs to be the name of an existing user.';
+$lang['e_users'] = '"%s" needs to be a comma-separated list of names of existing users.';
+$lang['e_min'] = '"%s" needs to be greater than %s.';
+$lang['e_max'] = '"%s" needs to be less than %s.';
+
+$lang['e_pagename'] = 'Missing pagename.';
+$lang['e_pageexists'] = 'The page "%s" exists already. Please choose a different pagename.';
+$lang['e_template'] = 'Could not read template "%s". Maybe it doesn\'t exist or you have no read permissions?';
+$lang['e_denied'] = 'You are not allowed to create this page, maybe you forgot to log in?';
+
+$lang['mailsubject'] = 'Form data submitted at %s';
+$lang['mailintro'] = 'The following data was submitted on %s.';
+
+$lang['mail_thanks'] = 'Your data was sent successfully. Thank you.';
+$lang['template_thanks'] = 'The page has been created, follow the link to open it.';
+
+$lang['summary'] = 'Created from the form at %s';
+
+$lang['attachmentMailEmpty'] = '(file not submitted)';
+$lang['attachmentMailToLarge'] = '(file too large for mail attachment)';
+$lang['attachmentMailToLarge_userinfo'] = 'file "%s" too large for mail attachment (>%s) (mail was sent nevertheless)';
+
+$lang['submit'] = 'Submit';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/en/settings.php b/platform/www/lib/plugins/bureaucracy/lang/en/settings.php
new file mode 100644
index 0000000..9c8f365
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/en/settings.php
@@ -0,0 +1,5 @@
+<?php
+
+$lang['runas'] = 'Affects the template mode. Use this (virtual) user\'s permissions when checking ACLs for reading templates and creating pages.';
+$lang['maxEmailAttachmentSize'] = 'Max size of mail attachments in Bytes. (per File)';
+
diff --git a/platform/www/lib/plugins/bureaucracy/lang/es/lang.php b/platform/www/lib/plugins/bureaucracy/lang/es/lang.php
new file mode 100644
index 0000000..52624d7
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/es/lang.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Vicente <tirantet@gmail.com>
+ */
+$lang['e_unknowntype'] = 'Tipo desconocido "%s"';
+$lang['e_unknownaction'] = 'Acción desconocida "%s"';
+$lang['e_missingargs'] = 'Faltan argumentos para %s %s';
+$lang['e_noaction'] = 'Falta definir la acción - ¿Dónde enviamos los datos?';
+$lang['e_mail'] = 'Algún problema al enviar los datos';
+$lang['e_unknownconstraint'] = 'Faltan los límites del campo %s';
+$lang['e_labelpage'] = 'Pagina de LABELS "%s" no encontrada';
+$lang['e_required'] = '"%s" es necesario';
+$lang['e_match'] = '"%s" no esta completado correctamente. %s';
+$lang['checkagainst'] = '(Comprobado con /%s/i)';
+$lang['e_email'] = '"%s" tiene que ser un eMail válido.';
+$lang['e_numeric'] = '"%s" debe ser numérico.';
+$lang['e_date'] = '"%s" debe que ser una fecha válida con formato yyyy-mm-dd';
+$lang['e_time'] = '"%s" debe ser una hora válida con formato (h)h:mm(:ss)';
+$lang['e_user'] = '"%s" debe ser el nombre de un usuario existente.';
+$lang['e_users'] = '"%s" tiene que contener una lista de usuarios existentes separados por comas.';
+$lang['e_min'] = '"%s" debe ser mayor de %s.';
+$lang['e_max'] = '"%s" debe ser menor de %s.';
+$lang['e_pagename'] = 'Falta el nombre de la página.';
+$lang['e_pageexists'] = 'La pagina "%s" existe. Escoja un nombre diferente.';
+$lang['e_template'] = 'No se puede leer la plantilla "%s". O no existe, o no tenemos permisos de lectura.';
+$lang['e_denied'] = 'No tiene permisos para crear la página, ¿Esta logueado?';
+$lang['mailsubject'] = 'Formulario enviado en %s';
+$lang['mailintro'] = 'Los siguientes datos enviados en %s';
+$lang['mail_thanks'] = 'Formulario enviado correctamente. Gracias.';
+$lang['template_thanks'] = 'La página esta creada, siga el enlace para abrirla.';
+$lang['summary'] = 'Creada desde el formulario en %s';
+$lang['attachmentMailEmpty'] = '(fichero no enviado)';
+$lang['attachmentMailToLarge'] = '(fichero demasiado largo para incrustarlo en un eMail)';
+$lang['attachmentMailToLarge_userinfo'] = 'Fichero "%s" demasiado largo para incrustarlo en un eMail (>%s) (eMail enviado de todas formas)';
+$lang['submit'] = 'Enviar';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/es/settings.php b/platform/www/lib/plugins/bureaucracy/lang/es/settings.php
new file mode 100644
index 0000000..e783e78
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/es/settings.php
@@ -0,0 +1,9 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Vicente <tirantet@gmail.com>
+ */
+$lang['runas'] = 'Afecta el modo plantilla. Use los permisos de este usuario (virtual) cuando compruebe los ACLs para leer plantillas y crear páginas.';
+$lang['maxEmailAttachmentSize'] = 'Maximo tamaño, en Bytes, de los elementos incrustados en un eMail. (por fichero)';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/fa/lang.php b/platform/www/lib/plugins/bureaucracy/lang/fa/lang.php
new file mode 100644
index 0000000..95043e6
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/fa/lang.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author nima <nima.hamidian@gmail.com>
+ */
+$lang['e_unknowntype'] = 'نوع ناشناخته "%s"';
+$lang['e_unknownaction'] = 'عمل ناشناخته "%s"';
+$lang['e_missingargs'] = 'آرگومانهای ناکافی برای %s %s';
+$lang['e_noaction'] = 'عملی تعریف نشده است- داده‌ها باید به کجا فرستاده شوند؟';
+$lang['e_mail'] = 'در فرستادن داده‌ها اشکالی پیش آمده است';
+$lang['e_unknownconstraint'] = 'قید فیلد ناشناخته %s';
+$lang['e_labelpage'] = 'صفحه برچسب %s یافته نشد';
+$lang['e_required'] = '"%s" ضروری است';
+$lang['e_match'] = '"%s" به درستی پر نشد. %s';
+$lang['checkagainst'] = '(بررسی شده نسبت به /%s/i)';
+$lang['e_email'] = '"%s" باید یک نشانی ایمیل صحیح باشد.';
+$lang['e_numeric'] = '"%s" باید یک عدد باشد.';
+$lang['e_date'] = '"%s" باید یک تاریخ صحیح با صورت yyyy-mm-dd باشد.';
+$lang['e_time'] = '"%s" باید یک زمان صحیح با صورت (h)h:mm(:ss) باشد.';
+$lang['e_user'] = '"%s" باید نام یک کاربر موجود باشد.';
+$lang['e_users'] = '"%s" باید یک لیست جداشده‌باکاما از نام کاربران موجود باشد.';
+$lang['e_min'] = '"%s" باید بزرگتر از %s باشد.';
+$lang['e_max'] = '"%s" باید کمتر از %s باشد.';
+$lang['e_pagename'] = 'نام صفحه فراموش شده است.';
+$lang['e_pageexists'] = 'صفحه "%s" هم‌اکنون موجود است. لطفاً یک نام صفحه متفاوت انتخاب کنید.';
+$lang['e_template'] = 'امکان خواندن قالب "%s" نبود. شاید وجود ندارد یا شما اجازه خواندن را ندارید.';
+$lang['e_denied'] = 'شما اجازه ایجاد این صفحه را ندارید، نکند فراموش کردید وارد حساب کاربری شوید؟';
+$lang['mailsubject'] = 'داده‌های فُرم در %s ارسال شدند. ';
+$lang['mailintro'] = 'داده‌های زیر روی %s ارسال شدند. ';
+$lang['mail_thanks'] = 'داده‌های شما با موفقیت فرستاده شدند. با تشکر از شما.';
+$lang['template_thanks'] = 'این صفحه ایجاد شده است، برای باز کردن آن روی پیوند کلیک کنید. ';
+$lang['summary'] = 'ایجاد شده از فُرم در %s';
+$lang['attachmentMailEmpty'] = '(فایل ارسال نشد)';
+$lang['attachmentMailToLarge'] = '(فایل برای پیوست شدن به ایمیل بیش از حد بزرگ است)';
+$lang['attachmentMailToLarge_userinfo'] = 'فایل "%s" برای پیوست شدن به ایمیل بیش‌ازحد بزرگ است (>%s)(با این‌حال ایمیل فرستاده شد)';
+$lang['submit'] = 'ارسال';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/fa/settings.php b/platform/www/lib/plugins/bureaucracy/lang/fa/settings.php
new file mode 100644
index 0000000..8bfc3b8
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/fa/settings.php
@@ -0,0 +1,9 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author nima <nima.hamidian@gmail.com>
+ */
+$lang['runas'] = 'روی حالت قالب اثر می‌گذارد. از این اجازه‌های کاربر (مجازی) وقتی استفاده کنید که ACL ها برای خواندن قالبها و ایجاد صفحات بررسی می‌شوند. ';
+$lang['maxEmailAttachmentSize'] = 'اندازه حداکثر پیوست‌های ایمیل بر حسب بایت. (به ازای هر فایل)';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/fr/lang.php b/platform/www/lib/plugins/bureaucracy/lang/fr/lang.php
new file mode 100644
index 0000000..5bae4e0
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/fr/lang.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Schplurtz le Déboulonné <schplurtz@laposte.net>
+ */
+$lang['e_unknowntype'] = 'Type inconu "%s"';
+$lang['e_unknownaction'] = 'Action inconnue "%s"';
+$lang['e_missingargs'] = 'Pas assez d\'arguments pour %s %s';
+$lang['e_noaction'] = 'Pas d\'action définie - que faire des données ?';
+$lang['e_mail'] = 'Erreur lors de l\'envoi des données';
+$lang['e_unknownconstraint'] = 'Contrainte de champ inconue %s';
+$lang['e_labelpage'] = 'Page de label %s non trouvée.';
+$lang['e_required'] = '"%s" est requis';
+$lang['e_match'] = '"%s" n\'est pas remplis correctement. %s';
+$lang['checkagainst'] = '(vérifié avec /%s/i)';
+$lang['e_email'] = '"%s" doit être une adresse de courriel valide.';
+$lang['e_numeric'] = '"%s" doit être un nombre.';
+$lang['e_date'] = '"%s" doit être une date valide au format yyyy-mm-dd.';
+$lang['e_time'] = '"%s" nécessite une heure valide au format (h)h:mm(:ss).';
+$lang['e_user'] = '"%s" doit être le nom d\'un utilisateur existant.';
+$lang['e_users'] = '"%s" doit être une liste à virgules de noms d\'utilisateurs.';
+$lang['e_min'] = '"%s" doit être plus grand que %s.';
+$lang['e_max'] = '"%s" doit être plus petit que %s.';
+$lang['e_pagename'] = 'Nom de page manquant.';
+$lang['e_pageexists'] = 'La page "%s" existe déjà. Veuillez choisir un autre nom.';
+$lang['e_template'] = 'Modèle "%s" introuvable. Il n\'existe pas ou vous n\'avez pas l\'autorisation de lecture.';
+$lang['e_denied'] = 'Vous n\'avez pas le droit de créer cette page, vous êtes vous connecté ?';
+$lang['mailsubject'] = 'Données du formulaire de la page %s';
+$lang['mailintro'] = 'Les données suivantes ont été envoyées le %s.';
+$lang['mail_thanks'] = 'Données envoyées avec succès. Merci.';
+$lang['template_thanks'] = 'La page est créée, suivez le lien pour l\'ouvrir.';
+$lang['summary'] = 'Créé depuis le formulaire %s';
+$lang['attachmentMailEmpty'] = '(fichier non envoyé)';
+$lang['attachmentMailToLarge'] = '(fichier trop grand comme pièce jointe de courriel)';
+$lang['attachmentMailToLarge_userinfo'] = 'fichier "%s" trop grand comme pièce jointe (>%s). Le message est tout de même parti.';
+$lang['submit'] = 'Envoyer';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/fr/settings.php b/platform/www/lib/plugins/bureaucracy/lang/fr/settings.php
new file mode 100644
index 0000000..72031df
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/fr/settings.php
@@ -0,0 +1,9 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Schplurtz le Déboulonné <schplurtz@laposte.net>
+ */
+$lang['runas'] = 'Mode «template» : teste les ACL avec les permissions de cet utilisateur (virtuel) pour la lecture des modèles et la création de page.';
+$lang['maxEmailAttachmentSize'] = 'Taille max en octet des pièces jointes dans les courriels. (par fichier)';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/hr/lang.php b/platform/www/lib/plugins/bureaucracy/lang/hr/lang.php
new file mode 100644
index 0000000..339d3b8
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/hr/lang.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Davor Turkalj <turki.bsc@gmail.com>
+ */
+$lang['e_unknowntype'] = 'Nepoznat tip "%s"';
+$lang['e_unknownaction'] = 'Nepoznata aktivnost "%s"';
+$lang['e_missingargs'] = 'Nema dovoljno argumenata za %s %s';
+$lang['e_noaction'] = 'Nema definirane akcije - gdje podaci trebaju biti poslani?';
+$lang['e_mail'] = 'Nešto je pošlo krivo s slanjem ovih podataka';
+$lang['e_unknownconstraint'] = 'Nepoznato ograničenje polja %s';
+$lang['e_labelpage'] = 'Stranica s labelama %s nije nađena';
+$lang['e_required'] = '"%s" je obvezan';
+$lang['e_match'] = '"%s" nije ispravno popunjen. %s';
+$lang['checkagainst'] = '(Provjereno prema /%s/i)';
+$lang['e_email'] = '"%s" treba biti valjana adresa e-pošte.';
+$lang['e_numeric'] = '"%s" treba biti broj.';
+$lang['e_date'] = '"%s" treba biti valjani datum u obliku gggg-mm-dd.';
+$lang['e_time'] = '"%s" treba biti u valjanom obliku (h)h:mm(:ss).';
+$lang['e_user'] = '"%s" treba biti ime postojećeg korisnika.';
+$lang['e_users'] = '"%s" treba biti zarezom odvojena lista imena postojećih korisnika.';
+$lang['e_min'] = '"%s" treba biti veći od %s.';
+$lang['e_max'] = '"%s" treba biti manji od %s.';
+$lang['e_pagename'] = 'Nedostaje ime stranice.';
+$lang['e_pageexists'] = 'Strnaica "%s" već postoji. Molimo odaberite drugo ime stranice.';
+$lang['e_template'] = 'Nemogu pročitati predložak "%s". Možda ne postoji ili nemate pravo čitanja?';
+$lang['e_denied'] = 'Nije Vam dopušteno stvaranje ove stranice, možda ste se zaboravili prijaviti?';
+$lang['mailsubject'] = 'Podaci proslijeđeni u %s';
+$lang['mailintro'] = 'Slijedeći podaci su proslijeđeni u %s.';
+$lang['mail_thanks'] = 'Vaši podaci su uspješno poslani. Hvala.';
+$lang['template_thanks'] = 'Stranica je kreirana, slijedi vezu za njeno otvaranje.';
+$lang['summary'] = 'Kreirano iz forme u %s';
+$lang['attachmentMailEmpty'] = '(datoteka nije poslana)';
+$lang['attachmentMailToLarge'] = '(datoteka prevelika za prilog pošte)';
+$lang['attachmentMailToLarge_userinfo'] = 'datoteka "%s" prevelika za prilog pošte (>%s) (pošta je ipak poslana)';
+$lang['submit'] = 'Proslijedi';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/hr/settings.php b/platform/www/lib/plugins/bureaucracy/lang/hr/settings.php
new file mode 100644
index 0000000..d9df8dd
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/hr/settings.php
@@ -0,0 +1,9 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Davor Turkalj <turki.bsc@gmail.com>
+ */
+$lang['runas'] = 'Utječe na mod predloška. Koristi ove (virtualne) ovlasti kada provjeravaš ACL za čitanje predloška i stvaranje stranice.';
+$lang['maxEmailAttachmentSize'] = 'Maksimalna veličina priloga pošti u Bajtovima. (po datoteci)';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/it/lang.php b/platform/www/lib/plugins/bureaucracy/lang/it/lang.php
new file mode 100644
index 0000000..dcbbd0c
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/it/lang.php
@@ -0,0 +1,19 @@
+<?php
+
+$lang['e_unknowntype'] = 'Tipo sconosciuto "%s"';
+$lang['e_missingargs'] = 'Gli argomenti specificati non sono sufficenti per %s %s';
+$lang['e_noaction'] = 'Nessuna azione definita - dove devono essere spediti i dati ?';
+$lang['e_mail'] = 'Si sono verificati dei problemi sulla spedizione dei dati';
+
+$lang['e_required'] = '"%s" deve essere specificato';
+$lang['e_match'] = '"%s" non corretto. %s';
+$lang['checkagainst'] = '(Controlla /%s/i)';
+$lang['e_email'] = '"%s" deve essere un indirizzo email valido.';
+$lang['e_numeric'] = '"%s" deve essere un valore numerico.';
+$lang['e_min'] = '"%s" deve essere maggiore di %s.';
+$lang['e_max'] = '"%s" deve essere minore di %s.';
+
+
+$lang['thanks'] = 'Le informazioni sono state inviate. Grazie.';
+$lang['mailsubject'] = 'Dati inviati alle %s';
+$lang['mailintro'] = 'Le seguenti informazioni sono state inviate alle %s.';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/ja/lang.php b/platform/www/lib/plugins/bureaucracy/lang/ja/lang.php
new file mode 100644
index 0000000..5c57791
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/ja/lang.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author HokkaidoPerson <dosankomali@yahoo.co.jp>
+ */
+$lang['e_unknowntype'] = '"%s" という型はありません。';
+$lang['e_unknownaction'] = '不明なアクション「%s」';
+$lang['e_missingargs'] = '%s %s には引数が十分ではありません。';
+$lang['e_noaction'] = 'action が定義されていません - どこにデータを送信するのですか?';
+$lang['e_mail'] = 'データの送信について何かがおかしいです。';
+$lang['e_unknownconstraint'] = '%s という項目制約がありません。';
+$lang['e_labelpage'] = '%s という Labelpage がありません。';
+$lang['e_required'] = '"%s" が必要です。';
+$lang['e_match'] = '"%s" が正しく記入されていません。%s';
+$lang['checkagainst'] = '(/%s/i と照合)';
+$lang['e_email'] = '"%s" は有効なメールアドレスである必要があります。';
+$lang['e_numeric'] = '"%s" は数字である必要があります。';
+$lang['e_date'] = '"%s" は yyyy-mm-dd 形式の日付である必要があります。';
+$lang['e_time'] = '「%s」は、型 (h)h:mm(:ss) に沿った適切な時刻である必要があります。';
+$lang['e_user'] = '"%s" 既存のユーザー名である必要があります。';
+$lang['e_users'] = '"%s" 既存のユーザー名のカンマ区切り一覧である必要があります。';
+$lang['e_min'] = '"%s" は %s より大きい必要があります。';
+$lang['e_max'] = '"%s" は %s より小さい必要があります。';
+$lang['e_pagename'] = 'ページ名がありません。';
+$lang['e_pageexists'] = '"%s" というページは既に存在します。別のページ名を選んで下さい。';
+$lang['e_template'] = '"%s" というテンプレートが読めません。存在しないか読み込み権限がないのではないですか?';
+$lang['e_denied'] = 'このページの作成は許可されません。ログインし忘れていませんか?';
+$lang['mailsubject'] = 'フォームのデータは %s へ送信されました。';
+$lang['mailintro'] = '以下のデータは %s に送信されました。';
+$lang['mail_thanks'] = 'データは正常に送信されました。ありがとう。';
+$lang['template_thanks'] = 'ページは作成されました。開くためにリンクをたどってください。';
+$lang['summary'] = '%s のフォームから作成されました。';
+$lang['attachmentMailEmpty'] = '(ファイル未選択)';
+$lang['attachmentMailToLarge'] = '(メールに添付するにはファイルが大き過ぎます)';
+$lang['attachmentMailToLarge_userinfo'] = 'ファイル「%s」はメールに添付するには大き過ぎます(>%s)(メール自体は送信されました)';
+$lang['submit'] = '送信';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/ja/settings.php b/platform/www/lib/plugins/bureaucracy/lang/ja/settings.php
new file mode 100644
index 0000000..ae1478a
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/ja/settings.php
@@ -0,0 +1,9 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author HokkaidoPerson <dosankomali@yahoo.co.jp>
+ */
+$lang['runas'] = 'テンプレートモードに影響があります。テンプレートを読み込み、ページを作成するために ACL チェックする場合、この(仮想)ユーザーの権限を使用してください。';
+$lang['maxEmailAttachmentSize'] = 'メールに添付するファイルの最大サイズ(バイト数/1ファイルごと)';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/lv/lang.php b/platform/www/lib/plugins/bureaucracy/lang/lv/lang.php
new file mode 100644
index 0000000..167971e
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/lv/lang.php
@@ -0,0 +1,30 @@
+<?php
+
+$lang['e_unknowntype'] = 'Nezināma tipa "%s"';
+$lang['e_missingargs'] = 'Pietrūkst argumentu %s %s';
+$lang['e_noaction'] = 'Nav definēta darbība, kur dati jāsūta vai jāievieto';
+$lang['e_mail'] = 'Kļūme nosūtot datus';
+
+$lang['e_required'] = 'Jāaizpilda "%s" ';
+$lang['e_match'] = 'Nav pareizi aizpildīts "%s" %s';
+$lang['checkagainst'] = '(neatbilst prasībai /%s/i)';
+$lang['e_email'] = '"%s" jābūt derīgai epasta adresei.';
+$lang['e_numeric'] = '"%s" jābūt skaitlim.';
+$lang['e_min'] = '"%s" jābūt lielākam par %s.';
+$lang['e_max'] = '"%s" jābūt mazākam par %s.';
+
+$lang['e_pagename'] = 'Nav lapas nosaukuma.';
+$lang['e_pageexists'] = 'Lapa "%s" jau eksistē. Lūdzu norādīt citu lapas vārdu.';
+$lang['e_template'] = 'Nevar nolasīt šablonu "%s". Varbūt tāda nav vai pietrūkst lasīšanas tiesību?';
+$lang['e_denied'] = 'Jums nav tiesību izveidot šo lapu, varbūt aizmirsāt ielogoties?';
+
+$lang['mailsubject'] = 'Veidlapas dati nosūtīti uz %s';
+$lang['mailintro'] = 'Norādīties dati nosūtīti uz %s.';
+
+$lang['mail_thanks'] = 'Jūsu dati veiksmīgi nosūtīti. Paldies!';
+$lang['template_thanks'] = 'Lapa izveidota, lai to atvērtu lieto šo saiti.';
+
+$lang['summary'] = 'Izveidots no veidlapas %s';
+
+
+$lang['submit'] = 'Saglabāt';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/nl/lang.php b/platform/www/lib/plugins/bureaucracy/lang/nl/lang.php
new file mode 100644
index 0000000..55dd82b
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/nl/lang.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Gerrit Uitslag <klapinklapin@gmail.com>
+ */
+$lang['e_unknowntype'] = 'Onbekend type "%s"';
+$lang['e_unknownaction'] = 'Onbekende actie "%s"';
+$lang['e_missingargs'] = 'Onvoldoende argumenten voor %s %s';
+$lang['e_noaction'] = 'Geen aktie opgegeven - waar moeten de gegevens heen?';
+$lang['e_mail'] = 'Het versturen van de gegevens is mislukt';
+$lang['e_unknownconstraint'] = 'Onbekende veld voorwaarde %s';
+$lang['e_labelpage'] = 'Labelpagina %s is niet gevonden';
+$lang['e_required'] = '"%s" is verplicht';
+$lang['e_match'] = '"%s" heeft een ongeldige waarde. %s';
+$lang['checkagainst'] = '(Moet voldoen aan /%s/i)';
+$lang['e_email'] = '"%s" moet een geldig e-mail adres zijn.';
+$lang['e_numeric'] = '"%s" moet een nummer zijn.';
+$lang['e_date'] = '"%s" moet een geldige datum zijn in het formaat jjjj-mm-dd.';
+$lang['e_time'] = '"%s" moet een geldige tijdstip zijn in het formaat (u)u:mm(:ss)';
+$lang['e_user'] = '"%s" moet de naam van een bestaande gebruiker zijn.';
+$lang['e_users'] = '"%s" moet een komma-gescheiden lijst van bestaande gebruikers zijn.';
+$lang['e_min'] = '"%s" moet groter zijn dan %s.';
+$lang['e_max'] = '"%s" moet kleiner zijn dan %s.';
+$lang['e_pagename'] = 'Pagina naam ontbreekt.';
+$lang['e_pageexists'] = 'De pagina "%s" bestaat al. Kies een andere pagina naam.';
+$lang['e_template'] = 'Kon de template "%s" niet lezen. wellicht bestaat de pagina niet of zijn de rechten onvoldoende?';
+$lang['e_denied'] = 'Onvoldoende rechten om deze pagina te maken, niet ingelogd?';
+$lang['mailsubject'] = 'Formulier gegevens verstuurd op %s';
+$lang['mailintro'] = 'De volgende gegevens zijn verstuurd op %s.';
+$lang['mail_thanks'] = 'De gegevens zijn verstuurt. Bedankt.';
+$lang['template_thanks'] = 'De pagina is aangemaakt, volg de link om hem te openen.';
+$lang['summary'] = 'Gemaakt door het formulier op %s';
+$lang['attachmentMailEmpty'] = '(bestand niet ingediend)';
+$lang['attachmentMailToLarge'] = '(bestand te groot voor een e-mailbijlage)';
+$lang['attachmentMailToLarge_userinfo'] = 'bestand "%s" te groot voor de e-mailbijlage (>%s) (e-mail is niettemin verstuurd)';
+$lang['submit'] = 'Submit';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/nl/settings.php b/platform/www/lib/plugins/bureaucracy/lang/nl/settings.php
new file mode 100644
index 0000000..9a10022
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/nl/settings.php
@@ -0,0 +1,9 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Gerrit Uitslag <klapinklapin@gmail.com>
+ */
+$lang['runas'] = 'Gebruikt in de template mode. Gebruik de rechten van deze (virtuele) gebruiker bij het controleren van de ACL gebruiker voor het lezen van templates en het maken van pagina\'s';
+$lang['maxEmailAttachmentSize'] = 'Max grootte van e-mailbijlages in Bytes. (per bestand)';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/no/lang.php b/platform/www/lib/plugins/bureaucracy/lang/no/lang.php
new file mode 100644
index 0000000..27916f4
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/no/lang.php
@@ -0,0 +1,39 @@
+<?php
+
+$lang['e_unknowntype'] = 'Ukjent type "%s"';
+$lang['e_unknownaction'] = 'Ukjent handling "%s"';
+$lang['e_missingargs'] = 'Ikke nok verdier for %s %s';
+$lang['e_noaction'] = 'Ingen handling valgt - hvor skal dataene sendes til?';
+$lang['e_mail'] = 'Det oppsto en feil ved innsending av dataene';
+$lang['e_unknownconstraint'] = 'Ukjent feltverdi %s';
+$lang['e_labelpage'] = 'Finner ikke siden %s';
+
+$lang['e_required'] = '"%s" er påkrevet';
+$lang['e_match'] = '"%s" var ikke riktig utfylt. %s';
+$lang['checkagainst'] = '(Sjekk mot /%s/i)';
+$lang['e_email'] = '"%s" må være gyldig epostadresse.';
+$lang['e_numeric'] = '"%s" må være et nummer.';
+$lang['e_date'] = '"%s" må være gyldig dato på formatet åååå-mm-dd.';
+$lang['e_time'] = '"%s" må være gyldig tidsformat (t)t:mm(:ss).';
+$lang['e_user'] = '"%s" må være navnet til en eksisterende bruker.';
+$lang['e_users'] = '"%s" må være en komma-separert liste over eksisterende brukere.';
+$lang['e_min'] = '"%s" må være større enn %s.';
+$lang['e_max'] = '"%s" må være mindre enn %s.';
+
+$lang['e_pagename'] = 'Sidenavn mangler.';
+$lang['e_pageexists'] = 'Siden "%s" eksisterer allerede. Velg en anne side.';
+$lang['e_template'] = 'Kan ikke lese malen "%s". Enten finnes den ikke eller så har du ikke leserettigheter?';
+$lang['e_denied'] = 'Du har ikke tillatelse til å opprette denne siden, har du glemt å logge inn?';
+
+$lang['mailsubject'] = 'Skjemaet ble sendt ved %s';
+$lang['mailintro'] = 'Innholdet ble sendt på %s.';
+
+$lang['mail_thanks'] = 'Skjemaet er sendt, takk skal du ha.';
+$lang['template_thanks'] = 'Siden er opprettet, klikk på følgende link for å åpne siden.';
+
+$lang['summary'] = 'Opprettet av skjemaet %s';
+
+$lang['attachmentMailEmpty'] = '(filen er ikke bekreftet)';
+$lang['attachmentMailToLarge'] = '(filen er for stor til å legges ved eposten)';
+
+$lang['submit'] = 'Send';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/no/settings.php b/platform/www/lib/plugins/bureaucracy/lang/no/settings.php
new file mode 100644
index 0000000..70227ce
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/no/settings.php
@@ -0,0 +1,5 @@
+<?php
+
+$lang['runas'] = 'Påvirker malenes virkemåte. Bruk tillatelse for virituell bruker når du sjekker ACL for lesing av maler og opprettelse av sider.';
+$lang['maxEmailAttachmentSize'] = 'Maksimalstørrelse for epostvedlegg i bytes. (pr. fil)';
+
diff --git a/platform/www/lib/plugins/bureaucracy/lang/pt-br/lang.php b/platform/www/lib/plugins/bureaucracy/lang/pt-br/lang.php
new file mode 100644
index 0000000..a3ab322
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/pt-br/lang.php
@@ -0,0 +1,34 @@
+<?php
+
+$lang['e_unknowntype'] = 'Tipo desconhecido "%s".';
+$lang['e_missingargs'] = 'Argumentos insuficientes para %s %s.';
+$lang['e_noaction'] = 'Nenhuma ação definida - para onde deveriam os dados ser enviados?';
+$lang['e_mail'] = 'Ocorreu algum erro com o envio dos dados.';
+$lang['e_unknownconstraint'] = 'Restrição %s de campo desconhecida.';
+
+$lang['e_required'] = '"%s" é requerido.';
+$lang['e_match'] = '"%s" não foi corretamente preenchido. %s';
+$lang['checkagainst'] = '(Comparado com /%s/i)';
+$lang['e_email'] = '"%s" tem de ser um endereço de email válido.';
+$lang['e_numeric'] = '"%s" tem de ser um número.';
+$lang['e_date'] = '"%s" tem de ser uma data válida no formato dd-mm-yyyy.';
+$lang['e_time'] = '"%s" tem de ser um horário válido no formato (h)h:mm(:ss).';
+$lang['e_user'] = '"%s" tem de ser o nome de um usuário existente.';
+$lang['e_users'] = '"%s" tem de ser uma lista de nomes de usuários existentes separados por vírgulas.';
+$lang['e_min'] = '"%s" tem de ser maior que %s.';
+$lang['e_max'] = '"%s" tem de ser menor que %s.';
+
+$lang['e_pagename'] = 'Falta o nome da página.';
+$lang['e_pageexists'] = 'A página "%s" já existe. Escolha outro nome de página.';
+$lang['e_template'] = 'O modelo "%s" não pode ser lido. Talvez não exista ou você não tem permissão de lê-lo?';
+$lang['e_denied'] = 'Você não pode criar esta página. Esqueceu-se de Entrar?';
+
+$lang['mailsubject'] = 'Formulário de dados submetido em %s.';
+$lang['mailintro'] = 'Os dados seguintes foram submetidos em %s.';
+
+$lang['mail_thanks'] = 'Seus dados foram enviados com sucesso. Obrigado.';
+$lang['template_thanks'] = 'A página foi criada, clique no link para abri-la.';
+
+$lang['summary'] = 'Criada a partir do formulário em %s.';
+
+$lang['submit'] = 'Enviar';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/pt/lang.php b/platform/www/lib/plugins/bureaucracy/lang/pt/lang.php
new file mode 100644
index 0000000..3e9913d
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/pt/lang.php
@@ -0,0 +1,37 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Rafael Grando <r.grando@live.com>
+ */
+$lang['e_unknowntype'] = 'Tipo desconhecido "%s"';
+$lang['e_unknownaction'] = 'Ação desconhecida "%s"';
+$lang['e_missingargs'] = 'Argumentos insuficientes para %s %s';
+$lang['e_noaction'] = 'Nenhuma ação definida - para onde os dados devem ser enviados?';
+$lang['e_mail'] = 'Algo deu errado ao enviar esses dados';
+$lang['e_unknownconstraint'] = 'Restrição de campo desconhecida %s';
+$lang['e_labelpage'] = 'Labelpage %s não encontrada';
+$lang['e_required'] = '"%s" é obrigatório';
+$lang['e_match'] = '"%s" não foi preenchido corretamente. %s';
+$lang['checkagainst'] = '(Verificado contra /%s/i)';
+$lang['e_email'] = '"%s" precisa ser um endereço de email válido.';
+$lang['e_numeric'] = '"%s" precisa ser um número.';
+$lang['e_date'] = '"%s" precisa ser uma data válida no formato aaaa-mm-dd.';
+$lang['e_time'] = '"%s" precisa ser um horário válido no formato (h)h:mm:(:ss).';
+$lang['e_user'] = '"%s" precisa ser o nome de um usuário existente.';
+$lang['e_users'] = '"%s" precisa ser uma lista separada por vírgulas de nomes de usuários existentes.';
+$lang['e_min'] = '"%s" precisa ser maior que %s.';
+$lang['e_max'] = '"%s" precisa ser menor que %s.';
+$lang['e_pageexists'] = 'A página "%s" já existe. Por favor, escolha um nome diferente para a página.';
+$lang['e_template'] = 'Não foi possível ler o modelo "%s". Talvez ele não exista ou você não tenha permissões de leitura?';
+$lang['e_denied'] = 'Você não está autorizado a criar esta página. Talvez tenha esquecido de entrar?';
+$lang['mailsubject'] = 'Dados do formulário enviados às %s';
+$lang['mailintro'] = 'Os dados a seguir foram enviados em %s.';
+$lang['mail_thanks'] = 'Seus dados foram enviados com sucesso. Obrigado.';
+$lang['template_thanks'] = 'A página foi criada, siga o link para abri-la.';
+$lang['summary'] = 'Criado do formulário às %s.';
+$lang['attachmentMailEmpty'] = '(arquivo não enviado)';
+$lang['attachmentMailToLarge'] = '(arquivo muito grande para anexar ao email)';
+$lang['attachmentMailToLarge_userinfo'] = 'arquivo "%s" é muito grande para anexar ao email (>%s) (email enviado mesmo assim)';
+$lang['submit'] = 'Enviar';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/pt/settings.php b/platform/www/lib/plugins/bureaucracy/lang/pt/settings.php
new file mode 100644
index 0000000..174eb1c
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/pt/settings.php
@@ -0,0 +1,9 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Rafael Grando <r.grando@live.com>
+ */
+$lang['runas'] = 'Afeta o modo template. Use essas permissões (virtuais) de usuário quando checar ACLs para ler modelos e criar páginas.';
+$lang['maxEmailAttachmentSize'] = 'Tamanho máximo de anexos em bytes. (por arquivo)';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/ru/lang.php b/platform/www/lib/plugins/bureaucracy/lang/ru/lang.php
new file mode 100644
index 0000000..4981407
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/ru/lang.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Yuriy Skalko <yuriy.skalko@gmail.com>
+ */
+$lang['e_unknowntype'] = 'Неизвестный тип "%s"';
+$lang['e_unknownaction'] = 'Неизвестное действие "%s"';
+$lang['e_missingargs'] = 'Недостаточно аргументов для %s %s';
+$lang['e_noaction'] = 'Не указано действие - куда должны быть отправить данные?';
+$lang['e_mail'] = 'Произошла ошибка при отправке данных';
+$lang['e_unknownconstraint'] = 'Неизвестный ограничитель поля %s';
+$lang['e_labelpage'] = 'Метка страницы %s не найдена';
+$lang['e_required'] = '"%s" данное поле обязательно для заполнения';
+$lang['e_match'] = '"%s" заполнено неверно. %s';
+$lang['checkagainst'] = '(Checked against /%s/i)';
+$lang['e_email'] = '"%s" данное поле должно содержать правильный адрес электронной почты.';
+$lang['e_numeric'] = '"%s" данное поле должно содержать число.';
+$lang['e_date'] = '"%s" должно быть допустимой датой в формате гггг-мм-дд.';
+$lang['e_time'] = '"%s" должно быть допустимым временем в формате (ч)ч:мм(:сс).';
+$lang['e_user'] = '"%s" должно быть именем существующего пользователя.';
+$lang['e_users'] = '"%s" должно быть разделенным запятыми списком имен существующих пользователей.';
+$lang['e_min'] = '"%s" данное поле должно быть больше, чем %s.';
+$lang['e_max'] = '"%s" данное поле должно быть меньше, чем %s.';
+$lang['e_pagename'] = 'Отсутствует имя страницы.';
+$lang['e_pageexists'] = 'Страница "%s" уже существует. Пожалуйста, выберите другое имя.';
+$lang['e_template'] = 'Невозможно прочитать шаблон "%s". Возможно, он не существует, или у вас не хватает прав для чтения?';
+$lang['e_denied'] = 'Вам не разрешено создавать эту страницу, возможно, вы забыли войти?';
+$lang['mailsubject'] = 'Данные формы отправлены с %s';
+$lang['mailintro'] = 'Следующие данные отправлены %s.';
+$lang['mail_thanks'] = 'Ваши данные отправлены успешно. Спасибо.';
+$lang['template_thanks'] = 'Страница создана, следуйте по ссылке, чтобы открыть её.';
+$lang['summary'] = 'Создано по форме с %s';
+$lang['attachmentMailEmpty'] = '(файл не отправлен)';
+$lang['attachmentMailToLarge'] = '(файл слишком большой для почтового вложения)';
+$lang['attachmentMailToLarge_userinfo'] = 'файл "%s" слишком большой для почтового вложения (>%s) (но сообщение было отправлено)';
+$lang['submit'] = 'Отправить';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/ru/settings.php b/platform/www/lib/plugins/bureaucracy/lang/ru/settings.php
new file mode 100644
index 0000000..ab9a8fc
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/ru/settings.php
@@ -0,0 +1,9 @@
+<?php
+
+/**
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ *
+ * @author Yuriy Skalko <yuriy.skalko@gmail.com>
+ */
+$lang['runas'] = 'Использовать права (виртуального) пользователя при проверке доступа для чтения шаблонов и создания страниц.';
+$lang['maxEmailAttachmentSize'] = 'Макс. размер почтовых вложений в байтах. (на файл)';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/zh/lang.php b/platform/www/lib/plugins/bureaucracy/lang/zh/lang.php
new file mode 100644
index 0000000..84d6c5b
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/zh/lang.php
@@ -0,0 +1,39 @@
+<?php
+
+$lang['e_unknowntype'] = '未知类型 "%s"';
+$lang['e_unknownaction'] = '未知action "%s"';
+$lang['e_missingargs'] = '参数不足: %s %s';
+$lang['e_noaction'] = '未定义action - 数据要送到哪里去?';
+$lang['e_mail'] = '发送该数据时发生错误';
+$lang['e_unknownconstraint'] = '未知的域范围 %s';
+$lang['e_labelpage'] = '标签页 %s 未找到';
+
+$lang['e_required'] = '需要"%s"';
+$lang['e_match'] = '"%s" 填写错误. %s';
+$lang['checkagainst'] = '(请检查 /%s/i)';
+$lang['e_email'] = '"%s" 应为有效Email地址。';
+$lang['e_numeric'] = '"%s" 必须是数字';
+$lang['e_date'] = '"%s" 应为 yyyy-mm-dd 格式的日期';
+$lang['e_time'] = '"%s" 应为 (h)h:mm(:ss) 格式的时间';
+$lang['e_user'] = '"%s" 应为存在的用户名';
+$lang['e_users'] = '"%s" 应为逗号分隔的用户名列表';
+$lang['e_min'] = '"%s" 应大于 %s.';
+$lang['e_max'] = '"%s" 应小于 %s.';
+
+$lang['e_pagename'] = '未输入文件名';
+$lang['e_pageexists'] = '文件名 "%s" 已存在,请换一个名字。';
+$lang['e_template'] = '无法读取模板 "%s". 也许它不存在或你没有读取权限?';
+$lang['e_denied'] = '你不能创建该页面,也许您忘记登录了?';
+
+$lang['mailsubject'] = '表单数据已向 %s 提交';
+$lang['mailintro'] = '以下数据被提交在 %s.';
+
+$lang['mail_thanks'] = '您的数据发送成功。谢谢。';
+$lang['template_thanks'] = '页面已创建,点击以下链接查看。';
+
+$lang['summary'] = '创建自 %s 的表单';
+
+$lang['attachmentMailEmpty'] = '文件未提交';
+$lang['attachmentMailToLarge'] = '邮件附件过大';
+
+$lang['submit'] = '提交';
diff --git a/platform/www/lib/plugins/bureaucracy/lang/zh/settings.php b/platform/www/lib/plugins/bureaucracy/lang/zh/settings.php
new file mode 100644
index 0000000..6989239
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/lang/zh/settings.php
@@ -0,0 +1,5 @@
+<?php
+
+$lang['runas'] = '在template模式下起效。当读取模板和创建页面需要检查ACLs权限时,使用此(虚拟的)用户权限。';
+$lang['maxEmailAttachmentSize'] = '邮件附件大小上限,以Bytes为单位。(每份附件)';
+
diff --git a/platform/www/lib/plugins/bureaucracy/plugin.info.txt b/platform/www/lib/plugins/bureaucracy/plugin.info.txt
new file mode 100644
index 0000000..279baca
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/plugin.info.txt
@@ -0,0 +1,8 @@
+base bureaucracy
+author Andreas Gohr
+email andi@splitbrain.org
+date 2022-01-24
+name Bureaucracy Plugin
+desc Create forms and generate pages or emails from them
+url https://www.dokuwiki.org/plugin:bureaucracy
+
diff --git a/platform/www/lib/plugins/bureaucracy/script.js b/platform/www/lib/plugins/bureaucracy/script.js
new file mode 100644
index 0000000..06b63f0
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/script.js
@@ -0,0 +1,3 @@
+/* DOKUWIKI:include script/fieldsets.js */
+/* DOKUWIKI:include script/user.js */
+/* DOKUWIKI:include script/datepicker.js */
diff --git a/platform/www/lib/plugins/bureaucracy/script/datepicker.js b/platform/www/lib/plugins/bureaucracy/script/datepicker.js
new file mode 100755
index 0000000..1716cbe
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/script/datepicker.js
@@ -0,0 +1,11 @@
+/**
+ * Init datepicker for all date fields
+ */
+
+jQuery(function(){
+ jQuery('.bureaucracy__plugin .datepicker').datepicker({
+ dateFormat: "yy-mm-dd",
+ changeMonth: true,
+ changeYear: true
+ });
+}); \ No newline at end of file
diff --git a/platform/www/lib/plugins/bureaucracy/script/fieldsets.js b/platform/www/lib/plugins/bureaucracy/script/fieldsets.js
new file mode 100644
index 0000000..2a3c12d
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/script/fieldsets.js
@@ -0,0 +1,84 @@
+/**
+ * Handle display of dependent, i. e. optional fieldsets
+ *
+ * Fieldsets may be defined as dependent on the value of a certain input. In
+ * this case they contain a p element with the CSS class “bureaucracy_depends”.
+ * This p element holds a span with the class “bureaucracy_depends_fname”
+ * and optionally another span with “bureaucracy_depends_fvalue”. They
+ * specify the target input (fname) and the target value for which the fieldset
+ * is to be shown.
+ *
+ * This function adds onchange handlers to the relevant inputs for showing and
+ * heading the respective fieldsets.
+ *
+ * @author Adrian Lang <dokuwiki@cosmocode.de>
+ **/
+
+jQuery(function () {
+
+ jQuery('form.bureaucracy__plugin').each(function () {
+
+ //show/hide fieldset and trigger depending children
+ function updateFieldset(input) {
+ jQuery.each(jQuery(input).data('dparray'), function (i, dp) {
+ var showOrHide =
+ input.parentNode.parentNode.style.display !== 'none' && // input/checkbox is displayed AND
+ ((input.checked === dp.tval) || // ( checkbox is checked
+ (input.type !== 'checkbox' && (dp.tval === true && input.value !== '')) || // OR no checkbox, but input is set
+ input.value === dp.tval); // OR input === dp.tval )
+
+ dp.fset.toggle(showOrHide);
+
+ dp.fset.find('input,select')
+ .each(function () {
+ //toggle required attribute
+ var $inputelem = jQuery(this);
+ if($inputelem.hasClass('required')) {
+ if(showOrHide) {
+ $inputelem.attr('required', 'required');
+ } else {
+ $inputelem.removeAttr('required')
+ }
+ }
+ //update dependencies
+ if ($inputelem.data('dparray')) {
+ $inputelem.change();
+ }
+ });
+ });
+ }
+
+ //look for p (with info about controller) in depending fieldsets
+ jQuery('p.bureaucracy_depends', this)
+ .each(function () {
+ //get controller info
+ var fname = jQuery(this).find('span.bureaucracy_depends_fname').html(),
+ fvalue = jQuery(this).find('span.bureaucracy_depends_fvalue');
+ fvalue = (fvalue.length ? fvalue.html() : true);
+
+ //get controller field and add info and change event to the input that controls depending fieldset
+ var fieldsetinfo = {
+ fset: jQuery(this).parent(),
+ tval: fvalue
+ };
+
+ jQuery("label")
+ .has(":first-child:contains('" + fname + "')").first()
+ .find("select,input:last") //yesno field contains first a hidden input
+ .each(function () {
+ if (!jQuery(this).data('dparray')) {
+ jQuery(this).data('dparray', [fieldsetinfo]);
+ } else {
+ jQuery(this).data('dparray').push(fieldsetinfo);
+ }
+ })
+ .bind('change keyup', function () {
+ updateFieldset(this);
+ })
+ .change();
+
+ })
+ .hide(); //hide p.bureaucracy_depends in fieldset
+
+ });
+});
diff --git a/platform/www/lib/plugins/bureaucracy/script/user.js b/platform/www/lib/plugins/bureaucracy/script/user.js
new file mode 100755
index 0000000..9d5d806
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/script/user.js
@@ -0,0 +1,90 @@
+/**
+ * Provides a list of matching user names while user inputs into a userpicker
+ *
+ * @author Adrian Lang <lang@cosmocode.de>
+ * @author Gerrit Uitslag <klapinklapin@gmail.com>
+ */
+jQuery(function () {
+ /**
+ * Ajax request for user suggestions
+ *
+ * @param {Object} request object, with single 'term' property
+ * @param {Function} response callback, argument: the data array to suggest to the user.
+ * @param {Function} getterm callback, argument: the request Object, returns: search term
+ */
+ function ajaxsource(request, response, getterm) {
+ jQuery.getJSON(
+ DOKU_BASE + 'lib/exe/ajax.php', {
+ call: 'bureaucracy_user_field',
+ search: getterm(request)
+ }, function (data) {
+ response(jQuery.map(data, function (name, user) {
+ return {
+ label: name + ' (' + user + ')',
+ value: user
+ }
+ }))
+ }
+ );
+ }
+
+ function split(val) {
+ return val.split(/,\s*/);
+ }
+
+ function extractLast(term) {
+ return split(term).pop();
+ }
+
+
+ /**
+ * pick one user
+ */
+ jQuery(".userpicker").autocomplete({
+ source: function (request, response) {
+ ajaxsource(request, response, function (req) {
+ return req.term
+ })
+ }
+ });
+
+ /**
+ * pick one or more users
+ */
+ jQuery(".userspicker")
+ // don't navigate away from the field on tab when selecting an item
+ .bind("keydown", function (event) {
+ if (event.keyCode === jQuery.ui.keyCode.TAB &&
+ jQuery(this).data("ui-autocomplete").menu.active) {
+ event.preventDefault();
+ }
+ })
+ .autocomplete({
+ minLength: 0,
+ source: function (request, response) {
+ ajaxsource(request, response, function (req) {
+ return extractLast(req.term)
+ })
+ },
+ search: function () {
+ // custom minLength
+ var term = extractLast(this.value);
+ return term.length >= 2;
+ },
+ focus: function () {
+ // prevent value inserted on focus
+ return false;
+ },
+ select: function (event, ui) {
+ var terms = split(this.value);
+ // remove the current input
+ terms.pop();
+ // add the selected item
+ terms.push(ui.item.value);
+ // add placeholder to get the comma-and-space at the end
+ terms.push("");
+ this.value = terms.join(", ");
+ return false;
+ }
+ });
+});
diff --git a/platform/www/lib/plugins/bureaucracy/style.css b/platform/www/lib/plugins/bureaucracy/style.css
new file mode 100644
index 0000000..966de61
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/style.css
@@ -0,0 +1,101 @@
+/* Success message */
+.dokuwiki div.bureaucracy__plugin {
+ width: 50%;
+ font-size: 120%;
+ padding: 2em;
+}
+
+/* Form */
+.dokuwiki form.bureaucracy__plugin {
+ width: 100%;
+ text-align: center;
+ margin: 2em 0;
+ display: block;
+}
+
+.dokuwiki form.bureaucracy__plugin p {
+ font-size: 90%;
+ margin-top: 0.5em;
+}
+
+.dokuwiki form.bureaucracy__plugin fieldset {
+ width: 80%;
+ text-align: left;
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+.dokuwiki form.bureaucracy__plugin label {
+ display: block;
+ text-align: right;
+ line-height: 2em;
+}
+
+.dokuwiki form.bureaucracy__plugin label>span {
+ display: inline-block;
+ width: 47%;
+ line-height: normal;
+}
+.dokuwiki form.bureaucracy__plugin label.textareafield {
+ text-align: left;
+}
+.dokuwiki form.bureaucracy__plugin label.textareafield>span {
+ width: 100%;
+}
+
+.dokuwiki form.bureaucracy__plugin label input.edit,
+.dokuwiki form.bureaucracy__plugin label select {
+ width: 50%;
+}
+.dokuwiki form.bureaucracy__plugin label input.datepicker,
+.dokuwiki form.bureaucracy__plugin label input.timefield {
+ width: 25%;
+ margin-right: 25%;
+}
+
+.dokuwiki form.bureaucracy__plugin label textarea.edit {
+ width: 100%;
+}
+.dokuwiki form.bureaucracy__plugin label input[type=checkbox] {
+ width: 5%;
+ margin-right: 45%;
+}
+
+.dokuwiki form.bureaucracy__plugin input.button {
+ margin: 3px 0 3px 50%;
+ display: block;
+}
+.dokuwiki form.bureaucracy__plugin label.radiolabel span{
+ width: 100%;
+ text-align: left;
+}
+.dokuwiki form.bureaucracy__plugin label input[type=radio]~span {
+ width: 50%;
+ display: inline-block;
+ text-align: left;
+ line-height: normal;
+}
+
+.dokuwiki form.bureaucracy__plugin label.bureaucracy_error span {
+ color: #F00;
+}
+
+.dokuwiki form.bureaucracy__plugin #plugin__captcha_wrapper label {
+ text-align: left;
+}
+/*responsive - small screen*/
+@media (max-width: 480px) {
+ .dokuwiki form.bureaucracy__plugin label {
+ text-align: left;
+ }
+ .dokuwiki form.bureaucracy__plugin label>span {
+ width: 100%;
+ }
+ .dokuwiki form.bureaucracy__plugin input.button {
+ margin-left: 0;
+ }
+ .dokuwiki form.bureaucracy__plugin label .edit,
+ .dokuwiki form.bureaucracy__plugin label select {
+ width: 100% !important;
+ }
+} \ No newline at end of file
diff --git a/platform/www/lib/plugins/bureaucracy/syntax.php b/platform/www/lib/plugins/bureaucracy/syntax.php
new file mode 100644
index 0000000..154a9ef
--- /dev/null
+++ b/platform/www/lib/plugins/bureaucracy/syntax.php
@@ -0,0 +1,623 @@
+<?php
+/**
+ * Bureaucracy Plugin: Allows flexible creation of forms
+ *
+ * This plugin allows definition of forms in wiki pages. The forms can be
+ * submitted via email or used to create new pages from templates.
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @author Adrian Lang <dokuwiki@cosmocode.de>
+ */
+// must be run within Dokuwiki
+if(!defined('DOKU_INC')) die();
+
+/**
+ * All DokuWiki plugins to extend the parser/rendering mechanism
+ * need to inherit from this class
+ */
+class syntax_plugin_bureaucracy extends DokuWiki_Syntax_Plugin {
+
+ private $form_id = 0;
+ var $patterns = array();
+ var $values = array();
+ var $noreplace = null;
+ var $functions = array();
+
+ /**
+ * Prepare some replacements
+ */
+ public function __construct() {
+ $this->prepareDateTimereplacements();
+ $this->prepareNamespacetemplateReplacements();
+ $this->prepareFunctions();
+ }
+
+ /**
+ * What kind of syntax are we?
+ */
+ public function getType() {
+ return 'substition';
+ }
+
+ /**
+ * What about paragraphs?
+ */
+ public function getPType() {
+ return 'block';
+ }
+
+ /**
+ * Where to sort in?
+ */
+ public function getSort() {
+ return 155;
+ }
+
+ /**
+ * Connect pattern to lexer
+ *
+ * @param string $mode
+ */
+ public function connectTo($mode) {
+ $this->Lexer->addSpecialPattern('<form>.*?</form>', $mode, 'plugin_bureaucracy');
+ }
+
+ /**
+ * Handler to prepare matched data for the rendering process
+ *
+ * @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 bool|array Return an array with all data you want to use in render, false don't add an instruction
+ */
+ public function handle($match, $state, $pos, Doku_Handler $handler) {
+ $match = substr($match, 6, -7); // remove form wrap
+ $lines = explode("\n", $match);
+ $actions = $rawactions = array();
+ $thanks = '';
+ $labels = '';
+
+ // parse the lines into an command/argument array
+ $cmds = array();
+ while(count($lines) > 0) {
+ $line = trim(array_shift($lines));
+ if(!$line) continue;
+ $args = $this->_parse_line($line, $lines);
+ $args[0] = $this->_sanitizeClassName($args[0]);
+
+ if(in_array($args[0], array('action', 'thanks', 'labels'))) {
+ if(count($args) < 2) {
+ msg(sprintf($this->getLang('e_missingargs'), hsc($args[0]), hsc($args[1])), -1);
+ continue;
+ }
+
+ // is action element?
+ if($args[0] == 'action') {
+ array_shift($args);
+ $rawactions[] = array('type' => array_shift($args), 'argv' => $args);
+ continue;
+ }
+
+ // is thank you text?
+ if($args[0] == 'thanks') {
+ $thanks = $args[1];
+ continue;
+ }
+
+ // is labels?
+ if($args[0] == 'labels') {
+ $labels = $args[1];
+ continue;
+ }
+ }
+
+ if(strpos($args[0], '_') === false) {
+ $name = 'bureaucracy_field' . $args[0];
+ } else {
+ //name convention: plugin_componentname
+ $name = $args[0];
+ }
+
+ /** @var helper_plugin_bureaucracy_field $field */
+ $field = $this->loadHelper($name, false);
+ if($field && is_a($field, 'helper_plugin_bureaucracy_field')) {
+ $field->initialize($args);
+ $cmds[] = $field;
+ } else {
+ $evdata = array('fields' => &$cmds, 'args' => $args);
+ $event = new Doku_Event('PLUGIN_BUREAUCRACY_FIELD_UNKNOWN', $evdata);
+ if($event->advise_before()) {
+ msg(sprintf($this->getLang('e_unknowntype'), hsc($name)), -1);
+ }
+ }
+
+ }
+
+ // check if action is available
+ foreach($rawactions as $action) {
+ $action['type'] = $this->_sanitizeClassName($action['type']);
+
+ if(strpos($action['type'], '_') === false) {
+ $action['actionname'] = 'bureaucracy_action' . $action['type'];
+ } else {
+ //name convention for other plugins: plugin_componentname
+ $action['actionname'] = $action['type'];
+ }
+
+ list($plugin, $component) = explode('_', $action['actionname']);
+ $alternativename = $action['type'] . '_'. $action['type'];
+
+ // bureaucracy_action<name> or <plugin>_<componentname>
+ if(!plugin_isdisabled($action['actionname']) || @file_exists(DOKU_PLUGIN . $plugin . '/helper/' . $component . '.php')) {
+ $actions[] = $action;
+
+ // shortcut for other plugins with component name <name>_<name>
+ } elseif(plugin_isdisabled($alternativename) || !@file_exists(DOKU_PLUGIN . $action['type'] . '/helper/' . $action['type'] . '.php')) {
+ $action['actionname'] = $alternativename;
+ $actions[] = $action;
+
+ // not found
+ } else {
+ $evdata = array('actions' => &$actions, 'action' => $action);
+ $event = new Doku_Event('PLUGIN_BUREAUCRACY_ACTION_UNKNOWN', $evdata);
+ if($event->advise_before()) {
+ msg(sprintf($this->getLang('e_unknownaction'), hsc($action['actionname'])), -1);
+ }
+ }
+ }
+
+ // action(s) found?
+ if(count($actions) < 1) {
+ msg($this->getLang('e_noaction'), -1);
+ }
+
+ // set thank you message
+ if(!$thanks) {
+ $thanks = "";
+ foreach($actions as $action) {
+ $thanks .= $this->getLang($action['type'] . '_thanks');
+ }
+ } else {
+ $thanks = hsc($thanks);
+ }
+ return array(
+ 'fields' => $cmds,
+ 'actions' => $actions,
+ 'thanks' => $thanks,
+ 'labels' => $labels
+ );
+ }
+
+ /**
+ * Handles the actual output creation.
+ *
+ * @param string $format output format being rendered
+ * @param Doku_Renderer $R the current renderer object
+ * @param array $data data created by handler()
+ * @return boolean rendered correctly? (however, returned value is not used at the moment)
+ */
+ public function render($format, Doku_Renderer $R, $data) {
+ if($format != 'xhtml') return false;
+ $R->info['cache'] = false; // don't cache
+
+ /**
+ * replace some time and name placeholders in the default values
+ * @var $field helper_plugin_bureaucracy_field
+ */
+ foreach($data['fields'] as &$field) {
+ if(isset($field->opt['value'])) {
+ $field->opt['value'] = $this->replace($field->opt['value']);
+ }
+ }
+
+ if($data['labels']) $this->loadlabels($data);
+
+ $this->form_id++;
+ if(isset($_POST['bureaucracy']) && checkSecurityToken() && $_POST['bureaucracy']['$$id'] == $this->form_id) {
+ $success = $this->_handlepost($data);
+ if($success !== false) {
+ $R->doc .= '<div class="bureaucracy__plugin" id="scroll__here">' . $success . '</div>';
+ return true;
+ }
+ }
+
+ $R->doc .= $this->_htmlform($data['fields']);
+
+ return true;
+ }
+
+ /**
+ * Initializes the labels, loaded from a defined labelpage
+ *
+ * @param array $data all data passed to render()
+ */
+ protected function loadlabels(&$data) {
+ global $INFO;
+ $labelpage = $data['labels'];
+ $exists = false;
+ resolve_pageid($INFO['namespace'], $labelpage, $exists);
+ if(!$exists) {
+ msg(sprintf($this->getLang('e_labelpage'), html_wikilink($labelpage)), -1);
+ return;
+ }
+
+ // parse simple list (first level cdata only)
+ $labels = array();
+ $instructions = p_cached_instructions(wikiFN($labelpage));
+ $inli = 0;
+ $item = '';
+ foreach($instructions as $instruction) {
+ if($instruction[0] == 'listitem_open') {
+ $inli++;
+ continue;
+ }
+ if($inli === 1 && $instruction[0] == 'cdata') {
+ $item .= $instruction[1][0];
+ }
+ if($instruction[0] == 'listitem_close') {
+ $inli--;
+ if($inli === 0) {
+ list($k, $v) = explode('=', $item, 2);
+ $k = trim($k);
+ $v = trim($v);
+ if($k && $v) $labels[$k] = $v;
+ $item = '';
+ }
+ }
+ }
+
+ // apply labels to all fields
+ $len = count($data['fields']);
+ for($i = 0; $i < $len; $i++) {
+ if(isset($data['fields'][$i]->depends_on)) {
+ // translate dependency on fieldsets
+ $label = $data['fields'][$i]->depends_on[0];
+ if(isset($labels[$label])) {
+ $data['fields'][$i]->depends_on[0] = $labels[$label];
+ }
+
+ } else if(isset($data['fields'][$i]->opt['label'])) {
+ // translate field labels
+ $label = $data['fields'][$i]->opt['label'];
+ if(isset($labels[$label])) {
+ $data['fields'][$i]->opt['display'] = $labels[$label];
+ }
+ }
+ }
+
+ if(isset($data['thanks'])) {
+ if(isset($labels[$data['thanks']])) {
+ $data['thanks'] = $labels[$data['thanks']];
+ }
+ }
+
+ }
+
+ /**
+ * Validate posted data, perform action(s)
+ *
+ * @param array $data all data passed to render()
+ * @return bool|string
+ * returns thanks message when fields validated and performed the action(s) succesfully;
+ * otherwise returns false.
+ */
+ private function _handlepost($data) {
+ $success = true;
+ foreach($data['fields'] as $index => $field) {
+ /** @var $field helper_plugin_bureaucracy_field */
+
+ $isValid = true;
+ if($field->getFieldType() === 'file') {
+ $file = array();
+ foreach($_FILES['bureaucracy'] as $key => $value) {
+ $file[$key] = $value[$index];
+ }
+ $isValid = $field->handle_post($file, $data['fields'], $index, $this->form_id);
+
+ } elseif($field->getFieldType() === 'fieldset' || !$field->hidden) {
+ $isValid = $field->handle_post($_POST['bureaucracy'][$index], $data['fields'], $index, $this->form_id);
+ }
+
+ if(!$isValid) {
+ // Do not return instantly to allow validation of all fields.
+ $success = false;
+ }
+ }
+ if(!$success) {
+ return false;
+ }
+
+ $thanks_array = array();
+
+ foreach($data['actions'] as $actionData) {
+ /** @var helper_plugin_bureaucracy_action $action */
+ $action = $this->loadHelper($actionData['actionname'], false);
+
+ // action helper found?
+ if(!$action) {
+ msg(sprintf($this->getLang('e_unknownaction'), hsc($actionData['actionname'])), -1);
+ return false;
+ }
+
+ try {
+ $thanks_array[] = $action->run(
+ $data['fields'],
+ $data['thanks'],
+ $actionData['argv']
+ );
+ } catch(Exception $e) {
+ msg($e->getMessage(), -1);
+ return false;
+ }
+ }
+
+ // Perform after_action hooks
+ foreach($data['fields'] as $field) {
+ $field->after_action();
+ }
+
+ // create thanks string
+ $thanks = implode('', array_unique($thanks_array));
+
+ return $thanks;
+ }
+
+ /**
+ * Create the form
+ *
+ * @param helper_plugin_bureaucracy_field[] $fields array with form fields
+ * @return string html of the form
+ */
+ private function _htmlform($fields) {
+ global $INFO;
+
+ $form = new Doku_Form(array('class' => 'bureaucracy__plugin',
+ 'id' => 'bureaucracy__plugin' . $this->form_id,
+ 'enctype' => 'multipart/form-data'));
+ $form->addHidden('id', $INFO['id']);
+ $form->addHidden('bureaucracy[$$id]', $this->form_id);
+
+ foreach($fields as $id => $field) {
+ $field->renderfield(array('name' => 'bureaucracy[' . $id . ']'), $form, $this->form_id);
+ }
+
+ return $form->getForm();
+ }
+
+ /**
+ * Parse a line into (quoted) arguments
+ * Splits line at spaces, except when quoted
+ *
+ * @author William Fletcher <wfletcher@applestone.co.za>
+ *
+ * @param string $line line to parse
+ * @param array $lines all remaining lines
+ * @return array with all the arguments
+ */
+ private function _parse_line($line, &$lines) {
+ $args = array();
+ $inQuote = false;
+ $escapedQuote = false;
+ $arg = '';
+ do {
+ $len = strlen($line);
+ for($i = 0; $i < $len; $i++) {
+ if($line[$i] == '"') {
+ if($inQuote) {
+ if($escapedQuote) {
+ $arg .= '"';
+ $escapedQuote = false;
+ continue;
+ }
+ if($i + 1 < $len && $line[$i + 1] == '"') {
+ $escapedQuote = true;
+ continue;
+ }
+ array_push($args, $arg);
+ $inQuote = false;
+ $arg = '';
+ continue;
+ } else {
+ $inQuote = true;
+ continue;
+ }
+ } else if($line[$i] == ' ') {
+ if($inQuote) {
+ $arg .= ' ';
+ continue;
+ } else {
+ if(strlen($arg) < 1) continue;
+ array_push($args, $arg);
+ $arg = '';
+ continue;
+ }
+ }
+ $arg .= $line[$i];
+ }
+ if(!$inQuote || count($lines) === 0) break;
+ $line = array_shift($lines);
+ $arg .= "\n";
+ } while(true);
+ if(strlen($arg) > 0) array_push($args, $arg);
+ return $args;
+ }
+
+ /**
+ * Clean class name
+ *
+ * @param string $classname
+ * @return string cleaned name
+ */
+ private function _sanitizeClassName($classname) {
+ return preg_replace('/[^\w\x7f-\xff]/', '', strtolower($classname));
+ }
+
+ /**
+ * Save content in <noreplace> tags into $this->noreplace
+ *
+ * @param string $input The text to work on
+ */
+ protected function noreplace_save($input) {
+ $pattern = '/<noreplace>(.*?)<\/noreplace>/is';
+ //save content of <noreplace> tags
+ preg_match_all($pattern, $input, $matches);
+ $this->noreplace = $matches[1];
+ }
+
+ /**
+ * Apply replacement patterns and values as prepared earlier
+ * (disable $strftime to prevent double replacements with default strftime() replacements in nstemplate)
+ *
+ * @param string $input The text to work on
+ * @param bool $strftime Apply strftime() replacements
+ * @return string processed text
+ */
+ function replace($input, $strftime = true) {
+ //in helper_plugin_struct_field::setVal $input can be an array
+ //just return $input in that case
+ if (!is_string($input)) return $input;
+ if (is_null($this->noreplace)) $this->noreplace_save($input);
+
+ foreach ($this->values as $label => $value) {
+ $pattern = $this->patterns[$label];
+ if (is_callable($value)) {
+ $input = preg_replace_callback(
+ $pattern,
+ $value,
+ $input
+ );
+ } else {
+ $input = preg_replace($pattern, $value, $input);
+ }
+
+ }
+
+ if($strftime) {
+ $input = preg_replace_callback(
+ '/%./',
+ function($m){return strftime($m[0]);},
+ $input
+ );
+ }
+ // user syntax: %%.(.*?)
+ // strftime() is already applied once, so syntax is at this point: %.(.*?)
+ $input = preg_replace_callback(
+ '/@DATE\((.*?)(?:,\s*(.*?))?\)@/',
+ array($this, 'replacedate'),
+ $input
+ );
+
+ //run functions
+ foreach ($this->functions as $name => $callback) {
+ $pattern = '/@' . preg_quote($name) . '\((.*?)\)@/';
+ if (is_callable($callback)) {
+ $input = preg_replace_callback($pattern, function ($matches) use ($callback) {
+ return call_user_func($callback, $matches[1]);
+ }, $input);
+ }
+ }
+
+ //replace <noreplace> tags with their original content
+ $pattern = '/<noreplace>.*?<\/noreplace>/is';
+ if (is_array($this->noreplace)) foreach ($this->noreplace as $nr) {
+ $input = preg_replace($pattern, $nr, $input, 1);
+ }
+
+ return $input;
+ }
+
+ /**
+ * (callback) Replace date by request datestring
+ * e.g. '%m(30-11-1975)' is replaced by '11'
+ *
+ * @param array $match with [0]=>whole match, [1]=> first subpattern, [2] => second subpattern
+ * @return string
+ */
+ function replacedate($match) {
+ global $conf;
+
+ //no 2nd argument for default date format
+ $match[2] = $match[2] ?? $conf['dformat'];
+
+ return strftime($match[2], strtotime($match[1]));
+ }
+
+ /**
+ * Same replacements as applied at template namespaces
+ *
+ * @see parsePageTemplate()
+ */
+ function prepareNamespacetemplateReplacements() {
+ /* @var Input $INPUT */
+ global $INPUT;
+ global $INFO;
+ global $USERINFO;
+ global $conf;
+ global $ID;
+
+ $this->patterns['__formpage_id__'] = '/@FORMPAGE_ID@/';
+ $this->patterns['__formpage_ns__'] = '/@FORMPAGE_NS@/';
+ $this->patterns['__formpage_curns__'] = '/@FORMPAGE_CURNS@/';
+ $this->patterns['__formpage_file__'] = '/@FORMPAGE_FILE@/';
+ $this->patterns['__formpage_!file__'] = '/@FORMPAGE_!FILE@/';
+ $this->patterns['__formpage_!file!__'] = '/@FORMPAGE_!FILE!@/';
+ $this->patterns['__formpage_page__'] = '/@FORMPAGE_PAGE@/';
+ $this->patterns['__formpage_!page__'] = '/@FORMPAGE_!PAGE@/';
+ $this->patterns['__formpage_!!page__'] = '/@FORMPAGE_!!PAGE@/';
+ $this->patterns['__formpage_!page!__'] = '/@FORMPAGE_!PAGE!@/';
+ $this->patterns['__user__'] = '/@USER@/';
+ $this->patterns['__name__'] = '/@NAME@/';
+ $this->patterns['__mail__'] = '/@MAIL@/';
+ $this->patterns['__date__'] = '/@DATE@/';
+
+ // replace placeholders
+ $localid = isset($INFO['id']) ? $INFO['id'] : $ID;
+ $file = noNS($localid);
+ $page = strtr($file, $conf['sepchar'], ' ');
+ $this->values['__formpage_id__'] = $localid;
+ $this->values['__formpage_ns__'] = getNS($localid);
+ $this->values['__formpage_curns__'] = curNS($localid);
+ $this->values['__formpage_file__'] = $file;
+ $this->values['__formpage_!file__'] = utf8_ucfirst($file);
+ $this->values['__formpage_!file!__'] = utf8_strtoupper($file);
+ $this->values['__formpage_page__'] = $page;
+ $this->values['__formpage_!page__'] = utf8_ucfirst($page);
+ $this->values['__formpage_!!page__'] = utf8_ucwords($page);
+ $this->values['__formpage_!page!__'] = utf8_strtoupper($page);
+ $this->values['__user__'] = $INPUT->server->str('REMOTE_USER');
+ $this->values['__name__'] = $USERINFO['name'] ?? '';
+ $this->values['__mail__'] = $USERINFO['mail'] ?? '';
+ $this->values['__date__'] = strftime($conf['dformat']);
+ }
+
+ /**
+ * Date time replacements
+ */
+ function prepareDateTimereplacements() {
+ $this->patterns['__year__'] = '/@YEAR@/';
+ $this->patterns['__month__'] = '/@MONTH@/';
+ $this->patterns['__monthname__'] = '/@MONTHNAME@/';
+ $this->patterns['__day__'] = '/@DAY@/';
+ $this->patterns['__time__'] = '/@TIME@/';
+ $this->patterns['__timesec__'] = '/@TIMESEC@/';
+ $this->values['__year__'] = date('Y');
+ $this->values['__month__'] = date('m');
+ $this->values['__monthname__'] = date('B');
+ $this->values['__day__'] = date('d');
+ $this->values['__time__'] = date('H:i');
+ $this->values['__timesec__'] = date('H:i:s');
+
+ }
+
+ /**
+ * Functions that can be used after replacements
+ */
+ function prepareFunctions() {
+ $this->functions['curNS'] = 'curNS';
+ $this->functions['getNS'] = 'getNS';
+ $this->functions['noNS'] = 'noNS';
+ $this->functions['p_get_first_heading'] = 'p_get_first_heading';
+ }
+}