1<?php 2 3namespace ComboStrap; 4 5use action_plugin_combo_router; 6use ComboStrap\Meta\Field\Aliases; 7use ComboStrap\Meta\Field\AliasType; 8use ComboStrap\Meta\Store\MetadataDbStore; 9 10 11/** 12 * Class UrlManagerBestEndPage 13 * 14 * A class that implements the BestEndPage Algorithm for the {@link action_plugin_combo_router urlManager} 15 */ 16class RouterBestEndPage 17{ 18 19 /** 20 * If the number of names part that match is greater or equal to 21 * this configuration, an Id Redirect is performed 22 * A value of 0 disable and send only HTTP redirect 23 */ 24 const CONF_MINIMAL_SCORE_FOR_REDIRECT = 'BestEndPageMinimalScoreForAliasCreation'; 25 const CONF_MINIMAL_SCORE_FOR_REDIRECT_DEFAULT = '2'; 26 27 28 /** 29 * @param MarkupPath $requestedPage 30 * @return array - the best poge id and its score 31 * The score is the number of name that matches 32 */ 33 public static function getBestEndPageId(MarkupPath $requestedPage): array 34 { 35 36 $pagesWithSameName = Index::getOrCreate() 37 ->getPagesWithSameLastName($requestedPage); 38 if (sizeof($pagesWithSameName) == 0) { 39 return []; 40 } 41 return self::getBestEndPageIdFromPages($pagesWithSameName, $requestedPage); 42 43 44 } 45 46 47 /** 48 * @param MarkupPath $missingPage 49 * @return array with the best page and the type of redirect 50 * @throws ExceptionCompile 51 */ 52 public static function process(MarkupPath $missingPage): array 53 { 54 55 $return = array(); 56 57 $minimalScoreForARedirect = SiteConfig::getConfValue(self::CONF_MINIMAL_SCORE_FOR_REDIRECT, self::CONF_MINIMAL_SCORE_FOR_REDIRECT_DEFAULT); 58 59 list($bestPage, $bestScore) = self::getBestEndPageId($missingPage); 60 if ($bestPage != null) { 61 $redirectType = action_plugin_combo_router::REDIRECT_NOTFOUND_METHOD; 62 if ($minimalScoreForARedirect != 0 && $bestScore >= $minimalScoreForARedirect) { 63 Aliases::createForPage($bestPage) 64 ->addAlias($missingPage, AliasType::REDIRECT) 65 ->sendToWriteStore() 66 ->setReadStore(MetadataDbStore::getOrCreateFromResource($bestPage)) 67 ->sendToWriteStore(); 68 $redirectType = action_plugin_combo_router::REDIRECT_PERMANENT_METHOD; 69 } 70 $return = array( 71 $bestPage, 72 $redirectType 73 ); 74 } 75 return $return; 76 77 } 78 79 /** 80 * @param MarkupPath[] $candidatePagesWithSameLastName 81 * @param MarkupPath $requestedPage 82 * @return array 83 */ 84 public static function getBestEndPageIdFromPages(array $candidatePagesWithSameLastName, MarkupPath $requestedPage): array 85 { 86 // Default value 87 $bestScore = 0; 88 $bestPage = $candidatePagesWithSameLastName[0]; 89 90 // The name of the dokuwiki id 91 $requestedPageNames = $requestedPage->getPathObject()->getNames(); 92 93 // Loop 94 foreach ($candidatePagesWithSameLastName as $candidatePage) { 95 96 try { 97 if ($candidatePage->getWikiId() === $requestedPage->getWikiId()) { 98 // when the index is not up to date 99 continue; 100 } 101 } catch (ExceptionBadArgument $e) { 102 // should not happen but yeah 103 } 104 105 $candidatePageNames = $candidatePage->getPathObject()->getNames(); 106 $score = 0; 107 foreach ($candidatePageNames as $candidatePageName) { 108 if (in_array($candidatePageName, $requestedPageNames)) { 109 $score++; 110 } 111 } 112 if ($score > $bestScore) { 113 $bestScore = $score; 114 $bestPage = $candidatePage; 115 } else if ($score === $bestScore) { 116 /** 117 * Best backlink count 118 */ 119 $candidateBacklinksCount = sizeof($candidatePage->getBacklinks()); 120 $bestPageBacklinksCount = sizeof($bestPage->getBacklinks()); 121 if ($candidateBacklinksCount > $bestPageBacklinksCount) { 122 $bestPage = $candidatePage; 123 } 124 } 125 126 } 127 128 return array( 129 $bestPage, 130 $bestScore 131 ); 132 } 133} 134