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