*/ // must be run within Dokuwiki use dokuwiki\plugin\prosemirror\parser\LinkNode; if (!defined('DOKU_INC')) { die(); } class action_plugin_prosemirror_ajax 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, 'handleAjax'); $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'switchEditors'); } /** * [Custom event handler which performs action] * * Event: AJAX_CALL_UNKNOWN * * @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 void */ public function handleAjax(Doku_Event $event, $param) { if ($event->data !== 'plugin_prosemirror') { return; } $event->preventDefault(); $event->stopPropagation(); global $INPUT, $ID; $ID = $INPUT->str('id'); $responseData = []; foreach ($INPUT->arr('actions') as $action) { switch ($action) { case 'resolveInternalLink': { $inner = $INPUT->str('inner'); $responseData[$action] = $this->resolveInternalLink($inner, $ID); break; } case 'resolveInterWikiLink': { $inner = $INPUT->str('inner'); list($shortcut, $reference) = explode('>', $inner); $responseData[$action] = $this->resolveInterWikiLink($shortcut, $reference); break; } case 'resolveMedia': { $attrs = $INPUT->arr('attrs'); $responseData[$action] = [ 'data-resolvedHtml' => \dokuwiki\plugin\prosemirror\parser\ImageNode::resolveMedia( $attrs['id'], $attrs['title'], $attrs['align'], $attrs['width'], $attrs['height'], $attrs['cache'], $attrs['linking'] ) ]; break; } case 'resolveImageTitle': { $image = $INPUT->arr('image'); $responseData[$action] = []; $responseData[$action]['data-resolvedImage'] = LinkNode::resolveImageTitle( $ID, $image['id'], $image['title'], $image['align'], $image['width'], $image['height'], $image['cache'] ); break; } case 'resolveRSS': { $attrs = json_decode($INPUT->str('attrs'), true); $responseData[$action] = \dokuwiki\plugin\prosemirror\parser\RSSNode::renderAttrsToHTML($attrs); break; } default: { dbglog('Unknown action: ' . $action, __FILE__ . ': ' . __LINE__); http_status(400, 'unknown action'); return; } } } header('Content-Type: application/json'); echo json_encode($responseData); } protected function resolveInterWikiLink($shortcut, $reference) { $xhtml_renderer = p_get_renderer('xhtml'); $xhtml_renderer->interwiki = getInterwiki(); $url = $xhtml_renderer->_resolveInterWiki($shortcut, $reference, $exits); return [ 'url' => $url, 'resolvedClass' => 'interwikilink interwiki iw_' . $shortcut, ]; } protected function resolveInternalLink($inner, $curId) { if ($inner[0] === '#') { return dokuwiki\plugin\prosemirror\parser\LocalLinkNode::resolveLocalLink($inner, $curId); } return \dokuwiki\plugin\prosemirror\parser\InternalLinkNode::resolveLink($inner, $curId); } /** * [Custom event handler which performs action] * * Event: AJAX_CALL_UNKNOWN * * @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 void */ public function switchEditors(Doku_Event $event, $param) { if ($event->data !== 'plugin_prosemirror_switch_editors') { return; } $event->preventDefault(); $event->stopPropagation(); global $INPUT; if ($INPUT->bool('getJSON')) { $text = $INPUT->str('data'); $instructions = p_get_instructions($text); try { $prosemirrorJSON = p_render('prosemirror', $instructions, $info); } catch (Throwable $e) { $errorMsg = 'Rendering the page\'s syntax for the WYSIWYG editor failed: '; $errorMsg .= $e->getMessage(); /** @var \helper_plugin_prosemirror $helper */ $helper = plugin_load('helper', 'prosemirror'); if ($helper->tryToLogErrorToSentry($e, ['text' => $text])) { $errorMsg .= ' -- The error has been logged to Sentry.'; } else { $errorMsg .= '' . $e->getFile() . ':' . $e->getLine() . ''; $errorMsg .= '
' . $e->getTraceAsString() . '
'; } http_status(500); header('Content-Type: application/json'); echo json_encode(['error' => $errorMsg]); return; } $responseData = [ 'json' => $prosemirrorJSON, ]; } else { /** @var \helper_plugin_prosemirror $helper */ $helper = plugin_load('helper', 'prosemirror'); $json = $INPUT->str('data'); try { $syntax = $helper->getSyntaxFromProsemirrorData($json); } catch (Throwable $e) { $errorMsg = 'Parsing the data generated by Prosemirror failed with message: "'; $errorMsg .= $e->getMessage(); $errorMsg .= '"'; if ($helper->tryToLogErrorToSentry($e, ['json' => $json])) { $errorMsg .= ' -- The error has been logged to Sentry.'; } http_status(500); header('Content-Type: application/json'); echo json_encode(['error' => $errorMsg]); return; } $responseData = [ 'text' => $syntax, ]; } header('Content-Type: application/json'); echo json_encode($responseData); } }