xref: /template/strap/ComboStrap/Meta/Field/Aliases.php (revision 70bbd7f1f72440223cc13f3495efdcb2b0a11514)
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