/**
  * Synchronize with a physical folder 
  *
  * @param string $base_folder base folder path
  * @param Boolean $verbose If true, every file or database operation will issue an alert in STDOUT
  * @param Boolean $removeOrphanAssets If true, database assets with no associated file are removed
  * @param Boolean $removeOrphanFolders If true, database folders with no associated directory are removed
  */
 public function synchronizeWith($base_folder, $verbose = true, $removeOrphanAssets = false, $removeOrphanFolders = false)
 {
     if (!is_dir($base_folder)) {
         throw new sfAssetException(sprintf('%s is not a directory', $base_folder));
     }
     $files = sfFinder::type('file')->maxdepth(0)->ignore_version_control()->in($base_folder);
     $assets = $this->getAssetsWithFilenames();
     foreach ($files as $file) {
         if (!array_key_exists(basename($file), $assets)) {
             // File exists, asset does not exist: create asset
             $sfAsset = new sfAsset();
             $sfAsset->setFolderId($this->getId());
             $sfAsset->createAsset($file, false);
             try {
                 $sfAsset->save();
             } catch (sfAssetException $e) {
                 sfAssetsLibraryTools::log($e->getMessage(), 'red');
             }
             if ($verbose) {
                 sfAssetsLibraryTools::log(sprintf("Importing file %s", $file), 'green');
             }
         } else {
             // File exists, asset exists: do nothing
             unset($assets[basename($file)]);
         }
     }
     foreach ($assets as $name => $asset) {
         if ($removeOrphanAssets) {
             // File does not exist, asset exists: delete asset
             $asset->delete();
             if ($verbose) {
                 sfAssetsLibraryTools::log(sprintf("Deleting asset %s", $asset->getUrl()), 'yellow');
             }
         } else {
             if ($verbose) {
                 sfAssetsLibraryTools::log(sprintf("Warning: No file for asset %s", $asset->getUrl()), 'red');
             }
         }
     }
     $dirs = sfFinder::type('dir')->maxdepth(0)->discard(sfConfig::get('app_sfDoctrineAssetsLibrary_thumbnail_dir', 'thumbnail'))->ignore_version_control()->in($base_folder);
     $folders = $this->getSubfoldersWithFolderNames();
     foreach ($dirs as $dir) {
         list(, $name) = sfAssetsLibraryTools::splitPath($dir);
         if (!array_key_exists($name, $folders)) {
             // dir exists in filesystem, not in database: create folder in database
             $sfAssetFolder = new sfAssetFolder();
             $sfAssetFolder->setName($name);
             $sfAssetFolder->save();
             $sfAssetFolder->getNode()->insertAsLastChildOf($this);
             if ($verbose) {
                 sfAssetsLibraryTools::log(sprintf("Importing directory %s", $dir), 'green');
             }
         } else {
             // dir exists in filesystem and database: look inside
             $sfAssetFolder = $folders[$name];
             unset($folders[$name]);
         }
         $sfAssetFolder->synchronizeWith($dir, $verbose, $removeOrphanAssets, $removeOrphanFolders);
     }
     foreach ($folders as $name => $folder) {
         if ($removeOrphanFolders) {
             $folder->delete(null, true);
             if ($verbose) {
                 sfAssetsLibraryTools::log(sprintf("Deleting folder %s", $folder->getRelativePath()), 'yellow');
             }
         } else {
             if ($verbose) {
                 sfAssetsLibraryTools::log(sprintf("Warning: No directory for folder %s", $folder->getRelativePath()), 'red');
             }
         }
     }
 }
 $t->ok(is_file($test_asset), 'test asset found');
 $sfAsset = new sfAsset();
 $sfAsset->setsfAssetFolder($sfAssetFolder2);
 $sfAsset->createAsset($test_asset, false);
 $sfAsset->save();
 $t->ok(is_file($sfAsset->getFullPath()), 'asset found');
 $sf_asset_id = $sfAsset->getId();
 $sfAssetFolder3 = new sfAssetFolder();
 $sfAssetFolder3->setName('Test_Sub-sub-directory');
 $sfAssetFolder3->getNode()->insertAsFirstChildOf($sfAssetFolder2);
 $sfAssetFolder3->save();
 $t->is($sfAssetFolder3->getRelativePath(), $sfAssetFolder2->getRelativePath() . '/' . $sfAssetFolder3->getName(), 'getRelativePath() is updated on save for subfolders');
 $t->diag($sfAssetFolder3->getRelativePath());
 $sfAsset2 = new sfAsset();
 $sfAsset2->setsfAssetFolder($sfAssetFolder3);
 $sfAsset2->createAsset($test_asset, false);
 $sfAsset2->save();
 $t->ok(is_file($sfAsset2->getFullPath()), 'asset2 found');
 $sf_asset2_id = $sfAsset2->getId();
 $id3 = $sfAssetFolder3->getId();
 $sfAssetFolder2->move($root);
 $t->diag($sfAssetFolder3->getRelativePath());
 $sfAssetFolder3 = Doctrine::getTable('sfAssetFolder')->find($id3);
 $t->is($sfAssetFolder2->getNode()->getParent()->getId(), $root->getId(), 'move() gives the correct parent');
 $t->is($sfAssetFolder3->getNode()->getParent()->getNode()->getParent()->getId(), $root->getId(), 'move() changes descendants grandparents');
 $t->is($sfAssetFolder2->getRelativePath(), $root->getRelativePath() . '/' . $sfAssetFolder2->getName(), 'move() changes descendants relative paths');
 $t->is($sfAssetFolder3->getRelativePath(), $sfAssetFolder2->getRelativePath() . '/' . $sfAssetFolder3->getName(), 'move() changes descendants relative paths');
 $sfAsset = Doctrine::getTable('sfAsset')->find($sf_asset_id);
 $sfAsset2 = Doctrine::getTable('sfAsset')->find($sf_asset2_id);
 $t->ok(is_file($sfAsset->getFullPath()), 'base asset of moved folder found');
 $t->ok(is_file($sfAsset2->getFullPath()), 'deep asset of moved folder found');