Reset the internal state of the embedded object manager to its previous state (#4021)
authorAlexander Ebert <ebert@woltlab.com>
Wed, 24 Feb 2021 15:56:30 +0000 (16:56 +0100)
committerGitHub <noreply@github.com>
Wed, 24 Feb 2021 15:56:30 +0000 (16:56 +0100)
* Reset the internal state of the embedded object manager to its previous state

See #4018

* Isolate the active message for each call

* Typo

* Redundant call to a semi internal API

* Explicit global scope for `array_pop`

wcfsetup/install/files/lib/system/html/output/HtmlOutputProcessor.class.php
wcfsetup/install/files/lib/system/message/embedded/object/MessageEmbeddedObjectManager.class.php
wcfsetup/install/files/lib/system/user/signature/SignatureCache.class.php

index 0a6a1296f8f81320d8361806a2207cbcda2a6c4c..547c38f2b04597dd19dbccdc4ccc892c66e9d176 100644 (file)
@@ -65,11 +65,18 @@ class HtmlOutputProcessor extends AbstractHtmlProcessor {
        public function process($html, $objectType, $objectID, $doKeywordHighlighting = true, $languageID = null) {
                $this->languageID = $languageID;
                $this->setContext($objectType, $objectID);
-               
-               $this->getHtmlOutputNodeProcessor()->setOutputType($this->outputType);
-               $this->getHtmlOutputNodeProcessor()->enableKeywordHighlighting($doKeywordHighlighting);
-               $this->getHtmlOutputNodeProcessor()->load($this, $html);
-               $this->getHtmlOutputNodeProcessor()->process();
+
+               MessageEmbeddedObjectManager::getInstance()->setActiveMessage($objectType, $objectID, $this->languageID);
+
+               try {
+                       $this->getHtmlOutputNodeProcessor()->setOutputType($this->outputType);
+                       $this->getHtmlOutputNodeProcessor()->enableKeywordHighlighting($doKeywordHighlighting);
+                       $this->getHtmlOutputNodeProcessor()->load($this, $html);
+                       $this->getHtmlOutputNodeProcessor()->process();
+               }
+               finally {
+                       MessageEmbeddedObjectManager::getInstance()->reset();
+               }
        }
        
        /**
@@ -90,7 +97,17 @@ class HtmlOutputProcessor extends AbstractHtmlProcessor {
         * @inheritDoc
         */
        public function getHtml() {
-               return $this->getHtmlOutputNodeProcessor()->getHtml();
+               $context = $this->getContext();
+               MessageEmbeddedObjectManager::getInstance()->setActiveMessage($context['objectType'], $context['objectID'], $this->languageID);
+
+               try {
+                       $html = $this->getHtmlOutputNodeProcessor()->getHtml();
+               }
+               finally {
+                       MessageEmbeddedObjectManager::getInstance()->reset();
+               }
+
+               return $html;
        }
        
        /**
@@ -100,7 +117,6 @@ class HtmlOutputProcessor extends AbstractHtmlProcessor {
        public function setContext($objectType, $objectID) {
                parent::setContext($objectType, $objectID);
                
-               MessageEmbeddedObjectManager::getInstance()->setActiveMessage($objectType, $objectID, $this->languageID);
                $objectType = ObjectTypeCache::getInstance()->getObjectTypeByName('com.woltlab.wcf.message', $objectType);
                if ($this->enableToc === null) {
                        $this->enableToc = (!empty($objectType->additionalData['enableToc']));
index f7aef7d9a3c483172b1e910c059b0e151f0f42fe..d9af6697608b1a767a0f10e7869d2ca2881b9871 100644 (file)
@@ -66,6 +66,12 @@ class MessageEmbeddedObjectManager extends SingletonFactory {
                'insert' => [],
                'remove' => []
        ];
+
+       /**
+        * A list of previous active message settings used to restore
+        * the internal state in case of nested message processing.
+        */
+       protected $activeMessageHistory = [];
        
        /**
         * Registers the embedded objects found in given message.
@@ -283,10 +289,36 @@ class MessageEmbeddedObjectManager extends SingletonFactory {
         * @param       integer         $languageID
         */
        public function setActiveMessage($messageObjectType, $messageID, $languageID = null) {
+               if ($this->activeMessageObjectTypeID) {
+                       $this->activeMessageHistory[] = [
+                               'activeMessageID' => $this->activeMessageID,
+                               'activeMessageLanguageID' => $this->activeMessageLanguageID,
+                               'activeMessageObjectTypeID' => $this->activeMessageObjectTypeID,
+                       ];
+               }
+
                $this->activeMessageObjectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName('com.woltlab.wcf.message', $messageObjectType);
                $this->activeMessageID = $messageID;
                $this->activeMessageLanguageID = $languageID;
        }
+
+       /**
+        * Restores the internal state in case of nested message processing.
+        */
+       public function reset() {
+               $newState = \array_pop($this->activeMessageHistory);
+               if ($newState === null) {
+                       $newState = [
+                               'activeMessageID' => null,
+                               'activeMessageLanguageID' => null,
+                               'activeMessageObjectTypeID' => null,
+                       ];
+               }
+
+               $this->activeMessageID = $newState['activeMessageID'];
+               $this->activeMessageLanguageID = $newState['activeMessageLanguageID'];
+               $this->activeMessageObjectTypeID = $newState['activeMessageObjectTypeID'];
+       }
        
        /**
         * Returns the language id of the active message.
index ce9e8080e481203f2c1c3cf5b7cacaf411e3bf80..85b52fb7c37ddaeffe5054251fb9d01f4fff50c9 100644 (file)
@@ -47,7 +47,6 @@ class SignatureCache extends SingletonFactory {
                                $this->cacheUserSignature([$user->userID]);
                        }
                        
-                       $this->htmlOutputProcessor->setContext('com.woltlab.wcf.user.signature', $user->userID);
                        $this->htmlOutputProcessor->process($user->signature, 'com.woltlab.wcf.user.signature', $user->userID);
                        $this->signatures[$user->userID] = $this->htmlOutputProcessor->getHtml();
                }