PageRenderTime 133ms CodeModel.GetById 97ms app.highlight 28ms RepoModel.GetById 1ms app.codeStats 1ms

/web/concrete/core/models/file_version.php

https://github.com/glockops/concrete5
PHP | 599 lines | 458 code | 83 blank | 58 comment | 63 complexity | 1108e7bd19e2b54e6d12f9fa9906b772 MD5 | raw file
  1<?
  2
  3class Concrete5_Model_FileVersion extends Object {
  4
  5	protected $numThumbnailLevels = 3;
  6	protected $attributes = array();
  7
  8	// Update type constants
  9	const UT_REPLACE_FILE = 1;
 10	const UT_TITLE = 2;
 11	const UT_DESCRIPTION = 3;
 12	const UT_TAGS = 4;
 13	const UT_EXTENDED_ATTRIBUTE = 5;
 14
 15	public function getFileID() {return $this->fID;}
 16	public function getFileVersionID() {return $this->fvID;}
 17	public function getPrefix() {return $this->fvPrefix;}
 18	public function getFileName() {return $this->fvFilename;}
 19	public function getTitle() {return $this->fvTitle;}
 20	public function getTags() {return $this->fvTags;}
 21	public function getDescription() {return $this->fvDescription;}
 22	public function isApproved() {return $this->fvIsApproved;}
 23
 24	public function getGenericTypeText() {
 25		$to = $this->getTypeObject();
 26		return $to->getGenericTypeText( $to->getGenericType() );
 27	}
 28
 29	/**
 30	 * returns the File object associated with this FileVersion object
 31	 * @return File
 32	 */
 33	public function getFile() {
 34		$fo = File::getByID($this->fID);
 35		return $fo;
 36	}
 37
 38	//returns an array of tags, instead of a string
 39	public function getTagsList(){
 40		$tags=explode("\n",str_replace("\r","\n",trim($this->getTags())));
 41		$clean_tags=array();
 42		foreach($tags as $tag){
 43			if( strlen(trim($tag)) )
 44				$clean_tags[]=trim($tag);
 45		}
 46		return $clean_tags;
 47	}
 48
 49	/**
 50	 * Gets an associative array of all attributes for a file version
 51	 */
 52	public function getAttributeList() {
 53		$db = Loader::db();
 54		$v = array($this->fID, $this->fvID);
 55		Loader::model('attribute/categories/file');
 56		$attributes = FileAttributeKey::getAttributes($this->fID, $this->fvID);
 57		return $attributes;
 58	}
 59
 60	/**
 61	 * Gets an attribute for the file. If "nice mode" is set, we display it nicely
 62	 * for use in the file attributes table
 63	 */
 64
 65	public function getAttribute($ak, $mode = false) {
 66		if (is_object($ak)) {
 67			$akHandle = $ak->getAttributeKeyHandle();
 68		} else {
 69			$akHandle = $ak;
 70		}
 71
 72		if (!isset($this->attributes[$akHandle . $mode])) {
 73			$this->attributes[$akHandle . $mode] = false;
 74			$ak = FileAttributeKey::getByHandle($akHandle);
 75			if (is_object($ak)) {
 76				$av = $this->getAttributeValueObject($ak);
 77				if (is_object($av)) {
 78					$this->attributes[$akHandle . $mode] = $av->getValue($mode);
 79				}
 80			}
 81		}
 82		return $this->attributes[$akHandle . $mode];
 83	}
 84
 85
 86	public function getMimeType() {
 87		$h = Loader::helper('mime');
 88		$fh = Loader::helper('file');
 89		$ext = $fh->getExtension($this->fvFilename);
 90		return $h->mimeFromExtension($ext);
 91	}
 92
 93	public function getSize() {
 94		return Loader::helper('number')->formatSize($this->fvSize, 'KB');
 95	}
 96	public function getFullSize() {
 97		return $this->fvSize;
 98	}
 99	public function getAuthorName() {
100		return $this->fvAuthorName;
101	}
102
103	public function getAuthorUserID() {
104		return $this->fvAuthorUID;
105	}
106
107	/**
108	 * Gets the date a file version was added
109	 * if user is specified, returns in the current user's timezone
110	 * @param string $type (system || user)
111	 * @return string date formated like: 2009-01-01 00:00:00
112	*/
113	function getDateAdded($type = 'system') {
114		if(ENABLE_USER_TIMEZONES && $type == 'user') {
115			$dh = Loader::helper('date');
116			return $dh->getLocalDateTime($this->fvDateAdded);
117		} else {
118			return $this->fvDateAdded;
119		}
120	}
121
122	public function getExtension() {
123		return $this->fvExtension;
124	}
125
126	public function logVersionUpdate($updateTypeID, $updateTypeAttributeID = 0) {
127		$db = Loader::db();
128		$db->Execute('insert into FileVersionLog (fID, fvID, fvUpdateTypeID, fvUpdateTypeAttributeID) values (?, ?, ?, ?)', array(
129			$this->getFileID(),
130			$this->getFileVersionID(),
131			$updateTypeID,
132			$updateTypeAttributeID
133		));
134	}
135
136	/**
137	 * Takes the current value of the file version and makes a new one with the same values
138	 */
139	public function duplicate() {
140		$f = File::getByID($this->fID);
141
142		$dh = Loader::helper('date');
143		$date = $dh->getSystemDateTime();
144		$db = Loader::db();
145		$fvID = $db->GetOne("select max(fvID) from FileVersions where fID = ?", array($this->fID));
146		if ($fvID > 0) {
147			$fvID++;
148		}
149
150		$data = $db->GetRow("select * from FileVersions where fID = ? and fvID = ?", array($this->fID, $this->fvID));
151		$data['fvID'] = $fvID;
152		$data['fvDateAdded'] = $date;
153		$u = new User();
154		if ($u->isRegistered()) {
155            $data['fvAuthorUID'] = $u->getUserID();
156        } else {
157            $data['fvAuthorUID'] = 0;
158        }
159
160		// If This version is the approved version, we approve the new one.
161		if ($this->isApproved()) {
162			$data['fvIsApproved'] = 1;
163		} else {
164			$data['fvIsApproved'] = 0;
165		}
166
167		// build the field insert query
168		$fields = '';
169		$i = 0;
170		$data2 = array();
171		foreach($data as $key => $value) {
172			if (!is_integer($key)) {
173				$data2[$key] = $value;
174			}
175		}
176
177		foreach($data2 as $key => $value) {
178			$fields .= $key;
179			$questions .= '?';
180			if (($i + 1) < count($data2)) {
181				$fields .= ',';
182				$questions .= ',';
183			}
184			$i++;
185		}
186
187		$db->Execute("insert into FileVersions (" . $fields . ") values (" . $questions . ")", $data2);
188
189
190		$this->deny();
191
192		$r = $db->Execute('select fvID, akID, avID from FileAttributeValues where fID = ? and fvID = ?', array($this->getFileID(), $this->fvID));
193		while ($row = $r->fetchRow()) {
194			$db->Execute("insert into FileAttributeValues (fID, fvID, akID, avID) values (?, ?, ?, ?)", array(
195				$this->fID,
196				$fvID,
197				$row['akID'],
198				$row['avID']
199			));
200		}
201		$fv2 = $f->getVersion($fvID);
202		Events::fire('on_file_version_duplicate', $fv2);
203		return $fv2;
204	}
205
206
207	public function getType() {
208		$ftl = $this->getTypeObject();
209		if (is_object($ftl)) {
210			return $ftl->getName();
211		}
212	}
213
214	public function getTypeObject() {
215		$fh = Loader::helper('file');
216		$ext = $fh->getExtension($this->fvFilename);
217
218		$ftl = FileTypeList::getType($ext);
219		return $ftl;
220	}
221
222	/**
223	 * Returns an array containing human-readable descriptions of everything that happened in this version
224	 */
225	public function getVersionLogComments() {
226		$updates = array();
227		$db = Loader::db();
228		$ga = $db->GetAll('select fvUpdateTypeID, fvUpdateTypeAttributeID from FileVersionLog where fID = ? and fvID = ? order by fvlID asc', array($this->getFileID(), $this->getFileVersionID()));
229		foreach($ga as $a) {
230			switch($a['fvUpdateTypeID']) {
231				case FileVersion::UT_REPLACE_FILE:
232					$updates[] = t('File');
233					break;
234				case FileVersion::UT_TITLE:
235					$updates[] = t('Title');
236					break;
237				case FileVersion::UT_DESCRIPTION:
238					$updates[] = t('Description');
239					break;
240				case FileVersion::UT_TAGS:
241					$updates[] = t('Tags');
242					break;
243				case FileVersion::UT_EXTENDED_ATTRIBUTE:
244					$val = $db->GetOne("select akName from AttributeKeys where akID = ?", array($a['fvUpdateTypeAttributeID']));
245					if ($val != '') {
246						$updates[] = $val;
247					}
248					break;
249			}
250		}
251		$updates = array_unique($updates);
252		$updates1 = array();
253		foreach($updates as $val) {
254			// normalize the keys
255			$updates1[] = $val;
256		}
257		return $updates1;
258	}
259
260	public function updateTitle($title) {
261		$db = Loader::db();
262		$db->Execute("update FileVersions set fvTitle = ? where fID = ? and fvID = ?", array($title, $this->getFileID(), $this->getFileVersionID()));
263		$this->logVersionUpdate(FileVersion::UT_TITLE);
264		$this->fvTitle = $title;
265		Events::fire('on_file_version_update_title', $this, $title);
266		$fo = $this->getFile();
267		$fo->refreshCache();
268	}
269
270	public function updateTags($tags) {
271		$db = Loader::db();
272		$tags = FileVersion::cleanTags($tags);
273		$db->Execute("update FileVersions set fvTags = ? where fID = ? and fvID = ?", array($tags, $this->getFileID(), $this->getFileVersionID()));
274		$this->logVersionUpdate(FileVersion::UT_TAGS);
275		$this->fvTags = $tags;
276		Events::fire('on_file_version_update_tags', $this, $tags);
277		$fo = $this->getFile();
278		$fo->refreshCache();
279	}
280
281
282	public function updateDescription($descr) {
283		$db = Loader::db();
284		$db->Execute("update FileVersions set fvDescription = ? where fID = ? and fvID = ?", array($descr, $this->getFileID(), $this->getFileVersionID()));
285		$this->logVersionUpdate(FileVersion::UT_DESCRIPTION);
286		$this->fvDescription = $descr;
287		Events::fire('on_file_version_update_description', $this, $descr);
288		$fo = $this->getFile();
289		$fo->refreshCache();
290	}
291
292	public function updateFile($filename, $prefix) {
293		$db = Loader::db();
294		$db->Execute("update FileVersions set fvFilename = ?, fvPrefix = ? where fID = ? and fvID = ?", array($filename, $prefix, $this->getFileID(), $this->getFileVersionID()));
295		$this->logVersionUpdate(FileVersion::UT_REPLACE_FILE);
296		$this->fvFilename = $filename;
297		$this->fvPrefix = $prefix;
298
299		$fo = $this->getFile();
300		$fo->refreshCache();
301	}
302
303
304	public function approve() {
305		$db = Loader::db();
306		$db->Execute("update FileVersions set fvIsApproved = 0 where fID = ?", array($this->getFileID()));
307		$db->Execute("update FileVersions set fvIsApproved = 1 where fID = ? and fvID = ?", array($this->getFileID(), $this->getFileVersionID()));
308
309		Events::fire('on_file_version_approve', $this);
310		$fo = $this->getFile();
311		$fo->reindex();
312		$fo->refreshCache();
313	}
314
315
316	public function deny() {
317		$db = Loader::db();
318		$db->Execute("update FileVersions set fvIsApproved = 0 where fID = ? and fvID = ?", array($this->getFileID(), $this->getFileVersionID()));
319		Events::fire('on_file_version_deny', $this);
320		$fo = $this->getFile();
321		$fo->refreshCache();
322	}
323
324
325	public function setAttribute($ak, $value) {
326		if (!is_object($ak)) {
327			$ak = FileAttributeKey::getByHandle($ak);
328		}
329		$ak->setAttribute($this, $value);
330		$fo = $this->getFile();
331		$fo->refreshCache();
332		$fo->reindex();
333		unset($ak);
334	}
335
336
337	/**
338	 * Removes a version of a file. Note, does NOT remove the file because we don't know where the file might elsewhere be used/referenced.
339	 */
340	public function delete() {
341		if ($this->fvIsApproved == 1) {
342			return false; // can only delete non-live files
343		}
344
345		$db = Loader::db();
346		// now from the DB
347		$db->Execute("delete from FileVersions where fID = ? and fvID = ?", array($this->fID, $this->fvID));
348		$db->Execute("delete from FileAttributeValues where fID = ? and fvID = ?", array($this->fID, $this->fvID));
349		$db->Execute("delete from FileVersionLog where fID = ? and fvID = ?", array($this->fID, $this->fvID));
350	}
351
352
353	/**
354	 * Returns a full filesystem path to the file on disk.
355	 */
356	public function getPath() {
357		$f = Loader::helper('concrete/file');
358		if ($this->fslID > 0) {
359			Loader::model('file_storage_location');
360			$fsl = FileStorageLocation::getByID($this->fslID);
361			$path = $f->mapSystemPath($this->fvPrefix, $this->fvFilename, false, $fsl->getDirectory());
362		} else {
363			$path = $f->getSystemPath($this->fvPrefix, $this->fvFilename);
364		}
365		return $path;
366	}
367
368	/**
369	 * Returns a full URL to the file on disk
370	 */
371	public function getURL() {
372		return BASE_URL . $this->getRelativePath();
373	}
374
375	/**
376	 * Returns a URL that can be used to download the file. This passes through the download_file single page.
377	 */
378	public function getDownloadURL() {
379		$c = Page::getCurrentPage();
380		if($c instanceof Page) {
381			$cID = $c->getCollectionID();
382		} else {
383			$cID = 0;
384		}
385		return BASE_URL . View::url('/download_file',$this->getFileID(),$cID);
386	}
387	
388	/**
389	 * Returns a url that can be used to download a file, will force the download of all file types, even if your browser can display them.
390	 */
391	public function getForceDownloadURL() {
392		$c = Page::getCurrentPage();
393		if($c instanceof Page) {
394			$cID = $c->getCollectionID();
395		} else {
396			$cID = 0;
397		}
398		return BASE_URL . View::url('/download_file','force', $this->getFileID(),$cID);
399	}
400	
401
402	public function getRelativePath($fullurl = false) {
403		$f = Loader::helper('concrete/file');
404		if ($this->fslID > 0) {
405			$c = Page::getCurrentPage();
406			if($c instanceof Page) {
407				$cID = $c->getCollectionID();
408			} else {
409				$cID = 0;
410			}
411			$path = BASE_URL . View::url('/download_file', 'view_inline', $this->getFileID(),$cID);
412		} else {
413			if ($fullurl) {
414				$path = BASE_URL . $f->getFileRelativePath($this->fvPrefix, $this->fvFilename );
415			} else {
416				$path = $f->getFileRelativePath($this->fvPrefix, $this->fvFilename );
417			}
418		}
419		return $path;
420	}
421
422	public function getThumbnailPath($level) {
423		$f = Loader::helper('concrete/file');
424		$path = $f->getThumbnailSystemPath($this->fvPrefix, $this->fvFilename, $level);
425		return $path;
426	}
427
428	public function getThumbnailSRC($level) {
429		if ($this->{"fvHasThumbnail{$level}"}) {
430			$f = Loader::helper('concrete/file');
431			$path = $f->getThumbnailRelativePath($this->fvPrefix, $this->fvFilename, $level);
432			return $path;
433		}
434	}
435
436	public function hasThumbnail($level) {
437		return $this->{"fvHasThumbnail{$level}"};
438	}
439
440	public function getThumbnail($level, $fullImageTag = true) {
441		$html = Loader::helper('html');
442		if ($this->{"fvHasThumbnail{$level}"}) {
443			if ($fullImageTag) {
444				return $html->image($this->getThumbnailSRC($level));
445			} else {
446				return $this->getThumbnailSRC($level);
447			}
448		} else {
449			$ft = FileTypeList::getType($this->fvFilename);
450			return $ft->getThumbnail($level, $fullImageTag);
451		}
452	}
453
454	//
455	public function refreshThumbnails($refreshCache = true) {
456		$db = Loader::db();
457		$f = Loader::helper('concrete/file');
458		for ($i = 1; $i <= $this->numThumbnailLevels; $i++) {
459			$path = $f->getThumbnailSystemPath($this->fvPrefix, $this->fvFilename, $i);
460			$hasThumbnail = 0;
461			if (file_exists($path)) {
462				$hasThumbnail = 1;
463			}
464			$db->Execute("update FileVersions set fvHasThumbnail" . $i . "= ? where fID = ? and fvID = ?", array($hasThumbnail, $this->fID, $this->fvID));
465		}
466
467		if ($refreshCache) {
468			$fo = $this->getFile();
469			$fo->refreshCache();
470		}
471	}
472
473	// update types
474	const UT_NEW = 0;
475
476
477	/**
478	 * Responsible for taking a particular version of a file and rescanning all its attributes
479	 * This will run any type-based import routines, and store those attributes, generate thumbnails,
480	 * etc...
481	 */
482	public function refreshAttributes($firstRun = false) {
483		$fh = Loader::helper('file');
484		$ext = $fh->getExtension($this->fvFilename);
485		$ftl = FileTypeList::getType($ext);
486		$db = Loader::db();
487
488		if (!file_exists($this->getPath())) {
489			return File::F_ERROR_FILE_NOT_FOUND;
490		}
491
492		$size = filesize($this->getPath());
493
494		$title = ($firstRun) ? $this->getFilename() : $this->getTitle();
495
496		$db->Execute('update FileVersions set fvExtension = ?, fvType = ?, fvTitle = ?, fvSize = ? where fID = ? and fvID = ?',
497			array($ext, $ftl->getGenericType(), $title, $size, $this->getFileID(), $this->getFileVersionID())
498		);
499		if (is_object($ftl)) {
500			if ($ftl->getCustomImporter() != false) {
501				Loader::library('file/inspector');
502
503				$db->Execute('update FileVersions set fvGenericType = ? where fID = ? and fvID = ?',
504					array($ftl->getGenericType(), $this->getFileID(), $this->getFileVersionID())
505				);
506
507				// we have a custom library script that handles this stuff
508				$cl = $ftl->getCustomInspector();
509				$cl->inspect($this);
510
511			}
512		}
513		$this->refreshThumbnails(false);
514		$f = $this->getFile();
515		$f->refreshCache();
516		$f->reindex();
517	}
518
519	public function createThumbnailDirectories(){
520		$f = Loader::helper('concrete/file');
521		for ($i = 1; $i <= $this->numThumbnailLevels; $i++) {
522			$path = $f->getThumbnailSystemPath($this->fvPrefix, $this->fvFilename, $i, true);
523		}
524	}
525
526
527	/**
528	 * Checks current viewers for this type and returns true if there is a viewer for this type, false if not
529	 */
530	public function canView() {
531		$to = $this->getTypeObject();
532		if (is_object($to) && $to->getView() != '') {
533			return true;
534		}
535		return false;
536	}
537
538	public function canEdit() {
539		$to = $this->getTypeObject();
540		if (is_object($to) && $to->getEditor() != '') {
541			return true;
542		}
543		return false;
544	}
545
546	public function clearAttribute($ak) {
547		$db = Loader::db();
548		$cav = $this->getAttributeValueObject($ak);
549		if (is_object($cav)) {
550			$cav->delete();
551		}
552		$fo = $this->getFile();
553		$fo->refreshCache();
554		$fo->reindex();
555	}
556
557	public function getAttributeValueObject($ak, $createIfNotFound = false) {
558		$db = Loader::db();
559		$av = false;
560		$v = array($this->getFileID(), $this->getFileVersionID(), $ak->getAttributeKeyID());
561		$avID = $db->GetOne("select avID from FileAttributeValues where fID = ? and fvID = ? and akID = ?", $v);
562		if ($avID > 0) {
563			$av = FileAttributeValue::getByID($avID);
564			if (is_object($av)) {
565				$av->setFile($this->getFile());
566				$av->setAttributeKey($ak);
567			}
568		}
569
570		if ($createIfNotFound) {
571			$cnt = 0;
572
573			// Is this avID in use ?
574			if (is_object($av)) {
575				$cnt = $db->GetOne("select count(avID) from FileAttributeValues where avID = ?", $av->getAttributeValueID());
576			}
577
578			if ((!is_object($av)) || ($cnt > 1)) {
579				$newAV = $ak->addAttributeValue();
580				$av = FileAttributeValue::getByID($newAV->getAttributeValueID());
581				$av->setFile($this->getFile());
582			}
583		}
584
585		return $av;
586	}
587
588	//takes a string of comma or new line delimited tags, and puts them in the appropriate format
589	public static function cleanTags($tagsStr){
590		$tagsArray=explode("\n",str_replace(array("\r",","),"\n",$tagsStr));
591		$cleanTags=array();
592		foreach($tagsArray as $tag){
593			if( !strlen(trim($tag)) ) continue;
594			$cleanTags[]=trim($tag);
595		}
596		//the leading and trailing line break char is for searching: fvTag like %\ntag\n%
597		return "\n".join("\n",$cleanTags)."\n";
598	}
599}