home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / PEAR / phing / tasks / system / CopyTask.php < prev    next >
Encoding:
PHP Script  |  2007-09-05  |  14.1 KB  |  409 lines

  1. <?php
  2. /*
  3.  *  $Id: CopyTask.php 235 2007-09-05 18:42:02Z hans $
  4.  *
  5.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  6.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  7.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  8.  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  9.  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  10.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  11.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  12.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  13.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  14.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  15.  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  16.  *
  17.  * This software consists of voluntary contributions made by many individuals
  18.  * and is licensed under the LGPL. For more information please see
  19.  * <http://phing.info>.
  20.  */
  21.  
  22. require_once 'phing/Task.php';
  23. include_once 'phing/system/io/PhingFile.php';
  24. include_once 'phing/util/FileUtils.php';
  25. include_once 'phing/util/SourceFileScanner.php';
  26. include_once 'phing/mappers/IdentityMapper.php';
  27. include_once 'phing/mappers/FlattenMapper.php';
  28.  
  29. /**
  30.  * A phing copy task.  Copies a file or directory to a new file
  31.  * or directory.  Files are only copied if the source file is newer
  32.  * than the destination file, or when the destination file does not
  33.  * exist. It is possible to explictly overwrite existing files.
  34.  *
  35.  * @author   Andreas Aderhold, andi@binarycloud.com
  36.  * @version  $Revision: 1.16 $ $Date: 2007-09-05 20:42:02 +0200 (Wed, 05 Sep 2007) $
  37.  * @package  phing.tasks.system
  38.  */
  39. class CopyTask extends Task {
  40.     
  41.     protected $file          = null;   // the source file (from xml attribute)
  42.     protected $destFile      = null;   // the destiantion file (from xml attribute)
  43.     protected $destDir       = null;   // the destination dir (from xml attribute)
  44.     protected $overwrite     = false;  // overwrite destination (from xml attribute)
  45.     protected $preserveLMT   = true;   // sync timestamps (from xml attribute)
  46.     protected $includeEmpty  = true;   // include empty dirs? (from XML)
  47.     protected $flatten       = false;  // apply the FlattenMapper right way (from XML)
  48.     protected $mapperElement = null;
  49.  
  50.     protected $fileCopyMap   = array(); // asoc array containing mapped file names
  51.     protected $dirCopyMap    = array(); // asoc array containing mapped file names
  52.     protected $completeDirMap= array(); // asoc array containing complete dir names
  53.     protected $fileUtils     = null;    // a instance of fileutils
  54.     protected $filesets      = array(); // all fileset objects assigned to this task
  55.     protected $filterChains  = array(); // all filterchains objects assigned to this task
  56.  
  57.     protected $verbosity     = Project::MSG_VERBOSE;
  58.  
  59.     /**
  60.      * Sets up this object internal stuff. i.e. the Fileutils instance
  61.      *
  62.      * @return object   The CopyTask instnace
  63.      * @access public
  64.      */
  65.     function __construct() {
  66.         $this->fileUtils = new FileUtils();
  67.     }
  68.  
  69.     /**
  70.      * Set the overwrite flag. IntrospectionHelper takes care of
  71.      * booleans in set* methods so we can assume that the right
  72.      * value (boolean primitive) is coming in here.
  73.      *
  74.      * @param  boolean  Overwrite the destination file(s) if it/they already exist
  75.      * @return void
  76.      * @access public
  77.      */
  78.     function setOverwrite($bool) {
  79.         $this->overwrite = (boolean) $bool;
  80.     }
  81.  
  82.     /**
  83.      * Used to force listing of all names of copied files.
  84.      * @param boolean $verbosity
  85.      */
  86.     function setVerbose($verbosity) {
  87.         if ($verbosity) {
  88.             $this->verbosity = Project::MSG_INFO;
  89.         } else {
  90.             $this->verbosity = Project::MSG_VERBOSE;
  91.         }
  92.     }
  93.     
  94.     /**
  95.      * Set the preserve timestmap flag. IntrospectionHelper takes care of
  96.      * booleans in set* methods so we can assume that the right
  97.      * value (boolean primitive) is coming in here.
  98.      *
  99.      * @param  boolean  Preserve the timestamp on the destination file
  100.      * @return void
  101.      * @access public
  102.      */
  103.     function setTstamp($bool) {
  104.         $this->preserveLMT = (boolean) $bool;
  105.     }
  106.  
  107.  
  108.     /**
  109.      * Set the include empty dirs flag. IntrospectionHelper takes care of
  110.      * booleans in set* methods so we can assume that the right
  111.      * value (boolean primitive) is coming in here.
  112.      *
  113.      * @param  boolean  Flag if empty dirs should be cpoied too
  114.      * @return void
  115.      * @access public
  116.      */
  117.     function setIncludeEmptyDirs($bool) {
  118.         $this->includeEmpty = (boolean) $bool;
  119.     }
  120.  
  121.  
  122.     /**
  123.      * Set the file. We have to manually take care of the
  124.      * type that is coming due to limited type support in php
  125.      * in and convert it manually if neccessary.
  126.      *
  127.      * @param  string/object  The source file. Either a string or an PhingFile object
  128.      * @return void
  129.      * @access public
  130.      */
  131.     function setFile(PhingFile $file) {        
  132.         $this->file = $file;
  133.     }
  134.  
  135.  
  136.     /**
  137.      * Set the toFile. We have to manually take care of the
  138.      * type that is coming due to limited type support in php
  139.      * in and convert it manually if neccessary.
  140.      *
  141.      * @param  string/object  The dest file. Either a string or an PhingFile object
  142.      * @return void
  143.      * @access public
  144.      */
  145.     function setTofile(PhingFile $file) {       
  146.         $this->destFile = $file;
  147.     }
  148.  
  149.  
  150.     /**
  151.      * Set the toDir. We have to manually take care of the
  152.      * type that is coming due to limited type support in php
  153.      * in and convert it manually if neccessary.
  154.      *
  155.      * @param  string/object  The directory, either a string or an PhingFile object
  156.      * @return void
  157.      * @access public
  158.      */
  159.     function setTodir(PhingFile $dir) {        
  160.         $this->destDir = $dir;
  161.     }
  162.  
  163.     /**
  164.      * Nested creator, creates a FileSet for this task
  165.      *
  166.      * @access  public
  167.      * @return  object  The created fileset object
  168.      */
  169.     function createFileSet() {
  170.         $num = array_push($this->filesets, new FileSet());
  171.         return $this->filesets[$num-1];
  172.     }
  173.  
  174.     /**
  175.      * Creates a filterchain
  176.      *
  177.      * @access public
  178.      * @return  object  The created filterchain object
  179.      */
  180.     function createFilterChain() {
  181.         $num = array_push($this->filterChains, new FilterChain($this->project));
  182.         return $this->filterChains[$num-1];
  183.     }
  184.  
  185.     /**
  186.      * Nested creator, creates one Mapper for this task
  187.      *
  188.      * @access  public
  189.      * @return  object  The created Mapper type object
  190.      * @throws  BuildException
  191.      */
  192.     function createMapper() {
  193.         if ($this->mapperElement !== null) {
  194.             throw new BuildException("Cannot define more than one mapper", $this->location);
  195.         }
  196.         $this->mapperElement = new Mapper($this->project);
  197.         return $this->mapperElement;
  198.     }
  199.  
  200.     /**
  201.      * The main entry point where everything gets in motion.
  202.      *
  203.      * @access  public
  204.      * @return  true on success
  205.      * @throws  BuildException
  206.      */
  207.     function main() {
  208.     
  209.         $this->validateAttributes();
  210.  
  211.         if ($this->file !== null) {
  212.             if ($this->file->exists()) {
  213.                 if ($this->destFile === null) {
  214.                     $this->destFile = new PhingFile($this->destDir, (string) $this->file->getName());
  215.                 }
  216.                 if ($this->overwrite === true || ($this->file->lastModified() > $this->destFile->lastModified())) {
  217.                     $this->fileCopyMap[$this->file->getAbsolutePath()] = $this->destFile->getAbsolutePath();
  218.                 } else {
  219.                     $this->log($this->file->getName()." omitted, is up to date");
  220.                 }
  221.             } else {
  222.                 // terminate build
  223.                 throw new BuildException("Could not find file " . $this->file->__toString() . " to copy.");
  224.             }
  225.         }
  226.  
  227.         $project = $this->getProject();
  228.  
  229.         // process filesets
  230.         foreach($this->filesets as $fs) {
  231.             $ds = $fs->getDirectoryScanner($project);
  232.             $fromDir  = $fs->getDir($project);
  233.             $srcFiles = $ds->getIncludedFiles();
  234.             $srcDirs  = $ds->getIncludedDirectories();
  235.             
  236.             if (!$this->flatten && $this->mapperElement === null)
  237.             {
  238.                 $this->completeDirMap[$fromDir->getAbsolutePath()] = $this->destDir->getAbsolutePath();
  239.             }
  240.             
  241.             $this->_scan($fromDir, $this->destDir, $srcFiles, $srcDirs);
  242.         }
  243.  
  244.         // go and copy the stuff
  245.         $this->doWork();
  246.  
  247.         if ($this->destFile !== null) {
  248.             $this->destDir = null;
  249.         }
  250.     }
  251.  
  252.     /**
  253.      * Validates attributes coming in from XML
  254.      *
  255.      * @access  private
  256.      * @return  void
  257.      * @throws  BuildException
  258.      */
  259.     protected function validateAttributes() {
  260.     
  261.         if ($this->file === null && count($this->filesets) === 0) {
  262.             throw new BuildException("CopyTask. Specify at least one source - a file or a fileset.");
  263.         }
  264.  
  265.         if ($this->destFile !== null && $this->destDir !== null) {
  266.             throw new BuildException("Only one of destfile and destdir may be set.");
  267.         }
  268.  
  269.         if ($this->destFile === null && $this->destDir === null) {
  270.             throw new BuildException("One of destfile or destdir must be set.");
  271.         }
  272.  
  273.         if ($this->file !== null && $this->file->exists() && $this->file->isDirectory()) {
  274.             throw new BuildException("Use a fileset to copy directories.");
  275.         }
  276.  
  277.         if ($this->destFile !== null && count($this->filesets) > 0) {
  278.             throw new BuildException("Cannot concatenate multple files into a single file.");
  279.         }
  280.  
  281.         if ($this->destFile !== null) {
  282.             $this->destDir = new PhingFile($this->destFile->getParent());
  283.         }
  284.     }
  285.  
  286.     /**
  287.      * Compares source files to destination files to see if they
  288.      * should be copied.
  289.      *
  290.      * @access  private
  291.      * @return  void
  292.      */
  293.     private function _scan(&$fromDir, &$toDir, &$files, &$dirs) {
  294.         /* mappers should be generic, so we get the mappers here and
  295.         pass them on to builMap. This method is not redundan like it seems */
  296.         $mapper = null;
  297.         if ($this->mapperElement !== null) {
  298.             $mapper = $this->mapperElement->getImplementation();
  299.         } else if ($this->flatten) {
  300.             $mapper = new FlattenMapper();
  301.         } else {
  302.             $mapper = new IdentityMapper();
  303.         }
  304.         $this->buildMap($fromDir, $toDir, $files, $mapper, $this->fileCopyMap);
  305.         $this->buildMap($fromDir, $toDir, $dirs, $mapper, $this->dirCopyMap);
  306.     }
  307.  
  308.     /**
  309.      * Builds a map of filenames (from->to) that should be copied
  310.      *
  311.      * @access  private
  312.      * @return  void
  313.      */
  314.     private function buildMap(&$fromDir, &$toDir, &$names, &$mapper, &$map) {
  315.         $toCopy = null;
  316.         if ($this->overwrite) {
  317.             $v = array();
  318.             foreach($names as $name) {
  319.                 $result = $mapper->main($name);
  320.                 if ($result !== null) {
  321.                     $v[] = $name;
  322.                 }
  323.             }
  324.             $toCopy = $v;
  325.         } else {
  326.             $ds = new SourceFileScanner($this);
  327.             $toCopy = $ds->restrict($names, $fromDir, $toDir, $mapper);
  328.         }
  329.  
  330.         for ($i=0,$_i=count($toCopy); $i < $_i; $i++) {
  331.             $src  = new PhingFile($fromDir, $toCopy[$i]);
  332.             $mapped = $mapper->main($toCopy[$i]);
  333.             $dest = new PhingFile($toDir, $mapped[0]);
  334.             $map[$src->getAbsolutePath()] = $dest->getAbsolutePath();
  335.         }
  336.     }
  337.  
  338.  
  339.     /**
  340.      * Actually copies the files
  341.      *
  342.      * @access  private
  343.      * @return  void
  344.      * @throws  BuildException
  345.      */
  346.     protected function doWork() {
  347.         
  348.         // These "slots" allow filters to retrieve information about the currently-being-process files        
  349.         $fromSlot = $this->getRegisterSlot("currentFromFile");
  350.         $fromBasenameSlot = $this->getRegisterSlot("currentFromFile.basename");    
  351.  
  352.         $toSlot = $this->getRegisterSlot("currentToFile");
  353.         $toBasenameSlot = $this->getRegisterSlot("currentToFile.basename");    
  354.         
  355.         $mapSize = count($this->fileCopyMap);
  356.         $total = $mapSize;
  357.         if ($mapSize > 0) {
  358.             $this->log("Copying ".$mapSize." file".(($mapSize) === 1 ? '' : 's')." to ". $this->destDir->getAbsolutePath());
  359.             // walks the map and actually copies the files
  360.             $count=0;
  361.             foreach($this->fileCopyMap as $from => $to) {
  362.                 if ($from === $to) {
  363.                     $this->log("Skipping self-copy of " . $from, $this->verbosity);
  364.                     $total--;
  365.                     continue;
  366.                 }
  367.                 $this->log("From ".$from." to ".$to, $this->verbosity);
  368.                 try { // try to copy file
  369.                 
  370.                     $fromFile = new PhingFile($from);
  371.                     $toFile = new PhingFile($to);
  372.                     
  373.                     $fromSlot->setValue($fromFile->getPath());
  374.                     $fromBasenameSlot->setValue($fromFile->getName());
  375.  
  376.                     $toSlot->setValue($toFile->getPath());
  377.                     $toBasenameSlot->setValue($toFile->getName());
  378.                     
  379.                     $this->fileUtils->copyFile($fromFile, $toFile, $this->overwrite, $this->preserveLMT, $this->filterChains, $this->getProject());
  380.             
  381.                     $count++;
  382.                 } catch (IOException $ioe) {
  383.                     $this->log("Failed to copy " . $from . " to " . $to . ": " . $ioe->getMessage(), Project::MSG_ERR);
  384.                 }
  385.             }
  386.         }
  387.  
  388.         // handle empty dirs if appropriate
  389.         if ($this->includeEmpty) {
  390.             $destdirs = array_values($this->dirCopyMap);
  391.             $count = 0;
  392.             foreach ($destdirs as $destdir) {
  393.                 $d = new PhingFile((string) $destdir);
  394.                 if (!$d->exists()) {
  395.                     if (!$d->mkdirs()) {
  396.                         $this->log("Unable to create directory " . $d->__toString(), Project::MSG_ERR);
  397.                     } else {
  398.                         $count++;
  399.                     }
  400.                 }
  401.             }
  402.             if ($count > 0) {
  403.                 $this->log("Copied ".$count." empty director" . ($count == 1 ? "y" : "ies") . " to " . $this->destDir->getAbsolutePath());
  404.             }
  405.         }
  406.     }
  407.  
  408. }
  409.