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 * http://fusionforge.org
11 * This file is part of FusionForge.
13 * FusionForge is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published
15 * by the Free Software Foundation; either version 2 of the License,
16 * or (at your option) any later version.
18 * FusionForge is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with FusionForge; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
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.
47 * The Search engine path.
49 * @var string $engine_path
56 * @param object The Group object to which this document is associated.
57 * @param int The docid.
58 * @param array The associative array of data.
59 * @return boolean success.
61 function Document(&$Group, $docid=false, $arr=false, $engine = "") {
63 if (!$Group || !is_object($Group)) {
64 $this->setNotValidGroupObjectError();
67 if ($Group->isError()) {
68 $this->setError('Document:: '.$Group->getErrorMessage());
71 $this->Group =& $Group;
74 if (!$arr || !is_array($arr)) {
75 if (!$this->fetchData($docid)) {
79 $this->data_array =& $arr;
80 if ($this->data_array['group_id'] != $this->Group->getID()) {
81 $this->setError(_('Group_id in db result does not match Group Object'));
82 $this->data_array = null;
86 if (!$this->isPublic()) {
87 $perm =& $this->Group->getPermission ();
89 if (!$perm || !is_object($perm) || !$perm->isMember()) {
90 $this->setPermissionDeniedError();
91 $this->data_array = null;
96 $this->engine_path = $engine;
101 * create - use this function to create a new entry in the database.
103 * @param string The filename of this document. Can be a URL.
104 * @param string The filetype of this document. If filename is URL, this should be 'URL';
105 * @param string The contents of this document.
106 * @param int The doc_group id of the doc_groups table.
107 * @param string The title of this document.
108 * @param int The language id of the supported_languages table.
109 * @param string The description of this document.
110 * @return boolean success.
112 function create($filename,$filetype,$data,$doc_group,$title,$description) {
113 if (strlen($title) < 5) {
114 $this->setError(_('Title Must Be At Least 5 Characters'));
117 if (strlen($description) < 10) {
118 $this->setError(_('Document Description Must Be At Least 10 Characters'));
122 $result = db_query_params('SELECT filename,doc_group from docdata_vw',
123 array($filename,$doc_group));
125 if (!$result || db_numrows($res) > 0) {
126 $this->setError(_('Document already published in this directory'));
130 $user_id = ((session_loggedin()) ? user_getid() : 100);
132 $doc_initstatus = '3';
133 // If Editor - uploaded Documents are ACTIVE
134 if ( session_loggedin() ) {
135 $perm =& $this->Group->getPermission ();
136 if ($perm && is_object($perm) && $perm->isDocEditor()) {
137 $doc_initstatus = '1';
141 // If $filetype is "text/plain", $body convert UTF-8 encoding.
142 if (strcasecmp($filetype,"text/plain") === 0 &&
143 function_exists('mb_convert_encoding') &&
144 function_exists('mb_detect_encoding')) {
145 $data = mb_convert_encoding($data,'UTF-8',mb_detect_encoding($data));
149 // key words for in-document search
150 if ($this->Group->useDocmanSearch()) {
151 $kw = new Parsedata ($this->engine_path);
152 $kwords = $kw->get_parse_data ($data1, htmlspecialchars($title), htmlspecialchars($description), $filetype);
157 $filesize = strlen($data);
160 $result = db_query_params('INSERT INTO doc_data (group_id,title,description,createdate,doc_group,
161 stateid,filename,filetype,filesize,data_words,created_by)
162 VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11)',
163 array($this->Group->getId(),
164 htmlspecialchars($title),
165 htmlspecialchars($description),
175 $this->setError(_('Error Adding Document:').' '.db_error().$result);
180 $docid=db_insertid($result,'doc_data','docid');
182 switch ($this->Group->getStorageAPI()) {
184 $result = db_query_params('UPDATE doc_data set data = $1 where docid = $2',
185 array(base64_encode($data),
188 $this->setError(_('Error Adding Document:').' '.db_error().$result);
194 $this->setError(_('Error Adding Document: No Storage API'));
199 if (!$this->fetchData($docid)) {
203 $this->sendNotice(true);
209 * fetchData() - re-fetch the data for this document from the database.
211 * @param int The document id.
212 * @return boolean success
214 function fetchData($docid) {
215 $res = db_query_params ('SELECT * FROM docdata_vw WHERE docid=$1 AND group_id=$2',
217 $this->Group->getID()));
218 if (!$res || db_numrows($res) < 1) {
219 $this->setError(_('Document:: Invalid docid'));
222 $this->data_array = db_fetch_array($res);
223 db_free_result($res);
228 * getGroup - get the Group object this Document is associated with.
230 * @return Object The Group object.
232 function &getGroup() {
237 * getID - get this docid.
239 * @return int The docid.
242 return $this->data_array['docid'];
246 * getName - get the name of this document.
248 * @return string The name of this document.
251 return $this->data_array['title'];
255 * getDescription - the description of this document.
257 * @return string The description.
259 function getDescription() {
260 return $this->data_array['description'];
264 * isURL - whether this document is a URL and not a local file.
266 * @return boolean is_url.
269 return ($this->data_array['filetype'] == 'URL');
273 * isText - whether this document is a text document and not a binary one.
275 * @return boolean is_text.
278 $doctype = $this->data_array['filetype'];
279 if (preg_match('|^text/|i',$doctype)) { // text plain, text html, text x-patch, etc
286 * isHtml - whether this document is a html document.
288 * @return boolean is_html.
291 $doctype = $this->data_array['filetype'];
292 if (preg_match('/html/i',$doctype)) {
299 * isPublic - whether this document is available to the general public.
301 * @return boolean is_public.
303 function isPublic() {
304 return (($this->data_array['stateid'] == 1) ? true : false);
308 * getStateID - get this stateid.
310 * @return int The stateid.
312 function getStateID() {
313 return $this->data_array['stateid'];
317 * getStateName - the statename of this document.
319 * @return string The statename.
321 function getStateName() {
322 return $this->data_array['state_name'];
326 * getDocGroupID - get this doc_group_id.
328 * @return int The doc_group_id.
330 function getDocGroupID() {
331 return $this->data_array['doc_group'];
335 * getDocGroupName - the doc_group_name of this document.
337 * @return string The docgroupname.
339 function getDocGroupName() {
340 return $this->data_array['group_name'];
344 * getCreatorID - get this creator's user_id.
346 * @return int The user_id.
348 function getCreatorID() {
349 return $this->data_array['created_by'];
353 * getCreatorUserName - the unix name of the person who created this document.
355 * @return string The unix name of the creator.
357 function getCreatorUserName() {
358 return $this->data_array['user_name'];
362 * getCreatorRealName - the real name of the person who created this document.
364 * @return string The real name of the creator.
366 function getCreatorRealName() {
367 return $this->data_array['realname'];
371 * getCreatorEmail - the email of the person who created this document.
373 * @return string The email of the creator.
375 function getCreatorEmail() {
376 return $this->data_array['email'];
380 * getFileName - the filename of this document.
382 * @return string The filename.
384 function getFileName() {
385 return $this->data_array['filename'];
389 * getFileType - the filetype of this document.
391 * @return string The filetype.
393 function getFileType() {
394 return $this->data_array['filetype'];
398 * getFileData - the filedata of this document.
400 * @return string The filedata.
402 function getFileData() {
404 // Because this could be a large string, we only fetch if we actually need it
406 $res = db_query_params ('SELECT data FROM doc_data WHERE docid=$1',
407 array ($this->getID())) ;
408 return base64_decode(db_result($res,0,'data'));
412 * getFileSize - Return the size of the document
414 * @return int The file size
416 function getFileSize() {
417 return $this->data_array['filesize'];
420 * getUpdated - get the time this document was updated.
422 * @return int The epoch date this document was updated.
424 function getUpdated() {
425 return $this->data_array['updatedate'];
429 * getCreated - get the time this document was created.
431 * @return int The epoch date this document was created.
433 function getCreated() {
434 return $this->data_array['createdate'];
438 * getLocked - get the lock status of this document.
440 * @return int The lock status of this document.
442 function getLocked() {
443 return $this->data_array['locked'];
447 * getLockdate - get the lock time of this document.
449 * @return int The lock time of this document.
451 function getLockdate() {
452 return $this->data_array['lockdate'];
456 * getLockedBy - get the user id who set lock on this document.
458 * @return int The user id who set lock on this document.
460 function getLockedBy() {
461 return $this->data_array['locked_by'];
465 * getReservedBy - get the owner of the reversed status of this document.
467 * @return int The owner of the reversed status of this document.
469 function getReservedBy() {
470 return $this->data_array['reserved_by'];
474 * getReserved - get the reversed status of this document.
476 * @return int The reversed status of this document.
478 function getReserved() {
479 return $this->data_array['reserved'];
483 * getMonitoredUserEmailAddress - get the email addresses of users who monitor this file
485 * @return string The list of emails comma separated
487 function getMonitoredUserEmailAddress() {
488 $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()));
489 if (!$result || db_numrows($result) < 1) {
495 while ($arr = db_fetch_array($result)) {
499 $values .=$comma.$arr['email'];
507 * isMonitoredBy - get the monitored status of this document for a specific user id.
510 * @return bool true if monitored by this user
512 function isMonitoredBy($userid = 'ALL') {
513 if ( $userid == 'ALL' ) {
516 $condition = 'user_id='.$userid.' AND';
518 $result = db_query_params('SELECT * FROM docdata_monitored_docman WHERE '.$condition.' doc_id=$1',
519 array ($this->getID()));
521 if (!$result || db_numrows($result) < 1)
528 * removeMonitoredBy - remove this document for a specific user id for monitoring.
531 * @return bool true if success
533 function removeMonitoredBy($userid) {
534 $result = db_query_params('DELETE FROM docdata_monitored_docman WHERE doc_id=$1 AND user_id=$2',
535 array ($this->getID(), $userid));
538 $this->setError(_('Unable To Remove Monitor').' : '.db_error());
545 * addMonitoredBy - add this document for a specific user id for monitoring.
548 * @return bool true if success
550 function addMonitoredBy($userid) {
551 $result = db_query_params('SELECT * FROM docdata_monitored_docman WHERE user_id=$1 AND doc_id=$2',
552 array ($userid, $this->getID()));
554 if (!$result || db_numrows($result) < 1) {
555 $result = db_query_params('INSERT INTO docdata_monitored_docman (doc_id,user_id) VALUES ($1,$2)',
556 array ($this->getID(), $userid));
559 $this->setError(_('Unable To Add Monitor').' : '.db_error());
567 * setState - set the stateid of the document.
569 * @param int The state id of the doc_states table.
570 * @return boolean success.
572 function setState($stateid) {
573 $res = db_query_params ('UPDATE doc_data SET
578 $this->Group->getID(),
581 if (!$res || db_affected_rows($res) < 1) {
582 $this->setOnUpdateError(db_error());
585 $this->sendNotice(false);
590 * setLock - set the locking status of the document
592 * @param int The status of the lock
593 * @param int The userid who set the lock
594 * @return boolean success
596 function setLock($stateLock,$userid=NULL,$thistime=0) {
597 $res = db_query_params ('UPDATE doc_data SET
606 $this->Group->getID(),
609 if (!$res || db_affected_rows($res) < 1) {
610 $this->setOnUpdateError(_('Document lock failed').' '.db_error());
613 $this->sendNotice(false);
614 $this->data_array['locked'] = $stateLock;
615 $this->data_array['locked_by'] = $userid;
616 $this->data_array['lockdate'] = $thistime;
621 * setReservedBy - set the reserved status of the document and the owner
623 * @param int The status of the reserved
624 * @param int The ID of the owner : by default : noone
625 * @return boolean success
627 function setReservedBy($statusReserved,$idReserver=NULL) {
628 $res = db_query_params ('UPDATE doc_data SET
633 array ($statusReserved,
635 $this->Group->getID(),
638 if (!$res || db_affected_rows($res) < 1) {
639 $this->setOnUpdateError(_('Document reservation failed').' '.db_error());
642 $this->sendNotice(false);
647 * update - use this function to update an existing entry in the database.
649 * @param string The filename of this document. Can be a URL.
650 * @param string The filetype of this document. If filename is URL, this should be 'URL';
651 * @param string The contents of this document.
652 * @param int The doc_group id of the doc_groups table.
653 * @param string The title of this document.
654 * @param int The language id of the supported_languages table.
655 * @param string The description of this document.
656 * @param int The state id of the doc_states table.
657 * @return boolean success.
659 function update($filename,$filetype,$data,$doc_group,$title,$description,$stateid) {
661 if (strlen($title) < 5) {
662 $this->setError(_('Title Must Be At Least 5 Characters'));
665 if (strlen($description) < 10) {
666 $this->setError(_('Document Description Must Be At Least 10 Characters'));
670 $result = db_query_params('SELECT filename,doc_group from docdata_vw',
671 array($filename,$doc_group));
674 if (!$result || db_numrows($res) > 0) {
675 $this->setError(_('Document already published in this directory'));
680 $perm =& $this->Group->getPermission ();
682 if (!$perm || !is_object($perm) || !$perm->isDocEditor()) {
683 $this->setPermissionDeniedError();
686 if ($this->getLockedBy() != $LUSER->getID()) {
687 $this->setPermissionDeniedError();
691 $res = db_query_params ('UPDATE doc_data SET
703 array (htmlspecialchars($title),
704 htmlspecialchars($description),
712 $this->Group->getID(),
715 if (!$res || db_affected_rows($res) < 1) {
716 $this->setOnUpdateError(db_error());
723 // key words for in-document search
724 if ($this->Group->useDocmanSearch()) {
725 $kw = new Parsedata ($this->engine_path);
726 $kwords = $kw->get_parse_data ($data1, htmlspecialchars($title), htmlspecialchars($description), $filetype);
731 $res = db_query_params ('UPDATE doc_data SET filesize=$1, data_words=$2 WHERE group_id=$3 AND docid=$4',
732 array (strlen($data),
734 $this->Group->getID(),
737 if (!$res || db_affected_rows($res) < 1) {
738 $this->setOnUpdateError(db_error());
742 switch ($this->Group->getStorageAPI()) {
744 $res = db_query_params ('UPDATE doc_data SET data = $1 where group_id = $2 and docid = $3',
745 array(base64_encode($data),
746 $this->Group->getID(),
749 if (!$res || db_affected_rows($res) < 1) {
750 $this->setOnUpdateError(db_error());
755 $this->setOnUpdateError(_('No Storage API'));
760 $this->sendNotice(false);
765 * sendNotice - Notifies of document submissions
767 function sendNotice ($new=true) {
768 $BCC = $this->Group->getDocEmailAddress();
769 if ($this->isMonitoredBy('ALL')) {
770 $BCC .= $this->getMonitoredUserEmailAddress();
772 if (strlen($BCC) > 0) {
774 $status = _('New document');
776 $status = _('Updated document');
778 $subject = '['.$this->Group->getPublicName().'] '.$status.' - '.$this->getName();
779 $body = _('Project:').' '.$this->Group->getPublicName()."\n";
780 $body .= _('Directory:').' '.$this->getDocGroupName()."\n";
781 $body .= _('Document title:').' '.$this->getName()."\n";
782 $body .= _('Document description:').' '.util_unconvert_htmlspecialchars( $this->getDescription() )."\n";
783 $body .= _('Submitter:').' '.$this->getCreatorRealName()." (".$this->getCreatorUserName().") \n";
784 $body .= "\n\n-------------------------------------------------------\n".
785 _('For more info, visit:').
786 "\n\n" . util_make_url('/docman/?group_id='.$this->Group->getID().'&view=listfile&dirid='.$this->getDocGroupID());
788 util_send_message('',$subject,$body,'',$BCC);
795 * delete - Delete this file
798 $perm =& $this->Group->getPermission ();
799 if (!$perm || !is_object($perm) || !$perm->isDocEditor()) {
800 $this->setPermissionDeniedError();
804 $result = db_query_params ('DELETE FROM doc_data WHERE docid=$1',
805 array ($this->getID())) ;
807 $this->setError(_('Error Deleting Document:').' '.db_error());
812 switch ($this->Group->getStorageAPI()) {
816 $this->setError(_('Error Deleting Document: No Storage API'));
821 // we should be able to send a notice that this doc has been deleted .... but we need to rewrite sendNotice
822 //$this->sendNotice(false);
829 // c-file-style: "bsd"