3 * FusionForge FRS: Release Class
5 * Copyright 2002, Tim Perdue/GForge, LLC
6 * Copyright 2009, Roland Mas
7 * Copyright (C) 2012 Alain Peyrat - Alcatel-Lucent
8 * Copyright 2014,2016, Franck Villaume - TrivialDev
10 * This file is part of FusionForge. FusionForge is free software;
11 * you can redistribute it and/or modify it under the terms of the
12 * GNU General Public License as published by the Free Software
13 * Foundation; either version 2 of the Licence, or (at your option)
16 * FusionForge is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with FusionForge; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 require_once $gfcommon.'include/FFObject.class.php';
27 require_once $gfcommon.'frs/FRSFile.class.php';
30 * get_frs_releases - get all FRS releases for a specific package
32 * @param FRSPackage $package
35 function get_frs_releases($package) {
37 $res = db_query_params('SELECT * FROM frs_release WHERE package_id=$1',
38 array($package->getID()));
39 if (db_numrows($res) > 0) {
40 while($arr = db_fetch_array($res)) {
41 $rs[] = new FRSRelease($package, $arr['release_id'], $arr);
48 * Factory method which creates a FRSRelease from an release id
50 * @param int $release_id The release id
51 * @param array $data The result array, if it's passed in
52 * @return object|bool FRSRelease object
54 function frsrelease_get_object($release_id, $data = array()) {
55 global $FRSRELEASE_OBJ;
56 if (!isset($FRSRELEASE_OBJ['_'.$release_id.'_'])) {
58 //the db result handle was passed in
60 $res = db_query_params('SELECT * FROM frs_release WHERE release_id=$1',
62 if (db_numrows($res)<1 ) {
63 $FRSRELEASE_OBJ['_'.$release_id.'_'] = false;
66 $data = db_fetch_array($res);
68 $FRSPackage = frspackage_get_object($data['package_id']);
69 $FRSRELEASE_OBJ['_'.$release_id.'_'] = new FRSRelease($FRSPackage, $data['release_id'], $data);
71 return $FRSRELEASE_OBJ['_'.$release_id.'_'];
74 class FRSRelease extends FFObject {
77 * Associative array of data from db.
79 * @var array $data_array.
86 * @var object FRSPackage.
90 var $files_count = null;
93 * @param object $FRSPackage The FRSPackage object to which this release is associated.
94 * @param int|bool $release_id The release_id.
95 * @param array $arr The associative array of data.
97 function __construct(&$FRSPackage, $release_id = false, $arr = array()) {
98 if (!$FRSPackage || !is_object($FRSPackage)) {
99 $this->setError(_('Invalid FRS Package Object'));
102 if ($FRSPackage->isError()) {
103 $this->setError('FRSRelease: '.$FRSPackage->getErrorMessage());
107 $this->FRSPackage =& $FRSPackage;
110 parent::__construct($release_id, 'FRSRelease');
111 if (!$arr || !is_array($arr)) {
112 if (!$this->fetchData($release_id)) {
116 $this->data_array =& $arr;
117 if ($this->data_array['package_id'] != $this->FRSPackage->getID()) {
118 $this->setError('FRSPackage_id in db result does not match FRSPackage Object');
119 $this->data_array = null;
124 parent::__construct();
129 * create - create a new release in the database.
131 * @param string $name The name of the release.
132 * @param string $notes The release notes for the release.
133 * @param string $changes The change log for the release.
134 * @param int $preformatted Whether the notes/log are preformatted with \n chars (1) true (0) false.
135 * @param int|bool $release_date The unix date of the release.
136 * @param int $status_id
137 * @param array $importData Array of data to change creator, time of creation, bypass permission check and do not send notification like:
138 * array('user' => 127, 'time' => 1234556789, 'nopermcheck' => 1, 'nonotice' => 1)
139 * @return bool success.
141 function create($name, $notes, $changes, $preformatted, $release_date = false, $status_id = 1, $importData = array()) {
142 if (strlen($name) < 3) {
143 $this->setError(_('FRSRelease Name Must Be At Least 3 Characters'));
153 if (isset($importData['user'])) {
154 $userid = $importData['user'];
156 $userid = user_getid();
159 if (!isset($importData['nopermcheck']) || (isset($importData['nopermcheck']) && !$importData['nopermcheck'])) {
160 if (!forge_check_perm_for_user(user_get_object($userid), 'frs', $this->FRSPackage->getID(), 'release')) {
161 $this->setPermissionDeniedError();
166 if (!$release_date || !isset($importData['time'])) {
167 $release_date = time();
169 if (isset($importData['time'])) {
170 $release_date = $importData['time'];
173 $res = db_query_params('SELECT * FROM frs_release WHERE package_id=$1 AND name=$2',
174 array ($this->FRSPackage->getID(),
175 htmlspecialchars($name)));
176 if (db_numrows($res)) {
177 $this->setError(_('Error Adding Release: ')._('Name Already Exists'));
182 $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)',
183 array($this->FRSPackage->getID(),
184 htmlspecialchars($notes),
185 htmlspecialchars($changes),
187 htmlspecialchars($name),
192 $this->setError(_('Error Adding Release: ').db_error());
196 $this->release_id=db_insertid($result,'frs_release','release_id');
197 if (!$this->fetchData($this->release_id)) {
201 $newdirlocation = forge_get_config('upload_dir').'/'.$this->FRSPackage->Group->getUnixName().'/'.$this->FRSPackage->getFileName().'/'.$this->getFileName();
202 if (!is_dir($newdirlocation)) {
203 @mkdir($newdirlocation);
211 * fetchData - re-fetch the data for this Release from the database.
213 * @param int $release_id The release_id.
214 * @return bool success.
216 function fetchData($release_id) {
217 $res = db_query_params('SELECT * FROM frs_release WHERE release_id=$1 AND package_id=$2',
218 array($release_id, $this->FRSPackage->getID()));
219 if (!$res || db_numrows($res) < 1) {
220 $this->setError(_('Invalid release_id'));
223 $this->data_array = db_fetch_array($res);
224 db_free_result($res);
229 * getFRSPackage - get the FRSPackage object this release is associated with.
231 * @return object The FRSPackage object.
233 function &getFRSPackage() {
234 return $this->FRSPackage;
238 * getID - get this release_id.
240 * @return int The id of this release.
243 return $this->data_array['release_id'];
247 * getName - get the name of this release.
249 * @return string The name of this release.
252 return $this->data_array['name'];
256 * getFileName - get the filename of this release.
258 * @return string The filename of this release.
260 function getFileName() {
261 return util_secure_filename($this->data_array['name']);
265 * getStatus - get the status of this release.
267 * @return int The status.
269 function getStatus() {
270 return $this->data_array['status_id'];
274 * getNotes - get the release notes of this release.
276 * @return string The release notes.
278 function getNotes() {
279 return $this->data_array['notes'];
283 * getChanges - get the changelog of this release.
285 * @return string The changelog.
287 function getChanges() {
288 return $this->data_array['changes'];
292 * getPreformatted - get the preformatted option of this release.
294 * @return bool preserve_formatting.
296 function getPreformatted() {
297 return $this->data_array['preformatted'];
301 * getReleaseDate - get the releasedate of this release.
303 * @return int The release date in unix time.
305 function getReleaseDate() {
306 return $this->data_array['release_date'];
310 * sendNotice - the logic to send an email notice for a release.
312 * @return bool success.
314 function sendNotice() {
315 $arr =& $this->FRSPackage->getMonitorIDs();
317 $subject = sprintf(_('[%1$s Release] %2$s'),
318 $this->FRSPackage->Group->getUnixName(),
319 $this->FRSPackage->getName());
320 $text = sprintf(_('Project %1$s (%2$s) has released a new version of package “%3$s”.'),
321 $this->FRSPackage->Group->getPublicName(),
322 $this->FRSPackage->Group->getUnixName(),
323 $this->FRSPackage->getName())
325 . _('Release Notes')._(':')
328 . _('Change Log')._(':')
330 . $this->getChanges()
332 . _('You can download it by following this link')._(':')
334 . util_make_url('/frs/?group_id='.$this->FRSPackage->Group->getID().'&release_id='.$this->getID())
336 . sprintf(_('You receive this email because you requested to be notified when new '
337 . 'versions of this package were released. If you don\'t wish to be '
338 . 'notified in the future, please login to %s and click this link:'),
339 forge_get_config('forge_name'))
341 . util_make_url('/frs/monitor.php?filemodule_id='.$this->FRSPackage->getID()."&group_id=".$this->FRSPackage->Group->getID()."&stop=1");
342 // $text = util_line_wrap($text);
344 util_handle_message(array_unique($arr), $subject, $text);
349 * newFRSFile - generates a FRSFile (allows overloading by subclasses)
351 * @param string FRS file identifier
352 * @param array fetched data from the DB
353 * @return FRSFile new FRSFile object.
355 protected function newFRSFile($file_id, $data) {
356 return new FRSFile($this, $file_id, $data);
360 * getFiles - gets all the file objects for files in this release.
362 * @return array Array of FRSFile Objects.
364 function &getFiles() {
365 if (!is_array($this->release_files) || count($this->release_files) < 1) {
366 $this->release_files = array();
367 $res = db_query_params('SELECT * FROM frs_file_vw WHERE release_id=$1',
368 array($this->getID())) ;
369 while ($arr = db_fetch_array($res)) {
370 $this->release_files[$arr['file_id']] = $this->newFRSFile($arr['file_id'], $arr);
373 return $this->release_files;
376 function hasFiles() {
377 if ($this->files_count != null)
378 return $this->files_count;
380 $res = db_query_params('select count(file_id) as files_count from frs_file where release_id = $1', array($this->getID()));
381 if (db_numrows($res) >= 1) {
382 $row = db_fetch_array($res);
383 $this->files_count = $row['files_count'];
385 return $this->files_count;
389 * delete - delete this release and all its related data.
391 * @param bool $sure I'm Sure.
392 * @param bool $really_sure I'm REALLY sure.
393 * @return bool true/false;
395 function delete($sure, $really_sure) {
396 if (!$sure || !$really_sure) {
397 $this->setMissingParamsError(_('Please tick all checkboxes.'));
400 if (!forge_check_perm('frs', $this->FRSPackage->getID(), 'release')) {
401 $this->setPermissionDeniedError();
404 $f =& $this->getFiles();
406 while($file = current($f)) {
407 if (!is_object($file) || $file->isError() || !$file->delete()) {
408 $this->setError(_('File Error')._(': ').$file->getName()._(': ').$file->getErrorMessage());
413 $dir=forge_get_config('upload_dir').'/'.
414 $this->FRSPackage->Group->getUnixName() . '/' .
415 $this->FRSPackage->getFileName().'/'.
416 $this->getFileName().'/';
418 // double-check we're not trying to remove root dir
419 if (util_is_root_dir($dir)) {
420 $this->setError(_('Release delete error')._(': ')._('trying to delete root dir'));
423 $this->FRSPackage->deleteReleaseFilesAsZip($this->getID());
426 db_query_params('DELETE FROM frs_release WHERE release_id=$1 AND package_id=$2',
427 array ($this->getID(),
428 $this->FRSPackage->getID()));
433 * update - update a new release in the database.
435 * @param int The status of this release from the frs_status table.
436 * @param string The name of the release.
437 * @param string The release notes for the release.
438 * @param string The change log for the release.
439 * @param int Whether the notes/log are preformatted with \n chars (1) true (0) false.
440 * @param int The unix date of the release.
441 * @return bool success.
443 function update($status, $name, $notes, $changes, $preformatted, $release_date) {
444 if (strlen($name) < 3) {
445 $this->setError(_('FRSRelease Name Must Be At Least 3 Characters'));
449 if (!forge_check_perm('frs', $this->FRSPackage->getID(), 'release')) {
450 $this->setPermissionDeniedError();
460 if($this->getName() != htmlspecialchars($name)) {
461 $res = db_query_params ('SELECT * FROM frs_release WHERE package_id=$1 AND name=$2',
462 array ($this->FRSPackage->getID(),
463 htmlspecialchars($name))) ;
464 if (db_numrows($res)) {
465 $this->setError(_('Error On Update')._(': ')._('Name Already Exists'));
470 $res = db_query_params('UPDATE frs_release SET name=$1,status_id=$2,notes=$3,
471 changes=$4,preformatted=$5,release_date=$6,released_by=$7
472 WHERE package_id=$8 AND release_id=$9',
473 array (htmlspecialchars($name),
475 htmlspecialchars($notes),
476 htmlspecialchars($changes),
480 $this->FRSPackage->getID(),
483 if (!$res || db_affected_rows($res) < 1) {
484 $this->setError(_('Error On Update')._(': ').db_error());
489 $oldfilename = $this->getFileName();
490 if(!$this->fetchData($this->getID())){
491 $this->setError(_('Error Updating Release')._(': ')._("Couldn't fetch data"));
495 $newfilename = $this->getFileName();
496 $olddirlocation = forge_get_config('upload_dir').'/'.$this->FRSPackage->Group->getUnixName().'/'.$this->FRSPackage->getFileName().'/'.$oldfilename;
497 $newdirlocation = forge_get_config('upload_dir').'/'.$this->FRSPackage->Group->getUnixName().'/'.$this->FRSPackage->getFileName().'/'.$newfilename;
499 if (($oldfilename != $newfilename) && is_dir($olddirlocation)) {
500 if (is_dir($newdirlocation)) {
501 $this->setError(_('Error Updating Release')._(': ')._('Directory Already Exists'));
505 if(!rename($olddirlocation, $newdirlocation)) {
506 $this->setError(_('Error Updating Release')._(': ')._("Couldn't rename dir"));
513 if ($this->hasFiles()) {
514 $this->FRSPackage->createReleaseFilesAsZip($this->getID());
519 function isLinkedRoadmapRelease($roadmap_id, $roadmap_release) {
521 $res = db_query_params('SELECT roadmap_id FROM frs_release_tracker_roadmap_link WHERE release_id = $1 and roadmap_release = $2',
522 array($this->getID(), $roadmap_release));
526 $roadmaps = util_result_column_to_array($res);
530 function deleteLinkedRoadmap($roadmap_id, $roadmap_release) {
532 $res = db_query_params('DELETE FROM frs_release_tracker_roadmap_link where roadmap_id = $1 and release_id = $2 and roadmap_release = $3',
533 array($roadmap_id, $this->getID(), $roadmap_release));
535 $this->setError(_('Error Delete Linked Roadmap')._(': ').db_error());
543 function addLinkedRoadmap($roadmap_id, $roadmap_release) {
545 $res = db_query_params('INSERT INTO frs_release_tracker_roadmap_link (roadmap_id, release_id, roadmap_release) VALUES ($1, $2, $3)',
546 array($roadmap_id, $this->getID(), $roadmap_release));
548 $this->setError(_('Error Adding Linked Roadmap')._(': ').db_error());
556 function getLinkedRoadmaps() {
558 $res = db_query_params('SELECT roadmap_id, roadmap_release FROM frs_release_tracker_roadmap_link WHERE release_id = $1',
559 array($this->getID()));
563 while ($arr = db_fetch_array($res)) {
564 $roadmaps[$arr[0]][] = $arr[1];
569 function getPermalink() {
570 return '/frs/r_follow.php/'.$this->getID();
576 // c-file-style: "bsd"