Internal Link Suggestion Builder
Suggests related internal links using item type, category, tags, and content similarity.
Function signature
ogSuggestInternalLinks(current_item = array(), candidate_items = array(), max_links = 6)
Categories
- Search and Discovery
Parameters
current_itemCurrent item record used as the internal-link anchor context.candidate_itemsCandidate item rows scored for internal-link suggestions.max_linksMaximum number of related links to return.Return value
Public-safe status string returned by the function for controller branching or logging.
- success
- message
- data
Compatibility
Existing function name, slug, path, and call order preserved; advertised metadata corrected to the actual source behavior.
Minimum PHP version: 7.4
Security notes
Use caller-owned allowlists and context-specific escaping; validate file paths, routes, email tokens, cart totals, discount rules, and tax-region rules before production use.
Code
<?php
/*
* Copyright (c) 2026 Jeffery L. Paris <jparis@phpog.com>.
* Free for personal and internal use. Paid project use requires visible credit
* to Jeffery L. Paris. Corporate use requires a paid license fee unless a
* separate written license states otherwise.
*/
/**
* Suggests related internal links using item type, category, tags, and content similarity.
*
* Primary use case: SEO and user navigation.
* Typical inputs: current item, item index, max links.
* Typical output: link suggestions.
*
* Implementation note: Avoid circular repetitive link blocks.
*
* @param array $current_item Current item record with id, type, category, and tags.
* @param array $candidate_items Candidate item records.
* @param int $max_links Maximum number of links to return.
* @return array Suggested internal links.
*/
function ogSuggestInternalLinks($current_item = array(), $candidate_items = array(), $max_links = 6) {
$result = array(
'success' => false,
'message' => '',
'data' => array()
);
if (!is_array($current_item) || !is_array($candidate_items)) {
$result['message'] = 'Current item and candidates must be arrays.';
return $result;
}
$max_links = (int)$max_links;
if ($max_links < 1) {
$max_links = 1;
}
$current_id = 0;
if (!empty($current_item['id'])) {
$current_id = (int)$current_item['id'];
}
$current_tags = array();
if (!empty($current_item['tags']) && is_array($current_item['tags'])) {
$current_tags = $current_item['tags'];
}
$scores = array();
foreach ($candidate_items as $candidate) {
if (!is_array($candidate)) {
continue;
}
if (!empty($candidate['id']) && (int)$candidate['id'] == $current_id) {
continue;
}
$score = 0;
if (!empty($candidate['item_type']) && !empty($current_item['item_type']) && $candidate['item_type'] == $current_item['item_type']) {
$score += 3;
}
if (!empty($candidate['category_slug']) && !empty($current_item['category_slug']) && $candidate['category_slug'] == $current_item['category_slug']) {
$score += 4;
}
if (!empty($candidate['tags']) && is_array($candidate['tags'])) {
foreach ($candidate['tags'] as $tag) {
if (in_array($tag, $current_tags, true)) {
$score++;
}
}
}
if ($score > 0) {
$candidate['score'] = $score;
$scores[] = $candidate;
}
}
usort($scores, function($left, $right) {
if ($left['score'] == $right['score']) {
return 0;
}
if ($left['score'] > $right['score']) {
return -1;
}
return 1;
});
$result['success'] = true;
$result['message'] = 'Internal links suggested.';
$result['data'] = array(
'links' => array_slice($scores, 0, $max_links),
'candidate_count' => count($candidate_items)
);
return $result;
}