xref: /plugin/combo/ComboStrap/Tag/RelatedTag.php (revision 04fd306c7c155fa133ebb3669986875d65988276)
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