1<?php 2/* 3 * $Id: e581b40ff4e3eac5f62a32b48b4a22285cbc51c1 $ 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 22require_once 'phing/Task.php'; 23include_once 'phing/util/DirectoryScanner.php'; 24include_once 'phing/types/FileSet.php'; 25include_once 'phing/util/FileUtils.php'; 26include_once 'phing/system/io/PhingFile.php'; 27include_once 'phing/system/io/IOException.php'; 28 29/** 30 * Touch a file and/or fileset(s); corresponds to the Unix touch command. 31 * 32 * If the file to touch doesn't exist, an empty one is created. 33 * 34 * @version $Id$ 35 * @package phing.tasks.system 36 */ 37class TouchTask extends Task { 38 39 private $file; 40 private $millis = -1; 41 private $dateTime; 42 private $filesets = array(); 43 private $fileUtils; 44 45 function __construct() { 46 $this->fileUtils = new FileUtils(); 47 } 48 49 /** 50 * Sets a single source file to touch. If the file does not exist 51 * an empty file will be created. 52 */ 53 function setFile(PhingFile $file) { 54 $this->file = $file; 55 } 56 57 /** 58 * the new modification time of the file 59 * in milliseconds since midnight Jan 1 1970. 60 * Optional, default=now 61 */ 62 function setMillis($millis) { 63 $this->millis = (int) $millis; 64 } 65 66 /** 67 * the new modification time of the file 68 * in the format MM/DD/YYYY HH:MM AM or PM; 69 * Optional, default=now 70 */ 71 function setDatetime($dateTime) { 72 $this->dateTime = (string) $dateTime; 73 } 74 75 /** 76 * Nested creator, adds a set of files (nested fileset attribute). 77 * @return FileSet 78 */ 79 function createFileSet() { 80 $num = array_push($this->filesets, new FileSet()); 81 return $this->filesets[$num-1]; 82 } 83 84 /** 85 * Execute the touch operation. 86 */ 87 function main() { 88 $savedMillis = $this->millis; 89 90 if ($this->file === null && count($this->filesets) === 0) { 91 throw new BuildException("Specify at least one source - a file or a fileset."); 92 } 93 94 if ($this->file !== null && $this->file->exists() && $this->file->isDirectory()) { 95 throw new BuildException("Use a fileset to touch directories."); 96 } 97 98 try { // try to touch file 99 if ($this->dateTime !== null) { 100 $this->setMillis(strtotime($this->dateTime)); 101 if ($this->millis < 0) { 102 throw new BuildException("Date of {$this->dateTime} results in negative milliseconds value relative to epoch (January 1, 1970, 00:00:00 GMT)."); 103 } 104 } 105 $this->_touch(); 106 } catch (Exception $ex) { 107 throw new BuildException("Error touch()ing file", $ex, $this->location); 108 } 109 110 $this->millis = $savedMillis; 111 112 } 113 114 /** 115 * Does the actual work. 116 */ 117 function _touch() { 118 if ($this->file !== null) { 119 if (!$this->file->exists()) { 120 $this->log("Creating " . $this->file->__toString(), Project::MSG_INFO); 121 try { // try to create file 122 $this->file->createNewFile(); 123 } catch(IOException $ioe) { 124 throw new BuildException("Error creating new file " . $this->file->__toString(), $ioe, $this->location); 125 } 126 } 127 } 128 129 $resetMillis = false; 130 if ($this->millis < 0) { 131 $resetMillis = true; 132 $this->millis = Phing::currentTimeMillis(); 133 } 134 135 if ($this->file !== null) { 136 $this->touchFile($this->file); 137 } 138 139 // deal with the filesets 140 foreach($this->filesets as $fs) { 141 142 $ds = $fs->getDirectoryScanner($this->getProject()); 143 $fromDir = $fs->getDir($this->getProject()); 144 145 $srcFiles = $ds->getIncludedFiles(); 146 $srcDirs = $ds->getIncludedDirectories(); 147 148 for ($j=0,$_j=count($srcFiles); $j < $_j; $j++) { 149 $this->touchFile(new PhingFile($fromDir, (string) $srcFiles[$j])); 150 } 151 152 for ($j=0,$_j=count($srcDirs); $j < $_j ; $j++) { 153 $this->touchFile(new PhingFile($fromDir, (string) $srcDirs[$j])); 154 } 155 } 156 157 if ($resetMillis) { 158 $this->millis = -1; 159 } 160 } 161 162 private function touchFile($file) { 163 if ( !$file->canWrite() ) { 164 throw new BuildException("Can not change modification date of read-only file " . $file->__toString()); 165 } 166 $file->setLastModified($this->millis); 167 } 168 169} 170 171