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 $this->fetchData($release_id);
114 $this->data_array =& $arr;
115 if ($this->data_array['package_id'] != $this->FRSPackage->getID()) {
116 $this->setError('FRSPackage_id in db result does not match FRSPackage Object');
117 $this->data_array = null;
121 parent::__construct();
126 * create - create a new release in the database.
128 * @param string $name The name of the release.
129 * @param string $notes The release notes for the release.
130 * @param string $changes The change log for the release.
131 * @param int $preformatted Whether the notes/log are preformatted with \n chars (1) true (0) false.
132 * @param int|bool $release_date The unix date of the release.
133 * @param int $status_id
134 * @param array $importData Array of data to change creator, time of creation, bypass permission check and do not send notification like:
135 * array('user' => 127, 'time' => 1234556789, 'nopermcheck' => 1, 'nonotice' => 1)
136 * @return bool success.
138 function create($name, $notes, $changes, $preformatted, $release_date = false, $status_id = 1, $importData = array()) {
139 if (strlen($name) < 3) {
140 $this->setError(_('FRSRelease Name Must Be At Least 3 Characters'));
150 if (isset($importData['user'])) {
151 $userid = $importData['user'];
153 $userid = user_getid();
156 if (!isset($importData['nopermcheck']) || (isset($importData['nopermcheck']) && !$importData['nopermcheck'])) {
157 if (!forge_check_perm_for_user(user_get_object($userid), 'frs', $this->FRSPackage->getID(), 'release')) {
158 $this->setPermissionDeniedError();
163 if (!$release_date || !isset($importData['time'])) {
164 $release_date = time();
166 if (isset($importData['time'])) {
167 $release_date = $importData['time'];
170 $res = db_query_params('SELECT * FROM frs_release WHERE package_id=$1 AND name=$2',
171 array ($this->FRSPackage->getID(),
172 htmlspecialchars($name)));
173 if (db_numrows($res)) {
174 $this->setError(_('Error Adding Release: ')._('Name Already Exists'));
179 $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)',
180 array($this->FRSPackage->getID(),
181 htmlspecialchars($notes),
182 htmlspecialchars($changes),
184 htmlspecialchars($name),
189 $this->setError(_('Error Adding Release: ').db_error());
193 $this->release_id=db_insertid($result,'frs_release','release_id');
194 if (!$this->fetchData($this->release_id)) {
198 $newdirlocation = forge_get_config('upload_dir').'/'.$this->FRSPackage->Group->getUnixName().'/'.$this->FRSPackage->getFileName().'/'.$this->getFileName();
199 if (!is_dir($newdirlocation)) {
200 @mkdir($newdirlocation);
208 * fetchData - re-fetch the data for this Release from the database.
210 * @param int $release_id The release_id.
211 * @return bool success.
213 function fetchData($release_id) {
214 $res = db_query_params('SELECT * FROM frs_release WHERE release_id=$1 AND package_id=$2',
215 array($release_id, $this->FRSPackage->getID()));
216 if (!$res || db_numrows($res) < 1) {
217 $this->setError(_('Invalid release_id'));
220 $this->data_array = db_fetch_array($res);
221 db_free_result($res);
226 * getFRSPackage - get the FRSPackage object this release is associated with.
228 * @return object The FRSPackage object.
230 function &getFRSPackage() {
231 return $this->FRSPackage;
235 * getID - get this release_id.
237 * @return int The id of this release.
240 return $this->data_array['release_id'];
244 * getName - get the name of this release.
246 * @return string The name of this release.
249 return $this->data_array['name'];
253 * getFileName - get the filename of this release.
255 * @return string The filename of this release.
257 function getFileName() {
258 return util_secure_filename($this->data_array['name']);
262 * getStatus - get the status of this release.
264 * @return int The status.
266 function getStatus() {
267 return $this->data_array['status_id'];
271 * getNotes - get the release notes of this release.
273 * @return string The release notes.
275 function getNotes() {
276 return $this->data_array['notes'];
280 * getChanges - get the changelog of this release.
282 * @return string The changelog.
284 function getChanges() {
285 return $this->data_array['changes'];
289 * getPreformatted - get the preformatted option of this release.
291 * @return bool preserve_formatting.
293 function getPreformatted() {
294 return $this->data_array['preformatted'];
298 * getReleaseDate - get the releasedate of this release.
300 * @return int The release date in unix time.
302 function getReleaseDate() {
303 return $this->data_array['release_date'];
307 * sendNotice - the logic to send an email notice for a release.
309 * @return bool success.
311 function sendNotice() {
312 $arr =& $this->FRSPackage->getMonitorIDs();
314 $subject = sprintf(_('[%1$s Release] %2$s'),
315 $this->FRSPackage->Group->getUnixName(),
316 $this->FRSPackage->getName());
317 $text = sprintf(_('Project %1$s (%2$s) has released a new version of package “%3$s”.'),
318 $this->FRSPackage->Group->getPublicName(),
319 $this->FRSPackage->Group->getUnixName(),
320 $this->FRSPackage->getName())
322 . _('Release Notes')._(':')
325 . _('Change Log')._(':')
327 . $this->getChanges()
329 . _('You can download it by following this link')._(':')
331 . util_make_url('/frs/?group_id='.$this->FRSPackage->Group->getID().'&release_id='.$this->getID())
333 . sprintf(_('You receive this email because you requested to be notified when new '
334 . 'versions of this package were released. If you don\'t wish to be '
335 . 'notified in the future, please login to %s and click this link:'),
336 forge_get_config('forge_name'))
338 . util_make_url('/frs/monitor.php?filemodule_id='.$this->FRSPackage->getID()."&group_id=".$this->FRSPackage->Group->getID()."&stop=1");
340 util_handle_message(array_unique($arr), $subject, $text);
345 * newFRSFile - generates a FRSFile (allows overloading by subclasses)
347 * @param string FRS file identifier
348 * @param array fetched data from the DB
349 * @return FRSFile new FRSFile object.
351 protected function newFRSFile($file_id, $data) {
352 return new FRSFile($this, $file_id, $data);
356 * getFiles - gets all the file objects for files in this release.
358 * @return array Array of FRSFile Objects.
360 function &getFiles() {
361 if (!is_array($this->release_files) || count($this->release_files) < 1) {
362 $this->release_files = array();
363 $res = db_query_params('SELECT * FROM frs_file_vw WHERE release_id=$1',
364 array($this->getID())) ;
365 while ($arr = db_fetch_array($res)) {
366 $this->release_files[$arr['file_id']] = $this->newFRSFile($arr['file_id'], $arr);
369 return $this->release_files;
372 function hasFiles() {
373 if ($this->files_count != null) {
374 return $this->files_count;
376 $res = db_query_params('select count(file_id) as files_count from frs_file where release_id = $1', array($this->getID()));
377 if (db_numrows($res) >= 1) {
378 $row = db_fetch_array($res);
379 $this->files_count = $row['files_count'];
381 return $this->files_count;
385 * delete - delete this release and all its related data.
387 * @param bool $sure I'm Sure.
388 * @param bool $really_sure I'm REALLY sure.
389 * @return bool true/false;
391 function delete($sure, $really_sure) {
392 if (!$sure || !$really_sure) {
393 $this->setMissingParamsError(_('Please tick all checkboxes.'));
396 if (!forge_check_perm('frs', $this->FRSPackage->getID(), 'release')) {
397 $this->setPermissionDeniedError();
400 $f =& $this->getFiles();
402 while($file = current($f)) {
403 if (!is_object($file) || $file->isError() || !$file->delete()) {
404 $this->setError(_('File Error')._(': ').$file->getName()._(': ').$file->getErrorMessage());
409 $dir=forge_get_config('upload_dir').'/'.
410 $this->FRSPackage->Group->getUnixName() . '/' .
411 $this->FRSPackage->getFileName().'/'.
412 $this->getFileName().'/';
414 // double-check we're not trying to remove root dir
415 if (util_is_root_dir($dir)) {
416 $this->setError(_('Release delete error')._(': ')._('trying to delete root dir'));
419 $this->FRSPackage->deleteReleaseFilesAsZip($this->getID());
422 db_query_params('DELETE FROM frs_release WHERE release_id=$1 AND package_id=$2',
423 array ($this->getID(),
424 $this->FRSPackage->getID()));
429 * update - update a new release in the database.
431 * @param int The status of this release from the frs_status table.
432 * @param string The name of the release.
433 * @param string The release notes for the release.
434 * @param string The change log for the release.
435 * @param int Whether the notes/log are preformatted with \n chars (1) true (0) false.
436 * @param int The unix date of the release.
437 * @return bool success.
439 function update($status, $name, $notes, $changes, $preformatted, $release_date) {
440 if (strlen($name) < 3) {
441 $this->setError(_('FRSRelease Name Must Be At Least 3 Characters'));
445 if (!forge_check_perm('frs', $this->FRSPackage->getID(), 'release')) {
446 $this->setPermissionDeniedError();
456 if($this->getName() != htmlspecialchars($name)) {
457 $res = db_query_params ('SELECT * FROM frs_release WHERE package_id=$1 AND name=$2',
458 array ($this->FRSPackage->getID(),
459 htmlspecialchars($name))) ;
460 if (db_numrows($res)) {
461 $this->setError(_('Error On Update')._(': ')._('Name Already Exists'));
466 $res = db_query_params('UPDATE frs_release SET name=$1,status_id=$2,notes=$3,
467 changes=$4,preformatted=$5,release_date=$6,released_by=$7
468 WHERE package_id=$8 AND release_id=$9',
469 array (htmlspecialchars($name),
471 htmlspecialchars($notes),
472 htmlspecialchars($changes),
476 $this->FRSPackage->getID(),
479 if (!$res || db_affected_rows($res) < 1) {
480 $this->setError(_('Error On Update')._(': ').db_error());
485 $oldfilename = $this->getFileName();
486 if(!$this->fetchData($this->getID())){
487 $this->setError(_('Error Updating Release')._(': ')._("Couldn't fetch data"));
491 $newfilename = $this->getFileName();
492 $olddirlocation = forge_get_config('upload_dir').'/'.$this->FRSPackage->Group->getUnixName().'/'.$this->FRSPackage->getFileName().'/'.$oldfilename;
493 $newdirlocation = forge_get_config('upload_dir').'/'.$this->FRSPackage->Group->getUnixName().'/'.$this->FRSPackage->getFileName().'/'.$newfilename;
495 if (($oldfilename != $newfilename) && is_dir($olddirlocation)) {
496 if (is_dir($newdirlocation)) {
497 $this->setError(_('Error Updating Release')._(': ')._('Directory Already Exists'));
501 if(!rename($olddirlocation, $newdirlocation)) {
502 $this->setError(_('Error Updating Release')._(': ')._("Couldn't rename dir"));
509 if ($this->hasFiles()) {
510 $this->FRSPackage->createReleaseFilesAsZip($this->getID());
515 function isLinkedRoadmapRelease($roadmap_release) {
516 $res = db_query_params('SELECT roadmap_id FROM frs_release_tracker_roadmap_link WHERE release_id = $1 and roadmap_release = $2',
517 array($this->getID(), $roadmap_release));
521 return util_result_column_to_array($res);
524 function deleteLinkedRoadmap($roadmap_id, $roadmap_release) {
526 $res = db_query_params('DELETE FROM frs_release_tracker_roadmap_link where roadmap_id = $1 and release_id = $2 and roadmap_release = $3',
527 array($roadmap_id, $this->getID(), $roadmap_release));
529 $this->setError(_('Error Delete Linked Roadmap')._(': ').db_error());
537 function addLinkedRoadmap($roadmap_id, $roadmap_release) {
539 $res = db_query_params('INSERT INTO frs_release_tracker_roadmap_link (roadmap_id, release_id, roadmap_release) VALUES ($1, $2, $3)',
540 array($roadmap_id, $this->getID(), $roadmap_release));
542 $this->setError(_('Error Adding Linked Roadmap')._(': ').db_error());
550 function getLinkedRoadmaps() {
552 $res = db_query_params('SELECT roadmap_id, roadmap_release FROM frs_release_tracker_roadmap_link WHERE release_id = $1',
553 array($this->getID()));
557 while ($arr = db_fetch_array($res)) {
558 $roadmaps[$arr[0]][] = $arr[1];
563 function getPermalink() {
564 return '/frs/r_follow.php/'.$this->getID();
570 // c-file-style: "bsd"