Cache likeable objects to avoid multiple queries
authorJoshua Rüsweg <josh@bastelstu.be>
Wed, 8 Aug 2018 10:50:46 +0000 (12:50 +0200)
committerJoshua Rüsweg <josh@bastelstu.be>
Wed, 8 Aug 2018 10:50:46 +0000 (12:50 +0200)
See #2665

wcfsetup/install/files/lib/system/reaction/ReactionHandler.class.php

index fd0017b67e8fd75d5031ed387bdd230c95d6b13a..a4b8b7b1cde87ce27a41f31e54921b1ae36f73f8 100644 (file)
@@ -50,6 +50,12 @@ class ReactionHandler extends SingletonFactory {
         */
        protected $cache = null;
        
+       /**
+        * Cache for likeable objects sorted by objectType.
+        * @var ILikeObject[][] 
+        */
+       private $likeableObjectsCache = [];
+       
        /**
         * Creates a new ReactionHandler instance.
         */
@@ -102,32 +108,16 @@ class ReactionHandler extends SingletonFactory {
        /**
         * Builds the data attributes for the object container. 
         * 
-        * @param       string          $objectName
+        * @param       string          $objectTypeName
         * @param       integer         $objectID
         * @return      string
         */
-       public function getDataAttributes($objectName, $objectID) {
-               $objectType = $this->getObjectType($objectName);
-               if ($objectType === null) {
-                       throw new \InvalidArgumentException("ObjectName '{$objectName}' is unknown for definition 'com.woltlab.wcf.like.likeableObject'.");
-               }
-               
-               /** @var ILikeObjectTypeProvider $objectTypeProcessor */
-               $objectTypeProcessor = $objectType->getProcessor();
-               
-               $object = $objectTypeProcessor->getObjectByID($objectID);
-               
-               if ($object === null) {
-                       throw new \InvalidArgumentException("Object with the object id '{$objectID}' for object type '{$objectName}' is unknown.");
-               }
-               
-               if (!($object instanceof ILikeObject)) {
-                       throw new ImplementationException(get_class($object), ILikeObject::class);
-               }
+       public function getDataAttributes($objectTypeName, $objectID) {
+               $object = $this->getLikeableObject($objectTypeName, $objectID);
                
                $dataAttributes = [
                        'object-id' => $object->getObjectID(),
-                       'object-type' => $objectName,
+                       'object-type' => $objectTypeName,
                        'user-id' => $object->getUserID()
                ];
                
@@ -150,6 +140,55 @@ class ReactionHandler extends SingletonFactory {
                return $returnDataAttributes;
        }
        
+       /**
+        * Cache likeable objects. 
+        * 
+        * @param       string          $objectTypeName
+        * @param       integer[]       $objectIDs
+        */
+       public function cacheLikeableObjects($objectTypeName, array $objectIDs) {
+               $objectType = $this->getObjectType($objectTypeName);
+               if ($objectType === null) {
+                       throw new \InvalidArgumentException("ObjectName '{$objectTypeName}' is unknown for definition 'com.woltlab.wcf.like.likeableObject'.");
+               }
+               
+               /** @var ILikeObjectTypeProvider $objectTypeProcessor */
+               $objectTypeProcessor = $objectType->getProcessor();
+               
+               $objects = $objectTypeProcessor->getObjectsByIDs($objectIDs);
+               
+               if (!isset($this->likeableObjectsCache[$objectTypeName])) {
+                       $this->likeableObjectsCache[$objectTypeName] = [];
+               }
+               
+               foreach ($objects as $object) {
+                       $this->likeableObjectsCache[$objectTypeName][$object->getObjectID()] = $object; 
+               }
+       }
+       
+       /**
+        * Get an likeable object from the internal cache. 
+        * 
+        * @param       string          $objectTypeName
+        * @param       integer         $objectID
+        * @return      ILikeObject
+        */
+       public function getLikeableObject($objectTypeName, $objectID) {
+               if (!isset($this->likeableObjectsCache[$objectTypeName][$objectID])) {
+                       $this->cacheLikeableObjects($objectTypeName, [$objectID]);
+               }
+               
+               if (!isset($this->likeableObjectsCache[$objectTypeName][$objectID])) {
+                       throw new \InvalidArgumentException("Object with the object id '{$objectID}' for object type '{$objectTypeName}' is unknown.");
+               }
+               
+               if (!($this->likeableObjectsCache[$objectTypeName][$objectID] instanceof ILikeObject)) {
+                       throw new ImplementationException(get_class($this->likeableObjectsCache[$objectTypeName][$objectID]), ILikeObject::class);
+               }
+               
+               return $this->likeableObjectsCache[$objectTypeName][$objectID];
+       }
+       
        /**
         * Returns an object type from cache.
         *
@@ -206,6 +245,8 @@ class ReactionHandler extends SingletonFactory {
                        return 0;
                }
                
+               $this->cacheLikeableObjects($objectType->objectType, $objectIDs);
+               
                $i = 0;
                
                $conditions = new PreparedStatementConditionBuilder();