3 * FusionForge document manager
5 * Copyright 2000, Quentin Cregan/Sourceforge
6 * Copyright 2002-2003, Tim Perdue/GForge, LLC
7 * Copyright 2009, Roland Mas
8 * Copyright 2010, Franck Villaume - Capgemini
9 * Copyright (C) 2011 Alain Peyrat - Alcatel-Lucent
10 * Copyright 2012, Franck Villaume - TrivialDev
11 * http://fusionforge.org
13 * This file is part of FusionForge. FusionForge is free software;
14 * you can redistribute it and/or modify it under the terms of the
15 * GNU General Public License as published by the Free Software
16 * Foundation; either version 2 of the Licence, or (at your option)
19 * FusionForge is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License along
25 * with FusionForge; if not, write to the Free Software Foundation, Inc.,
26 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 require_once $gfcommon.'include/Error.class.php';
30 require_once $gfcommon.'docman/Parsedata.class.php';
32 class Document extends Error {
35 * Associative array of data from db.
37 * @var array $data_array.
49 * The Search engine path.
51 * @var string $engine_path
58 * @param object The Group object to which this document is associated.
59 * @param int The docid.
60 * @param array The associative array of data.
61 * @return boolean success.
63 function Document(&$Group, $docid = false, $arr = false, $engine = '') {
65 if (!$Group || !is_object($Group)) {
66 $this->setNotValidGroupObjectError();
69 if ($Group->isError()) {
70 $this->setError('Document:: '. $Group->getErrorMessage());
73 $this->Group =& $Group;
76 if (!$arr || !is_array($arr)) {
77 if (!$this->fetchData($docid)) {
81 $this->data_array =& $arr;
82 if ($this->data_array['group_id'] != $this->Group->getID()) {
83 $this->setError('Document:: '. _('Group_id in db result does not match Group Object'));
84 $this->data_array = null;
88 if (!$this->isPublic()) {
89 $perm =& $this->Group->getPermission();
91 if (!$perm || !is_object($perm) || !$perm->isMember()) {
92 $this->setPermissionDeniedError();
93 $this->data_array = null;
98 $this->engine_path = $engine;
103 * create - use this function to create a new entry in the database.
105 * @param string The filename of this document. Can be a URL.
106 * @param string The filetype of this document. If filename is URL, this should be 'URL';
107 * @param string The contents of this document.
108 * @param int The doc_group id of the doc_groups table.
109 * @param string The title of this document.
110 * @param string The description of this document.
111 * @return boolean success.
113 function create($filename, $filetype, $data, $doc_group, $title, $description) {
114 if (strlen($title) < 5) {
115 $this->setError(_('Title Must Be At Least 5 Characters'));
118 if (strlen($description) < 10) {
119 $this->setError(_('Document Description Must Be At Least 10 Characters'));
123 $result = db_query_params('SELECT filename, doc_group from docdata_vw where filename = $1 and doc_group = $2',
124 array($filename, $doc_group));
126 if (!$result || db_numrows($result) > 0) {
127 $this->setError(_('Document already published in this directory'));
131 $user_id = ((session_loggedin()) ? user_getid() : 100);
133 $doc_initstatus = '3';
134 // If Editor - uploaded Documents are ACTIVE
135 if (session_loggedin()) {
136 $perm =& $this->Group->getPermission ();
137 if ($perm && is_object($perm) && $perm->isDocEditor()) {
138 $doc_initstatus = '1';
142 // If $filetype is "text/plain", $body convert UTF-8 encoding.
143 if (strcasecmp($filetype,"text/plain") === 0 &&
144 function_exists('mb_convert_encoding') &&
145 function_exists('mb_detect_encoding')) {
146 $data = mb_convert_encoding($data, 'UTF-8', mb_detect_encoding($data));
150 // key words for in-document search
151 if ($this->Group->useDocmanSearch()) {
152 $kw = new Parsedata();
153 $kwords = $kw->get_parse_data($data1, htmlspecialchars($title), htmlspecialchars($description), $filetype);
158 $filesize = strlen($data);
161 $result = db_query_params('INSERT INTO doc_data (group_id,title,description,createdate,doc_group,
162 stateid,filename,filetype,filesize,data_words,created_by)
163 VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11)',
164 array($this->Group->getId(),
165 htmlspecialchars($title),
166 htmlspecialchars($description),
176 $this->setError(_('Error Adding Document:').' '.db_error().$result);
181 $docid = db_insertid($result,'doc_data','docid');
183 switch ($this->Group->getStorageAPI()) {
185 $result = db_query_params('UPDATE doc_data set data = $1 where docid = $2',
186 array(base64_encode($data),$docid));
188 $this->setError(_('Error Adding Document:').' '.db_error().$result);
195 $this->setError(_('Error Adding Document: No Storage API'));
201 if (!$this->fetchData($docid)) {
202 $this->setError(_('Error fetching Document'));
206 $this->sendNotice(true);
212 * fetchData() - re-fetch the data for this document from the database.
214 * @param int The document id.
215 * @return boolean success
217 function fetchData($docid) {
218 $res = db_query_params('SELECT * FROM docdata_vw WHERE docid=$1 AND group_id=$2',
219 array($docid, $this->Group->getID()));
220 if (!$res || db_numrows($res) < 1) {
221 $this->setError(_('Document:: Invalid docid'));
224 $this->data_array = db_fetch_array($res);
225 db_free_result($res);
230 * getGroup - get the Group object this Document is associated with.
232 * @return Object The Group object.
234 function &getGroup() {
239 * getID - get this docid.
241 * @return int The docid.
244 return $this->data_array['docid'];
248 * getName - get the name of this document.
250 * @return string The name of this document.
253 return $this->data_array['title'];
257 * getDescription - the description of this document.
259 * @return string The description.
261 function getDescription() {
262 return $this->data_array['description'];
266 * isURL - whether this document is a URL and not a local file.
268 * @return boolean is_url.
271 return ($this->data_array['filetype'] == 'URL');
275 * isText - whether this document is a text document and not a binary one.
277 * @return boolean is_text.
280 $doctype = $this->data_array['filetype'];
281 if (preg_match('|^text/|i', $doctype)) { // text plain, text html, text x-patch, etc
288 * isHtml - whether this document is a html document.
290 * @return boolean is_html.
293 $doctype = $this->data_array['filetype'];
294 if (preg_match('/html/i',$doctype)) {
301 * isPublic - whether this document is available to the general public.
303 * @return boolean is_public.
305 function isPublic() {
306 return (($this->data_array['stateid'] == 1) ? true : false);
310 * getStateID - get this stateid.
312 * @return int The stateid.
314 function getStateID() {
315 return $this->data_array['stateid'];
319 * getStateName - the statename of this document.
321 * @return string The statename.
323 function getStateName() {
324 return $this->data_array['state_name'];
328 * getDocGroupID - get this doc_group_id.
330 * @return int The doc_group_id.
332 function getDocGroupID() {
333 return $this->data_array['doc_group'];
337 * getDocGroupName - the doc_group_name of this document.
339 * @return string The docgroupname.
341 function getDocGroupName() {
342 return $this->data_array['group_name'];
346 * getCreatorID - get this creator's user_id.
348 * @return int The user_id.
350 function getCreatorID() {
351 return $this->data_array['created_by'];
355 * getCreatorUserName - the unix name of the person who created this document.
357 * @return string The unix name of the creator.
359 function getCreatorUserName() {
360 return $this->data_array['user_name'];
364 * getCreatorRealName - the real name of the person who created this document.
366 * @return string The real name of the creator.
368 function getCreatorRealName() {
369 return $this->data_array['realname'];
373 * getCreatorEmail - the email of the person who created this document.
375 * @return string The email of the creator.
377 function getCreatorEmail() {
378 return $this->data_array['email'];
382 * getFileName - the filename of this document.
384 * @return string The filename.
386 function getFileName() {
387 return $this->data_array['filename'];
391 * getFileType - the filetype of this document.
393 * @return string The filetype.
395 function getFileType() {
396 return $this->data_array['filetype'];
400 * getFileData - the filedata of this document.
402 * @return string The filedata.
404 function getFileData() {
406 // Because this could be a large string, we only fetch if we actually need it
408 $res = db_query_params('SELECT data FROM doc_data WHERE docid=$1',array($this->getID()));
409 return base64_decode(db_result($res,0,'data'));
413 * getFileSize - Return the size of the document
415 * @return int The file size
417 function getFileSize() {
418 return $this->data_array['filesize'];
422 * getUpdated - get the time this document was updated.
424 * @return int The epoch date this document was updated.
426 function getUpdated() {
427 return $this->data_array['updatedate'];
431 * getCreated - get the time this document was created.
433 * @return int The epoch date this document was created.
435 function getCreated() {
436 return $this->data_array['createdate'];
440 * getLocked - get the lock status of this document.
442 * @return int The lock status of this document.
444 function getLocked() {
445 return $this->data_array['locked'];
449 * getLockdate - get the lock time of this document.
451 * @return int The lock time of this document.
453 function getLockdate() {
454 return $this->data_array['lockdate'];
458 * getLockedBy - get the user id who set lock on this document.
460 * @return int The user id who set lock on this document.
462 function getLockedBy() {
463 return $this->data_array['locked_by'];
467 * getReservedBy - get the owner of the reversed status of this document.
469 * @return int The owner of the reversed status of this document.
471 function getReservedBy() {
472 return $this->data_array['reserved_by'];
476 * getReserved - get the reversed status of this document.
478 * @return int The reversed status of this document.
480 function getReserved() {
481 return $this->data_array['reserved'];
485 * getMonitoredUserEmailAddress - get the email addresses of users who monitor this file
487 * @return string The list of emails comma separated
489 function getMonitoredUserEmailAddress() {
490 $result = db_query_params('select users.email from users,docdata_monitored_docman where users.user_id = docdata_monitored_docman.user_id and docdata_monitored_docman.doc_id = $1', array ($this->getID()));
491 if (!$result || db_numrows($result) < 1) {
497 while ($arr = db_fetch_array($result)) {
501 $values .= $comma.$arr['email'];
509 * isMonitoredBy - get the monitored status of this document for a specific user id.
512 * @return boolean true if monitored by this user
514 function isMonitoredBy($userid = 'ALL') {
515 if ( $userid == 'ALL' ) {
518 $condition = 'user_id='.$userid.' AND';
520 $result = db_query_params('SELECT * FROM docdata_monitored_docman WHERE '.$condition.' doc_id=$1',
521 array($this->getID()));
523 if (!$result || db_numrows($result) < 1)
530 * removeMonitoredBy - remove this document for a specific user id for monitoring.
533 * @return boolean true if success
535 function removeMonitoredBy($userid) {
536 $result = db_query_params('DELETE FROM docdata_monitored_docman WHERE doc_id=$1 AND user_id=$2',
537 array ($this->getID(), $userid));
540 $this->setError(_('Unable To Remove Monitor').' : '.db_error());
547 * addMonitoredBy - add this document for a specific user id for monitoring.
550 * @return boolean true if success
552 function addMonitoredBy($userid) {
553 $result = db_query_params('SELECT * FROM docdata_monitored_docman WHERE user_id=$1 AND doc_id=$2',
554 array($userid, $this->getID()));
556 if (!$result || db_numrows($result) < 1) {
557 $result = db_query_params('INSERT INTO docdata_monitored_docman (doc_id,user_id) VALUES ($1,$2)',
558 array($this->getID(), $userid));
561 $this->setError(_('Unable To Add Monitor').' : '.db_error());
569 * setState - set the stateid of the document.
571 * @param int The state id of the doc_states table.
572 * @return boolean success.
574 function setState($stateid) {
575 $res = db_query_params('UPDATE doc_data SET
580 $this->Group->getID(),
583 if (!$res || db_affected_rows($res) < 1) {
584 $this->setOnUpdateError(db_error());
587 $this->sendNotice(false);
592 * setLock - set the locking status of the document
594 * @param int The status of the lock
595 * @param int The userid who set the lock
596 * @param time the epoch time
597 * @return boolean success
599 function setLock($stateLock, $userid = NULL, $thistime = 0) {
600 $res = db_query_params('UPDATE doc_data SET
609 $this->Group->getID(),
612 if (!$res || db_affected_rows($res) < 1) {
613 $this->setOnUpdateError(_('Document lock failed').' '.db_error());
616 $this->data_array['locked'] = $stateLock;
617 $this->data_array['locked_by'] = $userid;
618 $this->data_array['lockdate'] = $thistime;
623 * setReservedBy - set the reserved status of the document and the owner
625 * @param int The status of the reserved
626 * @param int The ID of the owner : by default : noone
627 * @return boolean success
629 function setReservedBy($statusReserved, $idReserver = NULL) {
630 $res = db_query_params('UPDATE doc_data SET
635 array($statusReserved,
637 $this->Group->getID(),
640 if (!$res || db_affected_rows($res) < 1) {
641 $this->setOnUpdateError(_('Document reservation failed').' '.db_error());
644 $this->sendNotice(false);
649 * update - use this function to update an existing entry in the database.
651 * @param string The filename of this document. Can be a URL.
652 * @param string The filetype of this document. If filename is URL, this should be 'URL';
653 * @param string The contents of this document.
654 * @param int The doc_group id of the doc_groups table.
655 * @param string The title of this document.
656 * @param string The description of this document.
657 * @param int The state id of the doc_states table.
658 * @return boolean success.
660 function update($filename, $filetype, $data, $doc_group, $title, $description, $stateid) {
662 $perm =& $this->Group->getPermission();
663 if (!$perm || !is_object($perm) || !$perm->isDocEditor()) {
664 $this->setPermissionDeniedError();
668 $user = session_get_user();
669 if ($this->getLocked() && ($this->getLockedBy() != $user->getID())) {
670 $this->setPermissionDeniedError();
674 if (strlen($title) < 5) {
675 $this->setError(_('Title Must Be At Least 5 Characters'));
679 if (strlen($description) < 10) {
680 $this->setError(_('Document Description Must Be At Least 10 Characters'));
685 $result = db_query_params('SELECT filename, doc_group FROM docdata_vw WHERE filename = $1 AND doc_group = $2 AND stateid = $3 AND docid != $4',
686 array($filename, $doc_group, $stateid, $this->getID()));
687 if (!$result || db_numrows($result) > 0) {
688 $this->setError(_('Document already published in this directory'));
693 $res = db_query_params('UPDATE doc_data SET
705 array(htmlspecialchars($title),
706 htmlspecialchars($description),
714 $this->Group->getID(),
718 if (!$res || db_affected_rows($res) < 1) {
719 $this->setOnUpdateError(db_error());
726 // key words for in-document search
727 if ($this->Group->useDocmanSearch()) {
728 $kw = new Parsedata();
729 $kwords = $kw->get_parse_data($data1, htmlspecialchars($title), htmlspecialchars($description), $filetype);
734 $res = db_query_params('UPDATE doc_data SET filesize=$1, data_words=$2 WHERE group_id=$3 AND docid=$4',
737 $this->Group->getID(),
741 if (!$res || db_affected_rows($res) < 1) {
742 $this->setOnUpdateError(db_error());
746 switch ($this->Group->getStorageAPI()) {
748 $res = db_query_params('UPDATE doc_data SET data = $1 where group_id = $2 and docid = $3',
749 array(base64_encode($data),
750 $this->Group->getID(),
754 if (!$res || db_affected_rows($res) < 1) {
755 $this->setOnUpdateError(db_error());
761 $this->setOnUpdateError(_('No Storage API'));
767 $this->sendNotice(false);
772 * sendNotice - Notifies of document submissions
774 * @param boolean true = new document (default value)
776 function sendNotice ($new=true) {
777 $BCC = $this->Group->getDocEmailAddress();
778 if ($this->isMonitoredBy('ALL')) {
779 $BCC .= $this->getMonitoredUserEmailAddress();
781 if (strlen($BCC) > 0) {
783 $status = _('New document');
785 $status = _('Updated document');
787 $subject = '['.$this->Group->getPublicName().'] '.$status.' - '.$this->getName();
788 $body = _('Project:').' '.$this->Group->getPublicName()."\n";
789 $body .= _('Directory:').' '.$this->getDocGroupName()."\n";
790 $body .= _('Document title:').' '.$this->getName()."\n";
791 $body .= _('Document description:').' '.util_unconvert_htmlspecialchars($this->getDescription())."\n";
792 $body .= _('Submitter:').' '.$this->getCreatorRealName()." (".$this->getCreatorUserName().") \n";
793 $body .= "\n\n-------------------------------------------------------\n".
794 _('For more info, visit:').
795 "\n\n" . util_make_url('/docman/?group_id='.$this->Group->getID().'&view=listfile&dirid='.$this->getDocGroupID());
797 util_send_message('', $subject, $body, '', $BCC);
804 * delete - Delete this file
806 * @return boolean success
809 $perm =& $this->Group->getPermission();
810 if (!$perm || !is_object($perm) || !$perm->isDocEditor()) {
811 $this->setPermissionDeniedError();
815 $result = db_query_params('DELETE FROM doc_data WHERE docid=$1',
816 array($this->getID()));
818 $this->setError(_('Error Deleting Document:').' '.db_error());
823 switch ($this->Group->getStorageAPI()) {
828 $this->setError(_('Error Deleting Document: No Storage API'));
834 // we should be able to send a notice that this doc has been deleted .... but we need to rewrite sendNotice
835 //$this->sendNotice(false);
842 // c-file-style: "bsd"