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