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-2017 Edward Almasy and Internet Scout Research Group
7 # http://scout.wisc.edu/cwis/
8 #
9
13 class File extends Item
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
34 public static function Create($SourceFile, $DesiredFileName = NULL)
35 {
36 # check that file exists
37 if (!file_exists($SourceFile))
38 {
39 return self::FILESTAT_DOESNOTEXIST;
40 }
41
42 # check that file is readable
43 if (!is_readable($SourceFile))
44 {
45 return self::FILESTAT_UNREADABLE;
46 }
47
48 # check that file is not zero length
49 $FileSize = filesize($SourceFile);
50 if (!$FileSize)
51 {
52 return self::FILESTAT_ZEROLENGTH;
53 }
54
55 # generate secret string (used to protect from unauthorized download)
56 srand((double)microtime() * 1000000);
57 $SecretString = sprintf("%04X", rand(1, 30000));
58
59 # get next file ID by adding file to database
60 $DB = new Database();
61 $DB->Query("INSERT INTO Files (SecretString) VALUES ('".$SecretString."')");
62 $FileId = $DB->LastInsertId();
63
64 # build name for stored file
65 $BaseFileName = ($DesiredFileName === NULL)
66 ? basename($SourceFile) : basename($DesiredFileName);
67 $StoredFile = sprintf(self::GetStorageDirectory()."/%06d-%s-%s",
68 $FileId, $SecretString, $BaseFileName);
69
70 # attempt to copy file to storage
71 $Result = copy($SourceFile, $StoredFile);
72
73 # if copy attempt failed
74 if ($Result === FALSE)
75 {
76 # remove file from database
77 $DB->Query("DELETE FROM Files WHERE FileId = ".$FileId);
78
79 # report error to caller
80 return self::FILESTAT_COPYERROR;
81 }
82
83 # attempt to get file type
84 $FileType = self::DetermineFileType($SourceFile);
85
86 # save file info in database
87 $DB->Query("UPDATE Files SET"
88 ." FileName = '".addslashes($BaseFileName)."',"
89 ." FileType = '".addslashes($FileType)."',"
90 ." FileLength = '".addslashes($FileSize)."'"
91 ." WHERE FileId = ".$FileId);
92
93 # instantiate new object and return it to caller
94 return new File($FileId);
95 }
96
102 public function CreateCopy()
103 {
104 $Copy = self::Create($this->GetNameOfStoredFile(), $this->Name());
105 if (!$Copy instanceof self)
106 {
107 throw new Exception("Copy failed with error ".$Copy);
108 }
109 $Copy->ResourceId($this->ResourceId());
110 $Copy->FieldId($this->FieldId());
111 return $Copy;
112 }
113
118 public function GetLength()
119 {
120 return $this->ValueCache["FileLength"];
121 }
122
127 public function GetType()
128 {
129 return $this->ValueCache["FileType"];
130 }
131
137 public function Comment($NewValue = DB_NOVALUE)
138 {
139 return $this->UpdateValue("FileComment", $NewValue);
140 }
141
147 public function FieldId($NewValue = DB_NOVALUE)
148 {
149 return $this->UpdateValue("FieldId", $NewValue);
150 }
151
157 public function ResourceId($NewValue = DB_NOVALUE)
158 {
159 return $this->UpdateValue("ResourceId", $NewValue);
160 }
161
166 public function GetMimeType()
167 {
168 return strlen($this->GetType())
169 ? $this->GetType() : "application/octet-stream";
170 }
171
177 public function GetLink()
178 {
179 # if CleanURLs are enabled, use the redirect that includes
180 # the file name so that browsers don't use index.php as the name
181 # for the downloaded file
182 if ($GLOBALS["G_PluginManager"]->PluginEnabled("CleanURLs"))
183 {
184 return "downloads/".$this->Id."/".rawurlencode($this->Name());
185 }
186
187 # otherwise use the download portal
188 else
189 {
190 return "index.php?P=DownloadFile&Id=".$this->Id;
191 }
192 }
193
198 public function Destroy()
199 {
200 # delete file
201 $FileName = $this->GetNameOfStoredFile();
202 if (file_exists($FileName))
203 {
204 unlink($FileName);
205 }
206
207 # call parent method
208 parent::Destroy();
209 }
210
216 public function Delete()
217 {
218 $this->Destroy();
219 }
220
225 public function GetNameOfStoredFile()
226 {
227 # for each possible storage location
228 foreach (self::$StorageLocations as $Dir)
229 {
230 # build file name for that location
231 $FileName = sprintf($Dir."/%06d-%s-%s",
232 $this->Id, $this->ValueCache["SecretString"], $this->Name());
233
234 # if file can be found in that location
235 if (file_exists($FileName))
236 {
237 # return file name to caller
238 return $FileName;
239 }
240 }
241
242 # build file name for default (most preferred) location
243 $FileName = sprintf(self::GetStorageDirectory()."/%06d-%s-%s",
244 $this->Id, $this->ValueCache["SecretString"], $this->Name());
245
246 # return file name to caller
247 return $FileName;
248 }
249
254 public static function GetStorageDirectory()
255 {
256 # for each possible storage location
257 foreach (self::$StorageLocations as $Dir)
258 {
259 # if location exists and is writeable
260 if (is_dir($Dir) && is_writeable($Dir))
261 {
262 # return location to caller
263 return $Dir;
264 }
265 }
266
267 # return default (most preferred) location to caller
268 return self::$StorageLocations[0];
269 }
270
271
272 # ---- PRIVATE INTERFACE -------------------------------------------------
273
275 static private $StorageLocations = array(
276 "local/data/files",
277 "FileStorage",
278 );
279
286 protected static function DetermineFileType($FileName)
287 {
288 $FileType = "";
289 if (function_exists("mime_content_type"))
290 {
291 $FileType = mime_content_type($FileName);
292 }
293 # Although mime_content_type is baked into PHP5 and PHP7, it is still
294 # part of extensions in some versions of PHP 5.x.
295 elseif (function_exists("finfo_open"))
296 {
297 $FInfoHandle = finfo_open(FILEINFO_MIME);
298 if ($FInfoHandle)
299 {
300 $Result = finfo_file($FInfoHandle, $FileName);
301 finfo_close($FInfoHandle);
302 if ($Result)
303 {
304 $FileType = $FInfoMime;
305 }
306 }
307 }
308
309 # handle Office XML formats
310 # These are recognized by PHP as zip files (because they are), but
311 # IE (and maybe other things?) need a special-snowflake MIME type to
312 # handle them properly.
313 # For a list of the required types, see
314 # https://technet.microsoft.com/en-us/library/ee309278(office.12).aspx
315 if ($FileType == "application/zip; charset=binary")
316 {
317 $MsftPrefix = "application/vnd.openxmlformats-officedocument";
318
319 $FileExt = strtolower(pathinfo($FileName, PATHINFO_EXTENSION));
320
321 switch ($FileExt)
322 {
323 case "docx":
324 $FileType = $MstfPrefix.".wordprocessingml.document";
325 break;
326
327 case "xlsx":
328 $FileType = $MsftPrefix.".spreadsheetml.sheet";
329 break;
330
331 case "pptx":
332 $FileType = $MsftPrefix.".presentationml.slideshow";
333 break;
334
335 default:
336 # do nothing
337 }
338 }
339
340 return $FileType;
341 }
342 }
File\FILESTAT_ZEROLENGTH
const FILESTAT_ZEROLENGTH
Definition: File.php:22
File\GetNameOfStoredFile
GetNameOfStoredFile()
Returns the relative link to the stored file.
Definition: File.php:225
Item\Name
Name($NewValue=DB_NOVALUE)
Get/set name of item.
Definition: Item.php:103
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:127
Item\Id
Id()
Get item ID.
Definition: Item.php:81
File\FILESTAT_DOESNOTEXIST
const FILESTAT_DOESNOTEXIST
Definition: File.php:23
Item\UpdateValue
UpdateValue($ColumnName, $NewValue=DB_NOVALUE)
Convenience function to supply parameters to Database::UpdateValue().
Definition: Item.php:285
Database
SQL database abstraction object with smart query caching.
Definition: Database.php:22
File\Destroy
Destroy()
Deletes the file and removes its entry from the database.
Definition: File.php:198
File\Create
static Create($SourceFile, $DesiredFileName=NULL)
Create a new File object using an existing file.
Definition: File.php:34
File\FieldId
FieldId($NewValue=DB_NOVALUE)
Gets or sets the field ID of the File.
Definition: File.php:147
File\DetermineFileType
static DetermineFileType($FileName)
Get MIME type for specified file, if possible.
Definition: File.php:286
Item\$DB
$DB
Definition: Item.php:210
File\GetLink
GetLink()
Returns the relative download link to download the file.
Definition: File.php:177
File\FILESTAT_PARAMERROR
const FILESTAT_PARAMERROR
Definition: File.php:21
File\Delete
Delete()
Deprecated method to delete file and remove entry from database.
Definition: File.php:216
File\GetMimeType
GetMimeType()
Gets the MIME type of the file.
Definition: File.php:166
PHP
PHP
Definition: RSSClient--Test.php:12
Item
Common base class for persistent items store in database.
Definition: Item.php:13
DB_NOVALUE
const DB_NOVALUE
Definition: Database.php:1784
File\CreateCopy
CreateCopy()
Create copy of File object.
Definition: File.php:102
File\GetLength
GetLength()
Gets the length of the file.
Definition: File.php:118
File\GetStorageDirectory
static GetStorageDirectory()
Get file storage directory.
Definition: File.php:254
File\ResourceId
ResourceId($NewValue=DB_NOVALUE)
Gets or sets the resource ID of the File.
Definition: File.php:157
File\FILESTAT_OK
const FILESTAT_OK
Definition: File.php:19
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:137