/**
  * Given a SecurableItem, add and remove permissions
  * based on what the provided ExplicitReadWriteModelPermissions indicates should be done.
  * Sets @see SecurableItem->setTreatCurrentUserAsOwnerForPermissions as true in order to ensure the current user
  * can effectively add permissions even if the current user is no longer the owner.
  * @param SecurableItem $securableItem
  * @param ExplicitReadWriteModelPermissions $explicitReadWriteModelPermissions
  * @return boolean
  * @throws NotSupportedException()
  */
 public static function resolveExplicitReadWriteModelPermissions(SecurableItem $securableItem, ExplicitReadWriteModelPermissions $explicitReadWriteModelPermissions)
 {
     assert('$securableItem->id > 0');
     $securableItem->setTreatCurrentUserAsOwnerForPermissions(true);
     $saveSecurableItem = false;
     if ($explicitReadWriteModelPermissions->getReadOnlyPermitablesCount() > 0) {
         $saveSecurableItem = true;
         foreach ($explicitReadWriteModelPermissions->getReadOnlyPermitables() as $permitable) {
             $securableItem->addPermissions($permitable, Permission::READ);
             if ($permitable instanceof Group) {
                 ReadPermissionsOptimizationUtil::securableItemGivenPermissionsForGroup($securableItem, $permitable);
             } elseif ($permitable instanceof User) {
                 ReadPermissionsOptimizationUtil::securableItemGivenPermissionsForUser($securableItem, $permitable);
             } else {
                 throw new NotSupportedException();
             }
         }
     }
     if ($explicitReadWriteModelPermissions->getReadWritePermitablesCount() > 0) {
         $saveSecurableItem = true;
         foreach ($explicitReadWriteModelPermissions->getReadWritePermitables() as $permitable) {
             $securableItem->addPermissions($permitable, Permission::READ_WRITE_CHANGE_PERMISSIONS_CHANGE_OWNER);
             if ($permitable instanceof Group) {
                 ReadPermissionsOptimizationUtil::securableItemGivenPermissionsForGroup($securableItem, $permitable);
             } elseif ($permitable instanceof User) {
                 ReadPermissionsOptimizationUtil::securableItemGivenPermissionsForUser($securableItem, $permitable);
             } else {
                 throw new NotSupportedException();
             }
         }
     }
     if ($explicitReadWriteModelPermissions->getReadOnlyPermitablesToRemoveCount() > 0) {
         $saveSecurableItem = true;
         foreach ($explicitReadWriteModelPermissions->getReadOnlyPermitablesToRemove() as $permitable) {
             $securableItem->removePermissions($permitable, Permission::READ, Permission::ALLOW);
             if ($permitable instanceof Group) {
                 ReadPermissionsOptimizationUtil::securableItemLostPermissionsForGroup($securableItem, $permitable);
             } elseif ($permitable instanceof User) {
                 ReadPermissionsOptimizationUtil::securableItemLostPermissionsForUser($securableItem, $permitable);
             } else {
                 throw new NotSupportedException();
             }
         }
     }
     if ($explicitReadWriteModelPermissions->getReadWritePermitablesToRemoveCount() > 0) {
         $saveSecurableItem = true;
         foreach ($explicitReadWriteModelPermissions->getReadWritePermitablesToRemove() as $permitable) {
             $securableItem->removePermissions($permitable, Permission::READ_WRITE_CHANGE_PERMISSIONS_CHANGE_OWNER, Permission::ALLOW);
             if ($permitable instanceof Group) {
                 ReadPermissionsOptimizationUtil::securableItemLostPermissionsForGroup($securableItem, $permitable);
             } elseif ($permitable instanceof User) {
                 ReadPermissionsOptimizationUtil::securableItemLostPermissionsForUser($securableItem, $permitable);
             } else {
                 throw new NotSupportedException();
             }
         }
     }
     if ($saveSecurableItem) {
         $setBackToProcess = false;
         if ($securableItem->shouldProcessWorkflowOnSave()) {
             $securableItem->setDoNotProcessWorkflowOnSave();
             $setBackToProcess = true;
         }
         $saved = $securableItem->save();
         if ($setBackToProcess) {
             $securableItem->setProcessWorkflowOnSave();
         }
         $securableItem->setTreatCurrentUserAsOwnerForPermissions(false);
         return $saved;
     }
     $securableItem->setTreatCurrentUserAsOwnerForPermissions(false);
     return true;
 }
 /**
  * @param SecurableItem $securableItem
  * @param User $user
  */
 public static function securableItemLostReadPermissionsForUser(SecurableItem $securableItem, User $user)
 {
     ReadPermissionsOptimizationUtil::securableItemLostPermissionsForUser($securableItem, $user);
     AllPermissionsOptimizationCache::forgetSecurableItemForRead($securableItem);
 }
 /**
  * @depends testGroupGivenReadOnOwnedSecurableItem_Slide6
  */
 public function testUserLosesReadOnOwnedSecurableItem_Slide7()
 {
     $u1 = User::getByUsername('u1.');
     $u2 = User::getByUsername('u2.');
     $u3 = User::getByUsername('u3.');
     Yii::app()->user->userModel = $u1;
     $a1 = new Account();
     $a1->name = 'A1.';
     $a1->addPermissions($u2, Permission::READ);
     $a1->addPermissions($u3, Permission::READ);
     $this->assertTrue($a1->save());
     //Called in OwnedSecurableItem::afterSave();
     //ReadPermissionsOptimizationUtil::ownedSecurableItemCreated($a1);
     ReadPermissionsOptimizationUtil::securableItemGivenPermissionsForUser($a1, $u2);
     ReadPermissionsOptimizationUtil::securableItemGivenPermissionsForUser($a1, $u3);
     $this->assertEquals(array(array('R2', 1), array('R3', 1), array('R5', 2), array('R6', 2), array('U2', 1), array('U3', 1)), self::getAccountMungeRows($a1));
     $this->assertTrue(self::accountMungeDoesntChangeWhenRebuilt());
     $a1->removePermissions($u2, Permission::READ);
     $this->assertTrue($a1->save());
     ReadPermissionsOptimizationUtil::securableItemLostPermissionsForUser($a1, $u2);
     $this->assertEquals(array(array('R2', 1), array('R3', 1), array('R5', 1), array('R6', 1), array('U3', 1)), self::getAccountMungeRows($a1));
     $this->assertTrue(self::accountMungeDoesntChangeWhenRebuilt());
     $a1->removePermissions($u3, Permission::READ);
     $this->assertTrue($a1->save());
     ReadPermissionsOptimizationUtil::securableItemLostPermissionsForUser($a1, $u3);
     $this->assertEquals(array(array('R2', 1), array('R3', 1)), self::getAccountMungeRows($a1));
     $this->assertTrue(self::accountMungeDoesntChangeWhenRebuilt());
     $a1->delete();
 }