3 * FusionForge file release system
5 * Copyright 2002, Tim Perdue/GForge, LLC
6 * Copyright 2009, Roland Mas
7 * Copyright (C) 2012 Alain Peyrat - Alcatel-Lucent
9 * This file is part of FusionForge. FusionForge is free software;
10 * you can redistribute it and/or modify it under the terms of the
11 * GNU General Public License as published by the Free Software
12 * Foundation; either version 2 of the Licence, or (at your option)
15 * FusionForge is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with FusionForge; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 require_once $gfcommon.'include/Error.class.php';
26 require_once $gfcommon.'frs/FRSFile.class.php';
29 * Factory method which creates a FRSRelease from an release id
31 * @param int $release_id The release id
32 * @param array $data The result array, if it's passed in
33 * @return object FRSRelease object
35 function frsrelease_get_object($release_id, $data = array()) {
36 global $FRSRELEASE_OBJ;
37 if (!isset($FRSRELEASE_OBJ['_'.$release_id.'_'])) {
39 //the db result handle was passed in
41 $res = db_query_params ('SELECT * FROM frs_release WHERE release_id=$1',
42 array ($release_id)) ;
43 if (db_numrows($res)<1 ) {
44 $FRSRELEASE_OBJ['_'.$release_id.'_']=false;
47 $data = db_fetch_array($res);
49 $FRSPackage = frspackage_get_object($data['package_id']);
50 $FRSRELEASE_OBJ['_'.$release_id.'_']= new FRSRelease($FRSPackage,$data['release_id'],$data);
52 return $FRSRELEASE_OBJ['_'.$release_id.'_'];
55 class FRSRelease extends Error {
58 * Associative array of data from db.
60 * @var array $data_array.
67 * @var object FRSPackage.
75 * @param object The FRSPackage object to which this release is associated.
76 * @param int|bool The release_id.
77 * @param array|bool The associative array of data.
78 * @return boolean success.
80 function FRSRelease(&$FRSPackage, $release_id = false, $arr = false) {
82 if (!$FRSPackage || !is_object($FRSPackage)) {
83 $this->setError(_('Invalid FRS Package Object'));
86 if ($FRSPackage->isError()) {
87 $this->setError('FRSRelease: '.$FRSPackage->getErrorMessage());
90 $this->FRSPackage =& $FRSPackage;
93 if (!$arr || !is_array($arr)) {
94 if (!$this->fetchData($release_id)) {
98 $this->data_array =& $arr;
99 if ($this->data_array['package_id'] != $this->FRSPackage->getID()) {
100 $this->setError('FRSPackage_id in db result does not match FRSPackage Object');
101 $this->data_array=null;
110 * create - create a new release in the database.
112 * @param string $name The name of the release.
113 * @param string $notes The release notes for the release.
114 * @param string $changes The change log for the release.
115 * @param int $preformatted Whether the notes/log are preformatted with \n chars (1) true (0) false.
116 * @param int $release_date The unix date of the release.
117 * @return boolean success.
119 function create($name,$notes,$changes,$preformatted,$release_date=false) {
120 if (strlen($name) < 3) {
121 $this->setError(_('FRSPackage Name Must Be At Least 3 Characters'));
131 if (!forge_check_perm ('frs', $this->FRSPackage->Group->getID(), 'write')) {
132 $this->setPermissionDeniedError();
136 if (!$release_date) {
137 $release_date=time();
139 $res = db_query_params ('SELECT * FROM frs_release WHERE package_id=$1 AND name=$2',
140 array ($this->FRSPackage->getID(),
141 htmlspecialchars($name))) ;
142 if (db_numrows($res)) {
143 $this->setError(_('Error Adding Release: Name Already Exists'));
148 $result=db_query_params ('INSERT INTO frs_release(package_id,notes,changes,preformatted,name,release_date,released_by,status_id) VALUES ($1,$2,$3,$4,$5,$6,$7,$8)',
149 array ($this->FRSPackage->getId(),
150 htmlspecialchars($notes),
151 htmlspecialchars($changes),
153 htmlspecialchars($name),
158 $this->setError(_('Error Adding Release: ').db_error());
162 $this->release_id=db_insertid($result,'frs_release','release_id');
163 if (!$this->fetchData($this->release_id)) {
167 $newdirlocation = forge_get_config('upload_dir').'/'.$this->FRSPackage->Group->getUnixName().'/'.$this->FRSPackage->getFileName().'/'.$this->getFileName();
168 if (!is_dir($newdirlocation)) {
169 @mkdir($newdirlocation);
177 * fetchData - re-fetch the data for this Release from the database.
179 * @param int The release_id.
180 * @return boolean success.
182 function fetchData($release_id) {
183 $res = db_query_params ('SELECT * FROM frs_release WHERE release_id=$1 AND package_id=$2',
185 $this->FRSPackage->getID())) ;
186 if (!$res || db_numrows($res) < 1) {
187 $this->setError(_('Invalid release_id'));
190 $this->data_array = db_fetch_array($res);
191 db_free_result($res);
196 * getFRSPackage - get the FRSPackage object this release is associated with.
198 * @return object The FRSPackage object.
200 function &getFRSPackage() {
201 return $this->FRSPackage;
205 * getID - get this release_id.
207 * @return int The id of this release.
210 return $this->data_array['release_id'];
214 * getName - get the name of this release.
216 * @return string The name of this release.
219 return $this->data_array['name'];
223 * getFileName - get the filename of this release.
225 * @return string The filename of this release.
227 function getFileName() {
228 return util_secure_filename($this->data_array['name']);
232 * getStatus - get the status of this release.
234 * @return int The status.
236 function getStatus() {
237 return $this->data_array['status_id'];
241 * getNotes - get the release notes of this release.
243 * @return string The release notes.
245 function getNotes() {
246 return $this->data_array['notes'];
250 * getChanges - get the changelog of this release.
252 * @return string The changelog.
254 function getChanges() {
255 return $this->data_array['changes'];
259 * getPreformatted - get the preformatted option of this release.
261 * @return boolean preserve_formatting.
263 function getPreformatted() {
264 return $this->data_array['preformatted'];
268 * getReleaseDate - get the releasedate of this release.
270 * @return int The release date in unix time.
272 function getReleaseDate() {
273 return $this->data_array['release_date'];
277 * sendNotice - the logic to send an email notice for a release.
279 * @return boolean success.
281 function sendNotice() {
282 $arr =& $this->FRSPackage->getMonitorIDs();
284 $date = date('Y-m-d H:i',time());
286 $subject = sprintf (_('[%1$s Release] %2$s'),
287 $this->FRSPackage->Group->getUnixName(),
288 $this->FRSPackage->getName());
289 $text = stripcslashes(sprintf(_('Project %1$s (%2$s) has released a new version of package “%3$s”.'),
290 $this->FRSPackage->Group->getPublicName(),
291 $this->FRSPackage->Group->getUnixName(),
292 $this->FRSPackage->getName())
294 . _('Release Notes')._(':')
297 . _('Change Log')._(':')
299 . $this->getChanges()
301 . _('You can download it by following this link')._(':')
303 . util_make_url ("/frs/?group_id=". $this->FRSPackage->Group->getID() ."&release_id=". $this->getID())
305 . sprintf(_('You receive this email because you requested to be notified when new '
306 . 'versions of this package were released. If you don\'t wish to be '
307 . 'notified in the future, please login to %s and click this link:'),
308 forge_get_config('forge_name'))
310 . util_make_url ("/frs/monitor.php?filemodule_id=".$this->FRSPackage->getID()."&group_id=".$this->FRSPackage->Group->getID()."&stop=1"));
311 // $text = util_line_wrap($text);
313 util_handle_message(array_unique($arr),$subject,$text);
318 * newFRSFile - generates a FRSFile (allows overloading by subclasses)
320 * @param string FRS file identifier
321 * @param array fetched data from the DB
322 * @return FRSFile new FRSFile object.
324 protected function newFRSFile($file_id, $data) {
325 return new FRSFile($this,$file_id, $data);
329 * getFiles - gets all the file objects for files in this release.
331 * return array Array of FRSFile Objects.
333 function &getFiles() {
334 if (!is_array($this->release_files) || count($this->release_files) < 1) {
335 $this->release_files=array();
336 $res = db_query_params ('SELECT * FROM frs_file_vw WHERE release_id=$1',
337 array ($this->getID())) ;
338 while ($arr = db_fetch_array($res)) {
339 $this->release_files[]=$this->newFRSFile($arr['file_id'],$arr);
342 return $this->release_files;
346 * delete - delete this release and all its related data.
348 * @param bool I'm Sure.
349 * @param bool I'm REALLY sure.
350 * @return bool true/false;
352 function delete($sure, $really_sure) {
353 if (!$sure || !$really_sure) {
354 $this->setMissingParamsError(_('Please tick all checkboxes.'));
357 if (!forge_check_perm ('frs', $this->FRSPackage->Group->getID(), 'write')) {
358 $this->setPermissionDeniedError();
361 $f =& $this->getFiles();
362 for ($i=0; $i<count($f); $i++) {
363 if (!is_object($f[$i]) || $f[$i]->isError() || !$f[$i]->delete()) {
364 $this->setError('File Error: '.$f[$i]->getName().':'.$f[$i]->getErrorMessage());
368 $dir=forge_get_config('upload_dir').'/'.
369 $this->FRSPackage->Group->getUnixName() . '/' .
370 $this->FRSPackage->getFileName().'/'.
371 $this->getFileName().'/';
373 // double-check we're not trying to remove root dir
374 if (util_is_root_dir($dir)) {
375 $this->setError(_('Release delete error: trying to delete root dir'));
380 db_query_params ('DELETE FROM frs_release WHERE release_id=$1 AND package_id=$2',
381 array ($this->getID(),
382 $this->FRSPackage->getID())) ;
387 * update - update a new release in the database.
389 * @param int The status of this release from the frs_status table.
390 * @param string The name of the release.
391 * @param string The release notes for the release.
392 * @param string The change log for the release.
393 * @param int Whether the notes/log are preformatted with \n chars (1) true (0) false.
394 * @param int The unix date of the release.
395 * @return boolean success.
397 function update($status, $name, $notes, $changes, $preformatted, $release_date) {
398 if (strlen($name) < 3) {
399 $this->setError(_('FRSPackage Name Must Be At Least 3 Characters'));
403 if (!forge_check_perm('frs', $this->FRSPackage->Group->getID(), 'write')) {
404 $this->setPermissionDeniedError();
414 if($this->getName() != htmlspecialchars($name)) {
415 $res = db_query_params ('SELECT * FROM frs_release WHERE package_id=$1 AND name=$2',
416 array ($this->FRSPackage->getID(),
417 htmlspecialchars($name))) ;
418 if (db_numrows($res)) {
419 $this->setError(_('Error On Update: Name Already Exists'));
424 $res = db_query_params ('UPDATE frs_release SET name=$1,status_id=$2,notes=$3,
425 changes=$4,preformatted=$5,release_date=$6,released_by=$7
426 WHERE package_id=$8 AND release_id=$9',
427 array (htmlspecialchars($name),
429 htmlspecialchars($notes),
430 htmlspecialchars($changes),
434 $this->FRSPackage->getID(),
437 if (!$res || db_affected_rows($res) < 1) {
438 $this->setError(sprintf(_('Error On Update: %s'), db_error()));
443 $oldfilename = $this->getFileName();
444 if(!$this->fetchData($this->getID())){
445 $this->setError(_("Error Updating Release: Couldn't fetch data"));
449 $newfilename = $this->getFileName();
450 $olddirlocation = forge_get_config('upload_dir').'/'.$this->FRSPackage->Group->getUnixName().'/'.$this->FRSPackage->getFileName().'/'.$oldfilename;
451 $newdirlocation = forge_get_config('upload_dir').'/'.$this->FRSPackage->Group->getUnixName().'/'.$this->FRSPackage->getFileName().'/'.$newfilename;
453 if (($oldfilename!=$newfilename) && is_dir($olddirlocation)) {
454 if (is_dir($newdirlocation)) {
455 $this->setError(_('Error Updating Release: Directory Already Exists'));
459 if(!rename($olddirlocation, $newdirlocation)) {
460 $this->setError(_("Error Updating Release: Couldn't rename dir"));
467 $this->FRSPackage->createNewestReleaseFilesAsZip();
475 // c-file-style: "bsd"