Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SEO improvements to avoid URL duplication #1009

Open
wants to merge 7 commits into
base: bugfix
Choose a base branch
from
4 changes: 4 additions & 0 deletions qa-include/app/format.php
Original file line number Diff line number Diff line change
Expand Up @@ -2220,6 +2220,10 @@ function qa_get_post_content($editorfield, $contentfield, &$ineditor, &$inconten

$ineditor = qa_post_text($editorfield);
$editor = qa_load_module('editor', $ineditor);
if ($editor === null) {
$editor = qa_load_module('editor', '');
}

$readdata = $editor->read_post($contentfield);

// sanitise 4-byte Unicode
Expand Down
22 changes: 14 additions & 8 deletions qa-include/pages/hot.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,45 +30,51 @@

// Get list of hottest questions, allow per-category if QA_ALLOW_UNINDEXED_QUERIES set in qa-config.php

$categoryslugs = QA_ALLOW_UNINDEXED_QUERIES ? qa_request_parts(1) : null;
$countslugs = $categoryslugs === null ? null : count($categoryslugs);
$categoryslugs = qa_request_parts(1);
$hasSlugs = !empty($categoryslugs);
if (!QA_ALLOW_UNINDEXED_QUERIES && $hasSlugs) {
qa_redirect('hot');
}

$start = qa_get_start();
$userid = qa_get_logged_in_userid();

list($questions, $categories, $categoryid) = qa_db_select_with_pending(
qa_db_qs_selectspec($userid, 'hotness', $start, $categoryslugs, null, false, false, qa_opt_if_loaded('page_size_hot_qs')),
qa_db_category_nav_selectspec($categoryslugs, false, false, true),
$countslugs ? qa_db_slugs_to_category_id_selectspec($categoryslugs) : null
$hasSlugs ? qa_db_slugs_to_category_id_selectspec($categoryslugs) : null
);

if ($countslugs) {
if ($hasSlugs) {
if (!isset($categoryid))
return include QA_INCLUDE_DIR . 'qa-page-not-found.php';

$categorytitlehtml = qa_html($categories[$categoryid]['title']);
$sometitle = qa_lang_html_sub('main/hot_qs_in_x', $categorytitlehtml);
$nonetitle = qa_lang_html_sub('main/no_questions_in_x', $categorytitlehtml);

} else {
$sometitle = qa_lang_html('main/hot_qs_title');
$nonetitle = qa_lang_html('main/no_questions_found');
}

if (isset($categoryid) && $categories[$categoryid]['backpath'] !== qa_db_slugs_to_backpath($categoryslugs)) {
$expectedPathInUrl = implode('/', array_reverse(explode('/', $categories[$categoryid]['backpath'])));
qa_redirect('hot/' . $expectedPathInUrl);
}

// Prepare and return content for theme

return qa_q_list_page_content(
$questions, // questions
qa_opt('page_size_hot_qs'), // questions per page
$start, // start offset
$countslugs ? $categories[$categoryid]['qcount'] : qa_opt('cache_qcount'), // total count
$hasSlugs ? $categories[$categoryid]['qcount'] : qa_opt('cache_qcount'), // total count
$sometitle, // title if some questions
$nonetitle, // title if no questions
QA_ALLOW_UNINDEXED_QUERIES ? $categories : array(), // categories for navigation
$categories, // categories for navigation
$categoryid, // selected category id
true, // show question counts in category navigation
QA_ALLOW_UNINDEXED_QUERIES ? 'hot/' : null, // prefix for links in category navigation (null if no navigation)
QA_ALLOW_UNINDEXED_QUERIES ? 'hot/' : null, // prefix for links in category navigation
qa_opt('feed_for_hot') ? 'hot' : null, // prefix for RSS feed paths (null to hide)
qa_html_suggest_ask() // suggest what to do next
);
41 changes: 23 additions & 18 deletions qa-include/pages/questions.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,17 @@
require_once QA_INCLUDE_DIR . 'app/q-list.php';

$categoryslugs = qa_request_parts(1);
$countslugs = count($categoryslugs);
$hasSlugs = !empty($categoryslugs);
$sort = qa_get('sort');

if (!QA_ALLOW_UNINDEXED_QUERIES && $hasSlugs) {
$getParams = $sort === null ? [] : ['sort' => $sort];
qa_redirect('questions', $getParams);
}

$sort = ($countslugs && !QA_ALLOW_UNINDEXED_QUERIES) ? null : qa_get('sort');
$start = qa_get_start();
$userid = qa_get_logged_in_userid();


// Get list of questions, plus category information

switch ($sort) {
Expand Down Expand Up @@ -63,75 +67,76 @@
list($questions, $categories, $categoryid) = qa_db_select_with_pending(
qa_db_qs_selectspec($userid, $selectsort, $start, $categoryslugs, null, false, false, qa_opt_if_loaded('page_size_qs')),
qa_db_category_nav_selectspec($categoryslugs, false, false, true),
$countslugs ? qa_db_slugs_to_category_id_selectspec($categoryslugs) : null
$hasSlugs ? qa_db_slugs_to_category_id_selectspec($categoryslugs) : null
);

if ($countslugs) {
if ($hasSlugs) {
if (!isset($categoryid)) {
return include QA_INCLUDE_DIR . 'qa-page-not-found.php';
}

if ($categories[$categoryid]['backpath'] !== qa_db_slugs_to_backpath($categoryslugs)) {
$expectedPathInUrl = implode('/', array_reverse(explode('/', $categories[$categoryid]['backpath'])));
$getParams = $sort === null ? [] : ['sort' => $sort];
qa_redirect('questions/' . $expectedPathInUrl, $getParams);
}

$categorytitlehtml = qa_html($categories[$categoryid]['title']);
$nonetitle = qa_lang_html_sub('main/no_questions_in_x', $categorytitlehtml);

} else {
$nonetitle = qa_lang_html('main/no_questions_found');
}


$categorypathprefix = QA_ALLOW_UNINDEXED_QUERIES ? 'questions/' : null; // this default is applied if sorted not by recent
$feedpathprefix = null;
$linkparams = array('sort' => $sort);

switch ($sort) {
case 'hot':
$sometitle = $countslugs ? qa_lang_html_sub('main/hot_qs_in_x', $categorytitlehtml) : qa_lang_html('main/hot_qs_title');
$sometitle = $hasSlugs ? qa_lang_html_sub('main/hot_qs_in_x', $categorytitlehtml) : qa_lang_html('main/hot_qs_title');
$feedpathprefix = qa_opt('feed_for_hot') ? 'hot' : null;
break;

case 'votes':
$sometitle = $countslugs ? qa_lang_html_sub('main/voted_qs_in_x', $categorytitlehtml) : qa_lang_html('main/voted_qs_title');
$sometitle = $hasSlugs ? qa_lang_html_sub('main/voted_qs_in_x', $categorytitlehtml) : qa_lang_html('main/voted_qs_title');
break;

case 'answers':
$sometitle = $countslugs ? qa_lang_html_sub('main/answered_qs_in_x', $categorytitlehtml) : qa_lang_html('main/answered_qs_title');
$sometitle = $hasSlugs ? qa_lang_html_sub('main/answered_qs_in_x', $categorytitlehtml) : qa_lang_html('main/answered_qs_title');
break;

case 'views':
$sometitle = $countslugs ? qa_lang_html_sub('main/viewed_qs_in_x', $categorytitlehtml) : qa_lang_html('main/viewed_qs_title');
$sometitle = $hasSlugs ? qa_lang_html_sub('main/viewed_qs_in_x', $categorytitlehtml) : qa_lang_html('main/viewed_qs_title');
break;

default:
$linkparams = array();
$sometitle = $countslugs ? qa_lang_html_sub('main/recent_qs_in_x', $categorytitlehtml) : qa_lang_html('main/recent_qs_title');
$categorypathprefix = 'questions/';
$sometitle = $hasSlugs ? qa_lang_html_sub('main/recent_qs_in_x', $categorytitlehtml) : qa_lang_html('main/recent_qs_title');
$feedpathprefix = qa_opt('feed_for_questions') ? 'questions' : null;
break;
}


// Prepare and return content for theme

$qa_content = qa_q_list_page_content(
$questions, // questions
qa_opt('page_size_qs'), // questions per page
$start, // start offset
$countslugs ? $categories[$categoryid]['qcount'] : qa_opt('cache_qcount'), // total count
$hasSlugs ? $categories[$categoryid]['qcount'] : qa_opt('cache_qcount'), // total count
$sometitle, // title if some questions
$nonetitle, // title if no questions
$categories, // categories for navigation
$categoryid, // selected category id
true, // show question counts in category navigation
$categorypathprefix, // prefix for links in category navigation
$feedpathprefix, // prefix for RSS feed paths
$countslugs ? qa_html_suggest_qs_tags(qa_using_tags()) : qa_html_suggest_ask($categoryid), // suggest what to do next
$hasSlugs ? qa_html_suggest_qs_tags(qa_using_tags()) : qa_html_suggest_ask($categoryid), // suggest what to do next
$linkparams, // extra parameters for page links
$linkparams // category nav params
);

if (QA_ALLOW_UNINDEXED_QUERIES || !$countslugs) {
if (QA_ALLOW_UNINDEXED_QUERIES || !$hasSlugs) {
$qa_content['navigation']['sub'] = qa_qs_sub_navigation($sort, $categoryslugs);
}


return $qa_content;
6 changes: 5 additions & 1 deletion qa-include/pages/tag.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

// Find the questions with this tag

if (!strlen((string)$tag)) {
if ((string)$tag === '') {
qa_redirect('tags');
}

Expand All @@ -44,6 +44,10 @@
qa_db_tag_word_selectspec($tag)
);

if (isset($tagword['word']) && $tagword['word'] !== $tag) {
qa_redirect('tag/' . $tagword['word']);
}

$pagesize = qa_opt('page_size_tag_qs');
$questions = array_slice($questions, 0, $pagesize);
$usershtml = qa_userids_handles_html($questions);
Expand Down
33 changes: 19 additions & 14 deletions qa-include/pages/unanswered.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@

// Get list of unanswered questions, allow per-category if QA_ALLOW_UNINDEXED_QUERIES set in qa-config.php

if (QA_ALLOW_UNINDEXED_QUERIES)
$categoryslugs = qa_request_parts(1);
else
$categoryslugs = null;
$categoryslugs = qa_request_parts(1);
$hasSlugs = !empty($categoryslugs);
if (!QA_ALLOW_UNINDEXED_QUERIES && $hasSlugs) {
qa_redirect('unanswered');
}

$countslugs = $categoryslugs === null ? null : count($categoryslugs);
$by = qa_get('by');
$start = qa_get_start();
$userid = qa_get_logged_in_userid();
Expand All @@ -57,23 +57,28 @@

list($questions, $categories, $categoryid) = qa_db_select_with_pending(
qa_db_unanswered_qs_selectspec($userid, $selectby, $start, $categoryslugs, false, false, qa_opt_if_loaded('page_size_una_qs')),
QA_ALLOW_UNINDEXED_QUERIES ? qa_db_category_nav_selectspec($categoryslugs, false, false, true) : null,
$countslugs ? qa_db_slugs_to_category_id_selectspec($categoryslugs) : null
qa_db_category_nav_selectspec($categoryslugs, false, false, true),
$hasSlugs ? qa_db_slugs_to_category_id_selectspec($categoryslugs) : null
);

if ($countslugs) {
if ($hasSlugs) {
if (!isset($categoryid))
return include QA_INCLUDE_DIR . 'qa-page-not-found.php';

$categorytitlehtml = qa_html($categories[$categoryid]['title']);
}

if (isset($categoryid) && $categories[$categoryid]['backpath'] !== qa_db_slugs_to_backpath($categoryslugs)) {
$expectedPathInUrl = implode('/', array_reverse(explode('/', $categories[$categoryid]['backpath'])));
qa_redirect('unanswered/' . $expectedPathInUrl);
}

$feedpathprefix = null;
$linkparams = array('by' => $by);

switch ($by) {
case 'selected':
if ($countslugs) {
if ($hasSlugs) {
$sometitle = qa_lang_html_sub('main/unselected_qs_in_x', $categorytitlehtml);
$nonetitle = qa_lang_html_sub('main/no_una_questions_in_x', $categorytitlehtml);

Expand All @@ -85,7 +90,7 @@
break;

case 'upvotes':
if ($countslugs) {
if ($hasSlugs) {
$sometitle = qa_lang_html_sub('main/unupvoteda_qs_in_x', $categorytitlehtml);
$nonetitle = qa_lang_html_sub('main/no_una_questions_in_x', $categorytitlehtml);

Expand All @@ -100,7 +105,7 @@
$feedpathprefix = qa_opt('feed_for_unanswered') ? 'unanswered' : null;
$linkparams = array();

if ($countslugs) {
if ($hasSlugs) {
$sometitle = qa_lang_html_sub('main/unanswered_qs_in_x', $categorytitlehtml);
$nonetitle = qa_lang_html_sub('main/no_una_questions_in_x', $categorytitlehtml);

Expand All @@ -122,10 +127,10 @@
@$count, // total count
$sometitle, // title if some questions
$nonetitle, // title if no questions
QA_ALLOW_UNINDEXED_QUERIES ? $categories : array(), // categories for navigation (null if not shown on this page)
QA_ALLOW_UNINDEXED_QUERIES ? $categoryid : null, // selected category id (null if not relevant)
$categories, // categories for navigation
$categoryid, // selected category id
false, // show question counts in category navigation
QA_ALLOW_UNINDEXED_QUERIES ? 'unanswered/' : null, // prefix for links in category navigation (null if no navigation)
QA_ALLOW_UNINDEXED_QUERIES ? 'unanswered/' : null, // prefix for links in category navigation
$feedpathprefix, // prefix for RSS feed paths (null to hide)
qa_html_suggest_qs_tags(qa_using_tags()), // suggest what to do next
$linkparams, // extra parameters for page links
Expand Down
13 changes: 11 additions & 2 deletions qa-include/pages/user-activity.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,18 @@
qa_db_user_recent_edit_qs_selectspec($loginuserid, $identifier)
);

if (!QA_FINAL_EXTERNAL_USERS && !is_array($useraccount)) // check the user exists
return include QA_INCLUDE_DIR . 'qa-page-not-found.php';
if (!QA_FINAL_EXTERNAL_USERS) {
if ($useraccount === null) { // check the user exists
return include QA_INCLUDE_DIR . 'qa-page-not-found.php';
}
if ($handle !== $useraccount['handle']) {
qa_redirect('user/' . $useraccount['handle'] . '/activity');
}
}

if ($handle !== $useraccount['handle']) {
qa_redirect('user/' . $useraccount['handle'] . '/activity');
}

// Get information on user references

Expand Down
11 changes: 8 additions & 3 deletions qa-include/pages/user-answers.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,14 @@
qa_db_user_recent_a_qs_selectspec($loginuserid, $identifier, qa_opt_if_loaded('page_size_activity'), $start)
);

if (!QA_FINAL_EXTERNAL_USERS && !is_array($useraccount)) // check the user exists
return include QA_INCLUDE_DIR . 'qa-page-not-found.php';

if (!QA_FINAL_EXTERNAL_USERS) {
if ($useraccount === null) { // check the user exists
return include QA_INCLUDE_DIR . 'qa-page-not-found.php';
}
if ($handle !== $useraccount['handle']) {
qa_redirect('user/' . $useraccount['handle'] . '/answers');
}
}

// Get information on user questions

Expand Down
3 changes: 3 additions & 0 deletions qa-include/pages/user-profile.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@
}

$userid = $useraccount['userid'];
if ($handle !== $useraccount['handle']) {
qa_redirect('user/' . $useraccount['handle']);
}
}

list($userprofile, $userfields, $usermessages, $userpoints, $userlevels, $navcategories, $userrank) =
Expand Down
11 changes: 8 additions & 3 deletions qa-include/pages/user-questions.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,14 @@
qa_db_user_recent_qs_selectspec($loginuserid, $identifier, qa_opt_if_loaded('page_size_qs'), $start)
);

if (!QA_FINAL_EXTERNAL_USERS && !is_array($useraccount)) // check the user exists
return include QA_INCLUDE_DIR . 'qa-page-not-found.php';

if (!QA_FINAL_EXTERNAL_USERS) {
if ($useraccount === null) { // check the user exists
return include QA_INCLUDE_DIR . 'qa-page-not-found.php';
}
if ($handle !== $useraccount['handle']) {
qa_redirect('user/' . $useraccount['handle'] . '/questions');
}
}

// Get information on user questions

Expand Down
6 changes: 4 additions & 2 deletions qa-include/pages/user-wall.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
qa_exit();
}


// $handle, $userhtml are already set by /qa-include/page/user.php

$start = qa_get_start();
Expand All @@ -49,9 +48,12 @@
qa_db_recent_messages_selectspec(null, null, $handle, false, qa_opt_if_loaded('page_size_wall'), $start)
);

if (!is_array($useraccount)) // check the user exists
if ($useraccount === null) // check the user exists
return include QA_INCLUDE_DIR . 'qa-page-not-found.php';

if ($handle !== $useraccount['handle']) {
qa_redirect('user/' . $useraccount['handle'] . '/wall');
}

// Perform pagination

Expand Down
8 changes: 4 additions & 4 deletions qa-include/qa-base.php
Original file line number Diff line number Diff line change
Expand Up @@ -1803,17 +1803,17 @@ function qa_redirect($request, $params = null, $rooturl = null, $neaturls = null
qa_redirect_raw(qa_path($request, $params, $rooturl, $neaturls, $anchor));
}


/**
* Redirect the user's web browser to page $path which is already a URL
* @param $url
* @param string $url
* @param int $statusCode
* @return mixed
*/
function qa_redirect_raw($url)
function qa_redirect_raw($url, $statusCode = 301)
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }

header('Location: ' . $url);
header('Location: ' . $url, true, $statusCode);
qa_exit('redirect');
}

Expand Down