PageRenderTime 26ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/concrete/models/file.php

https://github.com/rii-J/concrete5-de
PHP | 526 lines | 403 code | 82 blank | 41 comment | 54 complexity | c3de54ea988075e61dc4a5c9b89afffe MD5 | raw file
  1. <?php
  2. Loader::model('file_version');
  3. class File extends Object {
  4. const CREATE_NEW_VERSION_THRESHOLD = 300; // in seconds (5 minutes)
  5. const F_ERROR_INVALID_FILE = 1;
  6. const F_ERROR_FILE_NOT_FOUND = 2;
  7. /**
  8. * returns a file object for the given file ID
  9. * @param int $fID
  10. * @return File
  11. */
  12. public function getByID($fID) {
  13. $f = Cache::get('file_approved', $fID);
  14. if (is_object($f)) {
  15. return $f;
  16. }
  17. Loader::model('file_set');
  18. $db = Loader::db();
  19. $f = new File();
  20. $row = $db->GetRow("SELECT Files.*, FileVersions.fvID
  21. FROM Files LEFT JOIN FileVersions on Files.fID = FileVersions.fID and FileVersions.fvIsApproved = 1
  22. WHERE Files.fID = ?", array($fID));
  23. if ($row['fID'] == $fID) {
  24. $f->setPropertiesFromArray($row);
  25. Cache::set('file_approved', $fID, $f);
  26. } else {
  27. $f->error = File::F_ERROR_INVALID_FILE;
  28. }
  29. return $f;
  30. }
  31. /**
  32. * For all methods that file does not implement, we pass through to the currently active file version object
  33. */
  34. public function __call($nm, $a) {
  35. $fv = $this->getApprovedVersion();
  36. return call_user_func_array(array($fv, $nm), $a);
  37. }
  38. public function getPath() {
  39. $fv = $this->getVersion();
  40. return $fv->getPath();
  41. }
  42. public function getPassword() {
  43. return $this->fPassword;
  44. }
  45. public function getStorageLocationID() {
  46. return $this->fslID;
  47. }
  48. public function refreshCache() {
  49. $db = Loader::db();
  50. Cache::delete('file_relative_path', $this->getFileID());
  51. Cache::delete('file_approved', $this->getFileID());
  52. $r = $db->GetCol('select fvID from FileVersions where fID = ?', array($this->getFileID()));
  53. foreach($r as $fvID) {
  54. Cache::delete('file_version_' . $this->getFileID(), $fvID);
  55. }
  56. }
  57. public function reindex() {
  58. Loader::model('attribute/categories/file');
  59. $attribs = FileAttributeKey::getAttributes($this->getFileID(), $this->getFileVersionID(), 'getSearchIndexValue');
  60. $db = Loader::db();
  61. $db->Execute('delete from FileSearchIndexAttributes where fID = ?', array($this->getFileID()));
  62. $searchableAttributes = array('fID' => $this->getFileID());
  63. $rs = $db->Execute('select * from FileSearchIndexAttributes where fID = -1');
  64. AttributeKey::reindex('FileSearchIndexAttributes', $searchableAttributes, $attribs, $rs);
  65. }
  66. public static function getRelativePathFromID($fID) {
  67. $path = Cache::get('file_relative_path', $fID);
  68. if ($path != false) {
  69. return $path;
  70. }
  71. $f = File::getByID($fID);
  72. $path = $f->getRelativePath();
  73. Cache::set('file_relative_path', $fID, $path);
  74. return $path;
  75. }
  76. public function setStorageLocation($item) {
  77. if ($item == 0) {
  78. // set to default
  79. $itemID = 0;
  80. $path = DIR_FILES_UPLOADED;
  81. } else {
  82. $itemID = $item->getID();
  83. $path = $item->getDirectory();
  84. }
  85. if ($itemID != $this->getStorageLocationID()) {
  86. // retrieve all versions of a file and move its stuff
  87. $list = $this->getVersionList();
  88. $fh = Loader::helper('concrete/file');
  89. foreach($list as $fv) {
  90. $newPath = $fh->mapSystemPath($fv->getPrefix(), $fv->getFileName(), true, $path);
  91. $currPath = $fv->getPath();
  92. rename($currPath, $newPath);
  93. }
  94. $db = Loader::db();
  95. $db->Execute('update Files set fslID = ? where fID = ?', array($itemID, $this->fID));
  96. }
  97. $this->refreshCache();
  98. }
  99. public function setPassword($pw) {
  100. Events::fire('on_file_set_password', $this, $pw);
  101. $db = Loader::db();
  102. $db->Execute("update Files set fPassword = ? where fID = ?", array($pw, $this->getFileID()));
  103. $this->fPassword = $pw;
  104. $this->refreshCache();
  105. }
  106. public function setOriginalPage($ocID) {
  107. if ($ocID < 1) {
  108. return false;
  109. }
  110. $db = Loader::db();
  111. $db->Execute("update Files set ocID = ? where fID = ?", array($ocID, $this->getFileID()));
  112. $this->refreshCache();
  113. }
  114. public function getOriginalPageObject() {
  115. if ($this->ocID > 0) {
  116. $c = Page::getByID($this->ocID);
  117. if (is_object($c) && !$c->isError()) {
  118. return $c;
  119. }
  120. }
  121. }
  122. public function overrideFileSetPermissions() {
  123. return $this->fOverrideSetPermissions;
  124. }
  125. public function resetPermissions($fOverrideSetPermissions = 0) {
  126. $db = Loader::db();
  127. $db->Execute("delete from FilePermissions where fID = ?", array($this->fID));
  128. $db->Execute("update Files set fOverrideSetPermissions = ? where fID = ?", array($fOverrideSetPermissions, $this->fID));
  129. $this->refreshCache();
  130. }
  131. public function setPermissions($obj, $canRead, $canSearch, $canWrite, $canAdmin) {
  132. $fID = $this->fID;
  133. $uID = 0;
  134. $gID = 0;
  135. $db = Loader::db();
  136. if (is_a($obj, 'UserInfo')) {
  137. $uID = $obj->getUserID();
  138. } else {
  139. $gID = $obj->getGroupID();
  140. }
  141. if ($canRead < 1) {
  142. $canRead = 0;
  143. }
  144. if ($canSearch < 1) {
  145. $canSearch = 0;
  146. }
  147. if ($canWrite < 1) {
  148. $canWrite = 0;
  149. }
  150. if ($canAdmin < 1) {
  151. $canAdmin = 0;
  152. }
  153. $db->Replace('FilePermissions', array(
  154. 'fID' => $fID,
  155. 'uID' => $uID,
  156. 'gID' => $gID,
  157. 'canRead' => $canRead,
  158. 'canSearch' => $canSearch,
  159. 'canWrite' => $canWrite,
  160. 'canAdmin' => $canAdmin
  161. ),
  162. array('fID', 'gID', 'uID'), true);
  163. $this->refreshCache();
  164. }
  165. public function getUserID() {
  166. return $this->uID;
  167. }
  168. public function setUserID($uID) {
  169. $this->uID = $uID;
  170. $db = Loader::db();
  171. $db->Execute("update Files set uID = ? where fID = ?", array($uID, $this->fID));
  172. }
  173. public function getFileSets() {
  174. $db = Loader::db();
  175. Loader::model('file_set');
  176. $fsIDs = $db->Execute("select fsID from FileSetFiles where fID = ?", array($this->getFileID()));
  177. $filesets = array();
  178. foreach($fsIDs as $fsID) {
  179. $filesets[] = FileSet::getByID($fsID);
  180. }
  181. return $filesets;
  182. }
  183. public function isStarred($u = false) {
  184. if (!$u) {
  185. $u = new User();
  186. }
  187. $db = Loader::db();
  188. Loader::model('file_set');
  189. $r = $db->GetOne("select fsfID from FileSetFiles fsf inner join FileSets fs on fs.fsID = fsf.fsID where fsf.fID = ? and fs.uID = ? and fs.fsType = ?",
  190. array($this->getFileID(), $u->getUserID(), FileSet::TYPE_STARRED));
  191. return $r > 0;
  192. }
  193. public function getDateAdded() {
  194. return $this->fDateAdded;
  195. }
  196. /**
  197. * Returns a file version object that is to be written to. Computes whether we can use the current most recent version, OR a new one should be created
  198. */
  199. public function getVersionToModify($forceCreateNew = false) {
  200. $u = new User();
  201. $createNew = false;
  202. $fv = $this->getRecentVersion();
  203. $fav = $this->getApprovedVersion();
  204. // first test. Does the user ID of the most recent version match ours? If not, then we create new
  205. if ($u->getUserID() != $fv->getAuthorUserID()) {
  206. $createNew = true;
  207. }
  208. // second test. If the date the version was added is older than File::CREATE_NEW_VERSION_THRESHOLD, we create new
  209. $unixTime = strtotime($fv->getDateAdded());
  210. $diff = time() - $unixTime;
  211. if ($diff > File::CREATE_NEW_VERSION_THRESHOLD) {
  212. $createNew = true;
  213. }
  214. if ($forceCreateNew) {
  215. $createNew = true;
  216. }
  217. if ($createNew) {
  218. $fv2 = $fv->duplicate();
  219. // Are the recent and active versions the same? If so, we approve this new version we just made
  220. if ($fv->getFileVersionID() == $fav->getFileVersionID()) {
  221. $fv2->approve();
  222. }
  223. return $fv2;
  224. } else {
  225. return $fv;
  226. }
  227. }
  228. public function getFileID() { return $this->fID;}
  229. public function duplicate() {
  230. $dh = Loader::helper('date');
  231. $db = Loader::db();
  232. $date = $dh->getSystemDateTime();
  233. $far = new ADODB_Active_Record('Files');
  234. $far->Load('fID=?', array($this->fID));
  235. $far2 = clone $far;
  236. $far2->fID = null;
  237. $far2->fDateAdded = $date;
  238. $far2->Insert();
  239. $fIDNew = $db->Insert_ID();
  240. $fvIDs = $db->GetCol('select fvID from FileVersions where fID = ?', $this->fID);
  241. foreach($fvIDs as $fvID) {
  242. $farv = new ADODB_Active_Record('FileVersions');
  243. $farv->Load('fID=? and fvID = ?', array($this->fID, $fvID));
  244. $farv2 = clone $farv;
  245. $farv2->fID = $fIDNew;
  246. $farv2->fvActivateDatetime = $date;
  247. $farv2->fvDateAdded = $date;
  248. $farv2->Insert();
  249. }
  250. $r = $db->Execute('select fvID, akID, avID from FileAttributeValues where fID = ?', array($this->getFileID()));
  251. while ($row = $r->fetchRow()) {
  252. $db->Execute("insert into FileAttributeValues (fID, fvID, akID, avID) values (?, ?, ?, ?)", array(
  253. $fIDNew,
  254. $row['fvID'],
  255. $row['akID'],
  256. $row['avID']
  257. ));
  258. }
  259. // return the new file object
  260. return File::getByID($fIDNew);
  261. }
  262. public static function add($filename, $prefix, $data = array()) {
  263. $db = Loader::db();
  264. $dh = Loader::helper('date');
  265. $date = $dh->getSystemDateTime();
  266. $uID = 0;
  267. $u = new User();
  268. if (isset($data['uID'])) {
  269. $uID = $data['uID'];
  270. } else if ($u->isRegistered()) {
  271. $uID = $u->getUserID();
  272. }
  273. $db->Execute('insert into Files (fDateAdded, uID) values (?, ?)', array($date, $uID));
  274. $fID = $db->Insert_ID();
  275. $f = File::getByID($fID);
  276. $fv = $f->addVersion($filename, $prefix, $data);
  277. Events::fire('on_file_add', $f, $fv);
  278. return $fv;
  279. }
  280. public function addVersion($filename, $prefix, $data = array()) {
  281. $u = new User();
  282. $uID = (isset($data['uID']) && $data['uID'] > 0) ? $data['uID'] : $u->getUserID();
  283. if ($uID < 1) {
  284. $uID = 0;
  285. }
  286. $fvTitle = (isset($data['fvTitle'])) ? $data['fvTitle'] : '';
  287. $fvDescription = (isset($data['fvDescription'])) ? $data['fvDescription'] : '';
  288. $fvTags = (isset($data['fvTags'])) ? FileVersion::cleanTags($data['fvTags']) : '';
  289. $fvIsApproved = (isset($data['fvIsApproved'])) ? $data['fvIsApproved'] : '1';
  290. $db = Loader::db();
  291. $dh = Loader::helper('date');
  292. $date = $dh->getSystemDateTime();
  293. $fvID = $db->GetOne("select max(fvID) from FileVersions where fID = ?", array($this->fID));
  294. if ($fvID > 0) {
  295. $fvID++;
  296. } else {
  297. $fvID = 1;
  298. }
  299. $db->Execute('insert into FileVersions (fID, fvID, fvFilename, fvPrefix, fvDateAdded, fvIsApproved, fvApproverUID, fvAuthorUID, fvActivateDateTime, fvTitle, fvDescription, fvTags, fvExtension)
  300. values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', array(
  301. $this->fID,
  302. $fvID,
  303. $filename,
  304. $prefix,
  305. $date,
  306. $fvIsApproved,
  307. $uID,
  308. $uID,
  309. $date,
  310. $fvTitle,
  311. $fvDescription,
  312. $fvTags,
  313. ''));;
  314. $fv = $this->getVersion($fvID);
  315. Events::fire('on_file_version_add', $fv);
  316. return $fv;
  317. }
  318. public function getApprovedVersion() {
  319. return $this->getVersion();
  320. }
  321. public function inFileSet($fs) {
  322. $db = Loader::db();
  323. $r = $db->GetOne("select fsfID from FileSetFiles where fID = ? and fsID = ?", array($this->getFileID(), $fs->getFileSetID()));
  324. return $r > 0;
  325. }
  326. /**
  327. * Removes a file, including all of its versions
  328. */
  329. public function delete() {
  330. // first, we remove all files from the drive
  331. $db = Loader::db();
  332. $pathbase = false;
  333. $r = $db->GetAll('select fvFilename, fvPrefix from FileVersions where fID = ?', array($this->fID));
  334. $h = Loader::helper('concrete/file');
  335. Loader::model('file_storage_location');
  336. if ($this->getStorageLocationID() > 0) {
  337. $fsl = FileStorageLocation::getByID($this->getStorageLocationID());
  338. $pathbase = $fsl->getDirectory();
  339. }
  340. foreach($r as $val) {
  341. // Now, we make sure this file isn't referenced by something else. If it is we don't delete the file from the drive
  342. $cnt = $db->GetOne('select count(*) as total from FileVersions where fID <> ? and fvFilename = ? and fvPrefix = ?', array(
  343. $this->fID,
  344. $val['fvFilename'],
  345. $val['fvPrefix']
  346. ));
  347. if ($cnt == 0) {
  348. if ($pathbase != false) {
  349. $path = $h->mapSystemPath($val['fvPrefix'], $val['fvFilename'], false, $pathbase);
  350. } else {
  351. $path = $h->mapSystemPath($val['fvPrefix'], $val['fvFilename'], false);
  352. }
  353. $t1 = $h->getThumbnailSystemPath($val['fvPrefix'], $val['fvFilename'], 1);
  354. $t2 = $h->getThumbnailSystemPath($val['fvPrefix'], $val['fvFilename'], 2);
  355. $t3 = $h->getThumbnailSystemPath($val['fvPrefix'], $val['fvFilename'], 3);
  356. if (file_exists($path)) {
  357. unlink($path);
  358. }
  359. if (file_exists($t1)) {
  360. unlink($t1);
  361. }
  362. if (file_exists($t2)) {
  363. unlink($t2);
  364. }
  365. if (file_exists($t3)) {
  366. unlink($t3);
  367. }
  368. }
  369. }
  370. // now from the DB
  371. $db->Execute("delete from Files where fID = ?", array($this->fID));
  372. $db->Execute("delete from FileVersions where fID = ?", array($this->fID));
  373. $db->Execute("delete from FileAttributeValues where fID = ?", array($this->fID));
  374. $db->Execute("delete from FileSetFiles where fID = ?", array($this->fID));
  375. $db->Execute("delete from FileVersionLog where fID = ?", array($this->fID));
  376. $this->refreshCache();
  377. }
  378. /**
  379. * returns the most recent FileVersion object
  380. * @return FileVersion
  381. */
  382. public function getRecentVersion() {
  383. $db = Loader::db();
  384. $fvID = $db->GetOne("select fvID from FileVersions where fID = ? order by fvID desc", array($this->fID));
  385. return $this->getVersion($fvID);
  386. }
  387. /**
  388. * returns the FileVersion object for the provided fvID
  389. * if none provided returns the approved version
  390. * @param int $fvID
  391. * @return FileVersion
  392. */
  393. public function getVersion($fvID = null) {
  394. if ($fvID == null) {
  395. $fvID = $this->fvID; // approved version
  396. }
  397. $fv = Cache::get('file_version_' . $this->getFileID(), $fvID);
  398. if (is_object($fv)) {
  399. return $fv;
  400. }
  401. $db = Loader::db();
  402. $row = $db->GetRow("select * from FileVersions where fvID = ? and fID = ?", array($fvID, $this->fID));
  403. $row['fvAuthorName'] = $db->GetOne("select uName from Users where uID = ?", array($row['fvAuthorUID']));
  404. $fv = new FileVersion();
  405. $row['fslID'] = $this->fslID;
  406. $fv->setPropertiesFromArray($row);
  407. $fv->populateAttributes();
  408. Cache::set('file_version_' . $this->getFileID(), $fvID, $fv);
  409. return $fv;
  410. }
  411. /**
  412. * Returns an array of all FileVersion objects owned by this file
  413. */
  414. public function getVersionList() {
  415. $db = Loader::db();
  416. $r = $db->Execute("select fvID from FileVersions where fID = ? order by fvDateAdded desc", array($this->getFileID()));
  417. $files = array();
  418. while ($row = $r->FetchRow()) {
  419. $files[] = $this->getVersion($row['fvID']);
  420. }
  421. return $files;
  422. }
  423. public function getDownloadStatistics(){
  424. $db = Loader::db();
  425. return $db->getAll("SELECT * FROM DownloadStatistics WHERE fID = ? ORDER BY timestamp desc", array($this->getFileID()));
  426. }
  427. /**
  428. * Tracks File Download, takes the cID of the page that the file was downloaded from
  429. * @param int $rcID
  430. * @return void
  431. */
  432. public function trackDownload($rcID=NULL){
  433. $u = new User();
  434. $uID = intval( $u->getUserID() );
  435. $fv = $this->getVersion();
  436. $fvID = $fv->getFileVersionID();
  437. if(!isset($rcID) || !is_numeric($rcID)) {
  438. $rcID = 0;
  439. }
  440. Events::fire('on_file_download', $fv, $u);
  441. $db = Loader::db();
  442. $db->Execute('insert into DownloadStatistics (fID, fvID, uID, rcID) values (?, ?, ?, ?)', array( $this->fID, intval($fvID), $uID, $rcID ) );
  443. }
  444. }