public function handle_action_act_preprocess(Doku_Event &$event, $param) { global $ID; global $TEXT; global $ACT; global $SUM; global $RANGE; global $REV; $act = $event->data; if ($act != 'dokutranslate_review') { $act = act_clean($act); $act = act_permcheck($act); } # Ignore drafts if the page is being translated # FIXME: Find a way to save $_REQUEST['parid'] into the draft if (@file_exists(metaFN($ID, '.translate')) && in_array($act, array('draft', 'recover'))) { act_draftdel('draftdel'); $ACT = $act = 'edit'; } if ($act == 'save') { # Take over save action if translation is in progress # or we're starting it if (!@file_exists(metaFN($ID, '.translate')) && empty($_REQUEST['translate'])) { return; } if (!checkSecurityToken()) { return; } # We're starting a translation if (!@file_exists(metaFN($ID, '.translate')) && !empty($_REQUEST['translate'])) { # Check if the user has permission to start # translation in this namespace if (!isModerator($ID)) { return; } # Take the event over $event->stopPropagation(); $event->preventDefault(); # Save the data but exit if it fails $ACT = act_save($act); if ($ACT != 'show') { return; } # Page was deleted, exit if (!@file_exists(wikiFN($ID))) { return; } # Prepare data path $datapath = dataPath($ID); io_mkdir_p($datapath, 0755, true); # Backup the original page io_rename(wikiFN($ID), $datapath . '/orig.txt'); # Backup old revisions $revisions = allRevisions($ID); foreach ($revisions as $rev) { $tmp = wikiFN($ID, $rev); io_rename($tmp, $datapath . '/' . basename($tmp)); } # Backup meta files $metas = metaFiles($ID); foreach ($metas as $f) { io_rename($f, $datapath . '/' . basename($f)); } # Generate empty page to hold translated text $data = getCleanInstructions($datapath . '/orig.txt'); saveWikiText($ID, genTranslateFile($data), $SUM, $_REQUEST['minor']); $translateMeta = genMeta(count($data)); # create meta file for current translation state io_saveFile(metaFN($ID, '.translate'), serialize($translateMeta)); # create separate meta file for translation history io_saveFile(metaFN($ID, '.translateHistory'), serialize(array('current' => $translateMeta))); } else { # Translation in progress, take the event over $event->preventDefault(); # Save the data but exit if it fails $ACT = act_save($act); # Save failed, exit if ($ACT != 'show') { return; } # Save successful, update translation metadata $lastrev = getRevisions($ID, 0, 1, 1024); updateMeta($ID, getParID(), $lastrev[0]); } } else { if ($act == 'revert') { # Take over save action if translation is in progress if (!@file_exists(metaFN($ID, '.translate'))) { return; } if (!checkSecurityToken()) { return; } # Translation in progress, take the event over $event->preventDefault(); # Save the data but exit if it fails $revert = $REV; $ACT = act_revert($act); # Revert failed, exit if ($ACT != 'show') { return; } # Revert successful, update translation metadata $lastrev = getRevisions($ID, 0, 1, 1024); updateMeta($ID, getParID(), $lastrev[0], $revert); } else { if (in_array($act, array('edit', 'preview'))) { if (!@file_exists(metaFN($ID, '.translate')) || isset($TEXT)) { return; } $parid = getParID(); $instructions = p_cached_instructions(wikiFN($ID)); $separators = array(); # Build array of paragraph separators foreach ($instructions as $ins) { if ($ins[0] == 'plugin' && $ins[1][0] == 'dokutranslate' && in_array($ins[1][1][0], array(DOKU_LEXER_ENTER, DOKU_LEXER_SPECIAL, DOKU_LEXER_EXIT))) { $separators[] = $ins[1][1]; } } # Validate paragraph ID if ($parid >= count($separators) - 1) { $parid = 0; } # Build range for paragraph $RANGE = strval($separators[$parid][2] + 1) . '-' . strval($separators[$parid + 1][1] - 1); } else { if ($act == 'dokutranslate_review') { # This action is mine $event->stopPropagation(); $event->preventDefault(); # Show the page when done $ACT = 'show'; # Load data $meta = unserialize(io_readFile(metaFN($ID, '.translateHistory'), false)); $parid = getParID(); $writeRev = empty($REV) ? 'current' : intval($REV); $writeRev = empty($meta[$writeRev][$parid]['changed']) ? $writeRev : $meta[$writeRev][$parid]['changed']; $user = $_SERVER['REMOTE_USER']; # Check for permission to write reviews if (!canReview($ID, $meta[$writeRev], $parid)) { return; } # Add review to meta array $data['message'] = $_REQUEST['review']; $data['quality'] = intval($_REQUEST['quality']); $data['incomplete'] = !empty($_REQUEST['incomplete']); $meta[$writeRev][$parid]['reviews'][$user] = $data; # Review applies to latest revision as well if (empty($REV) || $meta['current'][$parid]['changed'] == $writeRev) { $meta['current'][$parid]['reviews'][$user] = $data; io_saveFile(metaFN($ID, '.translate'), serialize($meta['current'])); } # Save metadata io_saveFile(metaFN($ID, '.translateHistory'), serialize($meta)); } } } } }
public function render($mode, Doku_Renderer $renderer, $data) { global $DOKUTRANSLATE_NEST; global $ID; global $ACT; global $TEXT; global $REV; # No metadata rendering if ($mode == 'metadata') { return false; } # Allow exporting the page if (substr($ACT, 0, 7) == 'export_') { # Ignore plugin-specific markup, just let text through if ($data[0] != DOKU_LEXER_UNMATCHED) { return true; } $renderer->cdata($data[1]); return true; # Not exporting, allow only XHTML } else { if ($mode != 'xhtml') { return false; } } # Load instructions for original text on first call if (is_null($this->origIns)) { $DOKUTRANSLATE_NEST++; $this->origIns = getCleanInstructions(dataPath($ID) . '/orig.txt'); $this->meta = loadTranslationMeta($ID); $this->parCounter = 0; $DOKUTRANSLATE_NEST--; } $parid = getParID(); $edithere = in_array($ACT, array('edit', 'preview')) && $parid == $this->parCounter; switch ($data[0]) { # Open the table case DOKU_LEXER_ENTER: $renderer->doc .= '<table width="100%" class="dokutranslate"><tbody><tr>'; $cls = parReviewClass($this->meta, $this->parCounter); # Start the cell with proper review class if (empty($cls)) { $renderer->doc .= '<td width="50%">'; } else { $renderer->doc .= '<td width="50%" class="' . $cls . '">'; } # Paragraph anchor (yes, empty named anchor is valid) $renderer->doc .= "<a name=\"_par{$this->parCounter}\"></a>\n"; # Insert edit form if we're editing the first paragraph if ($edithere) { startEditForm($renderer); } break; # Dump original text and close the row # Dump original text and close the row case DOKU_LEXER_SPECIAL: # Generate edit button if ($ACT == 'show') { if (empty($REV)) { $renderer->doc .= parEditButton($this->parCounter); } $renderer->doc .= $this->_renderReviews($ID, $this->meta, $this->parCounter); # Finish erasure if we're editing this paragraph } else { if ($edithere) { endEditForm($renderer); $renderer->doc .= $this->_renderReviews($ID, $this->meta, $this->parCounter); } } $renderer->doc .= "</td>\n"; if (needsReview($ID, $this->meta, $this->parCounter) || $edithere) { $renderer->doc .= '<td class="reviewme">'; } else { $renderer->doc .= '<td>'; } # If this condition fails, somebody's been messing # with the data if (current($this->origIns) !== FALSE) { $renderer->nest(current($this->origIns)); next($this->origIns); } $renderer->doc .= "</td></tr>\n<tr>"; $this->parCounter++; $cls = parReviewClass($this->meta, $this->parCounter); # Start the cell with proper review class if (empty($cls)) { $renderer->doc .= '<td width="50%">'; } else { $renderer->doc .= '<td width="50%" class="' . $cls . '">'; } # Paragraph anchor (yes, empty named anchor is valid) $renderer->doc .= "<a name=\"_par{$this->parCounter}\"></a>\n"; # Insert edit form if we're editing this paragraph if (in_array($ACT, array('edit', 'preview')) && getParID() == $this->parCounter) { startEditForm($renderer); } break; # Dump the rest of the original text and close the table # Dump the rest of the original text and close the table case DOKU_LEXER_EXIT: # Generate edit button if ($ACT == 'show') { if (empty($REV)) { $renderer->doc .= parEditButton($this->parCounter); } $renderer->doc .= $this->_renderReviews($ID, $this->meta, $this->parCounter); # Finish erasure if we're editing the last paragraph } else { if (in_array($ACT, array('edit', 'preview'))) { $parid = getParID(); if ($parid == $this->parCounter) { endEditForm($renderer); $renderer->doc .= $this->_renderReviews($ID, $this->meta, $this->parCounter); # Invalid paragraph ID, show form here } else { if ($parid > $this->parCounter) { startEditForm($renderer, true); } } } } $renderer->doc .= "</td>\n"; if (needsReview($ID, $this->meta, $this->parCounter) || $edithere) { $renderer->doc .= '<td class="reviewme">'; } else { $renderer->doc .= '<td>'; } # Loop to make sure all remaining text gets dumped # (external edit safety) while (current($this->origIns) !== FALSE) { $renderer->nest(current($this->origIns)); next($this->origIns); } $renderer->doc .= '</td></tr></tbody></table>'; break; # Just sanitize and dump the text # Just sanitize and dump the text default: $renderer->cdata($data[1]); break; } return true; }