*/ // must be run within Dokuwiki if (!defined('DOKU_INC')) { die(); } //Resolve to absolute page ID use dokuwiki\File\PageResolver; class action_plugin_jsongendoc extends DokuWiki_Action_Plugin { /** * Registers a callback function for a given event * * @param Doku_Event_Handler $controller DokuWiki's event controller object * * @return void */ public function register(Doku_Event_Handler $controller) { $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handle_ajax_call_unknown'); } /** * Handle event AJAX_CALL_UNKNOWN for json_plugin_save_inline and * json_plugin_archive call * * @param Doku_Event $event event object by reference * @param mixed $param [the parameters passed as fifth argument to register_hook() when this * handler was registered] * * @return Ajax response as json */ public function handle_ajax_call_unknown(Doku_Event $event, $param) { if ($event->data !== 'jsongendoc_plugin') { return; } //no other ajax call handlers needed $event->stopPropagation(); $event->preventDefault(); //access additional request variables global $INPUT; $new_page_id = cleanID($INPUT->str('name')); $data = json_decode($INPUT->str('data'), true); $parent_id = strval($data['parent_id']); $mime = strval($data['mime']); $docname_meta = strval($data['docname_meta']); $namespace = strval($data['namespace']); $template_id = cleanID($data['template']); $json = $data['json']; $new_page_exist = $template_exist = false; $resolver = new PageResolver($namespace.':page'); // ':page' will be stripped //resolve tempalate_id if($template_id) { $template_id = $resolver->resolveId($template_id); $template_exist = page_exists($template_id); $template_link = ''.$template_id.''; } //resolve page_id, if page will be stored locally (mime undefined) if(!$mime && $new_page_id) { $new_page_id = $resolver->resolveId($new_page_id); $new_page_exist = page_exists($new_page_id); $new_page_link = ''.$new_page_id.''; $new_page_id_for_template = $new_page_id; } else { //document will be downloaded to the client machine $new_page_link = $new_page_id; $new_page_id_for_template = $template_id; } //verify parameters, existances and rights $err = ''; if(!isset($json)) { $err = $this->getLang('err_json'); } else if($data['template'] && $template_exist === false) { $err = sprintf($this->getLang('err_template_not_exist'), $template_link); } else if($template_id && auth_quickaclcheck($template_id) < AUTH_READ) { $err = sprintf($this->getLang('permision_denied_template'), $template_id); } else if(!$mime) { if(!$new_page_id) { $err = $this->getLang('err_no_page_name'); } else if($new_page_exist === true) { $err = sprintf($this->getLang('err_page_exists'), $new_page_link); } else if(auth_quickaclcheck($new_page_id) < AUTH_CREATE) { $err = sprintf($this->getLang('permision_denied_write'), $new_page_link); } } //load template text from user or default namespace template //and replace standard replacement patterns //https://www.dokuwiki.org/namespace_templates if($err === '') { if($template_exist === true) { //load user template $parsePageTemplate_arg = array('id'=>$new_page_id_for_template, 'tpl'=>rawWiki($template_id)); //perform common page template replacements $new_page_text = parsePageTemplate($parsePageTemplate_arg); } else { //load default template $template_id = 'Namespace Template'; //for info $new_page_text = pageTemplate($new_page_id_for_template); $template_link = $this->external_link('https://www.dokuwiki.org/namespace_templates', 'Namespace Template', 'urlextern'); } if(!$new_page_text) { $err = sprintf($this->getLang('err_empty_template'), $template_link, $new_page_link); } } //statistics $cnt = array( 'sections shown' => 0, 'sections removed' => 0, 'scalars extracted' => 0, 'json extracted' => 0, 'null values' => 0 ); //helper functions from JSON plugin $json_o = $this->loadHelper('json'); //display or remove sections @%$-start (filter)% ... %$end%@ if($err === '') { $new_page_text = preg_replace_callback( '/@(\%\$-start\s*\(([^[\]{}%]*?)\)%)(.*?)%\$end\%@/s', function($matches) use($json_o, $json, &$cnt, &$err) { if($err === '') { list($match, $pattern, $filter, $contents) = array_pad($matches, 4, ''); $filter = $json_o->parse_filter($filter); if(count($filter) > 0) { if($json_o->filter($json, $filter)) { $cnt['sections shown'] ++; return $contents; } else { $cnt['sections removed'] ++; return ''; } } else { $err = printf($this->getLang('err_tpl_section'), $template_link, $pattern); } } return ''; }, $new_page_text ); } //replace patterns @%$ ... %@ if($err === '') { $new_page_text = preg_replace_callback( '/@%\$(.*?)%@/s', function($matches) use($json_o, $json, &$cnt) { list(, $path) = $matches; $var = $json; $tokens = $json_o->parse_tokens($path); //get variable on specified path of the json data foreach($tokens as $tok) { if(is_array($var) && isset($var[$tok])) { $var = $var[$tok]; } else { $var = null; break; } } //return extraced data if(is_bool($var)) { $cnt['scalars extracted'] ++; return $var ? 'true' : 'false'; } else if(is_scalar($var)) { $cnt['scalars extracted'] ++; return strval($var); } else if(is_array($var)) { $cnt['json extracted'] ++; return json_encode($var); } else { $cnt['null values'] ++; return 'null'; } }, $new_page_text ); } //create new file or send error if($err === '') { $response = array( 'response' => 'OK', 'mime' => '', 'msg' => sprintf($this->getLang('file_created_msg'), $new_page_link, $template_link) .'
     ' .sprintf($this->getLang('file_created_stat'), $cnt['sections shown'], $cnt['sections removed'], $cnt['scalars extracted'], $cnt['json extracted'], $cnt['null values'] ) .'
' ); if(!$mime) { //save document as new Dokuwiki page saveWikiText($new_page_id, $new_page_text, sprintf($this->getLang('file_created_summary'), $template_id)); } else { //send data, so they can be downloaded $response['mime'] = $mime; $response['document'] = $new_page_text; } //store autoincrement into metadata of the caller if(strlen($docname_meta) > 0 && preg_match('/^(.+?)(\d+)$/', $new_page_id, $matches)) { list(, $base, $number) = $matches; $base .= str_repeat('0', strlen($number)); if($docname_meta === $base && strlen($parent_id) > 0) { p_set_metadata($parent_id, array('jsongendoc_'.$docname_meta => $number + 1)); } } } else { $response = array( 'response' => 'error', 'msg' => ''.$this->getLang('err').': '.$err.'
' ); } //send response header('Content-Type: application/json'); echo json_encode($response); } }