[SECURITY] [API BREAKING CHANGE] Require logout token.
[lhc/web/wiklou.git] / includes / Storage / SlotRecord.php
index b59d92f..50d1100 100644 (file)
@@ -96,8 +96,13 @@ class SlotRecord {
         * @return SlotRecord
         */
        public static function newInherited( SlotRecord $slot ) {
+               // Sanity check - we can't inherit from a Slot that's not attached to a revision.
+               $slot->getRevision();
+               $slot->getOrigin();
+               $slot->getAddress();
+
+               // NOTE: slot_origin and content_address are copied from $slot.
                return self::newDerived( $slot, [
-                       'slot_inherited' => true,
                        'slot_revision_id' => null,
                ] );
        }
@@ -122,7 +127,7 @@ class SlotRecord {
                $row = [
                        'slot_id' => null, // not yet known
                        'slot_revision_id' => null, // not yet known
-                       'slot_inherited' => 0, // not inherited
+                       'slot_origin' => null, // not yet known, will be set in newSaved()
                        'content_size' => null, // compute later
                        'content_sha1' => null, // compute later
                        'slot_content_id' => null, // not yet known, will be set in newSaved()
@@ -183,15 +188,26 @@ class SlotRecord {
                        );
                }
 
-               if ( $protoSlot->isInherited() && !$protoSlot->hasAddress() ) {
-                       throw new InvalidArgumentException(
-                               "An inherited blob should have a content address!"
-                       );
+               if ( $protoSlot->isInherited() ) {
+                       if ( !$protoSlot->hasAddress() ) {
+                               throw new InvalidArgumentException(
+                                       "An inherited blob should have a content address!"
+                               );
+                       }
+                       if ( !$protoSlot->hasField( 'slot_origin' ) ) {
+                               throw new InvalidArgumentException(
+                                       "A saved inherited slot should have an origin set!"
+                               );
+                       }
+                       $origin = $protoSlot->getOrigin();
+               } else {
+                       $origin = $revisionId;
                }
 
                return self::newDerived( $protoSlot, [
                        'slot_revision_id' => $revisionId,
                        'slot_content_id' => $contentId,
+                       'slot_origin' => $origin,
                        'content_address' => $contentAddress,
                ] );
        }
@@ -225,11 +241,6 @@ class SlotRecord {
                        '$row->slot_revision_id',
                        'must exist'
                );
-               Assert::parameter(
-                       property_exists( $row, 'slot_inherited' ),
-                       '$row->slot_inherited',
-                       'must exist'
-               );
                Assert::parameter(
                        property_exists( $row, 'slot_content_id' ),
                        '$row->slot_content_id',
@@ -245,6 +256,21 @@ class SlotRecord {
                        '$row->model_name',
                        'must exist'
                );
+               Assert::parameter(
+                       property_exists( $row, 'slot_origin' ),
+                       '$row->slot_origin',
+                       'must exist'
+               );
+               Assert::parameter(
+                       !property_exists( $row, 'slot_inherited' ),
+                       '$row->slot_inherited',
+                       'must not exist'
+               );
+               Assert::parameter(
+                       !property_exists( $row, 'slot_revision' ),
+                       '$row->slot_revision',
+                       'must not exist'
+               );
 
                $this->row = $row;
                $this->content = $content;
@@ -365,13 +391,32 @@ class SlotRecord {
                return $this->getIntField( 'slot_revision_id' );
        }
 
+       /**
+        * Returns the revision ID of the revision that originated the slot's content.
+        *
+        * @return int
+        */
+       public function getOrigin() {
+               return $this->getIntField( 'slot_origin' );
+       }
+
        /**
         * Whether this slot was inherited from an older revision.
         *
+        * If this SlotRecord is already attached to a revision, this returns true
+        * if the slot's revision of origin is the same as the revision it belongs to.
+        *
+        * If this SlotRecord is not yet attached to a revision, this returns true
+        * if the slot already has an address.
+        *
         * @return bool
         */
        public function isInherited() {
-               return $this->getIntField( 'slot_inherited' ) !== 0;
+               if ( $this->hasRevision() ) {
+                       return $this->getRevision() !== $this->getOrigin();
+               } else {
+                       return $this->hasAddress();
+               }
        }
 
        /**