xref: /plugin/combo/action/metamanager.php (revision c3437056399326d621a01da73b649707fbb0ae69)
1*c3437056SNickeau<?php
2*c3437056SNickeau
3*c3437056SNickeaurequire_once(__DIR__ . '/../ComboStrap/PluginUtility.php');
4*c3437056SNickeau
5*c3437056SNickeauuse ComboStrap\DataType;
6*c3437056SNickeauuse ComboStrap\ExceptionCombo;
7*c3437056SNickeauuse ComboStrap\FormMeta;
8*c3437056SNickeauuse ComboStrap\FormMetaField;
9*c3437056SNickeauuse ComboStrap\HttpResponse;
10*c3437056SNickeauuse ComboStrap\Identity;
11*c3437056SNickeauuse ComboStrap\Json;
12*c3437056SNickeauuse ComboStrap\LowQualityPageOverwrite;
13*c3437056SNickeauuse ComboStrap\Message;
14*c3437056SNickeauuse ComboStrap\Metadata;
15*c3437056SNickeauuse ComboStrap\MetadataDokuWikiStore;
16*c3437056SNickeauuse ComboStrap\MetadataFormDataStore;
17*c3437056SNickeauuse ComboStrap\MetadataFrontmatterStore;
18*c3437056SNickeauuse ComboStrap\MetadataStoreTransfer;
19*c3437056SNickeauuse ComboStrap\MetaManagerForm;
20*c3437056SNickeauuse ComboStrap\MetaManagerMenuItem;
21*c3437056SNickeauuse ComboStrap\Mime;
22*c3437056SNickeauuse ComboStrap\Page;
23*c3437056SNickeauuse ComboStrap\PluginUtility;
24*c3437056SNickeauuse ComboStrap\QualityDynamicMonitoringOverwrite;
25*c3437056SNickeau
26*c3437056SNickeauif (!defined('DOKU_INC')) die();
27*c3437056SNickeau
28*c3437056SNickeau/**
29*c3437056SNickeau *
30*c3437056SNickeau * Save metadata that were send by ajax
31*c3437056SNickeau */
32*c3437056SNickeauclass action_plugin_combo_metamanager extends DokuWiki_Action_Plugin
33*c3437056SNickeau{
34*c3437056SNickeau
35*c3437056SNickeau
36*c3437056SNickeau    const META_MANAGER_CALL_ID = "combo-meta-manager";
37*c3437056SNickeau    const META_VIEWER_CALL_ID = "combo-meta-viewer";
38*c3437056SNickeau
39*c3437056SNickeau    const CANONICAL = "meta-manager";
40*c3437056SNickeau
41*c3437056SNickeau
42*c3437056SNickeau
43*c3437056SNickeau    /**
44*c3437056SNickeau     * The canonical for the metadata page
45*c3437056SNickeau     */
46*c3437056SNickeau    const METADATA_CANONICAL = "metadata";
47*c3437056SNickeau
48*c3437056SNickeau    const SUCCESS_MESSAGE = "The data were updated without errors.";
49*c3437056SNickeau
50*c3437056SNickeau
51*c3437056SNickeau    public function register(Doku_Event_Handler $controller)
52*c3437056SNickeau    {
53*c3437056SNickeau
54*c3437056SNickeau        /**
55*c3437056SNickeau         * The ajax api to return data
56*c3437056SNickeau         */
57*c3437056SNickeau        $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, '_ajax_call');
58*c3437056SNickeau
59*c3437056SNickeau        /**
60*c3437056SNickeau         * Add a icon in the page tools menu
61*c3437056SNickeau         * https://www.dokuwiki.org/devel:event:menu_items_assembly
62*c3437056SNickeau         */
63*c3437056SNickeau        $controller->register_hook('MENU_ITEMS_ASSEMBLY', 'AFTER', $this, 'handle_rail_bar');
64*c3437056SNickeau    }
65*c3437056SNickeau
66*c3437056SNickeau    /**
67*c3437056SNickeau     * Handle Metadata HTTP ajax requests
68*c3437056SNickeau     * @param $event Doku_Event
69*c3437056SNickeau     *
70*c3437056SNickeau     *
71*c3437056SNickeau     * https://www.dokuwiki.org/devel:plugin_programming_tips#handle_json_ajax_request
72*c3437056SNickeau     *
73*c3437056SNickeau     * CSRF checks are only for logged in users
74*c3437056SNickeau     * This is public ({@link getSecurityToken()}
75*c3437056SNickeau     */
76*c3437056SNickeau    function _ajax_call(Doku_Event &$event): void
77*c3437056SNickeau    {
78*c3437056SNickeau
79*c3437056SNickeau        $call = $event->data;
80*c3437056SNickeau        if (!in_array($call, [self::META_MANAGER_CALL_ID, self::META_VIEWER_CALL_ID])) {
81*c3437056SNickeau            return;
82*c3437056SNickeau        }
83*c3437056SNickeau        //no other ajax call handlers needed
84*c3437056SNickeau        $event->stopPropagation();
85*c3437056SNickeau        $event->preventDefault();
86*c3437056SNickeau
87*c3437056SNickeau        /**
88*c3437056SNickeau         * Shared check between post and get HTTP method
89*c3437056SNickeau         */
90*c3437056SNickeau        $id = $_GET["id"];
91*c3437056SNickeau        if ($id === null) {
92*c3437056SNickeau            /**
93*c3437056SNickeau             * With {@link TestRequest}
94*c3437056SNickeau             * for instance
95*c3437056SNickeau             */
96*c3437056SNickeau            $id = $_REQUEST["id"];
97*c3437056SNickeau        }
98*c3437056SNickeau
99*c3437056SNickeau        if (empty($id)) {
100*c3437056SNickeau            HttpResponse::create(HttpResponse::STATUS_BAD_REQUEST)
101*c3437056SNickeau                ->setEvent($event)
102*c3437056SNickeau                ->setCanonical(self::CANONICAL)
103*c3437056SNickeau                ->sendMessage("The page path (id form) is empty");
104*c3437056SNickeau            return;
105*c3437056SNickeau        }
106*c3437056SNickeau        $page = Page::createPageFromId($id);
107*c3437056SNickeau        if (!$page->exists()) {
108*c3437056SNickeau            HttpResponse::create(HttpResponse::STATUS_DOES_NOT_EXIST)
109*c3437056SNickeau                ->setEvent($event)
110*c3437056SNickeau                ->setCanonical(self::CANONICAL)
111*c3437056SNickeau                ->sendMessage("The page ($id) does not exist");
112*c3437056SNickeau            return;
113*c3437056SNickeau        }
114*c3437056SNickeau
115*c3437056SNickeau        /**
116*c3437056SNickeau         * Security
117*c3437056SNickeau         */
118*c3437056SNickeau        if (!$page->canBeUpdatedByCurrentUser()) {
119*c3437056SNickeau            $user = Identity::getUser();
120*c3437056SNickeau            HttpResponse::create(HttpResponse::STATUS_NOT_AUTHORIZED)
121*c3437056SNickeau                ->setEvent($event)
122*c3437056SNickeau                ->setCanonical(self::CANONICAL)
123*c3437056SNickeau                ->sendMessage("Not Authorized: The user ($user) has not the `write` permission for the page (:$id).");
124*c3437056SNickeau            return;
125*c3437056SNickeau        }
126*c3437056SNickeau
127*c3437056SNickeau        /**
128*c3437056SNickeau         * Functional code
129*c3437056SNickeau         */
130*c3437056SNickeau
131*c3437056SNickeau        $requestMethod = $_SERVER['REQUEST_METHOD'];
132*c3437056SNickeau        switch ($requestMethod) {
133*c3437056SNickeau            case 'POST':
134*c3437056SNickeau
135*c3437056SNickeau                if ($_SERVER["CONTENT_TYPE"] !== "application/json") {
136*c3437056SNickeau                    /**
137*c3437056SNickeau                     * We can't set the mime content in a {@link TestRequest}
138*c3437056SNickeau                     */
139*c3437056SNickeau                    if (!PluginUtility::isTest()) {
140*c3437056SNickeau                        HttpResponse::create(HttpResponse::STATUS_UNSUPPORTED_MEDIA_TYPE)
141*c3437056SNickeau                            ->setEvent($event)
142*c3437056SNickeau                            ->setCanonical(self::CANONICAL)
143*c3437056SNickeau                            ->sendMessage("The post content should be in json format");
144*c3437056SNickeau                        return;
145*c3437056SNickeau                    }
146*c3437056SNickeau                }
147*c3437056SNickeau
148*c3437056SNickeau                /**
149*c3437056SNickeau                 * We can't simulate a php://input in a {@link TestRequest}
150*c3437056SNickeau                 * We set therefore the post
151*c3437056SNickeau                 */
152*c3437056SNickeau                if (!PluginUtility::isTest()) {
153*c3437056SNickeau                    $jsonString = file_get_contents('php://input');
154*c3437056SNickeau                    $_POST = Json::createFromString($jsonString)->toArray();
155*c3437056SNickeau                }
156*c3437056SNickeau
157*c3437056SNickeau                if ($call === self::META_MANAGER_CALL_ID) {
158*c3437056SNickeau                    $this->handleManagerPost($event, $page, $_POST);
159*c3437056SNickeau                } else {
160*c3437056SNickeau                    $this->handleViewerPost($event, $page, $_POST);
161*c3437056SNickeau                }
162*c3437056SNickeau
163*c3437056SNickeau                return;
164*c3437056SNickeau            case "GET":
165*c3437056SNickeau
166*c3437056SNickeau                if ($call === self::META_MANAGER_CALL_ID) {
167*c3437056SNickeau                    $this->handleManagerGet($event, $page);
168*c3437056SNickeau                } else {
169*c3437056SNickeau                    $this->handleViewerGet($event, $page);
170*c3437056SNickeau                }
171*c3437056SNickeau                return;
172*c3437056SNickeau
173*c3437056SNickeau        }
174*c3437056SNickeau
175*c3437056SNickeau    }
176*c3437056SNickeau
177*c3437056SNickeau    public function handle_rail_bar(Doku_Event $event, $param)
178*c3437056SNickeau    {
179*c3437056SNickeau
180*c3437056SNickeau        if (!Identity::isWriter()) {
181*c3437056SNickeau            return;
182*c3437056SNickeau        }
183*c3437056SNickeau
184*c3437056SNickeau        /**
185*c3437056SNickeau         * The `view` property defines the menu that is currently built
186*c3437056SNickeau         * https://www.dokuwiki.org/devel:menus
187*c3437056SNickeau         * If this is not the page menu, return
188*c3437056SNickeau         */
189*c3437056SNickeau        if ($event->data['view'] != 'page') return;
190*c3437056SNickeau
191*c3437056SNickeau        global $INFO;
192*c3437056SNickeau        if (!$INFO['exists']) {
193*c3437056SNickeau            return;
194*c3437056SNickeau        }
195*c3437056SNickeau        array_splice($event->data['items'], -1, 0, array(new MetaManagerMenuItem()));
196*c3437056SNickeau
197*c3437056SNickeau    }
198*c3437056SNickeau
199*c3437056SNickeau    /**
200*c3437056SNickeau     * @param $event
201*c3437056SNickeau     * @param Page $page
202*c3437056SNickeau     * @param array $post
203*c3437056SNickeau     */
204*c3437056SNickeau    private function handleManagerPost($event, Page $page, array $post)
205*c3437056SNickeau    {
206*c3437056SNickeau
207*c3437056SNickeau        $formStore = MetadataFormDataStore::getOrCreateFromResource($page, $post);
208*c3437056SNickeau        $targetStore = MetadataDokuWikiStore::getOrCreateFromResource($page);
209*c3437056SNickeau
210*c3437056SNickeau        /**
211*c3437056SNickeau         * Boolean form field (default values)
212*c3437056SNickeau         * are not send back by the HTML form
213*c3437056SNickeau         */
214*c3437056SNickeau        $defaultBooleanMetadata = [
215*c3437056SNickeau            LowQualityPageOverwrite::PROPERTY_NAME,
216*c3437056SNickeau            QualityDynamicMonitoringOverwrite::PROPERTY_NAME
217*c3437056SNickeau        ];
218*c3437056SNickeau        $defaultBoolean = [];
219*c3437056SNickeau        foreach ($defaultBooleanMetadata as $booleanMeta) {
220*c3437056SNickeau            $metadata = Metadata::getForName($booleanMeta)
221*c3437056SNickeau                ->setResource($page)
222*c3437056SNickeau                ->setReadStore($formStore)
223*c3437056SNickeau                ->setWriteStore($targetStore);
224*c3437056SNickeau            $defaultBoolean[$metadata::getName()] = $metadata->toStoreDefaultValue();
225*c3437056SNickeau        }
226*c3437056SNickeau        $post = array_merge($defaultBoolean, $post);
227*c3437056SNickeau
228*c3437056SNickeau        /**
229*c3437056SNickeau         * Processing
230*c3437056SNickeau         */
231*c3437056SNickeau        $transfer = MetadataStoreTransfer::createForPage($page)
232*c3437056SNickeau            ->fromStore($formStore)
233*c3437056SNickeau            ->toStore($targetStore)
234*c3437056SNickeau            ->process($post);
235*c3437056SNickeau        $processingMessages = $transfer->getMessages();
236*c3437056SNickeau
237*c3437056SNickeau
238*c3437056SNickeau        $responseMessages = [];
239*c3437056SNickeau        $responseStatus = HttpResponse::STATUS_ALL_GOOD;
240*c3437056SNickeau        foreach ($processingMessages as $upsertMessages) {
241*c3437056SNickeau            $responseMessage = [ucfirst($upsertMessages->getType())];
242*c3437056SNickeau            $documentationHyperlink = $upsertMessages->getDocumentationHyperLink();
243*c3437056SNickeau            if ($documentationHyperlink !== null) {
244*c3437056SNickeau                $responseMessage[] = $documentationHyperlink;
245*c3437056SNickeau            }
246*c3437056SNickeau            $responseMessage[] = $upsertMessages->getContent(Mime::PLAIN_TEXT);
247*c3437056SNickeau            $responseMessages[] = implode(" - ", $responseMessage);
248*c3437056SNickeau            if ($upsertMessages->getType() === Message::TYPE_ERROR && $responseStatus !== HttpResponse::STATUS_BAD_REQUEST) {
249*c3437056SNickeau                $responseStatus = HttpResponse::STATUS_BAD_REQUEST;
250*c3437056SNickeau            }
251*c3437056SNickeau        }
252*c3437056SNickeau
253*c3437056SNickeau        if (sizeof($responseMessages) === 0) {
254*c3437056SNickeau            $responseMessages[] = self::SUCCESS_MESSAGE;
255*c3437056SNickeau        }
256*c3437056SNickeau
257*c3437056SNickeau        try {
258*c3437056SNickeau            $frontMatterMessage = MetadataFrontmatterStore::createFromPage($page)
259*c3437056SNickeau                ->sync();
260*c3437056SNickeau            $responseMessages[] = $frontMatterMessage->getPlainTextContent();
261*c3437056SNickeau        } catch (ExceptionCombo $e) {
262*c3437056SNickeau            $responseMessages[] = $e->getMessage();
263*c3437056SNickeau        }
264*c3437056SNickeau
265*c3437056SNickeau
266*c3437056SNickeau        /**
267*c3437056SNickeau         * Response
268*c3437056SNickeau         */
269*c3437056SNickeau        HttpResponse::create(HttpResponse::STATUS_ALL_GOOD)
270*c3437056SNickeau            ->setEvent($event)
271*c3437056SNickeau            ->sendMessage($responseMessages);
272*c3437056SNickeau
273*c3437056SNickeau
274*c3437056SNickeau    }
275*c3437056SNickeau
276*c3437056SNickeau    /**
277*c3437056SNickeau     * @param Doku_Event $event
278*c3437056SNickeau     * @param Page $page
279*c3437056SNickeau     * @throws ExceptionCombo
280*c3437056SNickeau     */
281*c3437056SNickeau    private
282*c3437056SNickeau    function handleManagerGet(Doku_Event $event, Page $page)
283*c3437056SNickeau    {
284*c3437056SNickeau        $formMeta = MetaManagerForm::createForPage($page)->toFormMeta();
285*c3437056SNickeau        $payload = json_encode($formMeta->toAssociativeArray());
286*c3437056SNickeau        HttpResponse::create(HttpResponse::STATUS_ALL_GOOD)
287*c3437056SNickeau            ->setEvent($event)
288*c3437056SNickeau            ->send($payload, Mime::JSON);
289*c3437056SNickeau    }
290*c3437056SNickeau
291*c3437056SNickeau    /**
292*c3437056SNickeau     * @param Doku_Event $event
293*c3437056SNickeau     * @param Page $page
294*c3437056SNickeau     */
295*c3437056SNickeau    private function handleViewerGet(Doku_Event $event, Page $page)
296*c3437056SNickeau    {
297*c3437056SNickeau        if (!Identity::isManager()) {
298*c3437056SNickeau            HttpResponse::create(HttpResponse::STATUS_NOT_AUTHORIZED)
299*c3437056SNickeau                ->setEvent($event)
300*c3437056SNickeau                ->setCanonical(self::CANONICAL)
301*c3437056SNickeau                ->sendMessage("Not Authorized (managers only)");
302*c3437056SNickeau            return;
303*c3437056SNickeau        }
304*c3437056SNickeau        $metadata = MetadataDokuWikiStore::getOrCreateFromResource($page)->getData();
305*c3437056SNickeau        $persistent = $metadata[MetadataDokuWikiStore::PERSISTENT_METADATA];
306*c3437056SNickeau        ksort($persistent);
307*c3437056SNickeau        $current = $metadata[MetadataDokuWikiStore::CURRENT_METADATA];
308*c3437056SNickeau        ksort($current);
309*c3437056SNickeau        $form = FormMeta::create("raw_metadata")
310*c3437056SNickeau            ->addField(
311*c3437056SNickeau                FormMetaField::create(MetadataDokuWikiStore::PERSISTENT_METADATA)
312*c3437056SNickeau                    ->setLabel("Persistent Metadata (User Metadata)")
313*c3437056SNickeau                    ->setTab("persistent")
314*c3437056SNickeau                    ->setDescription("The persistent metadata contains raw values. They contains the values set by the user and the fixed values such as page id.")
315*c3437056SNickeau                    ->addValue(json_encode($persistent))
316*c3437056SNickeau                    ->setType(DataType::JSON_TYPE_VALUE)
317*c3437056SNickeau            )
318*c3437056SNickeau            ->addField(FormMetaField::create(MetadataDokuWikiStore::CURRENT_METADATA)
319*c3437056SNickeau                ->setLabel("Current (Derived) Metadata")
320*c3437056SNickeau                ->setTab("current")
321*c3437056SNickeau                ->setDescription("The current metadata are the derived / calculated / runtime metadata values (extended with the persistent metadata).")
322*c3437056SNickeau                ->addValue(json_encode($current))
323*c3437056SNickeau                ->setType(DataType::JSON_TYPE_VALUE)
324*c3437056SNickeau                ->setMutable(false)
325*c3437056SNickeau            )
326*c3437056SNickeau            ->toAssociativeArray();
327*c3437056SNickeau
328*c3437056SNickeau        HttpResponse::create(HttpResponse::STATUS_ALL_GOOD)
329*c3437056SNickeau            ->setEvent($event)
330*c3437056SNickeau            ->setCanonical(self::CANONICAL)
331*c3437056SNickeau            ->send(json_encode($form), Mime::JSON);
332*c3437056SNickeau
333*c3437056SNickeau    }
334*c3437056SNickeau
335*c3437056SNickeau    private function handleViewerPost(Doku_Event $event, Page $page, array $post)
336*c3437056SNickeau    {
337*c3437056SNickeau
338*c3437056SNickeau        $metadataStore = MetadataDokuWikiStore::getOrCreateFromResource($page);
339*c3437056SNickeau        $metaData = $metadataStore->getData();
340*c3437056SNickeau
341*c3437056SNickeau        /**
342*c3437056SNickeau         * @var Message[]
343*c3437056SNickeau         */
344*c3437056SNickeau        $messages = [];
345*c3437056SNickeau        /**
346*c3437056SNickeau         * Only Persistent, current cannot be modified
347*c3437056SNickeau         */
348*c3437056SNickeau        $persistentMetadataType = MetadataDokuWikiStore::PERSISTENT_METADATA;
349*c3437056SNickeau        $postMeta = json_decode($post[$persistentMetadataType], true);
350*c3437056SNickeau        if ($postMeta === null) {
351*c3437056SNickeau            HttpResponse::create(HttpResponse::STATUS_BAD_REQUEST)
352*c3437056SNickeau                ->setEvent($event)
353*c3437056SNickeau                ->sendMessage("The metadata $persistentMetadataType should be in json format");
354*c3437056SNickeau            return;
355*c3437056SNickeau        }
356*c3437056SNickeau        $persistentPageMeta = &$metaData[$persistentMetadataType];
357*c3437056SNickeau
358*c3437056SNickeau
359*c3437056SNickeau        $managedMetaMessageSuffix = "is a managed metadata, you need to use the metadata manager to delete it";
360*c3437056SNickeau
361*c3437056SNickeau        /**
362*c3437056SNickeau         * Process the actual attribute
363*c3437056SNickeau         */
364*c3437056SNickeau        foreach ($persistentPageMeta as $key => $value) {
365*c3437056SNickeau            $postMetaValue = null;
366*c3437056SNickeau            if (isset($postMeta[$key])) {
367*c3437056SNickeau                $postMetaValue = $postMeta[$key];
368*c3437056SNickeau                unset($postMeta[$key]);
369*c3437056SNickeau            }
370*c3437056SNickeau
371*c3437056SNickeau            if ($postMetaValue === null) {
372*c3437056SNickeau                if (in_array($key, Metadata::MUTABLE_METADATA)) {
373*c3437056SNickeau                    $messages[] = Message::createInfoMessage("The $persistentMetadataType metadata ($key) $managedMetaMessageSuffix");
374*c3437056SNickeau                    continue;
375*c3437056SNickeau                }
376*c3437056SNickeau                if (in_array($key, Metadata::NOT_MODIFIABLE_PERSISTENT_METADATA)) {
377*c3437056SNickeau                    $messages[] = Message::createInfoMessage("The $persistentMetadataType metadata ($key) is a internal metadata, you can't delete it");
378*c3437056SNickeau                    continue;
379*c3437056SNickeau                }
380*c3437056SNickeau                unset($persistentPageMeta[$key]);
381*c3437056SNickeau                $messages[] = Message::createInfoMessage("The $persistentMetadataType metadata ($key) with the value ($value) was deleted");
382*c3437056SNickeau            } else {
383*c3437056SNickeau                if ($value !== $postMetaValue) {
384*c3437056SNickeau                    if (in_array($key, Metadata::MUTABLE_METADATA)) {
385*c3437056SNickeau                        $messages[] = Message::createInfoMessage("The $persistentMetadataType metadata ($key) $managedMetaMessageSuffix");
386*c3437056SNickeau                        continue;
387*c3437056SNickeau                    }
388*c3437056SNickeau                    if (in_array($key, Metadata::NOT_MODIFIABLE_PERSISTENT_METADATA)) {
389*c3437056SNickeau                        $messages[] = Message::createInfoMessage("The $persistentMetadataType metadata ($key) is a internal metadata, you can't modify it");
390*c3437056SNickeau                        continue;
391*c3437056SNickeau                    }
392*c3437056SNickeau                    $persistentPageMeta[$key] = $postMetaValue;
393*c3437056SNickeau                    $messages[] = Message::createInfoMessage("The $persistentMetadataType metadata ($key) was updated to the value ($postMetaValue) - Old value ($value)");
394*c3437056SNickeau                }
395*c3437056SNickeau            }
396*c3437056SNickeau        }
397*c3437056SNickeau        /**
398*c3437056SNickeau         * Process the new attribute
399*c3437056SNickeau         */
400*c3437056SNickeau        foreach ($postMeta as $key => $value) {
401*c3437056SNickeau            if (in_array($key, Metadata::MUTABLE_METADATA)) {
402*c3437056SNickeau                // This meta should be modified via the form
403*c3437056SNickeau                $messages[] = Message::createInfoMessage("The $persistentMetadataType metadata ($key) can only be added via the meta manager");
404*c3437056SNickeau                continue;
405*c3437056SNickeau            }
406*c3437056SNickeau            if (in_array($key, Metadata::NOT_MODIFIABLE_PERSISTENT_METADATA)) {
407*c3437056SNickeau                // this meta are not modifiable
408*c3437056SNickeau                $messages[] = Message::createInfoMessage("The $persistentMetadataType metadata ($key) is a internal metadata, you can't modify it");
409*c3437056SNickeau                continue;
410*c3437056SNickeau            }
411*c3437056SNickeau            $persistentPageMeta[$key] = $value;
412*c3437056SNickeau            $messages[] = Message::createInfoMessage("The $persistentMetadataType metadata ($key) was created with the value ($value)");
413*c3437056SNickeau        }
414*c3437056SNickeau
415*c3437056SNickeau        /**
416*c3437056SNickeau         * Delete the runtime if present
417*c3437056SNickeau         * (They were saved in persistent)
418*c3437056SNickeau         */
419*c3437056SNickeau        Metadata::deleteIfPresent($persistentPageMeta, Metadata::RUNTIME_META);
420*c3437056SNickeau
421*c3437056SNickeau        p_save_metadata($page->getDokuwikiId(), $metaData);
422*c3437056SNickeau        $metadataStore->setData($metaData);
423*c3437056SNickeau
424*c3437056SNickeau        if (sizeof($messages) !== 0) {
425*c3437056SNickeau            $messagesToSend = [];
426*c3437056SNickeau            foreach ($messages as $message) {
427*c3437056SNickeau                $messagesToSend[] = $message->getPlainTextContent();
428*c3437056SNickeau            }
429*c3437056SNickeau        } else {
430*c3437056SNickeau            $messagesToSend = "No metadata has been changed.";
431*c3437056SNickeau        }
432*c3437056SNickeau        HttpResponse::create(HttpResponse::STATUS_ALL_GOOD)
433*c3437056SNickeau            ->setEvent($event)
434*c3437056SNickeau            ->sendMessage($messagesToSend);
435*c3437056SNickeau
436*c3437056SNickeau    }
437*c3437056SNickeau
438*c3437056SNickeau
439*c3437056SNickeau}
440