"multipart/form-data");
for ($i = 0; $i < 10; ++$i) {
$form['upload'. $i] = array('#type' => 'file');
}
$form['submit_same'] = array('#type' => 'submit', '#value' => t('Upload more'));
$form['submit_next'] = array('#type' => 'submit', '#value' => t('Next'));
break;
case 2:
// create release
$form['name'] = array(
'#type' => 'textfield',
'#title' => t('Name'),
'#required' => TRUE,
'#size' => 30,
'#maxlength' => 255,
'#description' => t('Name of the release')
);
$form['version'] = array(
'#type' => 'textfield',
'#title' => t('Version'),
'#required' => TRUE,
'#size' => 30,
'#maxlength' => 255,
'#description' => t('Version of the release')
);
$form['description'] = array(
'#type' => 'textarea',
'#title' => t('Description'),
'#required' => TRUE,
'#cols' => 60,
'#rows' => 5,
'#description' => t('Description of the release')
);
// create form elements for file selection
$pass = origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'user.my_password');
$files = get_files_from_ftp(variable_get('origo_ftp', ''), $user->name, $pass);
$i = 0;
$platform_values = drupal_map_assoc(array_merge(array('ignore', 'remove'), variable_get('origo_release_platforms', array())));
foreach ($files as $file) {
$form['file'. $i] = array(
'#type' => 'value',
'#value' => $file);
$form['platform'. $i] = array(
'#type' => 'select',
'#options' => $platform_values,
'#default_value' => 'ignore'
);
++$i;
}
$form['count'] = array('#type' => 'value', '#value' => $i);
$form['submit'] = array('#type' => 'submit', '#value' => t('Create Release'));
break;
default:
///blah blah, really you should never get here
break;
}
return $form;
}
/**
* Special theme function for our wizard form.
* @param $form the form elements to template
* @return the string of the themed form
*/
function theme_origo_home_create_release_form($form) {
$output = '';
// Unfortunately we don't have access to $form_state in the theming function,
// thus we switch between the pages according to the button that was clicked:
// - we only render the second page, if either "next" was clicked (in this case
// the user wants to advance), or the "Create Release" button (in case the user
// made an error, and the 2nd form is re-displayed.
if ($form['#parameters'][1]['values']['op'] != t('Next') &&
$form['#parameters'][1]['values']['op'] != t('Create Release')) {
// first page
$output .= drupal_render($form);
$output .= t('
It is also possible to use FTP to upload files, connect to '. variable_get('origo_ftp', '') .' using your Origo user name and password. Don\'t upload whole directories because only files will be processed and added to your release.');
}
else {
// second page
$output .= drupal_render($form['name']);
$output .= drupal_render($form['version']);
$output .= drupal_render($form['description']);
// add button for setting all platforms
$platforms = array_diff(
variable_get('origo_release_platforms', Array()),
array('other', 'all', 'source')
);
$js = << 0) {
$js = drupal_substr($js, 0, -2);
}
$js .= << longestMatch) {
defaultPlatform = parseInt(platform) + 4; // + 4 is added because 'ignore', 'other', 'all', 'source' are not added
longestMatch = platforms[platform].length;
}
}
document.getElementById('edit-platform'+i).selectedIndex = defaultPlatform;
// get next file
i++;
file = $("#uploadFileName"+i).html();
}
});
$(".showOnLoad").css("display", "block");
});
EOF;
drupal_add_js($js, 'inline');
$output .= t('Automatically assign all matching '
.'platforms. If the filename contains a platform name from the selection, it will be '
.'selected in the dropdown. ');
// Format file selection table
$header = array(
array('data' => t('File')),
array('data' => t('Action/Platform'))
);
$data = array();
for ( $i = 0; $i < $form['count']['#value']; ++$i ) {
$row = array(
array('data' => $form['file'. $i]['#value'], 'id' => 'uploadFileName'. $i),
array('data' => drupal_render($form['platform'. $i]))
);
$data[] = $row;
}
$output .= theme('table', $header, $data);
$output .= '
';
$output .= t('It is also possible to use the various IDE integrations to create a release. '
.'If your desired platform is not listed, please report an issue and it will be added.
');
}
$output .= drupal_render($form);
return $output;
}
/**
* Additional validation for our wizard form.
* @param $form_id id of the submited form
* @param $form_values values of the submited form
*/
function origo_home_create_release_form_validate($form, &$form_state) {
switch ($form_state['storage']['step']) {
// file upload
case 1:
break;
// create release
case 2:
$any_file_included = False;
for ($i = 0; !$any_file_included && $i < $form_state['values']['count']; ++$i) {
$current_value = $form_state['values']['platform'. $i];
$any_file_included = ($current_value != 'ignore') && ($current_value != 'remove');
}
if (!$any_file_included) {
form_set_error('', t('At least one file has to be included in a release, select an appropriate platform for each file that should be included'));
}
break;
}
}
/**
* Handle the form submit
* @param $form_id id of the submited form
* @param $form_values values of the submited form
*/
function origo_home_create_release_form_submit($form, &$form_state) {
global $user;
switch ($form_state['storage']['step']) {
case 1:
// file upload
$connection_id = ftp_connect(variable_get('origo_ftp', ''));
$pass = origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'user.my_password');
if ( ftp_login($connection_id, $user->name, $pass) ) {
$uploaded = False;
for ($i = 0; $i < 10; ++$i) {
if ($source = file_save_upload('upload'. $i)) {
if (ftp_put($connection_id, $source->filename, $source->filepath, FTP_BINARY)) {
$uploaded = True;
}
}
}
if ($uploaded) {
drupal_set_message(t('File uploaded'));
}
ftp_close($connection_id);
}
//tell Drupal we are redrawing the same form
$form_state['rebuild'] = TRUE;
break;
case 2:
// create release
$files_remove = array();
$files_release = array();
for ($i = 0; $i < $form_state['values']['count']; ++$i) {
$cur_file = $form_state['values']['file'. $i];
$current_platform = $form_state['values']['platform'. $i];
if ($current_platform == 'remove') {
$files_remove[] = $cur_file;
}
elseif ($current_platform != 'ignore') {
$files_release[] = array('name' => $cur_file, 'platform' => $current_platform);
}
}
// remove files selected to be removed
if (!empty($files_remove)) {
$connection_id = ftp_connect(variable_get('origo_ftp', ''));
$pass = origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'user.my_password');
if (ftp_login($connection_id, $user->name, $pass)) {
foreach ($files_remove as $file) {
ftp_delete($connection_id, $file);
}
ftp_close($connection_id);
}
}
// execute the api call
origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'release.add', (int)variable_get('origo_project_id', 0), $form_state['values']['name'], $form_state['values']['description'], $form_state['values']['version'], $files_release);
drupal_set_message(t('Your release has been created.'));
drupal_goto('download');
break;
}
}
// Returns a human readable size
function _origo_home_size_hum_read($size) {
$i=0;
$iec = array("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB");
if (is_numeric($size) && $size > 0) {
while (($size/1024)>1) {
$size=$size/1024;
$i++;
}
if ($i == 0) {
return sprintf('%d ', $size) . $iec[$i];
}
else {
return sprintf('%0.2f ', $size) . $iec[$i];
}
}
else {
return "0 B";
}
}
/**
* Show releases for project
*/
function origo_home_release_page() {
global $pager_total;
drupal_add_js(drupal_get_path('module', 'origo_home') .'/projects.js', 'module', 'header', FALSE, FALSE);
drupal_add_css(drupal_get_path('module', 'origo_home') .'/projects.css', 'module', 'all', FALSE, FALSE);
return _origo_xmlrpc_table_get_page('_releases_dataprovider');
}
/**
* This dataprovider feeds the data for the xmlrpc-table for releases.
*/
function _releases_dataprovider($page, $pagesize, $order, $direction) {
$header = array(
"",
array('data' => t('Date'), 'width' => '15%', 'field' => 'date', 'sort' => 'asc'),
array('data' => t('Version'), 'width' => '10%', 'field' => 'version'),
array('data' => t('Name'), 'width' => '55%', 'colspan' => '2', 'field' => 'Name'),
array('data' => t('Platform'), 'width' => '10%'),
array('data' => t('Size'), 'width' => '10%'),
);
// Some small helper functions:
function cmp_release_date($a, $b) {
return $a['creation_time'] - $b['creation_time'];
}
function cmp_release_version($a, $b) {
// Split both version
$sa = explode('.', $a['version']);
$sb = explode('.', $b['version']);
for ($i = 0; $i < count($sb); $i++) {
if (is_numeric($sa[$i]) && is_numeric($sb[$i]) && $sa[$i] != $sb[$i]) {
return $sa[$i] - $sb[$i];
}
elseif ($sa[$i] != $sb[$i]) {
return strcasecmp($sa[$i], $sb[$i]);
}
}
}
function cmp_release_name($a, $b) {
return strcasecmp($a['name'], $b['name']);
}
// Retrieve the stuff
$releases = origo_auth_xml_rpc(variable_get('origo_api_internal', ''), 'internal_release.list', (int)variable_get('origo_project_id', 1));
if ((int)xmlrpc_errno() > 0) {
$rows[] = array(array('data' => t('An internal error occured: the download list is currently not available.'), 'colspan' => '7', 'class' => 'message'));
return array(
'header' => $header,
'rows' => $rows,
'options' => array('style' => 'width: 100%', 'id' => 'releases')
);
}
if (count($releases) < 1)
return array(
'header' => $header,
'rows' => array(array(array('data' => t('This project has not released anything, yet.'), 'colspan' => '7', 'class' => 'message'))),
'total_size' => 0,
'options' => array('style' => 'width: 100%', 'id' => 'releases')
);
// Get filesizes:
foreach ($releases as $k => $release) {
for ($i = 1; $i <= $release['file_count']; $i++) {
$escaped = rawurlencode($release['file_name_'. $i]);
$headers = get_headers('http://'. variable_get('origo_internal_file_server_ip', '') .'/'. variable_get('origo_project_name', '') .'/'. $release['release_id'] .'/'. $escaped, 1);
$releases[$k]['file_size_'. $i] = $headers['Content-Length'] > 0 ? $headers['Content-Length'] : "-";
}
}
if (empty($order))
$order = 'Date';
if (empty($direction))
$direction = 'asc';
// Order it
switch ($order) {
case 'Date':
usort($releases, 'cmp_release_date');
break;
case 'Name':
usort($releases, 'cmp_release_name');
break;
case 'Version':
usort($releases, 'cmp_release_version');
break;
}
// Invert the order if we are actually ascending:
$releases = $direction == "asc" ? array_reverse($releases) : $releases;
// Mark the first release to be expanded (will later be replaced with result)
$releases[0]['expanded'] = TRUE;
// Create the rows
foreach ($releases as $release) {
// Build the switcher imgs
$img = drupal_get_path('module', 'origo_home') . ($release['expanded'] ? "/img/checkbox_minus.gif" : "/img/checkbox_plus.gif");
$alt = drupal_get_path('module', 'origo_home') . ($release['expanded'] ? "/img/checkbox_plus.gif" : "/img/checkbox_minus.gif");
// Add the release row:
$rows[] = array(
array('data' => "", 'class' => "release_description"),
array('data' => date('Y-m-d H:i', $release['creation_time']), 'width' => '15%', 'class' => 'release_description'),
array('data' => check_plain($release['version']), 'width' => '10%', 'class' => 'release_description'),
array('data' => l($release['name'], 'download/'. $release['release_id']), 'width' => '55%', 'colspan' => '2', 'class' => 'release_description'),
);
// the last col is only shown if we have the right to edit the releases:
if (user_access('origo delete release')) {
$rows[count($rows)-1][] = array(
'data' => l('[remove]', 'download/delete/'. $release['release_id']),
'width' => '20%',
'colspan' => '2',
'class' => 'release_description'
);
}
else {
$rows[count($rows)-1][] = array('data' => "", 'colspan' => 4, 'class' => 'release_description');
}
// Build the files for this release
$base_path = drupal_get_path('module', 'origo_home');
for ($i = 1; $i <= $release['file_count']; $i++) {
$metalink = l(
"metalink ",
variable_get('origo_download_path', '') .'/'. variable_get('origo_project_name', '') .'/'. $release['release_id'] .'/'. $release['file_name_'. $i] .'.metalink',
array(
'html' => True
)
);
$rows[]['data'] = array(
"",
array('data' => "", 'colspan' => '3', 'class' => 'release_file'),
array('data' => l($release['file_name_'. $i], variable_get('origo_download_path', '') .'/'. variable_get('origo_project_name', '') .'/'. $release['release_id'] .'/'. $release['file_name_'. $i])
.' ('. $metalink .')', 'width' => '53%', 'class' => 'release_file'),
array('data' => t($release['file_platform_'. $i]), 'width' => '10%', 'class' => 'release_file'),
array('data' => t(_origo_home_size_hum_read($release['file_size_'. $i])), 'width' => '10%', 'class' => 'release_file')
);
$rows[count($rows)-1]['class'] = ($release['expanded'] ? "" : "collapsed ") ."release". $release['release_id'];
}
}
// If we have no release just return a message:
if (empty($rows)) {
$rows[] = array(array('data' => t('No downloads available.'), 'colspan' => '6', 'class' => 'message'));
}
return array(
'header' => $header,
'rows' => $rows,
'total_size' => $total_size,
'options' => array('style' => 'width: 100%', 'id' => 'releases')
);
}
/**
* Show release for project
*/
function origo_home_release_detail_page($release_id) {
$output = '';
// get release
$release = origo_auth_xml_rpc(variable_get('origo_api_internal', ''), 'internal_release.retrieve', (int)$release_id);
$output .= ''. check_plain($release['name']) .' - '. check_plain($release['version']) .' ('. date('Y-m-d H:i', $release['creation_time']) .')
';
$description= $release['description'];
$output .= check_markup($description, FILTER_FORMAT_DEFAULT, False) .'
';
$header = array(
array('data' => t('File'), 'width' => '80%'),
array('data' => t('Platform'), 'width' => '10%'),
array('data' => t('Size'), 'width' => '10%'),
);
$rows = array();
$color = '#EEEEEE';
for ($i = 1; $i <= $release['file_count']; $i++) {
$size = '-';
$headers = get_headers('http://'. variable_get('origo_internal_file_server_ip', '') .'/'. variable_get('origo_project_name', '') .'/'. $release['release_id'] .'/'. $release['file_name_'. $i], 1);
$filesize = $headers['Content-Length'];
if ($filesize > 0) {
$size = _origo_home_size_hum_read($filesize);
}
$rows[] = array(
array('data' => l($release['file_name_'. $i], variable_get('origo_download_path', '') .'/'. variable_get('origo_project_name', '') .'/'. $release['release_id'] .'/'. $release['file_name_'. $i])
.' ('. l('metalink', variable_get('origo_download_path', '') .'/'. variable_get('origo_project_name', '') .'/'. $release['release_id'] .'/'. $release['file_name_'. $i] .'.metalink') .')', 'width' => '80%', 'style' => 'background-color:'. $color),
array('data' => t($release['file_platform_'. $i]), 'width' => '10%', 'style' => 'background-color:'. $color),
array('data' => t($size), 'width' => '10%', 'style' => 'background-color:'. $color),
);
}
if (empty($rows)) {
$rows[] = array(array('data' => t('No files available.'), 'colspan' => '3', 'class' => 'message'));
}
$output .= theme('table', $header, $rows, array('style' => 'width:100%'));
return $output;
}
/**
* Page to delete a release.
*
* @param release_id Release ID
*/
function origo_home_release_delete_page($release_id) {
$output = '';
// get release
$release = origo_auth_xml_rpc(variable_get('origo_api_internal', ''), 'internal_release.retrieve', (int)$release_id);
$output .= ''. check_plain($release['name']) .' - '. check_plain($release['version']) .' ('. date('Y-m-d H:i', $release['creation_time']) .')
';
$description= $release['description'];
$output .= check_markup($description, FILTER_FORMAT_DEFAULT, False) .'
';
$output .= '
';
$output .= t('Do you really want to delete this release?') .'
';
$output .= drupal_get_form('origo_home_release_delete_form', $release_id);
return $output;
}
/**
* Form to delete a release.
*
* @param $release_id Release ID
*/
function origo_home_release_delete_form(&$form_state, $release_id) {
// store the id of the current release
$form['release_id'] = array(
'#type' => 'hidden',
'#value' => $release_id
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Delete'),
);
return $form;
}
/**
* Submit form handler to delete a release.
*
* @param $release_id Release ID
*/
function origo_home_release_delete_form_submit($form, &$form_state) {
$project_id = variable_get('origo_project_id', 0);
origo_auth_xmlrpc_session(variable_get('origo_api', ''), 'release.delete', (int)$project_id, (int)$form_state['values']['release_id']);
if ((int)xmlrpc_errno() > 0) {
form_set_error(NULL, t('Error: '. xmlrpc_error_msg()));
}
else {
drupal_set_message('Release has been deleted.');
drupal_goto('download');
}
}