104fd306cSNickeau<?php 204fd306cSNickeau 304fd306cSNickeaunamespace ComboStrap; 404fd306cSNickeau 504fd306cSNickeauuse action_plugin_combo_router; 604fd306cSNickeauuse ComboStrap\Meta\Field\Aliases; 704fd306cSNickeauuse ComboStrap\Meta\Field\AliasType; 804fd306cSNickeauuse ComboStrap\Meta\Store\MetadataDbStore; 904fd306cSNickeau 1004fd306cSNickeau 1104fd306cSNickeau/** 1204fd306cSNickeau * Class UrlManagerBestEndPage 1304fd306cSNickeau * 1404fd306cSNickeau * A class that implements the BestEndPage Algorithm for the {@link action_plugin_combo_router urlManager} 1504fd306cSNickeau */ 1604fd306cSNickeauclass RouterBestEndPage 1704fd306cSNickeau{ 1804fd306cSNickeau 1904fd306cSNickeau /** 2004fd306cSNickeau * If the number of names part that match is greater or equal to 2104fd306cSNickeau * this configuration, an Id Redirect is performed 2204fd306cSNickeau * A value of 0 disable and send only HTTP redirect 2304fd306cSNickeau */ 2404fd306cSNickeau const CONF_MINIMAL_SCORE_FOR_REDIRECT = 'BestEndPageMinimalScoreForAliasCreation'; 2504fd306cSNickeau const CONF_MINIMAL_SCORE_FOR_REDIRECT_DEFAULT = '2'; 2604fd306cSNickeau 2704fd306cSNickeau 2804fd306cSNickeau /** 2904fd306cSNickeau * @param MarkupPath $requestedPage 30*45a874f4SNico * @return array - the best page id and its score 3104fd306cSNickeau * The score is the number of name that matches 3204fd306cSNickeau */ 3304fd306cSNickeau public static function getBestEndPageId(MarkupPath $requestedPage): array 3404fd306cSNickeau { 3504fd306cSNickeau 3604fd306cSNickeau $pagesWithSameName = Index::getOrCreate() 3704fd306cSNickeau ->getPagesWithSameLastName($requestedPage); 3804fd306cSNickeau if (sizeof($pagesWithSameName) == 0) { 39ad79af66SNico return [null, null]; 4004fd306cSNickeau } 4104fd306cSNickeau return self::getBestEndPageIdFromPages($pagesWithSameName, $requestedPage); 4204fd306cSNickeau 4304fd306cSNickeau 4404fd306cSNickeau } 4504fd306cSNickeau 4604fd306cSNickeau 4704fd306cSNickeau /** 4804fd306cSNickeau * @param MarkupPath $missingPage 4904fd306cSNickeau * @return array with the best page and the type of redirect 5004fd306cSNickeau */ 5104fd306cSNickeau public static function process(MarkupPath $missingPage): array 5204fd306cSNickeau { 5304fd306cSNickeau 54ad79af66SNico $return = [null, null]; 5504fd306cSNickeau 5604fd306cSNickeau $minimalScoreForARedirect = SiteConfig::getConfValue(self::CONF_MINIMAL_SCORE_FOR_REDIRECT, self::CONF_MINIMAL_SCORE_FOR_REDIRECT_DEFAULT); 5704fd306cSNickeau 5804fd306cSNickeau list($bestPage, $bestScore) = self::getBestEndPageId($missingPage); 5904fd306cSNickeau if ($bestPage != null) { 60*45a874f4SNico $redirectType = RouterRedirection::REDIRECT_NOTFOUND_METHOD; 6104fd306cSNickeau if ($minimalScoreForARedirect != 0 && $bestScore >= $minimalScoreForARedirect) { 62*45a874f4SNico try { 6304fd306cSNickeau Aliases::createForPage($bestPage) 6404fd306cSNickeau ->addAlias($missingPage, AliasType::REDIRECT) 6504fd306cSNickeau ->sendToWriteStore() 6604fd306cSNickeau ->setReadStore(MetadataDbStore::getOrCreateFromResource($bestPage)) 6704fd306cSNickeau ->sendToWriteStore(); 68*45a874f4SNico } catch (ExceptionBadArgument|ExceptionCompile $e) { 69*45a874f4SNico LogUtility::error("Error while creating an alias",LogUtility::SUPPORT_CANONICAL,$e); 70*45a874f4SNico return $return; 71*45a874f4SNico } 72*45a874f4SNico $redirectType = RouterRedirection::REDIRECT_PERMANENT_METHOD; 7304fd306cSNickeau } 7404fd306cSNickeau $return = array( 7504fd306cSNickeau $bestPage, 7604fd306cSNickeau $redirectType 7704fd306cSNickeau ); 7804fd306cSNickeau } 7904fd306cSNickeau return $return; 8004fd306cSNickeau 8104fd306cSNickeau } 8204fd306cSNickeau 8304fd306cSNickeau /** 8404fd306cSNickeau * @param MarkupPath[] $candidatePagesWithSameLastName 8504fd306cSNickeau * @param MarkupPath $requestedPage 8604fd306cSNickeau * @return array 8704fd306cSNickeau */ 8804fd306cSNickeau public static function getBestEndPageIdFromPages(array $candidatePagesWithSameLastName, MarkupPath $requestedPage): array 8904fd306cSNickeau { 9004fd306cSNickeau // Default value 9104fd306cSNickeau $bestScore = 0; 9204fd306cSNickeau $bestPage = $candidatePagesWithSameLastName[0]; 9304fd306cSNickeau 9404fd306cSNickeau // The name of the dokuwiki id 9504fd306cSNickeau $requestedPageNames = $requestedPage->getPathObject()->getNames(); 9604fd306cSNickeau 9704fd306cSNickeau // Loop 9804fd306cSNickeau foreach ($candidatePagesWithSameLastName as $candidatePage) { 9904fd306cSNickeau 100ea801fd8Sgerardnico try { 101ea801fd8Sgerardnico if ($candidatePage->getWikiId() === $requestedPage->getWikiId()) { 102ea801fd8Sgerardnico // when the index is not up to date 103ea801fd8Sgerardnico continue; 104ea801fd8Sgerardnico } 105ea801fd8Sgerardnico } catch (ExceptionBadArgument $e) { 106ea801fd8Sgerardnico // should not happen but yeah 107ea801fd8Sgerardnico } 108ea801fd8Sgerardnico 10904fd306cSNickeau $candidatePageNames = $candidatePage->getPathObject()->getNames(); 11004fd306cSNickeau $score = 0; 11104fd306cSNickeau foreach ($candidatePageNames as $candidatePageName) { 11204fd306cSNickeau if (in_array($candidatePageName, $requestedPageNames)) { 11304fd306cSNickeau $score++; 11404fd306cSNickeau } 11504fd306cSNickeau } 11604fd306cSNickeau if ($score > $bestScore) { 11704fd306cSNickeau $bestScore = $score; 11804fd306cSNickeau $bestPage = $candidatePage; 11904fd306cSNickeau } else if ($score === $bestScore) { 12004fd306cSNickeau /** 12104fd306cSNickeau * Best backlink count 12204fd306cSNickeau */ 12304fd306cSNickeau $candidateBacklinksCount = sizeof($candidatePage->getBacklinks()); 12404fd306cSNickeau $bestPageBacklinksCount = sizeof($bestPage->getBacklinks()); 12504fd306cSNickeau if ($candidateBacklinksCount > $bestPageBacklinksCount) { 12604fd306cSNickeau $bestPage = $candidatePage; 12704fd306cSNickeau } 12804fd306cSNickeau } 12904fd306cSNickeau 13004fd306cSNickeau } 13104fd306cSNickeau 13204fd306cSNickeau return array( 13304fd306cSNickeau $bestPage, 13404fd306cSNickeau $bestScore 13504fd306cSNickeau ); 13604fd306cSNickeau } 13704fd306cSNickeau} 138