*/ public function load(string $id): array { $hash = substr(md5($id), 0, 16); $notes_file = $_SERVER['DOCUMENT_ROOT'] . "/backend/notes/" . substr($hash, 0, 2) . "/$hash"; // Open the note file for reading and get the data (12KB) // ..if it exists if (!file_exists($notes_file)) { return []; } $notes = []; if ($fp = @fopen($notes_file, "r")) { while (!feof($fp)) { $line = chop(fgets($fp, 12288)); if ($line == "") { continue; } @list($id, $sect, $rate, $ts, $user, $note, $up, $down) = explode("|", $line); $notes[$id] = new UserNote($id, $sect, $rate, $ts, $user, base64_decode($note, true), (int) $up, (int) $down); } fclose($fp); } return $notes; } /** * Print out all user notes for this manual page * * @param array $notes */ public function display($notes):void { global $LANG; // Get needed values list($filename) = $GLOBALS['PGI']['this']; // Drop file extension from the name if (substr($filename, -4) == '.php') { $filename = substr($filename, 0, -4); } $sorter = new Sorter(); $sorter->sort($notes); $addNote = autogen('add_a_note', $LANG); $repo = strtolower($LANG); // Link target to add a note to the current manual page, // and it's extended form with a [+] image $addnotelink = '/manual/add-note.php?sect=' . $filename . '&repo=' . $repo . '&redirect=' . $_SERVER['BASE_HREF']; $addnotesnippet = make_link( $addnotelink, "+$addNote", ); $num_notes = count($notes); $noteCountHtml = ''; if ($num_notes) { $noteCountHtml = "$num_notes note" . ($num_notes == 1 ? '' : 's') . ""; } $userContributedNotes = autogen('user_contributed_notes', $LANG); echo <<
{$addnotesnippet}

$userContributedNotes {$noteCountHtml}

END_USERNOTE_HEADER; // If we have no notes, then inform the user if ($num_notes === 0) { $noUserContributedNotes = autogen('no_user_notes', $LANG); echo "\n
$noUserContributedNotes
"; } else { // If we have notes, print them out echo '
'; foreach ($notes as $note) { $this->displaySingle($note); } echo "
\n"; echo "
$addnotesnippet
\n"; } echo ""; } /** * Print out one user note entry */ public function displaySingle(UserNote $note, $voteOption = true): void { if ($note->user) { $name = "\n " . htmlspecialchars($note->user) . ""; } else { $name = "Anonymous"; } $name = ($note->id ? "\n id}\" class=\"name\">$nameid}\"> ¶" : "\n $name"); // New date style will be relative time $date = new \DateTime("@{$note->ts}"); $datestr = $this->relTime($date); $fdatestr = $date->format("Y-m-d h:i"); $text = $this->cleanContent($note->text); // Calculate note rating by up/down votes $vote = $note->upvotes - $note->downvotes; $p = floor(($note->upvotes / (($note->upvotes + $note->downvotes) ?: 1)) * 100); $rate = !$p && !($note->upvotes + $note->downvotes) ? "no votes..." : "$p% like this..."; // Vote User Notes Div if ($voteOption) { list($redir_filename) = $GLOBALS['PGI']['this']; if (substr($redir_filename, -4) == '.php') { $redir_filename = substr($redir_filename, 0, -4); } $rredir_filename = urlencode($redir_filename); $votediv = <<
up
{$vote}
VOTEDIV; } else { $votediv = null; } // If the viewer is logged in, show admin options if (isset($_COOKIE['IS_DEV']) && $note->id) { $admin = "\n \n " . $this->makePopupLink( 'https://main.php.net/manage/user-notes.php?action=edit+' . $note->id, 'edit note', 'admin', 'scrollbars=yes,width=650,height=400', ) . "\n " . $this->makePopupLink( 'https://main.php.net/manage/user-notes.php?action=reject+' . $note->id, 'reject note', 'admin', 'scrollbars=no,width=300,height=200', ) . "\n " . $this->makePopupLink( 'https://main.php.net/manage/user-notes.php?action=delete+' . $note->id, 'delete note', 'admin', 'scrollbars=no,width=300,height=200', ) . "\n "; } else { $admin = ''; } echo <<{$votediv}{$name}{$admin}
{$datestr}
{$text}
USER_NOTE_TEXT; } // Clean out the content of one user note for printing to HTML private function cleanContent(string $text): string { // Highlight PHP source $text = highlight_php(trim($text), true); // Turn urls into links return preg_replace( '!((mailto:|(https?|ftp|nntp|news)://).*?)(\s|<|\)|"|\\\\|\'|$)!', '\1\4', $text, ); } /** * This function takes a DateTime object and returns a formated string of the time difference relative to now */ private function relTime(\DateTime $date): string { $current = new \DateTime(); $diff = $current->diff($date); $units = ["year" => $diff->format("%y"), "month" => $diff->format("%m"), "day" => $diff->format("%d"), "hour" => $diff->format("%h"), "minute" => $diff->format("%i"), "second" => $diff->format("%s"), ]; $out = "just now..."; foreach ($units as $unit => $amount) { if (empty($amount)) { continue; } $out = $amount . " " . ($amount == 1 ? $unit : $unit . "s") . " ago"; break; } return $out; } /** * Return a hyperlink to something, within the site, that pops up a new window */ private function makePopupLink(string $url, string $linktext = '', string $target = '', string $windowprops = ''): string { return sprintf("%s", htmlspecialchars($url, ENT_QUOTES | ENT_IGNORE), ($target ?: "_new"), htmlspecialchars($url, ENT_QUOTES | ENT_IGNORE), ($target ?: "_new"), $windowprops, ($linktext ?: $url), ); } }