104fd306cSNickeau<?php 204fd306cSNickeau 304fd306cSNickeau 404fd306cSNickeaunamespace ComboStrap\Meta\Field; 504fd306cSNickeau 604fd306cSNickeau 704fd306cSNickeauuse ComboStrap\ExceptionCompile; 804fd306cSNickeauuse ComboStrap\ExceptionNotFound; 904fd306cSNickeauuse ComboStrap\ExceptionSqliteNotAvailable; 1004fd306cSNickeauuse ComboStrap\LogUtility; 1104fd306cSNickeauuse ComboStrap\MarkupPath; 1204fd306cSNickeauuse ComboStrap\Meta\Api\Metadata; 1304fd306cSNickeauuse ComboStrap\Meta\Api\MetadataSystem; 1404fd306cSNickeauuse ComboStrap\Meta\Store\MetadataDokuWikiStore; 1504fd306cSNickeauuse ComboStrap\Meta\Api\MetadataTabular; 1604fd306cSNickeauuse ComboStrap\MetaManagerForm; 1704fd306cSNickeauuse ComboStrap\Sqlite; 1804fd306cSNickeauuse ComboStrap\StringUtility; 1904fd306cSNickeauuse ComboStrap\WikiPath; 2004fd306cSNickeau 2104fd306cSNickeauclass Aliases extends MetadataTabular 2204fd306cSNickeau{ 2304fd306cSNickeau 2404fd306cSNickeau public const PROPERTY_NAME = "aliases"; 2504fd306cSNickeau 2604fd306cSNickeau 2704fd306cSNickeau public static function createForPage(MarkupPath $page): Aliases 2804fd306cSNickeau { 2904fd306cSNickeau 3004fd306cSNickeau return (new Aliases())->setResource($page); 3104fd306cSNickeau 3204fd306cSNickeau } 3304fd306cSNickeau 3404fd306cSNickeau public static function create(): Aliases 3504fd306cSNickeau { 3604fd306cSNickeau return new Aliases(); 3704fd306cSNickeau } 3804fd306cSNickeau 3904fd306cSNickeau /** 4004fd306cSNickeau * @return Alias[]|null 4104fd306cSNickeau * @throws ExceptionNotFound 4204fd306cSNickeau */ 4304fd306cSNickeau public function getValueAsAlias(): array 4404fd306cSNickeau { 4504fd306cSNickeau $rows = $this->getValue(); 4604fd306cSNickeau $aliases = []; 4704fd306cSNickeau foreach ($rows as $row) { 4804fd306cSNickeau /** 4904fd306cSNickeau * @var AliasPath $aliasMeta 5004fd306cSNickeau */ 5104fd306cSNickeau $aliasMeta = $row[AliasPath::getPersistentName()]; 5204fd306cSNickeau $alias = Alias::create($this->getResource(), $aliasMeta->getValue()); 5304fd306cSNickeau /** 5404fd306cSNickeau * @var AliasType $aliasType 5504fd306cSNickeau */ 56*70bbd7f1Sgerardnico $aliasType = $row[AliasType::getPersistentName()] ?? null; 5704fd306cSNickeau if ($aliasType !== null) { 5804fd306cSNickeau try { 5904fd306cSNickeau $alias->setType($aliasType->getValue()); 6004fd306cSNickeau } catch (ExceptionNotFound $e) { 6104fd306cSNickeau // ok 6204fd306cSNickeau } 6304fd306cSNickeau 6404fd306cSNickeau } 6504fd306cSNickeau $aliases[] = $alias; 6604fd306cSNickeau } 6704fd306cSNickeau return $aliases; 6804fd306cSNickeau } 6904fd306cSNickeau 7004fd306cSNickeau 7104fd306cSNickeau /** 7204fd306cSNickeau * @param array|null $aliasesPersistentValues 7304fd306cSNickeau * return Alias[] 7404fd306cSNickeau */ 7504fd306cSNickeau private function toNativeAliasArray(?array $aliasesPersistentValues): array 7604fd306cSNickeau { 7704fd306cSNickeau if ($aliasesPersistentValues === null) { 7804fd306cSNickeau return []; 7904fd306cSNickeau } 8004fd306cSNickeau $aliases = []; 8104fd306cSNickeau foreach ($aliasesPersistentValues as $key => $value) { 8204fd306cSNickeau if (is_array($value)) { 8304fd306cSNickeau $path = $value[AliasPath::PERSISTENT_NAME]; 8404fd306cSNickeau if (empty($path)) { 8504fd306cSNickeau if (is_string($key)) { 8604fd306cSNickeau // Old way (deprecated) 8704fd306cSNickeau $path = $key; 8804fd306cSNickeau } else { 8904fd306cSNickeau LogUtility::msg("The path of the alias should not be empty to create a path", Alias::CANONICAL); 9004fd306cSNickeau } 9104fd306cSNickeau } 9204fd306cSNickeau $type = $value[AliasType::PERSISTENT_NAME]; 9304fd306cSNickeau 9404fd306cSNickeau /** 9504fd306cSNickeau * We don't create via the {@link Aliases::addAlias()} 9604fd306cSNickeau * to not persist for each each alias value 9704fd306cSNickeau **/ 9804fd306cSNickeau $aliases[] = Alias::create($this->getResource(), $path) 9904fd306cSNickeau ->setType($type); 10004fd306cSNickeau } else { 10104fd306cSNickeau $path = $value; 10204fd306cSNickeau if (empty($path)) { 10304fd306cSNickeau LogUtility::msg("The value of the alias array should not be empty as it's the alias path", Alias::CANONICAL); 10404fd306cSNickeau } 10504fd306cSNickeau if (!is_string($path)) { 10604fd306cSNickeau $path = StringUtility::toString($path); 10704fd306cSNickeau LogUtility::error("The alias element ($path) is not a string", Alias::CANONICAL); 10804fd306cSNickeau } 10904fd306cSNickeau $path = WikiPath::createMarkupPathFromId($path); 11004fd306cSNickeau $aliases[] = Alias::create($this->getResource(), $path); 11104fd306cSNickeau } 11204fd306cSNickeau } 11304fd306cSNickeau return $aliases; 11404fd306cSNickeau } 11504fd306cSNickeau 11604fd306cSNickeau 11704fd306cSNickeau /** 11804fd306cSNickeau * @param Alias[] $aliases 11904fd306cSNickeau * @return null|array - the array to be saved in a text/json file 12004fd306cSNickeau */ 12104fd306cSNickeau public static function toMetadataArray(?array $aliases): ?array 12204fd306cSNickeau { 12304fd306cSNickeau if ($aliases === null) { 12404fd306cSNickeau return null; 12504fd306cSNickeau } 12604fd306cSNickeau $array = []; 12704fd306cSNickeau foreach ($aliases as $alias) { 12804fd306cSNickeau $array[$alias->getPath()->toAbsoluteId()] = [ 12904fd306cSNickeau AliasPath::PERSISTENT_NAME => $alias->getPath()->toAbsoluteId(), 13004fd306cSNickeau AliasType::PERSISTENT_NAME => $alias->getType() 13104fd306cSNickeau ]; 13204fd306cSNickeau } 13304fd306cSNickeau return array_values($array); 13404fd306cSNickeau } 13504fd306cSNickeau 13604fd306cSNickeau public static function getName(): string 13704fd306cSNickeau { 13804fd306cSNickeau return self::PROPERTY_NAME; 13904fd306cSNickeau } 14004fd306cSNickeau 14104fd306cSNickeau 14204fd306cSNickeau static public function getPersistenceType(): string 14304fd306cSNickeau { 14404fd306cSNickeau return MetadataDokuWikiStore::PERSISTENT_DOKUWIKI_KEY; 14504fd306cSNickeau } 14604fd306cSNickeau 14704fd306cSNickeau /** 14804fd306cSNickeau * Code refactoring 14904fd306cSNickeau * This method is not in the database page 15004fd306cSNickeau * because it would create a cycle 15104fd306cSNickeau * 15204fd306cSNickeau * The old data was saved in the database 15304fd306cSNickeau * but should have been saved on the file system 15404fd306cSNickeau * 15504fd306cSNickeau * Once 15604fd306cSNickeau * @return Alias[] 15704fd306cSNickeau * @throws ExceptionSqliteNotAvailable 15804fd306cSNickeau * @deprecated 2021-10-31 15904fd306cSNickeau */ 16004fd306cSNickeau private 16104fd306cSNickeau function getAndDeleteDeprecatedAlias(): array 16204fd306cSNickeau { 16304fd306cSNickeau $sqlite = Sqlite::createOrGetSqlite(); 16404fd306cSNickeau 16504fd306cSNickeau try { 16604fd306cSNickeau $canonicalOrDefault = $this->getResource()->getCanonicalOrDefault(); 16704fd306cSNickeau } catch (ExceptionNotFound $e) { 16804fd306cSNickeau return []; 16904fd306cSNickeau } 17004fd306cSNickeau /** @noinspection SqlResolve */ 17104fd306cSNickeau $request = $sqlite 17204fd306cSNickeau ->createRequest() 17304fd306cSNickeau ->setQueryParametrized("select ALIAS from DEPRECATED_PAGES_ALIAS where CANONICAL = ?", [$canonicalOrDefault]); 17404fd306cSNickeau $deprecatedAliases = []; 17504fd306cSNickeau $deprecatedAliasInDb = []; 17604fd306cSNickeau try { 17704fd306cSNickeau $deprecatedAliasInDb = $request 17804fd306cSNickeau ->execute() 17904fd306cSNickeau ->getRows(); 18004fd306cSNickeau } catch (ExceptionCompile $e) { 18104fd306cSNickeau LogUtility::msg("An exception has occurred with the deprecated alias selection query. {$e->getMessage()}"); 18204fd306cSNickeau return []; 18304fd306cSNickeau } finally { 18404fd306cSNickeau $request->close(); 18504fd306cSNickeau } 18604fd306cSNickeau 18704fd306cSNickeau array_map( 18804fd306cSNickeau function ($row) use ($deprecatedAliases) { 18904fd306cSNickeau $alias = $row['ALIAS']; 19004fd306cSNickeau $deprecatedAliases[$alias] = Alias::create($this->getResource(), $alias) 19104fd306cSNickeau ->setType(AliasType::REDIRECT); 19204fd306cSNickeau }, 19304fd306cSNickeau $deprecatedAliasInDb 19404fd306cSNickeau ); 19504fd306cSNickeau 19604fd306cSNickeau /** 19704fd306cSNickeau * Delete them 19804fd306cSNickeau */ 19904fd306cSNickeau 20004fd306cSNickeau if (sizeof($deprecatedAliasInDb) > 0) { 20104fd306cSNickeau /** @noinspection SqlResolve */ 20204fd306cSNickeau $request = $sqlite 20304fd306cSNickeau ->createRequest() 20404fd306cSNickeau ->setQueryParametrized("delete from DEPRECATED_PAGE_ALIASES where CANONICAL = ?", [$canonicalOrDefault]); 20504fd306cSNickeau try { 20604fd306cSNickeau $request->execute(); 20704fd306cSNickeau } catch (ExceptionCompile $e) { 20804fd306cSNickeau LogUtility::msg("An exception has occurred with the delete deprecated alias statement. {$e->getMessage()}", LogUtility::LVL_MSG_ERROR); 20904fd306cSNickeau } finally { 21004fd306cSNickeau $request->close(); 21104fd306cSNickeau } 21204fd306cSNickeau } 21304fd306cSNickeau 21404fd306cSNickeau 21504fd306cSNickeau /** 21604fd306cSNickeau * Return 21704fd306cSNickeau */ 21804fd306cSNickeau return $deprecatedAliases; 21904fd306cSNickeau 22004fd306cSNickeau } 22104fd306cSNickeau 22204fd306cSNickeau 22304fd306cSNickeau /** 22404fd306cSNickeau * @return Metadata[][] - an list of rows of metadata columns 22504fd306cSNickeau */ 22604fd306cSNickeau public function getDefaultValue(): array 22704fd306cSNickeau { 22804fd306cSNickeau return 22904fd306cSNickeau [ 23004fd306cSNickeau [ 23104fd306cSNickeau AliasPath::getPersistentName() => AliasPath::createForParent($this), 23204fd306cSNickeau AliasType::getPersistentName() => AliasType::createForParent($this)->setFromStoreValueWithoutException(AliasType::DEFAULT) 23304fd306cSNickeau ] 23404fd306cSNickeau ]; 23504fd306cSNickeau } 23604fd306cSNickeau 23704fd306cSNickeau 23804fd306cSNickeau public function getValue(): array 23904fd306cSNickeau { 24004fd306cSNickeau $this->buildCheck(); 24104fd306cSNickeau 24204fd306cSNickeau /** 24304fd306cSNickeau * We don't do that on build because 24404fd306cSNickeau * we are using a set a metadata method that creates 24504fd306cSNickeau * a cycle via the {@link MetadataMutation::PAGE_METADATA_MUTATION_EVENT} 24604fd306cSNickeau */ 24704fd306cSNickeau if ( 24804fd306cSNickeau !$this->valueIsNotNull() 24904fd306cSNickeau && 25004fd306cSNickeau $this->getReadStore() !== null 25104fd306cSNickeau && 25204fd306cSNickeau $this->getReadStore() instanceof MetadataDokuWikiStore 25304fd306cSNickeau ) { 25404fd306cSNickeau $this->getAndDeleteDeprecatedAlias(); 25504fd306cSNickeau /** 25604fd306cSNickeau * To validate the migration we set a value 25704fd306cSNickeau * (the array may be empty) 25804fd306cSNickeau */ 25904fd306cSNickeau try { 26004fd306cSNickeau $this->sendToWriteStore(); 26104fd306cSNickeau } catch (ExceptionCompile $e) { 26204fd306cSNickeau LogUtility::msg("Error while persisting the new data"); 26304fd306cSNickeau } 26404fd306cSNickeau } 26504fd306cSNickeau 26604fd306cSNickeau return parent::getValue(); 26704fd306cSNickeau } 26804fd306cSNickeau 26904fd306cSNickeau /** 27004fd306cSNickeau * @throws ExceptionCompile 27104fd306cSNickeau */ 27204fd306cSNickeau public 27304fd306cSNickeau function addAlias(string $aliasPath, $aliasType = null): Aliases 27404fd306cSNickeau { 27504fd306cSNickeau $this->addAndGetAlias($aliasPath, $aliasType); 27604fd306cSNickeau return $this; 27704fd306cSNickeau } 27804fd306cSNickeau 27904fd306cSNickeau /** 28004fd306cSNickeau * @throws ExceptionCompile 28104fd306cSNickeau */ 28204fd306cSNickeau public 28304fd306cSNickeau function addAndGetAlias($aliasPath, $aliasType = null): Alias 28404fd306cSNickeau { 28504fd306cSNickeau $this->buildCheck(); 28604fd306cSNickeau /** 28704fd306cSNickeau * @var AliasPath $path 28804fd306cSNickeau */ 28904fd306cSNickeau $path = MetadataSystem::toMetadataObject(AliasPath::class, $this) 29004fd306cSNickeau ->setFromStoreValue($aliasPath); 29104fd306cSNickeau $row[$path::getPersistentName()] = $path; 29204fd306cSNickeau 29304fd306cSNickeau $alias = Alias::create($this->getResource(), $path->getValue()); 29404fd306cSNickeau 29504fd306cSNickeau if ($aliasType !== null) { 29604fd306cSNickeau $aliasObject = MetadataSystem::toMetadataObject(AliasType::class, $this) 29704fd306cSNickeau ->setFromStoreValue($aliasType); 29804fd306cSNickeau $row[$aliasObject::getPersistentName()] = $aliasObject; 29904fd306cSNickeau $alias->setType($aliasType); 30004fd306cSNickeau } 30104fd306cSNickeau $this->rows[$path->getValue()->toAbsoluteId()] = $row; 30204fd306cSNickeau 30304fd306cSNickeau return $alias; 30404fd306cSNickeau } 30504fd306cSNickeau 30604fd306cSNickeau 30704fd306cSNickeau static public 30804fd306cSNickeau function getCanonical(): string 30904fd306cSNickeau { 31004fd306cSNickeau return Alias::CANONICAL; 31104fd306cSNickeau } 31204fd306cSNickeau 31304fd306cSNickeau static public 31404fd306cSNickeau function getTab(): string 31504fd306cSNickeau { 31604fd306cSNickeau return MetaManagerForm::TAB_REDIRECTION_VALUE; 31704fd306cSNickeau } 31804fd306cSNickeau 31904fd306cSNickeau static public 32004fd306cSNickeau function getDescription(): string 32104fd306cSNickeau { 32204fd306cSNickeau return "Aliases that will redirect to this page."; 32304fd306cSNickeau } 32404fd306cSNickeau 32504fd306cSNickeau static public function getLabel(): string 32604fd306cSNickeau { 32704fd306cSNickeau return "Page Aliases"; 32804fd306cSNickeau } 32904fd306cSNickeau 33004fd306cSNickeau 33104fd306cSNickeau static public function isMutable(): bool 33204fd306cSNickeau { 33304fd306cSNickeau return true; 33404fd306cSNickeau } 33504fd306cSNickeau 33604fd306cSNickeau public function getUidClass(): ?string 33704fd306cSNickeau { 33804fd306cSNickeau return AliasPath::class; 33904fd306cSNickeau } 34004fd306cSNickeau 34104fd306cSNickeau /** 34204fd306cSNickeau * @return Metadata[] 34304fd306cSNickeau */ 34404fd306cSNickeau static public function getChildrenClass(): array 34504fd306cSNickeau { 34604fd306cSNickeau return [AliasPath::class, AliasType::class]; 34704fd306cSNickeau } 34804fd306cSNickeau 34904fd306cSNickeau 35004fd306cSNickeau static public function isOnForm(): bool 35104fd306cSNickeau { 35204fd306cSNickeau return true; 35304fd306cSNickeau } 35404fd306cSNickeau} 355