1*04fd306cSNickeau<?php 2*04fd306cSNickeau 3*04fd306cSNickeaunamespace ComboStrap\Tag; 4*04fd306cSNickeau 5*04fd306cSNickeauuse ComboStrap\ExceptionCompile; 6*04fd306cSNickeauuse ComboStrap\LinkMarkup; 7*04fd306cSNickeauuse ComboStrap\LogUtility; 8*04fd306cSNickeauuse ComboStrap\MarkupPath; 9*04fd306cSNickeauuse ComboStrap\PluginUtility; 10*04fd306cSNickeauuse ComboStrap\SiteConfig; 11*04fd306cSNickeauuse ComboStrap\TagAttributes; 12*04fd306cSNickeauuse syntax_plugin_combo_iterator; 13*04fd306cSNickeauuse syntax_plugin_combo_related; 14*04fd306cSNickeau 15*04fd306cSNickeauclass RelatedTag 16*04fd306cSNickeau{ 17*04fd306cSNickeau 18*04fd306cSNickeau 19*04fd306cSNickeau public const TAG = "related"; 20*04fd306cSNickeau /** 21*04fd306cSNickeau * For when you come from another plugin (such as backlinks) and that you don't want to change the pattern on each page 22*04fd306cSNickeau */ 23*04fd306cSNickeau public const MORE_PAGE_ID = 'related_more'; 24*04fd306cSNickeau public const MAX_LINKS_CONF = 'maxLinks'; 25*04fd306cSNickeau public const EXTRA_PATTERN_CONF = 'extra_pattern'; 26*04fd306cSNickeau public const MAX_LINKS_CONF_DEFAULT = 10; 27*04fd306cSNickeau /** 28*04fd306cSNickeau * The array key of an array of related page 29*04fd306cSNickeau */ 30*04fd306cSNickeau public const RELATED_BACKLINKS_COUNT_PROP = 'backlinks'; 31*04fd306cSNickeau /** 32*04fd306cSNickeau * This is a fake page ID that is added 33*04fd306cSNickeau * to the related page array when the number of backlinks is bigger than the max 34*04fd306cSNickeau */ 35*04fd306cSNickeau public const RELATED_PAGE_ID_PROP = 'id'; 36*04fd306cSNickeau 37*04fd306cSNickeau /** 38*04fd306cSNickeau * @param TagAttributes $tagAttributes 39*04fd306cSNickeau * @param MarkupPath $page 40*04fd306cSNickeau * @param int|null $max 41*04fd306cSNickeau * @return string 42*04fd306cSNickeau */ 43*04fd306cSNickeau public static function render(TagAttributes $tagAttributes): string 44*04fd306cSNickeau { 45*04fd306cSNickeau $path = syntax_plugin_combo_iterator::getContextPathForComponentThatMayBeInFragment($tagAttributes); 46*04fd306cSNickeau $contextPage = MarkupPath::createPageFromPathObject($path); 47*04fd306cSNickeau return self::renderForPage($contextPage, $tagAttributes); 48*04fd306cSNickeau } 49*04fd306cSNickeau 50*04fd306cSNickeau public static function renderForPage(MarkupPath $page, TagAttributes $tagAttributes = null): string 51*04fd306cSNickeau { 52*04fd306cSNickeau global $lang; 53*04fd306cSNickeau 54*04fd306cSNickeau if ($tagAttributes === null) { 55*04fd306cSNickeau $tagAttributes = TagAttributes::createEmpty() 56*04fd306cSNickeau ->setLogicalTag(self::TAG); 57*04fd306cSNickeau } 58*04fd306cSNickeau 59*04fd306cSNickeau $max = $tagAttributes->getValue(RelatedTag::MAX_LINKS_CONF); 60*04fd306cSNickeau if ($max === NULL) { 61*04fd306cSNickeau $max = SiteConfig::getConfValue(RelatedTag::MAX_LINKS_CONF, RelatedTag::MAX_LINKS_CONF_DEFAULT); 62*04fd306cSNickeau } 63*04fd306cSNickeau 64*04fd306cSNickeau $tagAttributes->addClassName("d-print-none"); 65*04fd306cSNickeau $html = $tagAttributes->toHtmlEnterTag("div"); 66*04fd306cSNickeau 67*04fd306cSNickeau $relatedPages = self::getRelatedPagesOrderedByBacklinkCount($page, $max); 68*04fd306cSNickeau if (empty($relatedPages)) { 69*04fd306cSNickeau 70*04fd306cSNickeau $html .= "<strong>Plugin " . PluginUtility::PLUGIN_BASE_NAME . " - Component " . syntax_plugin_combo_related::getTag() . ": " . $lang['nothingfound'] . "</strong>"; 71*04fd306cSNickeau 72*04fd306cSNickeau } else { 73*04fd306cSNickeau 74*04fd306cSNickeau // Dokuwiki debug 75*04fd306cSNickeau 76*04fd306cSNickeau $html .= '<ul>'; 77*04fd306cSNickeau 78*04fd306cSNickeau foreach ($relatedPages as $backlink) { 79*04fd306cSNickeau $backlinkId = $backlink[self::RELATED_PAGE_ID_PROP]; 80*04fd306cSNickeau $html .= '<li>'; 81*04fd306cSNickeau if ($backlinkId != self::MORE_PAGE_ID) { 82*04fd306cSNickeau $linkUtility = LinkMarkup::createFromPageIdOrPath($backlinkId); 83*04fd306cSNickeau try { 84*04fd306cSNickeau $html .= $linkUtility->toAttributes(self::TAG)->toHtmlEnterTag("a"); 85*04fd306cSNickeau $html .= $linkUtility->getDefaultLabel(); 86*04fd306cSNickeau $html .= "</a>"; 87*04fd306cSNickeau } catch (ExceptionCompile $e) { 88*04fd306cSNickeau $html = "Error while trying to create the link for the page ($backlinkId). Error: {$e->getMessage()}"; 89*04fd306cSNickeau LogUtility::msg($html); 90*04fd306cSNickeau } 91*04fd306cSNickeau 92*04fd306cSNickeau } else { 93*04fd306cSNickeau $html .= 94*04fd306cSNickeau tpl_link( 95*04fd306cSNickeau wl($page->getWikiId()) . '?do=backlink', 96*04fd306cSNickeau "More ...", 97*04fd306cSNickeau 'class="" rel="nofollow" title="More..."', 98*04fd306cSNickeau true 99*04fd306cSNickeau ); 100*04fd306cSNickeau } 101*04fd306cSNickeau $html .= '</li>'; 102*04fd306cSNickeau } 103*04fd306cSNickeau 104*04fd306cSNickeau $html .= '</ul>'; 105*04fd306cSNickeau 106*04fd306cSNickeau } 107*04fd306cSNickeau 108*04fd306cSNickeau return $html . '</div>'; 109*04fd306cSNickeau } 110*04fd306cSNickeau 111*04fd306cSNickeau /** 112*04fd306cSNickeau * @param MarkupPath $page 113*04fd306cSNickeau * @param int|null $max 114*04fd306cSNickeau * @return array 115*04fd306cSNickeau */ 116*04fd306cSNickeau public static function getRelatedPagesOrderedByBacklinkCount(MarkupPath $page, ?int $max = null): array 117*04fd306cSNickeau { 118*04fd306cSNickeau 119*04fd306cSNickeau // Call the dokuwiki backlinks function 120*04fd306cSNickeau // @require_once(DOKU_INC . 'inc/fulltext.php'); 121*04fd306cSNickeau // Backlinks called the indexer, for more info 122*04fd306cSNickeau // See: https://www.dokuwiki.org/devel:metadata#metadata_index 123*04fd306cSNickeau $backlinks = ft_backlinks($page->getWikiId(), $ignore_perms = false); 124*04fd306cSNickeau 125*04fd306cSNickeau $related = array(); 126*04fd306cSNickeau foreach ($backlinks as $backlink) { 127*04fd306cSNickeau $page = array(); 128*04fd306cSNickeau $page[RelatedTag::RELATED_PAGE_ID_PROP] = $backlink; 129*04fd306cSNickeau $page[RelatedTag::RELATED_BACKLINKS_COUNT_PROP] = sizeof(ft_backlinks($backlink, $ignore_perms = false)); 130*04fd306cSNickeau $related[] = $page; 131*04fd306cSNickeau } 132*04fd306cSNickeau 133*04fd306cSNickeau usort($related, function ($a, $b) { 134*04fd306cSNickeau return $b[RelatedTag::RELATED_BACKLINKS_COUNT_PROP] - $a[RelatedTag::RELATED_BACKLINKS_COUNT_PROP]; 135*04fd306cSNickeau }); 136*04fd306cSNickeau 137*04fd306cSNickeau if ($max !== null) { 138*04fd306cSNickeau if (sizeof($related) > $max) { 139*04fd306cSNickeau $related = array_slice($related, 0, $max); 140*04fd306cSNickeau $page = array(); 141*04fd306cSNickeau $page[RelatedTag::RELATED_PAGE_ID_PROP] = RelatedTag::MORE_PAGE_ID; 142*04fd306cSNickeau $related[] = $page; 143*04fd306cSNickeau } 144*04fd306cSNickeau } 145*04fd306cSNickeau 146*04fd306cSNickeau return $related; 147*04fd306cSNickeau 148*04fd306cSNickeau } 149*04fd306cSNickeau} 150