CWIS Developer Documentation
File.php
Go to the documentation of this file.
1 <?PHP
2 #
3 # FILE: File.php
4 #
5 # Part of the Collection Workflow Integration System (CWIS)
6 # Copyright 2010-2013 Edward Almasy and Internet Scout Research Group
7 # http://scout.wisc.edu/cwis/
8 #
9 
13 class File {
14 
15  # ---- PUBLIC INTERFACE --------------------------------------------------
16 
17  # status codes (set by constructor and returned by File::Status())
18  const FILESTAT_OK = 0;
19  const FILESTAT_COPYERROR = 1;
24 
38  function File($IdOrFileName, $ResourceId = NULL, $FieldId = NULL,
39  $DesiredFileName = NULL, $CheckFileLength = TRUE)
40  {
41  # assume constructor will succeed
42  $this->Status = self::FILESTAT_OK;
43 
44  # get our own database handle
45  $DB = new Database();
46  $this->DB = $DB;
47 
48  # if ID supplied
49  if (is_int($IdOrFileName))
50  {
51  # set file ID from supplied value
52  $this->Id = intval($IdOrFileName);
53 
54  # load file info from database
55  $DB->Query("SELECT * FROM Files WHERE FileId = ".$this->Id);
56  $this->DBFields = $DB->FetchRow();
57 
58  # if the image wasn't found in the database
59  if (!$DB->NumRowsSelected())
60  {
61  $this->Status = self::FILESTAT_DOESNOTEXIST;
62  }
63  }
64  # else if file name and resource ID and field ID supplied
65  elseif (strlen($IdOrFileName) && ($ResourceId != NULL) && ($FieldId != NULL))
66  {
67  # if file does not exist
68  $TempFileName = $IdOrFileName;
69  if (!file_exists($TempFileName) || !is_readable($TempFileName))
70  {
71  # set status indicating appropriate error
72  $this->Status = file_exists($TempFileName)
73  ? self::FILESTAT_DOESNOTEXIST : self::FILESTAT_UNREADABLE;
74  }
75  else
76  {
77  # if we were asked to check file length and file was zero length
78  $FileLength = filesize($TempFileName);
79  if ($CheckFileLength && !$FileLength)
80  {
81  # set status indicating zero length file
82  $this->Status = self::FILESTAT_ZEROLENGTH;
83  }
84  else
85  {
86  # generate secret string (used to protect from unauthorized download)
87  srand((double)microtime() * 1000000);
88  $SecretString = sprintf("%04X", rand(1, 30000));
89 
90  # attempt to get file type
91  $FileType = "";
92  if (function_exists("finfo_open"))
93  {
94  $FInfoHandle = finfo_open(FILEINFO_MIME);
95 
96  if ($FInfoHandle)
97  {
98  $FInfoMime = finfo_file($FInfoHandle, $TempFileName);
99  finfo_close($FInfoHandle);
100 
101  if ($FInfoMime)
102  {
103  $FileType = $FInfoMime;
104  }
105  }
106  }
107  else if (function_exists("mime_content_type"))
108  {
109  # mime_content_type has been deprecated, but it may be
110  # the only way to get the mimetype for PHP < 5.3
111  $MimeType = mime_content_type($TempFileName);
112 
113  if ($MimeType)
114  {
115  $FileType = $MimeType;
116  }
117  }
118 
119  # add file info to database
120  $BaseFileName = $DesiredFileName
121  ? basename($DesiredFileName) : basename($TempFileName);
122  $DB->Query("INSERT INTO Files"
123  ." (ResourceId, FieldId, FileName, FileLength, FileType,"
124  ." SecretString)"
125  ." VALUES ("
126  .intval($ResourceId).", "
127  .intval($FieldId).", "
128  ."'".addslashes($BaseFileName)."', "
129  .$FileLength.", "
130  ."'".$FileType."', "
131  ."'".$SecretString."')");
132 
133  # retrieve ID of new file
134  $this->Id = $DB->LastInsertId();
135 
136  # load file info back in from database
137  $DB->Query("SELECT * FROM Files WHERE FileId = ".$this->Id);
138  $this->DBFields = $DB->FetchRow();
139 
140  # copy file to storage
141  $CopySucceeded = copy($IdOrFileName, $this->GetNameOfStoredFile());
142 
143  # if copy failed
144  if (!$CopySucceeded)
145  {
146  # remove file info from database
147  $DB->Query("DELETE FROM Files WHERE FileId = ".$this->Id);
148 
149  # set status indicating constructor failed
150  $this->Status = self::FILESTAT_COPYERROR;
151  }
152  }
153  }
154  }
155  else
156  {
157  # set status indicating constructor failed
158  $this->Status = self::FILESTAT_PARAMERROR;
159  }
160  }
161 
166  function Status() { return $this->Status; }
167 
172  function Id() { return $this->Id; }
173 
178  function Name() { return $this->DBFields["FileName"]; }
179 
184  function GetLength() { return $this->DBFields["FileLength"]; }
185 
190  function GetType() { return $this->DBFields["FileType"]; }
191 
197  function Comment($NewValue = DB_NOVALUE)
198  { return $this->UpdateValue("FileComment", $NewValue); }
199 
205  function FieldId($NewValue = DB_NOVALUE)
206  { return $this->UpdateValue("FieldId", $NewValue); }
207 
213  function ResourceId($NewValue = DB_NOVALUE)
214  { return $this->UpdateValue("ResourceId", $NewValue); }
215 
220  function GetMimeType()
221  {
222  return strlen($this->GetType())
223  ? $this->GetType() : "application/octet-stream";
224  }
225 
231  function GetLink()
232  {
233  global $AF;
234 
235  # if .htaccess files are supported, use the redirect that includes
236  # the file name so that browsers don't use index.php as the name
237  # for the downloaded file
238  if ($AF->HtaccessSupport())
239  {
240  return "downloads/".$this->Id."/".rawurlencode($this->Name());
241  }
242 
243  # otherwise use the download portal
244  else
245  {
246  return "index.php?P=DownloadFile&Id=".$this->Id;
247  }
248  }
249 
254  function Delete()
255  {
256  # remove file entry from DB
257  $this->DB->Query("DELETE FROM Files WHERE FileId = ".$this->Id);
258 
259  # delete file
260  $FileName = $this->GetNameOfStoredFile();
261  if (file_exists($FileName))
262  {
263  unlink($FileName);
264  }
265  }
266 
272  {
273  # for each possible storage location
274  foreach (self::$StorageLocations as $Dir)
275  {
276  # build file name for that location
277  $FileName = sprintf($Dir."/%06d-%s-%s",
278  $this->Id, $this->DBFields["SecretString"], $this->Name());
279 
280  # if file can be found in that location
281  if (file_exists($FileName))
282  {
283  # return file name to caller
284  return $FileName;
285  }
286  }
287 
288  # build file name for default (most preferred) location
289  $FileName = sprintf(self::GetStorageDirectory()."/%06d-%s-%s",
290  $this->Id, $this->DBFields["SecretString"], $this->Name());
291 
292  # return file name to caller
293  return $FileName;
294  }
295 
300  static function GetStorageDirectory()
301  {
302  # for each possible storage location
303  foreach (self::$StorageLocations as $Dir)
304  {
305  # if location exists and is writeable
306  if (is_dir($Dir) && is_writeable($Dir))
307  {
308  # return location to caller
309  return $Dir;
310  }
311  }
312 
313  # return default (most preferred) location to caller
314  return self::$StorageLocations[0];
315  }
316 
317 
318  # ---- PRIVATE INTERFACE -------------------------------------------------
319 
320  private $DB;
321  private $Status;
322  private $Id;
323  private $DBFields;
324 
326  static private $StorageLocations = array(
327  "local/data/files",
328  "FileStorage",
329  );
330 
337  private function UpdateValue($FieldName, $NewValue)
338  {
339  return $this->DB->UpdateValue("Files", $FieldName, $NewValue,
340  "FileId = ".intval($this->Id),
341  $this->DBFields, TRUE);
342  }
343 }
344 
345 
const FILESTAT_ZEROLENGTH
Definition: File.php:21
GetNameOfStoredFile()
Returns the relative link to the stored file.
Definition: File.php:271
const FILESTAT_UNREADABLE
Definition: File.php:23
const FILESTAT_COPYERROR
Definition: File.php:19
GetType()
Gets the file's type.
Definition: File.php:190
const FILESTAT_DOESNOTEXIST
Definition: File.php:22
SQL database abstraction object with smart query caching.
const DB_NOVALUE
FieldId($NewValue=DB_NOVALUE)
Gets or sets the field ID of the File.
Definition: File.php:205
Id()
Gets the object's ID.
Definition: File.php:172
GetLink()
Returns the relative download link to download the file.
Definition: File.php:231
const FILESTAT_PARAMERROR
Definition: File.php:20
Delete()
Deletes the file and removes its entry from the database.
Definition: File.php:254
Status()
Gets the object's status.
Definition: File.php:166
GetMimeType()
Gets the MIME type of the file.
Definition: File.php:220
PHP
Definition: OAIClient.php:39
GetLength()
Gets the length of the file.
Definition: File.php:184
static GetStorageDirectory()
Get file storage directory.
Definition: File.php:300
ResourceId($NewValue=DB_NOVALUE)
Gets or sets the resource ID of the File.
Definition: File.php:213
const FILESTAT_OK
Definition: File.php:18
Name()
Gets the name of the object.
Definition: File.php:178
Class representing a stored (usually uploaded) file.
Definition: File.php:13
Comment($NewValue=DB_NOVALUE)
Gets or sets the comment on the file.
Definition: File.php:197
File($IdOrFileName, $ResourceId=NULL, $FieldId=NULL, $DesiredFileName=NULL, $CheckFileLength=TRUE)
Constructs a File object using either an existing file or a new file.
Definition: File.php:38