/** * Fetch the value to display changes in artifact history * @param array $from the value(s) *before* * @param array $to the value(s) *after* * @return string */ public function fetchHistory($artifact, $from, $to) { $from_value = $this->getValue($from['value_id']); $from_value = isset($from_value['value']) ? $from_value['value'] : ''; $to_value = $this->getValue($to['value_id']); $to_value = isset($to_value['value']) ? $to_value['value'] : ''; $callback = array($this, '_filter_html_callback'); $d = new Codendi_Diff(array_map($callback, explode("\n", $from_value)), array_map($callback, explode("\n", $to_value))); $f = new Codendi_HtmlUnifiedDiffFormatter(); $diff = $f->format($d); return $diff ? $diff : '<em>No changes</em>'; }
/** * Format the changes * * @param changes: array of changes * @param $field_perm an array with the permission associated to each field. false to no check perms * @param string $artifact_href The direct link to the artifact * @param $visible_change only needed when using permissions. Returns true if there is any change * that the user has permission to see * * @return string */ function formatChangesHTML($changes, $field_perm, $artifact_href, &$visible_change) { global $art_field_fact, $Language; $group_id = $this->ArtifactType->getGroupID(); $visible_change = false; $out = ''; $out_com = ''; $out_ch = ''; reset($changes); $fmt = "%20s | %-25s | %s" . $GLOBALS['sys_lf']; $hp = $this->getHTMLPurifier(); $out .= '<h2>' . $Language->getText('tracker_include_artifact', 'mail_latest_modifications') . '</h2>'; $out .= ' <div class="tracker_artifact_followup_header"> <div class="tracker_artifact_followup_title"> <span class="tracker_artifact_followup_title_user">'; if ($this->hasFieldPermission($field_perm, 'assigned_to') || $this->hasFieldPermission($field_perm, 'multi_assigned_to') || !isset($field_perm['assigned_to']) && !isset($field_perm['multi_assigned_to'])) { $user = UserManager::instance()->getCurrentUser(); if ($user->isLoggedIn()) { $out .= '<a href="mailto:' . $hp->purify($user->getEmail()) . '">' . $hp->purify($user->getRealName()) . ' (' . $hp->purify($user->getUserName()) . ')</a>'; } else { $out = $Language->getText('tracker_include_artifact', 'anon_user'); } } $timezone = ''; if ($user->getId() != 0) { $timezone = ' (' . $user->getTimezone() . ')'; } $out .= ' </span> </div> <div class="tracker_artifact_followup_date">' . format_date($GLOBALS['Language']->getText('system', 'datefmt'), $_SERVER['REQUEST_TIME']) . $timezone . '</div> </div> <div class="tracker_artifact_followup_avatar"> ' . $user->fetchHtmlAvatar() . ' </div> <div class="tracker_artifact_followup_content"> <div class="tracker_artifact_followup_comment">'; //Process special cases first: follow-up comment if (!empty($changes['comment'])) { $visible_change = true; if (!empty($changes['comment']['type']) && $changes['comment']['type'] != $Language->getText('global', 'none')) { $out_com .= "<strong>[" . $changes['comment']['type'] . "]</strong><br />"; } $out_com .= '<div class="tracker_artifact_followup_comment_body">'; $out_com .= $this->formatFollowUp($group_id, $changes['comment']['format'], $changes['comment']['add'], self::OUTPUT_BROWSER); $out_com .= '</div>'; unset($changes['comment']); } //Process special cases first: file attachment if (!empty($changes['attach'])) { $visible_change = true; $out_ch .= '<tr>'; $out_ch .= '<td valign="top"><strong>' . $Language->getText('tracker_include_artifact', 'add_attachment') . '</strong></td>'; $out_ch .= '<td valign="top"><a href="' . $changes['attach']['href'] . '">' . $hp->purify($changes['attach']['name']) . '</a> (' . size_readable($changes['attach']['size']) . ')</td>'; $out_ch .= '</tr>'; unset($changes['attach']); } // All the rest of the fields now reset($changes); foreach ($changes as $field_name => $h) { // If both removed and added items are empty skip - Sanity check if ((!empty($h['del']) || !empty($h['add'])) && $this->hasFieldPermission($field_perm, $field_name)) { $visible_change = true; $label = $field_name; $field = $art_field_fact->getFieldFromName($field_name); if ($field) { $label = $field->getLabel(); if (isset($h['del'])) { $h['del'] = SimpleSanitizer::unsanitize(util_unconvert_htmlspecialchars($h['del'])); } if (isset($h['add'])) { $h['add'] = SimpleSanitizer::unsanitize(util_unconvert_htmlspecialchars($h['add'])); } } $out_ch .= '<tr>'; $out_ch .= ' <td valign="top" nowrap="nowrap"><ul style="margin:0; padding:0; margin-left:1.5em; "><li><strong>' . $hp->purify(SimpleSanitizer::unsanitize($label)) . ': </strong></li></ul></td>'; $out_ch .= ' <td valign="top">'; if ($field && ($field->getDisplayType() == 'TA' || $field->getDisplayType() == 'TF')) { $before = explode("\n", $h['del']); $after = explode("\n", $h['add']); $callback = array(Codendi_HTMLPurifier::instance(), 'purify'); $d = new Codendi_Diff(array_map($callback, $before, array_fill(0, count($before), CODENDI_PURIFIER_CONVERT_HTML)), array_map($callback, $after, array_fill(0, count($after), CODENDI_PURIFIER_CONVERT_HTML))); $f = new Codendi_HtmlUnifiedDiffFormatter(2); $diff = $f->format($d); if ($diff) { $out_ch .= '<div class="diff">' . $diff . '</div>'; } } else { $before = '<del>' . $hp->purify($h['del']) . '</del>'; $after = '<ins>' . $hp->purify($h['add']) . '</ins>'; if ($field && $field->getDisplayType() == 'MB') { if (strlen($before) != 11) { //'<del></del>' => empty $out_ch .= $before; } if (strlen($before) != 11 && strlen($after) != 11) { //'<ins></ins>' => empty $out_ch .= ' ± '; } if (strlen($after) != 11) { //'<ins></ins>' => empty $out_ch .= $after; } } else { $out_ch .= $before; $out_ch .= ' → '; $out_ch .= $after; } } $out_ch .= '</td>'; $out_ch .= '</tr>'; } } if ($out_ch) { $out_ch = '<div class="tracker_artifact_followup_comment_changes">' . $Language->getText('tracker_include_artifact', 'mail_changes') . '<table cellpadding="0" border="0" cellspacing="0" class="artifact_changes">' . $out_ch . '</table> </div>'; } $out .= $out_com . $out_ch; $out .= ' </div> </div> <div style="clear:both;"></div>'; $out .= $this->fetchHtmlAnswerButton($artifact_href); return $out; }
private function getFormatedDiff($previous, $next) { $callback = array(Codendi_HTMLPurifier::instance(), 'purify'); $formater = new Codendi_HtmlUnifiedDiffFormatter(); $diff = new Codendi_Diff(array_map($callback, $previous, array_fill(0, count($previous), CODENDI_PURIFIER_CONVERT_HTML)), array_map($callback, $next, array_fill(0, count($next), CODENDI_PURIFIER_CONVERT_HTML))); return $formater->format($diff); }
public function testHtmlUnifiedDiffFormatter_MultipleDiffs() { $formatter = new Codendi_HtmlUnifiedDiffFormatter(0); $this->assertEqual($formatter->format(new Codendi_Diff($this->f, $this->g)), '<div class="block">' . '<div class="difftext">' . '<div class="original">' . '<tt class="prefix">-</tt>Line <del>1</del> </div>' . '</div>' . '<div class="difftext">' . '<div class="final">' . '<tt class="prefix">+</tt>Line <ins>10</ins> </div>' . '</div>' . '</div>' . '<div class="block">' . '<tt>[...]</tt>' . '<div class="difftext">' . '<div class="original">' . '<tt class="prefix">-</tt>Line <del>5</del> </div>' . '</div>' . '<div class="difftext">' . '<div class="final">' . '<tt class="prefix">+</tt>Line <ins>50</ins> </div>' . '</div>' . '</div>'); }
protected function diff($before, $after) { $callback = array($this, '_filter_html_callback'); $before = array_map($callback, explode("\n", $before)); $after = array_map($callback, explode("\n", $after)); $d = new Codendi_Diff($before, $after); $f = new Codendi_HtmlUnifiedDiffFormatter(); $diff = $f->format($d); return $diff ? $diff : '<em>No changes</em>'; }
/** @return string */ private function describeStringDifferenceAsADiff($first, $second, $identical) { if (is_object($second) || is_array($second)) { return; } $first = explode(PHP_EOL, $first); $second = explode(PHP_EOL, $second); $diff = new Codendi_Diff($first, $second); $unified = new Codendi_HtmlUnifiedDiffFormatter(); return $unified->format($diff); }
/** * Display the diff in changeset * * @return string The text to display */ public function fetchDiff($previous, $next, $format) { $string = ''; switch ($format) { case 'html': $callback = array(Codendi_HTMLPurifier::instance(), 'purify'); $d = new Codendi_Diff(array_map($callback, $previous, array_fill(0, count($previous), CODENDI_PURIFIER_CONVERT_HTML)), array_map($callback, $next, array_fill(0, count($next), CODENDI_PURIFIER_CONVERT_HTML))); $f = new Codendi_HtmlUnifiedDiffFormatter(); $diff = $f->format($d); if ($diff) { $string .= '<div class="diff">' . $diff . '</div>'; } break; case 'text': $diff = new Codendi_Diff($previous, $next); $f = new Codendi_UnifiedDiffFormatter(); $string .= PHP_EOL . $f->format($diff); break; default: break; } return $string; }