public static function getPage_Review($contents, $containers) { $repositoryID = self::validateID(self::getDataGET('project'), true); $languageID = self::validateID(self::getDataGET('language'), true); $repositoryData = Database::getRepositoryData($repositoryID); $languageData = Database::getLanguageData($languageID); if (empty($repositoryData)) { self::addBreadcrumbItem(URL::toProject($repositoryID), 'Project not found'); self::setTitle('Project not found'); $contents[] = new UI_Heading('Project not found', true); $contents[] = new UI_Paragraph('We\'re sorry, but we could not find the project that you requested.'); $contents[] = new UI_Paragraph('Please check if you have made any typing errors.'); } else { if (Authentication::getUserID() <= 0) { self::setTitle($repositoryData['name']); $contents[] = new UI_Heading(htmlspecialchars($repositoryData['name']), true); $contents[] = self::getLoginForm(); } else { $isAllowedToReview = Repository::hasUserPermissions(Authentication::getUserID(), $repositoryID, $repositoryData, Repository::ROLE_MODERATOR); self::addBreadcrumbItem(URL::toReview($repositoryID), 'Review'); if (empty($languageData)) { // review index page for this repository self::setTitle('Review contributions'); $contents[] = new UI_Heading('Review contributions', true); if ($isAllowedToReview) { $table = new UI_Table(array('Language', 'Review')); $table->setColumnPriorities(9, 3); $pendingLanguages = Database::getPendingEditsByRepository($repositoryID); if (count($pendingLanguages) > 0) { foreach ($pendingLanguages as $pendingLanguage) { $reviewURL = URL::toReviewLanguage($repositoryID, $pendingLanguage['languageID']); $linkedName = new UI_Link(Language::getLanguageNameFull($pendingLanguage['languageID']), $reviewURL, UI_Link::TYPE_UNIMPORTANT); $pendingCount = new UI_Link($pendingLanguage['COUNT(*)'], $reviewURL, UI_Link::TYPE_INFO); $table->addRow(array($linkedName->getHTML(), $pendingCount->getHTML())); } } else { $table->addRow(array('No pending contributions', 'No pending contributions')); } $contents[] = $table; } else { $contents[] = new UI_Paragraph('Only administrators, developers and moderators of this project are allowed to review contributions.'); } } else { // single-language review details page for this repository $editID = self::validateID(self::getDataGET('edit'), true); if ($editID <= 0) { $currentPageURL = URL::toReviewLanguage($repositoryID, $languageID); } else { $currentPageURL = URL::toReviewLanguage($repositoryID, $languageID, $editID); } self::addBreadcrumbItem(htmlspecialchars($currentPageURL), Language::getLanguageNameFull($languageID)); self::setTitle($languageData->getNameFull()); if ($editID <= 0) { $editData = Database::getPendingEdit($repositoryID, $languageID); } else { $editData = Database::getPendingEdit($repositoryID, $languageID, $editID); } if (empty($editData)) { // no edits available for review (anymore) if ($isAllowedToReview) { // user is a staff member allowed to review phrases UI::redirectToURL(URL::toReview($repositoryID)); // redirect to review index page } else { // user is a guest taking part in the discussion only $contents[] = new UI_Heading($languageData->getNameFull(), true); $contents[] = new UI_Paragraph('This link has expired and is not valid anymore.'); $contents[] = new UI_Paragraph('The discussion has been closed. Thanks for your collaboration!'); } } else { // edits available for review $form = new UI_Form(htmlspecialchars($currentPageURL), false); $table = new UI_Table(array('', '')); $table->setColumnPriorities(3, 9); $contributorName = empty($editData[0]['real_name']) ? '<span class="text-muted">' . htmlspecialchars($editData[0]['username']) . '</span>' : htmlspecialchars($editData[0]['real_name']) . ' <span class="text-muted">(' . htmlspecialchars($editData[0]['username']) . ')</span>'; $buttonApprove = new UI_Form_Button('Approve', UI_Link::TYPE_SUCCESS, UI_Form_Button::ACTION_SUBMIT, 'review[action]', 'approve'); $buttonReviewLater = new UI_Form_Button('Review later', UI_Link::TYPE_UNIMPORTANT, UI_Form_Button::ACTION_SUBMIT, 'review[action]', 'reviewLater'); $buttonReject = new UI_Form_Button('Reject', UI_Link::TYPE_WARNING, UI_Form_Button::ACTION_SUBMIT, 'review[action]', 'reject'); $buttonApproveAllByContributor = new UI_Form_Button('Approve all from this contributor', UI_Link::TYPE_SUCCESS, UI_Form_Button::ACTION_SUBMIT, 'review[action]', 'approveAllFromThisContributor', 'return confirm(\'Are you sure you want to execute this batch operation? Danger: Validity checks (e.g. placeholders, whitespace, HTML) will not be performed!\');'); $buttonRejectAllByContributor = new UI_Form_Button('Reject all from this contributor', UI_Link::TYPE_DANGER, UI_Form_Button::ACTION_SUBMIT, 'review[action]', 'rejectAllFromThisContributor', 'return confirm(\'Are you sure you want to execute this batch operation?\');'); $actionButtons = new UI_Form_ButtonGroup(array($buttonApprove, $buttonReviewLater, $buttonReject), true); if ($isAllowedToReview) { $newValueEdit = new UI_Form_Textarea('', 'review[newValue]', $editData[0]['suggestedValue'], '', true, htmlspecialchars($editData[0]['suggestedValue']), UI_Form_Textarea::getOptimalRowCount($editData[0]['suggestedValue'], 2), Language::isLanguageRTL($languageID)); $newValueHTML = $newValueEdit->getHTML(); } else { $newValueHTML = '<span dir="' . (Language::isLanguageRTL($languageID) ? 'rtl' : 'ltr') . '">' . nl2br(htmlspecialchars($editData[0]['suggestedValue'])) . '</span>'; } $referencedPhrase = Phrase::create(0, $editData[0]['phraseKey'], $editData[0]['payload']); $previousPhraseData = Database::getPhrase($repositoryID, $languageID, $editData[0]['phraseKey']); if (empty($previousPhraseData)) { $previousPhrase = Phrase::create(0, $editData[0]['phraseKey'], $editData[0]['payload'], 0, true); } else { $previousPhrase = Phrase::create(0, $editData[0]['phraseKey'], $previousPhraseData['payload']); } $valuesReference = $referencedPhrase->getPhraseValues(); $valueReference = isset($valuesReference[$editData[0]['phraseSubKey']]) && is_string($valuesReference[$editData[0]['phraseSubKey']]) ? $valuesReference[$editData[0]['phraseSubKey']] : ''; $valuesPrevious = $previousPhrase->getPhraseValues(); $valuePrevious = isset($valuesPrevious[$editData[0]['phraseSubKey']]) && is_string($valuesPrevious[$editData[0]['phraseSubKey']]) ? trim($valuesPrevious[$editData[0]['phraseSubKey']]) : ''; $pendingEditsCount = Database::getPendingEditsByRepositoryAndLanguageCount($repositoryID, $languageID); $pendingEditsCountHTML = $pendingEditsCount . ' edit' . ($pendingEditsCount == 1 ? '' : 's') . ' to review'; $contents[] = new UI_Heading($languageData->getNameFull(), true, 1, $pendingEditsCountHTML); // mark placeholders and HTML tags in the reference phrase $phraseWithMarkedEntities = htmlspecialchars($valueReference); $phraseWithMarkedEntities = Phrase::markEntities($phraseWithMarkedEntities, Phrase_Android::getPlaceholders($valueReference), 'text-primary', true); $phraseWithMarkedEntities = Phrase::markEntities($phraseWithMarkedEntities, Phrase_Android::getHTMLTags($valueReference), 'text-success', true); // mark placeholders and HTML tags in the current (old) value of the phrase $originalWithMarkedEntities = htmlspecialchars($valuePrevious); $originalWithMarkedEntities = Phrase::markEntities($originalWithMarkedEntities, Phrase_Android::getPlaceholders($valueReference), 'text-primary', true); $originalWithMarkedEntities = Phrase::markEntities($originalWithMarkedEntities, Phrase_Android::getHTMLTags($valueReference), 'text-success', true); $fullyQualifiedName = Phrase_Android::getFullyQualifiedName($referencedPhrase, $editData[0]['phraseSubKey']); $fullyQualifiedNameHTML = '<span dir="ltr" class="small" style="display:block; color:#999; margin-top:4px;">' . htmlspecialchars($fullyQualifiedName) . '</span>'; $translateBackLink = self::linkToTranslationService('Check', $languageID, $repositoryData['defaultLanguage'], $editData[0]['suggestedValue']); $translateBackLink->setSize(UI_Link::SIZE_SMALL); $table->addRow(array('<strong>' . Language::getLanguageNameFull($repositoryData['defaultLanguage']) . '</strong>' . $fullyQualifiedNameHTML, '<span dir="' . (Language::isLanguageRTL($repositoryData['defaultLanguage']) ? 'rtl' : 'ltr') . '">' . nl2br($phraseWithMarkedEntities) . '</span>')); $table->addRow(array('<strong>Old value</strong>' . $fullyQualifiedNameHTML, '<span dir="' . (Language::isLanguageRTL($languageID) ? 'rtl' : 'ltr') . '">' . nl2br($originalWithMarkedEntities) . '</span>')); $table->addRow(array('<strong>Applied changes</strong>', '<div dir="' . (Language::isLanguageRTL($languageID) ? 'rtl' : 'ltr') . '">' . nl2br(htmlDiff(htmlspecialchars($valuePrevious), htmlspecialchars($editData[0]['suggestedValue']))) . '</div>')); $table->addRow(array('<strong>New value</strong>' . $fullyQualifiedNameHTML . '<br />' . $translateBackLink->getHTML(), $newValueHTML)); $table->addRow(array('<strong>Submit time</strong>', date('d.m.Y H:i', $editData[0]['submit_time']))); if ($isAllowedToReview) { $table->addRow(array('<strong>Contributor</strong>', $contributorName)); } if ($isAllowedToReview) { $form->addContent(new UI_Form_Hidden('review[editID]', URL::encodeID($editData[0]['id']))); $form->addContent(new UI_Form_Hidden('review[referenceValue]', $valueReference)); $form->addContent(new UI_Form_Hidden('review[phraseObject]', base64_encode(serialize($previousPhrase)))); $form->addContent(new UI_Form_Hidden('review[phraseKey]', htmlspecialchars($editData[0]['phraseKey']))); $form->addContent(new UI_Form_Hidden('review[phraseSubKey]', htmlspecialchars($editData[0]['phraseSubKey']))); $form->addContent(new UI_Form_Hidden('review[contributorID]', URL::encodeID($editData[0]['userID']))); } if ($isAllowedToReview) { $form->addContent($actionButtons); } $form->addContent($table); if ($isAllowedToReview) { $form->addContent($actionButtons); $form->addContent(new UI_Form_ButtonGroup(array($buttonApproveAllByContributor, $buttonRejectAllByContributor), true)); } $contents[] = $form; if ($editID > 0 || $isAllowedToReview) { // only for guest users who have the direct link to this edit ID and staff members who are allowed to review phrases $contents[] = new UI_Heading('Discussion', true, UI_Heading::LEVEL_MIN, URL::toReviewLanguage($repositoryID, $languageID, $editData[0]['id'])); $discussion = new UI_Form(htmlspecialchars($currentPageURL), false); $discussion->addContent(new UI_Form_Text('Your message', 'discussion[message]', 'Type here ...')); $discussion->addContent(new UI_Form_Hidden('discussion[editID]', URL::encodeID($editData[0]['id']))); $discussion->addContent(new UI_Form_ButtonGroup(array(new UI_Form_Button('Send')))); $contents[] = $discussion; $discussionEntries = Database::getDiscussionEntries($editData[0]['id']); foreach ($discussionEntries as $discussionEntry) { $contents[] = new UI_Paragraph('<strong>' . htmlspecialchars($discussionEntry['username']) . '</strong> (' . Time::getTimeAgo($discussionEntry['timeSent']) . '):<br />' . htmlspecialchars($discussionEntry['content'])); } } } } } } $cell = new UI_Cell($contents); $row = new UI_Row(array($cell)); $containers[] = new UI_Container(array($row)); return new UI_Group($containers); }