417 lines
12 KiB
PHP
417 lines
12 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Subclass for representing a row from the 'sf_asset_folder' table.
|
|
*
|
|
*
|
|
*
|
|
* @package plugins.sfAssetsLibraryPlugin.lib.model
|
|
*/
|
|
class sfAssetFolder extends BasesfAssetFolder
|
|
{
|
|
|
|
public function __toString()
|
|
{
|
|
return $this->getName();
|
|
}
|
|
|
|
public function getFullPath()
|
|
{
|
|
return sfAssetsLibraryTools::getMediaDir(true).$this->getRelativePath();
|
|
}
|
|
|
|
/**
|
|
* Folder physically exists
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function exists()
|
|
{
|
|
return is_dir(sfAssetsLibraryTools::fixPath($this->getRelativePath())) && is_writable(sfAssetsLibraryTools::fixPath($this->getRelativePath()));
|
|
}
|
|
|
|
/**
|
|
* Checks if a name already exists in the list of subfolders to a folder
|
|
*
|
|
* @param string $name A folder name
|
|
* @return bool
|
|
*/
|
|
public function hasSubFolder($name)
|
|
{
|
|
$c = new Criteria();
|
|
$c->add(sfAssetFolderPeer::NAME, $name);
|
|
$c->add(sfAssetFolderPeer::TREE_PARENT, $this->getId());
|
|
|
|
return sfAssetFolderPeer::doCount($c) > 0 ? true : false;
|
|
}
|
|
|
|
/**
|
|
* Physically creates folder
|
|
*
|
|
* @return bool succes
|
|
*/
|
|
public function create()
|
|
{
|
|
list ($base, $name ) = sfAssetsLibraryTools::splitPath($this->getRelativePath());
|
|
return sfAssetsLibraryTools::mkdir($name, $base);
|
|
}
|
|
|
|
public function hasAsset($asset_name)
|
|
{
|
|
$c = new Criteria();
|
|
$c->add(sfAssetPeer::FILENAME, $asset_name);
|
|
|
|
return $this->countsfAssets($c) > 0;
|
|
}
|
|
|
|
public function getAssetsWithFilenames()
|
|
{
|
|
$c = new Criteria();
|
|
$c->add(sfAssetPeer::FOLDER_ID, $this->getId());
|
|
$assets = sfAssetPeer::doSelect($c);
|
|
$filenames = array();
|
|
foreach ($assets as $asset)
|
|
{
|
|
$filenames[$asset->getFilename()] = $asset;
|
|
}
|
|
|
|
return $filenames;
|
|
}
|
|
|
|
public function getSubfoldersWithFolderNames()
|
|
{
|
|
$c = new Criteria();
|
|
$c->add(sfAssetFolderPeer::TREE_PARENT, $this->getId());
|
|
$folders = sfAssetFolderPeer::doSelect($c);
|
|
$foldernames = array();
|
|
foreach ($folders as $folder)
|
|
{
|
|
$foldernames[$folder->getName()] = $folder;
|
|
}
|
|
|
|
return $foldernames;
|
|
}
|
|
|
|
/**
|
|
* 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->create($file, false);
|
|
$sfAsset->save();
|
|
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_sfAssetsLibrary_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->insertAsLastChildOf($this->reload());
|
|
$sfAssetFolder->setName($name);
|
|
$sfAssetFolder->save();
|
|
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');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Recursively move assets and folders from $old_path to $new_path
|
|
*
|
|
* @param string $old_path
|
|
* @param string $new_path
|
|
* @return bool success
|
|
*/
|
|
static public function movePhysically($old_path, $new_path)
|
|
{
|
|
$old_path = sfAssetsLibraryTools::fixPath($old_path);
|
|
|
|
$new_path = sfAssetsLibraryTools::fixPath($new_path);
|
|
|
|
if (!is_dir($new_path) || !is_writable($new_path))
|
|
{
|
|
// $old = umask(0);
|
|
mkdir($new_path, 0755);
|
|
// umask($old);
|
|
}
|
|
|
|
$files = sfFinder::type('file')->maxdepth(0)->relative()->in($old_path);
|
|
|
|
$success = true;
|
|
|
|
foreach ($files as $file)
|
|
{
|
|
$success = rename($old_path.DIRECTORY_SEPARATOR.$file, $new_path.DIRECTORY_SEPARATOR.$file) && $success;
|
|
|
|
$old = umask(0);
|
|
|
|
chmod($new_path.DIRECTORY_SEPARATOR.$file, 0644);
|
|
|
|
umask($old);
|
|
}
|
|
|
|
if ($success)
|
|
{
|
|
$folders = sfFinder::type('dir')->maxdepth(0)->relative()->in($old_path);
|
|
|
|
foreach ($folders as $folder)
|
|
{
|
|
$success = self::movePhysically($old_path.DIRECTORY_SEPARATOR.$folder, $new_path.DIRECTORY_SEPARATOR.$folder) && $success;
|
|
}
|
|
}
|
|
|
|
$success = rmdir($old_path) && $success;
|
|
|
|
return $success;
|
|
}
|
|
|
|
/**
|
|
* Move under a new parent
|
|
*
|
|
* @param sfAssetFolder $new_parent
|
|
*/
|
|
public function move(sfAssetFolder $new_parent)
|
|
{
|
|
// controls
|
|
if ($this->isRoot())
|
|
{
|
|
throw new sfAssetException('The root folder cannot be moved');
|
|
}
|
|
else if ($new_parent->hasSubFolder($this->getName()))
|
|
{
|
|
throw new sfAssetException('The target folder "%folder%" already contains a folder named "%name%". The folder has not been moved.', array('%folder%' => $new_parent, '%name%' => $this->getName()));
|
|
}
|
|
else if ($new_parent->isDescendantOf($this))
|
|
{
|
|
throw new sfAssetException('The target folder cannot be a subfolder of moved folder. The folder has not been moved.');
|
|
}
|
|
else if ($this->getTreeParent() !== $new_parent->getId())
|
|
{
|
|
$descendants = $this->getDescendants();
|
|
$old_path = $this->getFullPath();
|
|
|
|
$this->moveToLastChildOf($new_parent);
|
|
$this->save();
|
|
|
|
// move its assets
|
|
self::movePhysically($old_path, $this->getFullPath());
|
|
|
|
foreach ($descendants as $descendant)
|
|
{
|
|
// Update relative path
|
|
$descendant->save();
|
|
}
|
|
}
|
|
// else: nothing to do
|
|
}
|
|
|
|
/**
|
|
* Change folder name
|
|
*
|
|
* @param string $name
|
|
*/
|
|
public function rename($name)
|
|
{
|
|
if ($this->getParent()->hasSubFolder($name))
|
|
{
|
|
throw new sfAssetException('The parent folder already contains a folder named "%name%". The folder has not been renamed.', array('%name%' => $name));
|
|
}
|
|
else if ($name !== $this->getName())
|
|
{
|
|
if (sfAssetsLibraryTools::sanitizeName($name) != $name)
|
|
{
|
|
throw new sfAssetException('The target folder name "%name%" contains incorrect characters. The folder has not be renamed.', array('%name%' => $name));
|
|
}
|
|
$old_path = $this->getFullPath();
|
|
$this->setName($name);
|
|
$this->save();
|
|
|
|
// move its assets
|
|
self::movePhysically($old_path, $this->getFullPath());
|
|
|
|
foreach ($this->getDescendants() as $descendant)
|
|
{
|
|
$descendant->save();
|
|
}
|
|
}
|
|
// else: nothing to do
|
|
}
|
|
|
|
/**
|
|
* Also delete all contents
|
|
*
|
|
* @param Connection $con
|
|
* @param Boolean $force If true, do not throw an exception if the physical directories cannot be removed
|
|
*/
|
|
public function delete($con = null, $force = true, $for = 'product')
|
|
{
|
|
foreach ($this->getsfAssets() as $asset)
|
|
{
|
|
$success = $asset->delete($con, $for) && $success;
|
|
}
|
|
|
|
return parent::delete($con);
|
|
}
|
|
|
|
public function getParentPath()
|
|
{
|
|
if ($this->isRoot())
|
|
{
|
|
throw new sfException('Root node has no parent path');
|
|
}
|
|
$path = $this->getRelativePath();
|
|
|
|
return trim(substr($path, 0, strrpos($path, '/')), '/');
|
|
}
|
|
|
|
public function save($con = null)
|
|
{
|
|
if (!$this->isColumnModified(sfAssetFolderPeer::RELATIVE_PATH))
|
|
{
|
|
if ($this->getParent())
|
|
{
|
|
$this->setRelativePath($this->getParent()->getRelativePath().'/'.$this->getName());
|
|
}
|
|
else
|
|
{
|
|
$this->setRelativePath($this->getName());
|
|
}
|
|
}
|
|
// physical existence
|
|
if (!$this->exists())
|
|
{
|
|
if (!$this->create())
|
|
{
|
|
throw new sfAssetException('Impossible to create folder "%name%"', array('%name%' => $this->getRelativePath()));
|
|
}
|
|
}
|
|
|
|
return parent::save($con);
|
|
}
|
|
|
|
public function setFillinFromPath($path, $depth = 0)
|
|
{
|
|
$path = sfAssetFolderPeer::cleanPath($path);
|
|
|
|
list($parent_path, $name) = sfAssetsLibraryTools::splitPath($path);
|
|
|
|
if (!$parent_folder = sfAssetFolderPeer::retrieveByPath($parent_path))
|
|
{
|
|
$parent_folder = $this->setFillinFromPath($parent_path, $depth + 1);
|
|
$parent_folder->save();
|
|
}
|
|
|
|
if ($depth > 0)
|
|
{
|
|
$folder = new sfAssetFolder();
|
|
|
|
$folder->setName($name);
|
|
|
|
$folder->setRelativePath($path);
|
|
|
|
$folder->insertAsLastChildOf($parent_folder);
|
|
|
|
$folder->save();
|
|
|
|
return $folder;
|
|
}
|
|
else
|
|
{
|
|
$this->setName($name);
|
|
|
|
$this->setRelativePath($path);
|
|
|
|
$this->insertAsLastChildOf($parent_folder);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
sfPropelBehavior::add('sfAssetFolder', array('actasnestedset' => array('columns' => array(
|
|
'left' => sfAssetFolderPeer::TREE_LEFT,
|
|
'right' => sfAssetFolderPeer::TREE_RIGHT,
|
|
'parent' => sfAssetFolderPeer::TREE_PARENT,
|
|
'scope' => sfAssetFolderPeer::STATIC_SCOPE,
|
|
'depth' => sfAssetFolderPeer::TREE_DEPTH,
|
|
)))); |