/**
  * 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
  * @param bool $validate
  * @return bool|void
  * @throws NotSupportedException
  */
 public static function resolveExplicitReadWriteModelPermissions(SecurableItem $securableItem, ExplicitReadWriteModelPermissions $explicitReadWriteModelPermissions, $validate = false)
 {
     assert('$securableItem->id > 0');
     $optimizeReadPermissions = $securableItem::hasReadPermissionsOptimization();
     $securableItem->setTreatCurrentUserAsOwnerForPermissions(true);
     $saveSecurableItem = false;
     if ($explicitReadWriteModelPermissions->getReadOnlyPermitablesCount() > 0) {
         $saveSecurableItem = true;
         foreach ($explicitReadWriteModelPermissions->getReadOnlyPermitables() as $permitable) {
             if ($securableItem->addPermissions($permitable, Permission::READ) && $optimizeReadPermissions) {
                 if ($permitable instanceof Group) {
                     AllPermissionsOptimizationUtil::securableItemGivenReadPermissionsForGroup($securableItem, $permitable);
                     ReadPermissionsSubscriptionUtil::securableItemGivenPermissionsForGroup($securableItem);
                 } elseif ($permitable instanceof User) {
                     AllPermissionsOptimizationUtil::securableItemGivenReadPermissionsForUser($securableItem, $permitable);
                     ReadPermissionsSubscriptionUtil::securableItemGivenPermissionsForUser($securableItem);
                 } else {
                     throw new NotSupportedException();
                 }
             }
         }
     }
     if ($explicitReadWriteModelPermissions->getReadWritePermitablesCount() > 0) {
         $saveSecurableItem = true;
         foreach ($explicitReadWriteModelPermissions->getReadWritePermitables() as $permitable) {
             if ($securableItem->addPermissions($permitable, Permission::READ_WRITE_CHANGE_PERMISSIONS_CHANGE_OWNER) && $optimizeReadPermissions) {
                 if ($permitable instanceof Group) {
                     AllPermissionsOptimizationUtil::securableItemGivenPermissionsForGroup($securableItem, $permitable);
                     ReadPermissionsSubscriptionUtil::securableItemGivenPermissionsForGroup($securableItem);
                 } elseif ($permitable instanceof User) {
                     AllPermissionsOptimizationUtil::securableItemGivenPermissionsForUser($securableItem, $permitable);
                     ReadPermissionsSubscriptionUtil::securableItemGivenPermissionsForUser($securableItem);
                 } else {
                     throw new NotSupportedException();
                 }
             }
         }
     }
     if ($explicitReadWriteModelPermissions->getReadOnlyPermitablesToRemoveCount() > 0) {
         $saveSecurableItem = true;
         foreach ($explicitReadWriteModelPermissions->getReadOnlyPermitablesToRemove() as $permitable) {
             $securableItem->removePermissions($permitable, Permission::READ, Permission::ALLOW);
             if ($optimizeReadPermissions) {
                 if ($permitable instanceof Group) {
                     AllPermissionsOptimizationUtil::securableItemLostReadPermissionsForGroup($securableItem, $permitable);
                     ReadPermissionsSubscriptionUtil::securableItemLostPermissionsForGroup($securableItem);
                 } elseif ($permitable instanceof User) {
                     AllPermissionsOptimizationUtil::securableItemLostReadPermissionsForUser($securableItem, $permitable);
                     ReadPermissionsSubscriptionUtil::securableItemLostPermissionsForUser($securableItem);
                 } 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 ($optimizeReadPermissions) {
                 if ($permitable instanceof Group) {
                     AllPermissionsOptimizationUtil::securableItemLostPermissionsForGroup($securableItem, $permitable);
                     ReadPermissionsSubscriptionUtil::securableItemLostPermissionsForGroup($securableItem);
                 } elseif ($permitable instanceof User) {
                     AllPermissionsOptimizationUtil::securableItemLostPermissionsForUser($securableItem, $permitable);
                     ReadPermissionsSubscriptionUtil::securableItemLostPermissionsForUser($securableItem);
                 } else {
                     throw new NotSupportedException();
                 }
             }
         }
     }
     if ($saveSecurableItem) {
         $setBackToProcess = false;
         if ($securableItem->shouldProcessWorkflowOnSave()) {
             $securableItem->setDoNotProcessWorkflowOnSave();
             $setBackToProcess = true;
         }
         $saved = $securableItem->save($validate);
         if ($setBackToProcess) {
             $securableItem->setProcessWorkflowOnSave();
         }
         $securableItem->setTreatCurrentUserAsOwnerForPermissions(false);
         return $saved;
     }
     $securableItem->setTreatCurrentUserAsOwnerForPermissions(false);
     return true;
 }
 public function testSecurableItemGivenOrLostPermissionsForUser()
 {
     $super = User::getByUsername('super');
     Yii::app()->user->userModel = $super;
     $this->deleteAllModelsAndRecordsFromReadPermissionTable('Account');
     Yii::app()->jobQueue->deleteAll();
     $job = new ReadPermissionSubscriptionUpdateForAccountJob();
     $jobBasedOnBuildTable = new ReadPermissionSubscriptionUpdateForAccountFromBuildTableJob();
     $account = AccountTestHelper::createAccountByNameForOwner('Test Account 2', $super);
     Yii::app()->jobQueue->deleteAll();
     sleep(1);
     $user = self::$johnny;
     ReadPermissionsSubscriptionUtil::securableItemGivenPermissionsForUser($account);
     $queuedJobs = Yii::app()->jobQueue->getAll();
     $this->assertEquals(1, count($queuedJobs[5]));
     $this->assertEquals('ReadPermissionSubscriptionUpdateForAccountFromBuildTable', $queuedJobs[5][0]['jobType']);
     Yii::app()->jobQueue->deleteAll();
     ReadPermissionsSubscriptionUtil::securableItemLostPermissionsForUser($account);
     $queuedJobs = Yii::app()->jobQueue->getAll();
     $this->assertEquals(1, count($queuedJobs[5]));
     $this->assertEquals('ReadPermissionSubscriptionUpdateForAccountFromBuildTable', $queuedJobs[5][0]['jobType']);
     Yii::app()->jobQueue->deleteAll();
 }