/**
  * Copy the permissions from the given folder to all child folders and items. Do not pass a results
  * parameter, that is for the recursive counting.
  *
  * @param FolderDao $folder folder DAO
  * @param UserDao $user user DAO
  * @param null|ProgressDao $progress progress DAO
  * @param array $results
  * @return array array('success' => number of resources whose policies were successfully changed,
  *                     'failure' => number of resources failed to change due to invalid permissions
  */
 public function applyPoliciesRecursive($folder, $user, $progress = null, $results = array('success' => 0, 'failure' => 0))
 {
     foreach ($folder->getFolders() as $subfolder) {
         if ($progress) {
             $current = $progress->getCurrent() + 1;
             $message = 'Set policies on ' . $current . ' of ' . $progress->getMaximum() . ' resources';
             $this->Progress->updateProgress($progress, $current, $message);
         }
         if (!$this->Folder->policyCheck($subfolder, $user, MIDAS_POLICY_ADMIN)) {
             ++$results['failure'];
             continue;
         }
         // delete all existing policies on the subfolder
         foreach ($subfolder->getFolderpolicygroup() as $folderPolicyGroup) {
             $this->Folderpolicygroup->delete($folderPolicyGroup);
         }
         foreach ($subfolder->getFolderpolicyuser() as $folderPolicyUser) {
             $this->Folderpolicyuser->delete($folderPolicyUser);
         }
         // copy down policies from parent folder
         foreach ($folder->getFolderpolicygroup() as $folderPolicyGroup) {
             $this->Folderpolicygroup->createPolicy($folderPolicyGroup->getGroup(), $subfolder, $folderPolicyGroup->getPolicy());
         }
         foreach ($folder->getFolderpolicyuser() as $folderPolicyUser) {
             $this->Folderpolicyuser->createPolicy($folderPolicyUser->getUser(), $subfolder, $folderPolicyUser->getPolicy());
         }
         ++$results['success'];
         $results = $this->applyPoliciesRecursive($subfolder, $user, $progress, $results);
     }
     foreach ($folder->getItems() as $item) {
         if ($progress) {
             $current = $progress->getCurrent() + 1;
             $message = 'Set policies on ' . $current . ' of ' . $progress->getMaximum() . ' resources';
             $this->Progress->updateProgress($progress, $current, $message);
         }
         if (!$this->Item->policyCheck($item, $user, MIDAS_POLICY_ADMIN)) {
             ++$results['failure'];
             continue;
         }
         // delete all existing policies on the item
         foreach ($item->getItempolicygroup() as $itemPolicyGroup) {
             $this->Itempolicygroup->delete($itemPolicyGroup);
         }
         foreach ($item->getItempolicyuser() as $itemPolicyUser) {
             $this->Itempolicyuser->delete($itemPolicyUser);
         }
         // copy down policies from parent folder
         foreach ($folder->getFolderpolicygroup() as $folderPolicyGroup) {
             $this->Itempolicygroup->createPolicy($folderPolicyGroup->getGroup(), $item, $folderPolicyGroup->getPolicy());
         }
         foreach ($folder->getFolderpolicyuser() as $folderPolicyUser) {
             $this->Itempolicyuser->createPolicy($folderPolicyUser->getUser(), $item, $folderPolicyUser->getPolicy());
         }
         ++$results['success'];
     }
     return $results;
 }
 /**
  * Move all bitstreams from one asset store to another.
  *
  * @param AssetstoreDao $srcAssetstore The source asset store
  * @param AssetstoreDao $dstAssetstore The destination asset store
  * @param null|ProgressDao $progressDao Progress dao for asynchronous updating
  * @throws Zend_Exception
  */
 public function moveBitstreams($srcAssetstore, $dstAssetstore, $progressDao = null)
 {
     $current = 0;
     /** @var ProgressModel $progressModel */
     $progressModel = MidasLoader::loadModel('Progress');
     /** @var BitstreamModel $bitstreamModel */
     $bitstreamModel = MidasLoader::loadModel('Bitstream');
     $sql = $this->database->select()->setIntegrityCheck(false)->from('bitstream')->where('assetstore_id = ?', $srcAssetstore->getKey());
     $rows = $this->database->fetchAll($sql);
     $srcPath = $srcAssetstore->getPath();
     $dstPath = $dstAssetstore->getPath();
     foreach ($rows as $row) {
         $bitstream = $this->initDao('Bitstream', $row);
         if ($progressDao) {
             ++$current;
             $message = $current . ' / ' . $progressDao->getMaximum() . ': Moving ' . $bitstream->getName() . ' (' . UtilityComponent::formatSize($bitstream->getSizebytes()) . ')';
             $progressModel->updateProgress($progressDao, $current, $message);
         }
         // Move the file on disk to its new location
         $dir1 = substr($bitstream->getChecksum(), 0, 2);
         $dir2 = substr($bitstream->getChecksum(), 2, 2);
         if (!is_dir($dstPath . '/' . $dir1)) {
             if (!mkdir($dstPath . '/' . $dir1)) {
                 throw new Zend_Exception('Failed to mkdir ' . $dstPath . '/' . $dir1);
             }
         }
         if (!is_dir($dstPath . '/' . $dir1 . '/' . $dir2)) {
             if (!mkdir($dstPath . '/' . $dir1 . '/' . $dir2)) {
                 throw new Zend_Exception('Failed to mkdir ' . $dstPath . '/' . $dir1 . '/' . $dir2);
             }
         }
         if (is_file($dstPath . '/' . $bitstream->getPath())) {
             if (is_file($srcPath . '/' . $bitstream->getPath())) {
                 unlink($srcPath . '/' . $bitstream->getPath());
             }
         } else {
             if (!rename($srcPath . '/' . $bitstream->getPath(), $dstPath . '/' . $bitstream->getPath())) {
                 throw new Zend_Exception('Error moving ' . $bitstream->getPath());
             }
         }
         // Update the asset store id on the bitstream record once it has been moved
         $bitstream->setAssetstoreId($dstAssetstore->getKey());
         $bitstreamModel->save($bitstream);
     }
 }