CWIS Developer Documentation

- Home
- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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
16 # ---- PUBLIC INTERFACE --------------------------------------------------
17
18 # status codes (set by constructor and returned by File::Status())
19 const FILESTAT_OK = 0;
20 const FILESTAT_COPYERROR = 1;
21 const FILESTAT_PARAMERROR = 2;
22 const FILESTAT_ZEROLENGTH = 3;
23 const FILESTAT_DOESNOTEXIST = 4;
24 const FILESTAT_UNREADABLE = 5;
25
39 public function __construct($IdOrFileName, $ResourceId = NULL, $FieldId = NULL,
40 $DesiredFileName = NULL, $CheckFileLength = TRUE)
41 {
42 # assume constructor will succeed
43 $this->Status = self::FILESTAT_OK;
44
45 # get our own database handle
46 $DB = new Database();
47 $this->DB = $DB;
48
49 # if ID supplied
50 if (is_numeric($IdOrFileName))
51 {
52 # set file ID from supplied value
53 $this->Id = intval($IdOrFileName);
54
55 # load file info from database
56 $DB->Query("SELECT * FROM Files WHERE FileId = ".$this->Id);
57 $this->DBFields = $DB->FetchRow();
58
59 # if the image wasn't found in the database
60 if (!$DB->NumRowsSelected())
61 {
62 $this->Status = self::FILESTAT_DOESNOTEXIST;
63 }
64 }
65 # else if file name and resource ID and field ID supplied
66 elseif (strlen($IdOrFileName) && ($ResourceId != NULL) && ($FieldId != NULL))
67 {
68 # if file does not exist
69 $TempFileName = $IdOrFileName;
70 if (!file_exists($TempFileName) || !is_readable($TempFileName))
71 {
72 # set status indicating appropriate error
73 $this->Status = file_exists($TempFileName)
74 ? self::FILESTAT_DOESNOTEXIST : self::FILESTAT_UNREADABLE;
75 }
76 else
77 {
78 # if we were asked to check file length and file was zero length
79 $FileLength = filesize($TempFileName);
80 if ($CheckFileLength && !$FileLength)
81 {
82 # set status indicating zero length file
83 $this->Status = self::FILESTAT_ZEROLENGTH;
84 }
85 else
86 {
87 # generate secret string (used to protect from unauthorized download)
88 srand((double)microtime() * 1000000);
89 $SecretString = sprintf("%04X", rand(1, 30000));
90
91 # attempt to get file type
92 $FileType = "";
93 if (function_exists("finfo_open"))
94 {
95 $FInfoHandle = finfo_open(FILEINFO_MIME);
96
97 if ($FInfoHandle)
98 {
99 $FInfoMime = finfo_file($FInfoHandle, $TempFileName);
100 finfo_close($FInfoHandle);
101
102 if ($FInfoMime)
103 {
104 $FileType = $FInfoMime;
105 }
106 }
107 }
108 else if (function_exists("mime_content_type"))
109 {
110 # mime_content_type has been deprecated, but it may be
111 # the only way to get the mimetype for PHP < 5.3
112 $MimeType = mime_content_type($TempFileName);
113
114 if ($MimeType)
115 {
116 $FileType = $MimeType;
117 }
118 }
119
120 # handle Office XML formats
121 # These are recognized by PHP as zip files (because they are), but
122 # IE (and maybe other things?) need a special-snowflake MIME type to
123 # handle them properly.
124 # For a list of the required types, see
125 # https://technet.microsoft.com/en-us/library/ee309278(office.12).aspx
126 if ($FileType == "application/zip; charset=binary")
127 {
128 $MstfPrefix = "application/vnd.openxmlformats-officedocument";
129
130 $FileNameForExt = is_null($DesiredFileName) ?
131 $TempFileName : $DesiredFileName ;
132
133 $FileExt = strtolower(pathinfo(
134 $FileNameForExt, PATHINFO_EXTENSION));
135
136 switch ($FileExt)
137 {
138 case "docx":
139 $FileType = $MstfPrefix.".wordprocessingml.document";
140 break;
141
142 case "xlsx":
143 $FileType = $MsftPrefix.".spreadsheetml.sheet";
144 break;
145
146 case "pptx":
147 $FileType = $MsftPrefix.".presentationml.slideshow";
148 break;
149
150 default:
151 # do nothing
152 }
153 }
154
155 # add file info to database
156 $BaseFileName = $DesiredFileName
157 ? basename($DesiredFileName) : basename($TempFileName);
158 $DB->Query("INSERT INTO Files"
159 ." (ResourceId, FieldId, FileName, FileLength, FileType,"
160 ." SecretString)"
161 ." VALUES ("
162 .intval($ResourceId).", "
163 .intval($FieldId).", "
164 ."'".addslashes($BaseFileName)."', "
165 .$FileLength.", "
166 ."'".addslashes($FileType)."', "
167 ."'".$SecretString."')");
168
169 # retrieve ID of new file
170 $this->Id = $DB->LastInsertId();
171
172 # load file info back in from database
173 $DB->Query("SELECT * FROM Files WHERE FileId = ".$this->Id);
174 $this->DBFields = $DB->FetchRow();
175
176 # copy file to storage
177 $CopySucceeded = copy($IdOrFileName, $this->GetNameOfStoredFile());
178
179 # if copy failed
180 if (!$CopySucceeded)
181 {
182 # remove file info from database
183 $DB->Query("DELETE FROM Files WHERE FileId = ".$this->Id);
184
185 # set status indicating constructor failed
186 $this->Status = self::FILESTAT_COPYERROR;
187 }
188 }
189 }
190 }
191 else
192 {
193 # set status indicating constructor failed
194 $this->Status = self::FILESTAT_PARAMERROR;
195 }
196 }
197
202 public function Status()
203 {
204 return $this->Status;
205 }
206
211 public function Id()
212 {
213 return $this->Id;
214 }
215
220 public function Name()
221 {
222 return $this->DBFields["FileName"];
223 }
224
229 public function GetLength()
230 {
231 return $this->DBFields["FileLength"];
232 }
233
238 public function GetType()
239 {
240 return $this->DBFields["FileType"];
241 }
242
248 public function Comment($NewValue = DB_NOVALUE)
249 {
250 return $this->UpdateValue("FileComment", $NewValue);
251 }
252
258 public function FieldId($NewValue = DB_NOVALUE)
259 {
260 return $this->UpdateValue("FieldId", $NewValue);
261 }
262
268 public function ResourceId($NewValue = DB_NOVALUE)
269 {
270 return $this->UpdateValue("ResourceId", $NewValue);
271 }
272
277 public function GetMimeType()
278 {
279 return strlen($this->GetType())
280 ? $this->GetType() : "application/octet-stream";
281 }
282
288 public function GetLink()
289 {
290 # if CleanURLs are enabled, use the redirect that includes
291 # the file name so that browsers don't use index.php as the name
292 # for the downloaded file
293 if ($GLOBALS["G_PluginManager"]->PluginEnabled("CleanURLs"))
294 {
295 return "downloads/".$this->Id."/".rawurlencode($this->Name());
296 }
297
298 # otherwise use the download portal
299 else
300 {
301 return "index.php?P=DownloadFile&Id=".$this->Id;
302 }
303 }
304
309 public function Delete()
310 {
311 # remove file entry from DB
312 $this->DB->Query("DELETE FROM Files WHERE FileId = ".$this->Id);
313
314 # delete file
315 $FileName = $this->GetNameOfStoredFile();
316 if (file_exists($FileName))
317 {
318 unlink($FileName);
319 }
320 }
321
326 public function GetNameOfStoredFile()
327 {
328 # for each possible storage location
329 foreach (self::$StorageLocations as $Dir)
330 {
331 # build file name for that location
332 $FileName = sprintf($Dir."/%06d-%s-%s",
333 $this->Id, $this->DBFields["SecretString"], $this->Name());
334
335 # if file can be found in that location
336 if (file_exists($FileName))
337 {
338 # return file name to caller
339 return $FileName;
340 }
341 }
342
343 # build file name for default (most preferred) location
344 $FileName = sprintf(self::GetStorageDirectory()."/%06d-%s-%s",
345 $this->Id, $this->DBFields["SecretString"], $this->Name());
346
347 # return file name to caller
348 return $FileName;
349 }
350
355 public static function GetStorageDirectory()
356 {
357 # for each possible storage location
358 foreach (self::$StorageLocations as $Dir)
359 {
360 # if location exists and is writeable
361 if (is_dir($Dir) && is_writeable($Dir))
362 {
363 # return location to caller
364 return $Dir;
365 }
366 }
367
368 # return default (most preferred) location to caller
369 return self::$StorageLocations[0];
370 }
371
372
373 # ---- PRIVATE INTERFACE -------------------------------------------------
374
375 private $DB;
376 private $Status;
377 private $Id;
378 private $DBFields;
379
381 static private $StorageLocations = array(
382 "local/data/files",
383 "FileStorage",
384 );
385
392 private function UpdateValue($FieldName, $NewValue)
393 {
394 return $this->DB->UpdateValue("Files", $FieldName, $NewValue,
395 "FileId = ".intval($this->Id),
396 $this->DBFields, TRUE);
397 }
398 }
File\FILESTAT_ZEROLENGTH
const FILESTAT_ZEROLENGTH
Definition: File.php:22
File\GetNameOfStoredFile
GetNameOfStoredFile()
Returns the relative link to the stored file.
Definition: File.php:326
File\FILESTAT_UNREADABLE
const FILESTAT_UNREADABLE
Definition: File.php:24
File\FILESTAT_COPYERROR
const FILESTAT_COPYERROR
Definition: File.php:20
File\GetType
GetType()
Gets the file&#39;s type.
Definition: File.php:238
File\FILESTAT_DOESNOTEXIST
const FILESTAT_DOESNOTEXIST
Definition: File.php:23
Database
SQL database abstraction object with smart query caching.
Definition: Database.php:22
File\FieldId
FieldId($NewValue=DB_NOVALUE)
Gets or sets the field ID of the File.
Definition: File.php:258
File\Id
Id()
Gets the object&#39;s ID.
Definition: File.php:211
File\GetLink
GetLink()
Returns the relative download link to download the file.
Definition: File.php:288
File\FILESTAT_PARAMERROR
const FILESTAT_PARAMERROR
Definition: File.php:21
File\Delete
Delete()
Deletes the file and removes its entry from the database.
Definition: File.php:309
File\Status
Status()
Gets the object&#39;s status.
Definition: File.php:202
File\__construct
__construct($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:39
File\GetMimeType
GetMimeType()
Gets the MIME type of the file.
Definition: File.php:277
PHP
PHP
Definition: RSSClient--Test.php:12
DB_NOVALUE
const DB_NOVALUE
Definition: Database.php:1396
File\GetLength
GetLength()
Gets the length of the file.
Definition: File.php:229
File\GetStorageDirectory
static GetStorageDirectory()
Get file storage directory.
Definition: File.php:355
File\ResourceId
ResourceId($NewValue=DB_NOVALUE)
Gets or sets the resource ID of the File.
Definition: File.php:268
File\FILESTAT_OK
const FILESTAT_OK
Definition: File.php:19
File\Name
Name()
Gets the name of the object.
Definition: File.php:220
File
Class representing a stored (usually uploaded) file.
Definition: File.php:13
File\Comment
Comment($NewValue=DB_NOVALUE)
Gets or sets the comment on the file.
Definition: File.php:248