import.php (mrbs-1.9.4) | : | import.php (mrbs-1.10.0) | ||
---|---|---|---|---|
<?php | <?php | |||
namespace MRBS; | namespace MRBS; | |||
use MRBS\Form\ElementInputHidden; | ||||
use MRBS\Form\FieldInputCheckboxGroup; | ||||
use MRBS\Form\Form; | use MRBS\Form\Form; | |||
use MRBS\Form\ElementFieldset; | use MRBS\Form\ElementFieldset; | |||
use MRBS\Form\FieldInputCheckbox; | use MRBS\Form\FieldInputCheckbox; | |||
use MRBS\Form\FieldInputFile; | use MRBS\Form\FieldInputFile; | |||
use MRBS\Form\FieldInputRadioGroup; | use MRBS\Form\FieldInputRadioGroup; | |||
use MRBS\Form\FieldInputSubmit; | use MRBS\Form\FieldInputSubmit; | |||
use MRBS\Form\FieldInputText; | use MRBS\Form\FieldInputText; | |||
use MRBS\Form\FieldInputUrl; | ||||
use MRBS\Form\FieldSelect; | use MRBS\Form\FieldSelect; | |||
use \ZipArchive; | use \ZipArchive; | |||
require "defaultincludes.inc"; | require "defaultincludes.inc"; | |||
require_once "functions_ical.inc"; | require_once "functions_ical.inc"; | |||
require_once "mrbs_sql.inc"; | require_once "mrbs_sql.inc"; | |||
$wrapper_mime_types = array('file' => 'text/calendar', | $wrapper_mime_types = array('file' => 'text/calendar', | |||
'zip' => 'application/zip', | 'zip' => 'application/zip', | |||
'compress.zlib' => 'application/x-gzip', | 'compress.zlib' => 'application/x-gzip', | |||
'compress.bzip2' => 'application/x-bzip2'); | 'compress.bzip2' => 'application/x-bzip2'); | |||
$wrapper_descriptions = array('file' => get_vocab('import_text_file') , | $wrapper_descriptions = array('file' => get_vocab('import_text_file') , | |||
'zip' => get_vocab('import_zip'), | 'zip' => get_vocab('import_zip'), | |||
'compress.zlib' => get_vocab('import_gzip'), | 'compress.zlib' => get_vocab('import_gzip'), | |||
'compress.bzip2' => get_vocab('import_bzip2')); | 'compress.bzip2' => get_vocab('import_bzip2')); | |||
// Get the available compression wrappers that we can use. | // Get the available compression wrappers that we can use. | |||
// Returns an array | // Returns an array | |||
function get_compression_wrappers() | function get_compression_wrappers() : array | |||
{ | { | |||
$result = array(); | $result = array(); | |||
if (function_exists('stream_get_wrappers')) | if (function_exists('stream_get_wrappers')) | |||
{ | { | |||
$wrappers = stream_get_wrappers(); | $wrappers = stream_get_wrappers(); | |||
foreach ($wrappers as $wrapper) | foreach ($wrappers as $wrapper) | |||
{ | { | |||
if ((($wrapper == 'zip') && class_exists('ZipArchive')) || | if ((($wrapper == 'zip') && class_exists('ZipArchive')) || | |||
(utf8_strpos($wrapper, 'compress.') === 0)) | (utf8_strpos($wrapper, 'compress.') === 0)) | |||
{ | { | |||
skipping to change at line 89 | skipping to change at line 92 | |||
if ($location_area == '') | if ($location_area == '') | |||
{ | { | |||
$sql = "SELECT COUNT(*) | $sql = "SELECT COUNT(*) | |||
FROM " . _tbl('room') . " | FROM " . _tbl('room') . " | |||
WHERE room_name=?"; | WHERE room_name=?"; | |||
$count = db()->query1($sql, array($location_room)); | $count = db()->query1($sql, array($location_room)); | |||
if ($count == 0) | if ($count == 0) | |||
{ | { | |||
$error = "'$location_room': " . get_vocab("room_does_not_exist_no_area"); | $error = "'$location_room': " . get_vocab("room_does_not_exist_no_area"); | |||
return FALSE; | return false; | |||
} | } | |||
elseif ($count > 1) | elseif ($count > 1) | |||
{ | { | |||
$error = "'$location_room': " . get_vocab("room_not_unique_no_area"); | $error = "'$location_room': " . get_vocab("room_not_unique_no_area"); | |||
return FALSE; | return false; | |||
} | } | |||
else // we've got a unique room name | else // we've got a unique room name | |||
{ | { | |||
$sql = "SELECT id | $sql = "SELECT id | |||
FROM " . _tbl('room') . " | FROM " . _tbl('room') . " | |||
WHERE room_name=? | WHERE room_name=? | |||
LIMIT 1"; | LIMIT 1"; | |||
$id = db()->query1($sql, array($location_room)); | $id = db()->query1($sql, array($location_room)); | |||
return $id; | return $id; | |||
} | } | |||
skipping to change at line 122 | skipping to change at line 125 | |||
FROM " . _tbl('area') . " | FROM " . _tbl('area') . " | |||
WHERE area_name=? | WHERE area_name=? | |||
LIMIT 1"; | LIMIT 1"; | |||
$area_id = db()->query1($sql, array($location_area)); | $area_id = db()->query1($sql, array($location_area)); | |||
if ($area_id < 0) | if ($area_id < 0) | |||
{ | { | |||
// The area does not exist - create it if we are allowed to | // The area does not exist - create it if we are allowed to | |||
if (!$area_room_create) | if (!$area_room_create) | |||
{ | { | |||
$error = get_vocab("area_does_not_exist") . " '$location_area'"; | $error = get_vocab("area_does_not_exist") . " '$location_area'"; | |||
return FALSE; | return false; | |||
} | } | |||
else | else | |||
{ | { | |||
echo get_vocab("creating_new_area") . " '$location_area'<br>\n"; | echo get_vocab("creating_new_area") . " '$location_area'<br>\n"; | |||
$error_add_area = ''; | $error_add_area = ''; | |||
$area_id = mrbsAddArea($location_area, $error_add_area); | $area_id = mrbsAddArea($location_area, $error_add_area); | |||
if ($area_id === FALSE) | if ($area_id === false) | |||
{ | { | |||
$error = get_vocab("could_not_create_area") . " '$location_area'"; | $error = get_vocab("could_not_create_area") . " '$location_area'"; | |||
return FALSE; | return false; | |||
} | } | |||
} | } | |||
} | } | |||
} | } | |||
// Now we've got the area_id get the room_id | // Now we've got the area_id get the room_id | |||
$sql = "SELECT id | $sql = "SELECT id | |||
FROM " . _tbl('room') . " | FROM " . _tbl('room') . " | |||
WHERE room_name=? | WHERE room_name=? | |||
AND area_id=? | AND area_id=? | |||
LIMIT 1"; | LIMIT 1"; | |||
$room_id = db()->query1($sql, array($location_room, $area_id)); | $room_id = db()->query1($sql, array($location_room, $area_id)); | |||
if ($room_id < 0) | if ($room_id < 0) | |||
{ | { | |||
// The room does not exist - create it if we are allowed to | // The room does not exist - create it if we are allowed to | |||
if (!$area_room_create) | if (!$area_room_create) | |||
{ | { | |||
$error = get_vocab("room_does_not_exist") . " '$location_room'"; | $error = get_vocab("room_does_not_exist") . " '$location_room'"; | |||
return FALSE; | return false; | |||
} | } | |||
else | else | |||
{ | { | |||
echo get_vocab("creating_new_room") . " '$location_room'<br>\n"; | echo get_vocab("creating_new_room") . " '$location_room'<br>\n"; | |||
$error_add_room = ''; | $error_add_room = ''; | |||
$room_id = mrbsAddRoom($location_room, $area_id, $error_add_room); | $room_id = mrbsAddRoom($location_room, $area_id, $error_add_room); | |||
if ($room_id === FALSE) | if ($room_id === false) | |||
{ | { | |||
$error = get_vocab("could_not_create_room") . " '$location_room'"; | $error = get_vocab("could_not_create_room") . " '$location_room'"; | |||
return FALSE; | return false; | |||
} | } | |||
} | } | |||
} | } | |||
return $room_id; | return $room_id; | |||
} | } | |||
// Get the next line, after unfolding, from the stream. | // Get the next line, after unfolding, from the stream. | |||
// Returns FALSE when EOF is reached | // Returns FALSE when EOF is reached | |||
function get_unfolded_line($handle) | function get_unfolded_line($handle) | |||
{ | { | |||
static $buffer_line; | static $buffer_line; | |||
// If there's something in the buffer line left over | // If there's something in the buffer line left over | |||
// from the last call, then start with that. | // from the last call, then start with that. | |||
if (isset($buffer_line)) | if (isset($buffer_line)) | |||
{ | { | |||
$unfolded_line = $buffer_line; | $unfolded_line = $buffer_line; | |||
$buffer_line = NULL; | $buffer_line = null; | |||
} | } | |||
// Theoretically the line should be folded if it's longer than 75 octets | // Theoretically the line should be folded if it's longer than 75 octets | |||
// but just in case the file has been created without using folding we | // but just in case the file has been created without using folding we | |||
// will read a large number (4096) of bytes to make sure that we get as | // will read a large number (4096) of bytes to make sure that we get as | |||
// far as the CRLF. | // far as the CRLF. | |||
while (FALSE !== ($line = stream_get_line($handle, 4096, "\r\n"))) | while (false !== ($line = stream_get_line($handle, 4096, "\r\n"))) | |||
{ | { | |||
if (!isset($unfolded_line)) | if (!isset($unfolded_line)) | |||
{ | { | |||
$unfolded_line = $line; | $unfolded_line = $line; | |||
} | } | |||
else | else | |||
{ | { | |||
$first_char = utf8_substr($line, 0, 1); | $first_char = utf8_substr($line, 0, 1); | |||
// If the first character of the line is a space or tab then it's | // If the first character of the line is a space or tab then it's | |||
// part of a fold | // part of a fold | |||
skipping to change at line 210 | skipping to change at line 213 | |||
// Otherwise we've reached the start of the next unfolded line, so | // Otherwise we've reached the start of the next unfolded line, so | |||
// save it for next time and finish | // save it for next time and finish | |||
else | else | |||
{ | { | |||
$buffer_line = $line; | $buffer_line = $line; | |||
break; | break; | |||
} | } | |||
} | } | |||
} | } | |||
return (isset($unfolded_line)) ? $unfolded_line : FALSE; | return (isset($unfolded_line)) ? $unfolded_line : false; | |||
} | } | |||
// Get the next event from the stream. | // Get the next event from the stream. | |||
// Returns FALSE if EOF has been reached, or else an array | // Returns FALSE if EOF has been reached, or else an array | |||
// of lines for the event. The BEGIN:VEVENT and END:VEVENT | // of lines for the event. The BEGIN:VEVENT and END:VEVENT | |||
// lines are not included in the array. | // lines are not included in the array. | |||
function get_event($handle) | function get_event($handle) | |||
{ | { | |||
// Advance to the beginning of the event | // Advance to the beginning of the event | |||
while ((FALSE !== ($ical_line = get_unfolded_line($handle))) && ($ical_line != 'BEGIN:VEVENT')) | while ((false !== ($ical_line = get_unfolded_line($handle))) && ($ical_line != 'BEGIN:VEVENT')) | |||
{ | { | |||
} | } | |||
// No more events | // No more events | |||
if ($ical_line === FALSE) | if ($ical_line === false) | |||
{ | { | |||
return FALSE; | return false; | |||
} | } | |||
// Get the event | // Get the event | |||
$vevent = array(); | $vevent = array(); | |||
while ((FALSE !== ($ical_line = get_unfolded_line($handle))) && ($ical_line != 'END:VEVENT')) | while ((false !== ($ical_line = get_unfolded_line($handle))) && ($ical_line != 'END:VEVENT')) | |||
{ | { | |||
$vevent[] = $ical_line; | $vevent[] = $ical_line; | |||
} | } | |||
return $vevent; | return $vevent; | |||
} | } | |||
// Add a VEVENT to MRBS. Returns TRUE on success, FALSE on failure | // Add a VEVENT to MRBS. Returns TRUE on success, FALSE if the event wasn't ad | |||
function process_event($vevent) | ded | |||
function process_event(array $vevent) | ||||
{ | { | |||
global $import_default_room, $import_default_type, $skip; | global $import_default_room, $import_default_type, $import_past, $skip; | |||
global $morningstarts, $morningstarts_minutes, $resolution; | global $morningstarts, $morningstarts_minutes, $resolution; | |||
global $booking_types; | global $booking_types; | |||
global $ignore_location, $add_location; | ||||
// We are going to cache the settings ($resolution etc.) for the rooms | // We are going to cache the settings ($resolution etc.) for the rooms | |||
// in order to avoid lots of database lookups | // in order to avoid lots of database lookups | |||
static $room_settings = array(); | static $room_settings = array(); | |||
// Set up the booking with some defaults | // Set up the booking with some defaults | |||
$booking = array(); | $booking = array(); | |||
$booking['awaiting_approval'] = false; | $booking['awaiting_approval'] = false; | |||
$booking['private'] = false; | $booking['private'] = false; | |||
$booking['tentative'] = false; | $booking['tentative'] = false; | |||
$booking['rep_type'] = REP_NONE; | $booking['rep_type'] = REP_NONE; | |||
$booking['type'] = $import_default_type; | $booking['type'] = $import_default_type; | |||
$booking['room_id'] = $import_default_room; | $booking['room_id'] = $import_default_room; | |||
// Parse all the lines first because we'll need to get the start date | // Parse all the lines first because we'll need to get the start date | |||
// for calculating some of the other settings | // for calculating some of the other settings | |||
$properties = array(); | $properties = array(); | |||
$problems = array(); | $problems = array(); | |||
$line = current($vevent); | $line = current($vevent); | |||
while ($line !== FALSE) | while ($line !== false) | |||
{ | { | |||
$property = parse_ical_property($line); | $property = parse_ical_property($line); | |||
// Ignore any sub-components (eg a VALARM inside a VEVENT) as MRBS does not | // Ignore any sub-components (eg a VALARM inside a VEVENT) as MRBS does not | |||
// yet handle things like reminders. Skip through to the end of the sub- | // yet handle things like reminders. Skip through to the end of the sub- | |||
// component. Just in case you can have sub-components at a greater depth | // component. Just in case you can have sub-components at a greater depth | |||
// than 1 (not sure if you can), make sure we've got to the matching END. | // than 1 (not sure if you can), make sure we've got to the matching END. | |||
if ($property['name'] != 'BEGIN') | if ($property['name'] != 'BEGIN') | |||
{ | { | |||
$properties[$property['name']] = array('params' => $property['params'], | $properties[$property['name']] = array('params' => $property['params'], | |||
'value' => $property['value']); | 'value' => $property['value']); | |||
skipping to change at line 317 | skipping to change at line 321 | |||
case 'SUMMARY': | case 'SUMMARY': | |||
$booking['name'] = $details['value']; | $booking['name'] = $details['value']; | |||
break; | break; | |||
case 'DESCRIPTION': | case 'DESCRIPTION': | |||
$booking['description'] = $details['value']; | $booking['description'] = $details['value']; | |||
break; | break; | |||
case 'LOCATION': | case 'LOCATION': | |||
$error = ''; | $location = $details['value']; // We may need the original LOCATION late | |||
$booking['room_id'] = get_room_id($details['value'], $error); | r | |||
if ($booking['room_id'] === FALSE) | if ($ignore_location) | |||
{ | { | |||
$problems[] = $error; | $booking['room_id'] = $import_default_room; | |||
} | ||||
else | ||||
{ | ||||
$error = ''; | ||||
$booking['room_id'] = get_room_id($location, $error); | ||||
if ($booking['room_id'] === false) | ||||
{ | ||||
$problems[] = $error; | ||||
} | ||||
} | } | |||
break; | break; | |||
case 'DTEND': | case 'DTEND': | |||
$booking['end_time'] = get_time($details['value'], $details['params']); | $booking['end_time'] = get_time($details['value'], $details['params']); | |||
break; | break; | |||
case 'DURATION': | case 'DURATION': | |||
trigger_error("DURATION not yet supported by MRBS", E_USER_WARNING); | trigger_error("DURATION not yet supported by MRBS", E_USER_WARNING); | |||
break; | break; | |||
case 'RRULE': | case 'RRULE': | |||
$rrule_errors = array(); | $rrule_errors = array(); | |||
$repeat_details = get_repeat_details($details['value'], $booking['start_ time'], $rrule_errors); | $repeat_details = get_repeat_details($details['value'], $booking['start_ time'], $rrule_errors); | |||
if ($repeat_details === FALSE) | if ($repeat_details === false) | |||
{ | { | |||
$problems = array_merge($problems, $rrule_errors); | $problems = array_merge($problems, $rrule_errors); | |||
} | } | |||
else | else | |||
{ | { | |||
foreach ($repeat_details as $key => $value) | foreach ($repeat_details as $key => $value) | |||
{ | { | |||
$booking[$key] = $value; | $booking[$key] = $value; | |||
} | } | |||
} | } | |||
skipping to change at line 386 | skipping to change at line 398 | |||
case 'LAST-MODIFIED': | case 'LAST-MODIFIED': | |||
// We probably ought to do something with LAST-MODIFIED and use it | // We probably ought to do something with LAST-MODIFIED and use it | |||
// for the timestamp field | // for the timestamp field | |||
break; | break; | |||
default: | default: | |||
break; | break; | |||
} | } | |||
} | } | |||
if (!$import_past && ($booking['end_time'] < time())) | ||||
{ | ||||
return false; | ||||
} | ||||
// If we didn't manage to work out a username then just put the booking | // If we didn't manage to work out a username then just put the booking | |||
// under the name of the current user | // under the name of the current user | |||
if (!isset($booking['create_by'])) | if (!isset($booking['create_by'])) | |||
{ | { | |||
$mrbs_user = session()->getCurrentUser(); | $mrbs_user = session()->getCurrentUser(); | |||
$mrbs_username = (isset($mrbs_user)) ? $mrbs_user->username : null; | $mrbs_username = (isset($mrbs_user)) ? $mrbs_user->username : null; | |||
$booking['create_by'] = $mrbs_username; | $booking['create_by'] = $mrbs_username; | |||
} | } | |||
// A SUMMARY is optional in RFC 5545, however a brief description is mandatory | ||||
// in MRBS. So if the VEVENT didn't include a name, we'll give it one | ||||
if (!isset($booking['name'])) | ||||
{ | ||||
$booking['name'] = "Imported event - no SUMMARY name"; | ||||
} | ||||
// On the other hand a UID is mandatory in RFC 5545. We'll be lenient and | // On the other hand a UID is mandatory in RFC 5545. We'll be lenient and | |||
// provide one if it is missing | // provide one if it is missing | |||
if (!isset($booking['ical_uid'])) | if (!isset($booking['ical_uid'])) | |||
{ | { | |||
$booking['ical_uid'] = generate_global_uid($booking['name']); | $booking['ical_uid'] = generate_global_uid($booking['name']); | |||
$booking['sequence'] = 0; // and we'll start the sequence from 0 | $booking['sequence'] = 0; // and we'll start the sequence from 0 | |||
} | } | |||
// Modify the brief and/or full descriptions | ||||
if (!empty($add_location) && isset($location) && ($location !== '')) | ||||
{ | ||||
// Brief description (SUMMARY) | ||||
if (in_array('summary', $add_location)) | ||||
{ | ||||
if (isset($booking['name']) && ($booking['name'] !== '')) | ||||
{ | ||||
$booking['name'] = get_vocab('expanded_name', | ||||
$booking['name'], | ||||
$location); | ||||
} | ||||
else | ||||
{ | ||||
$booking['name'] = get_vocab('expanded_empty_name', $location); | ||||
} | ||||
} | ||||
// Full description (DESCRIPTION) | ||||
if (in_array('description', $add_location)) | ||||
{ | ||||
if (isset($booking['description']) && ($booking['description'] !== '')) | ||||
{ | ||||
$booking['description'] = get_vocab('expanded_description', | ||||
$booking['description'], | ||||
$location); | ||||
} | ||||
else | ||||
{ | ||||
$booking['description'] = get_vocab('expanded_empty_description', $locat | ||||
ion); | ||||
} | ||||
} | ||||
} | ||||
// A SUMMARY is optional in RFC 5545, however a brief description is mandatory | ||||
// in MRBS. So if the VEVENT didn't include a name, we'll give it one | ||||
if (!isset($booking['name']) || ($booking['name']) === '') | ||||
{ | ||||
$tag = 'import_no_SUMMARY'; | ||||
$booking['name'] = get_vocab($tag); | ||||
// Throw an exception if it is still empty - probably because the vocab stri | ||||
ng has | ||||
// been overridden in the config file by an empty string. | ||||
if (!isset($booking['name']) || ($booking['name']) === '') | ||||
{ | ||||
throw new Exception("Vocab string for '$tag' is empty"); | ||||
} | ||||
} | ||||
// LOCATION is optional in RFC 5545 but is obviously mandatory in MRBS. | // LOCATION is optional in RFC 5545 but is obviously mandatory in MRBS. | |||
// If there is no LOCATION property we use the default_room specified on | // If there is no LOCATION property we use the default_room specified on | |||
// the form, but if there is no default room (most likely because no rooms | // the form, but if there is no default room (most likely because no rooms | |||
// have been created) then this error message is created). | // have been created) then this error message is created). | |||
if (!isset($booking['room_id'])) | if (!isset($booking['room_id'])) | |||
{ | { | |||
$problems[] = get_vocab("no_LOCATION"); | $problems[] = get_vocab("no_LOCATION"); | |||
} | } | |||
if (empty($problems)) | if (empty($problems)) | |||
skipping to change at line 445 | skipping to change at line 502 | |||
$room_settings[$booking['room_id']]['morningstarts_minutes'], | $room_settings[$booking['room_id']]['morningstarts_minutes'], | |||
0, $m, $d, $y); | 0, $m, $d, $y); | |||
$booking['start_time'] = round_t_down($booking['start_time'], | $booking['start_time'] = round_t_down($booking['start_time'], | |||
$room_settings[$booking['room_id']]['r esolution'], | $room_settings[$booking['room_id']]['r esolution'], | |||
$am7); | $am7); | |||
$booking['end_time'] = round_t_up($booking['end_time'], | $booking['end_time'] = round_t_up($booking['end_time'], | |||
$room_settings[$booking['room_id']]['resol ution'], | $room_settings[$booking['room_id']]['resol ution'], | |||
$am7); | $am7); | |||
// Make the bookings | // Make the bookings | |||
$bookings = array($booking); | $bookings = array($booking); | |||
$result = mrbsMakeBookings($bookings, NULL, FALSE, $skip); | $result = mrbsMakeBookings($bookings, null, false, $skip); | |||
if ($result['valid_booking']) | if ($result['valid_booking']) | |||
{ | { | |||
return TRUE; | return true; | |||
} | } | |||
} | } | |||
// There were problems - list them | // There were problems - list them | |||
echo "<div class=\"problem_report\">\n"; | echo "<div class=\"problem_report\">\n"; | |||
echo get_vocab("could_not_import") . " UID:" . htmlspecialchars($booking['ical _uid']); | echo htmlspecialchars(get_vocab("could_not_import", $booking['name'], $booking ['ical_uid'])); | |||
echo "<ul>\n"; | echo "<ul>\n"; | |||
foreach ($problems as $problem) | foreach ($problems as $problem) | |||
{ | { | |||
echo "<li>" . htmlspecialchars($problem) . "</li>\n"; | echo "<li>" . htmlspecialchars($problem) . "</li>\n"; | |||
} | } | |||
if (!empty($result['violations']['errors'])) | if (!empty($result['violations']['errors'])) | |||
{ | { | |||
echo "<li>" . get_vocab("rules_broken") . "\n"; | echo "<li>" . get_vocab("rules_broken") . "\n"; | |||
echo "<ul>\n"; | echo "<ul>\n"; | |||
foreach ($result['violations']['errors'] as $rule) | foreach ($result['violations']['errors'] as $rule) | |||
skipping to change at line 482 | skipping to change at line 539 | |||
echo "<ul>\n"; | echo "<ul>\n"; | |||
foreach ($result['conflicts'] as $conflict) | foreach ($result['conflicts'] as $conflict) | |||
{ | { | |||
echo "<li>$conflict</li>\n"; | echo "<li>$conflict</li>\n"; | |||
} | } | |||
echo "</ul></li>\n"; | echo "</ul></li>\n"; | |||
} | } | |||
echo "</ul>\n"; | echo "</ul>\n"; | |||
echo "</div>\n"; | echo "</div>\n"; | |||
return FALSE; | return false; | |||
} | ||||
function get_file_details_url($file) : array | ||||
{ | ||||
$files = array(); | ||||
list( , $tmp_name) = explode('://', $file, 2); | ||||
$files[] = array('name' => $file, | ||||
'tmp_name' => $tmp_name, | ||||
'size' => null); | ||||
return $files; | ||||
} | } | |||
function get_file_details_calendar($file) | function get_file_details_calendar($file) : array | |||
{ | { | |||
$files = array(); | $files = array(); | |||
$files[] = array('name' => $file['name'], | $files[] = array('name' => $file['name'], | |||
'tmp_name' => $file['tmp_name'], | 'tmp_name' => $file['tmp_name'], | |||
'size' => filesize($file['tmp_name'])); | 'size' => filesize($file['tmp_name'])); | |||
return $files; | return $files; | |||
} | } | |||
function get_file_details_bzip2($file) | function get_file_details_bzip2($file) : array | |||
{ | { | |||
// It's not possible to get the uncompressed size of a bzip2 file without firs t | // It's not possible to get the uncompressed size of a bzip2 file without firs t | |||
// decompressing the whole file | // decompressing the whole file | |||
$files = array(); | $files = array(); | |||
$files[] = array('name' => $file['name'], | $files[] = array('name' => $file['name'], | |||
'tmp_name' => $file['tmp_name'], | 'tmp_name' => $file['tmp_name'], | |||
'size' => NULL); | 'size' => null); | |||
return $files; | return $files; | |||
} | } | |||
function get_file_details_gzip($file) | function get_file_details_gzip($file) : array | |||
{ | { | |||
// Get the uncompressed size of the gzip file which is stored in the last four | // Get the uncompressed size of the gzip file which is stored in the last four | |||
// bytes of the file, little-endian | // bytes of the file, little-endian | |||
if (FALSE !== ($handle = fopen($file['tmp_name'], 'rb'))) | if (false !== ($handle = fopen($file['tmp_name'], 'rb'))) | |||
{ | { | |||
fseek($handle, -4, SEEK_END); | fseek($handle, -4, SEEK_END); | |||
$buffer = fread($handle, 4); | $buffer = fread($handle, 4); | |||
$size_array = unpack('V', $buffer); | $size_array = unpack('V', $buffer); | |||
$size = end($size_array); | $size = end($size_array); | |||
fclose($handle); | fclose($handle); | |||
} | } | |||
else | else | |||
{ | { | |||
$size = NULL; | $size = null; | |||
} | } | |||
$files = array(); | $files = array(); | |||
$files[] = array('name' => $file['name'], | $files[] = array('name' => $file['name'], | |||
'tmp_name' => $file['tmp_name'], | 'tmp_name' => $file['tmp_name'], | |||
'size' => $size); | 'size' => $size); | |||
return $files; | return $files; | |||
} | } | |||
function get_file_details_zip($file) | function get_file_details_zip($file) : array | |||
{ | { | |||
$files = array(); | $files = array(); | |||
if (class_exists('ZipArchive')) | if (class_exists('ZipArchive')) | |||
{ | { | |||
$zip = new ZipArchive(); | $zip = new ZipArchive(); | |||
if (TRUE === ($result = $zip->open($file['tmp_name']))) | if (true === ($result = $zip->open($file['tmp_name']))) | |||
{ | { | |||
for ($i=0; $i<$zip->numFiles; $i++) | for ($i=0; $i<$zip->numFiles; $i++) | |||
{ | { | |||
$details = array(); | $details = array(); | |||
$stats = $zip->statIndex($i); | $stats = $zip->statIndex($i); | |||
$details['name'] = $stats['name']; | $details['name'] = $stats['name']; | |||
$details['tmp_name'] = $file['tmp_name'] . '#' . $stats['name']; | $details['tmp_name'] = $file['tmp_name'] . '#' . $stats['name']; | |||
$details['size'] = $stats['size']; | $details['size'] = $stats['size']; | |||
$files[] = $details; | $files[] = $details; | |||
} | } | |||
skipping to change at line 595 | skipping to change at line 662 | |||
trigger_error($message, E_USER_WARNING); | trigger_error($message, E_USER_WARNING); | |||
} | } | |||
} | } | |||
else | else | |||
{ | { | |||
trigger_error("Could not open zip archive - the ZipArchive class does not ex ist on this system", E_USER_WARNING); | trigger_error("Could not open zip archive - the ZipArchive class does not ex ist on this system", E_USER_WARNING); | |||
} | } | |||
return $files; | return $files; | |||
} | } | |||
function get_archive_details($file) | function get_details($file) | |||
{ | { | |||
$result = array(); | $result = array(); | |||
switch ($file['type']) | ||||
if (is_string($file)) | ||||
{ | { | |||
case 'text/calendar': | list($result['wrapper']) = explode('://', $file, 2); | |||
case 'text/html': | $result['files'] = get_file_details_url($file); | |||
case 'text/plain': | ||||
case 'application/x-download': | ||||
$result['wrapper'] = 'file'; | ||||
$result['files'] = get_file_details_calendar($file); | ||||
break; | ||||
case 'application/x-bzip2': | ||||
$result['wrapper'] = 'compress.bzip2'; | ||||
$result['files'] = get_file_details_bzip2($file); | ||||
break; | ||||
case 'application/x-gzip': | ||||
$result['wrapper'] = 'compress.zlib'; | ||||
$result['files'] = get_file_details_gzip($file); | ||||
break; | ||||
case 'application/zip': | ||||
$result['wrapper'] = 'zip'; | ||||
$result['files'] = get_file_details_zip($file); | ||||
break; | ||||
default: | ||||
$result = FALSE; | ||||
trigger_error("Unknown file type '" . $file['type'] . "'", E_USER_NOTICE); | ||||
break; | ||||
} | } | |||
else | ||||
{ | ||||
switch ($file['type']) | ||||
{ | ||||
case 'text/calendar': | ||||
case 'text/html': | ||||
case 'text/plain': | ||||
case 'application/x-download': | ||||
$result['wrapper'] = 'file'; | ||||
$result['files'] = get_file_details_calendar($file); | ||||
break; | ||||
case 'application/x-bzip2': | ||||
$result['wrapper'] = 'compress.bzip2'; | ||||
$result['files'] = get_file_details_bzip2($file); | ||||
break; | ||||
case 'application/x-gzip': | ||||
$result['wrapper'] = 'compress.zlib'; | ||||
$result['files'] = get_file_details_gzip($file); | ||||
break; | ||||
case 'application/zip': | ||||
$result['wrapper'] = 'zip'; | ||||
$result['files'] = get_file_details_zip($file); | ||||
break; | ||||
default: | ||||
$result = false; | ||||
trigger_error("Unknown file type '" . $file['type'] . "'", E_USER_NOTICE | ||||
); | ||||
break; | ||||
} | ||||
} | ||||
return $result; | return $result; | |||
} | } | |||
function get_fieldset_location_settings() | function get_fieldset_source(array $compression_wrappers) : ElementFieldset | |||
{ | ||||
global $wrapper_mime_types; | ||||
global $source_type, $url; | ||||
$fieldset = new ElementFieldset(); | ||||
$fieldset->addLegend(get_vocab('source')); | ||||
// Source type | ||||
$field = new FieldInputRadioGroup(); | ||||
$options = array('file' => get_vocab('file'), | ||||
'url' => get_vocab('url')); | ||||
$field->setLabel(get_vocab('source_type')) | ||||
->addRadioOptions($options, 'source_type', $source_type, true); | ||||
$fieldset->addElement($field); | ||||
// File | ||||
$field = new FieldInputFile(); | ||||
$accept_mime_types = array(); | ||||
foreach ($compression_wrappers as $compression_wrapper) | ||||
{ | ||||
$accept_mime_types[] = $wrapper_mime_types[$compression_wrapper]; | ||||
} | ||||
// 'file' will always be available. Put it at the beginning of the array. | ||||
array_unshift($accept_mime_types, $wrapper_mime_types['file']); | ||||
$field->setLabel(get_vocab('file_name')) | ||||
->setAttribute('id', 'field_file') | ||||
->setControlAttributes(array( | ||||
'accept' => implode(',', $accept_mime_types), | ||||
'name' => 'upload_file', | ||||
'id' => 'upload_file') | ||||
); | ||||
$fieldset->addElement($field); | ||||
// URL | ||||
$field = new FieldInputUrl(); | ||||
$field->setLabel(get_vocab('url')) | ||||
->setAttribute('id', 'field_url') | ||||
->setControlAttributes(array( | ||||
'name' => 'url', | ||||
'id' => 'url', | ||||
'required' => true, | ||||
'value' => $url) | ||||
); | ||||
$fieldset->addElement($field); | ||||
return $fieldset; | ||||
} | ||||
function get_fieldset_location_parsing() : ElementFieldset | ||||
{ | { | |||
global $default_room; | ||||
global $area_room_order, $area_room_delimiter, $area_room_create; | global $area_room_order, $area_room_delimiter, $area_room_create; | |||
$fieldset = new ElementFieldset(); | $fieldset = new ElementFieldset(); | |||
$fieldset->setAttribute('id', 'location_parsing'); | ||||
// Area-room order | ||||
$field = new FieldInputRadioGroup(); | ||||
$options = array('area_room' => get_vocab('area_room'), | ||||
'room_area' => get_vocab('room_area')); | ||||
$field->setLabel(get_vocab('area_room_order')) | ||||
->setLabelAttribute('title', get_vocab('area_room_order_note')) | ||||
->addRadioOptions($options, 'area_room_order', $area_room_order, true); | ||||
$fieldset->addElement($field); | ||||
// Area-room delimiter | ||||
$field = new FieldInputText(); | ||||
$field->setLabel(get_vocab('area_room_delimiter')) | ||||
->setLabelAttribute('title', get_vocab('area_room_delimiter_note')) | ||||
->setControlAttributes(array('name' => 'area_room_delimiter', | ||||
'value' => $area_room_delimiter, | ||||
'class' => 'short', | ||||
'required' => true)); | ||||
$fieldset->addElement($field); | ||||
// Area/room create | ||||
$field =new FieldInputCheckbox(); | ||||
$field->setLabel(get_vocab('area_room_create')) | ||||
->setControlAttribute('name', 'area_room_create') | ||||
->setChecked($area_room_create); | ||||
$fieldset->addElement($field); | ||||
return $fieldset; | ||||
} | ||||
function get_fieldset_ignore_location_settings() : ElementFieldset | ||||
{ | ||||
global $add_location; | ||||
$fieldset = new ElementFieldset(); | ||||
$fieldset->setAttribute('id', 'ignore_location_settings'); | ||||
// Add the location to the brief and/or full description | ||||
$field =new FieldInputCheckboxGroup(); | ||||
$options = array( | ||||
'summary' => get_vocab('namebooker'), | ||||
'description' => get_vocab('fulldescription_short') | ||||
); | ||||
$field->setLabel(get_vocab('add_location')) | ||||
->setControlAttribute('name', 'add_location') | ||||
->addCheckboxOptions($options, 'add_location[]', $add_location); | ||||
$fieldset->addElement($field); | ||||
return $fieldset; | ||||
} | ||||
function get_fieldset_location_settings() : ElementFieldset | ||||
{ | ||||
global $default_room; | ||||
global $ignore_location; | ||||
$fieldset = new ElementFieldset(); | ||||
$fieldset->addLegend(get_vocab('area_room_settings')); | $fieldset->addLegend(get_vocab('area_room_settings')); | |||
// Default room | // Default room | |||
$areas = get_area_names($all=true); | $areas = get_area_names($all=true); | |||
if (count($areas) > 0) | if (count($areas) > 0) | |||
{ | { | |||
$options = array(); | $options = array(); | |||
foreach($areas as $area_id => $area_name) | foreach($areas as $area_id => $area_name) | |||
skipping to change at line 668 | skipping to change at line 855 | |||
$field->setLabel(get_vocab('default_room')) | $field->setLabel(get_vocab('default_room')) | |||
->setLabelAttribute('title', get_vocab('default_room_note')) | ->setLabelAttribute('title', get_vocab('default_room_note')) | |||
->setControlAttribute('name', 'import_default_room') | ->setControlAttribute('name', 'import_default_room') | |||
->addSelectOptions($options, $default_room, true); | ->addSelectOptions($options, $default_room, true); | |||
$fieldset->addElement($field); | $fieldset->addElement($field); | |||
} | } | |||
} | } | |||
// Area-room order | // Ignore location | |||
$field = new FieldInputRadioGroup(); | $field =new FieldInputCheckbox(); | |||
$options = array('area_room' => get_vocab('area_room'), | $field->setLabel(get_vocab('ignore_location')) | |||
'room_area' => get_vocab('room_area')); | ->setControlAttribute('name', 'ignore_location') | |||
$field->setLabel(get_vocab('area_room_order')) | ->setChecked($ignore_location); | |||
->setLabelAttribute('title', get_vocab('area_room_order_note')) | ||||
->addRadioOptions($options, 'area_room_order', $area_room_order, true); | ||||
$fieldset->addElement($field); | $fieldset->addElement($field); | |||
// Area-room delimiter | // Location parsing fieldset | |||
$field = new FieldInputText(); | $fieldset->addElement(get_fieldset_location_parsing()); | |||
$field->setLabel(get_vocab('area_room_delimiter')) | ||||
->setLabelAttribute('title', get_vocab('area_room_delimiter_note')) | ||||
->setControlAttributes(array('name' => 'area_room_delimiter', | ||||
'value' => $area_room_delimiter, | ||||
'class' => 'short', | ||||
'required' => true)); | ||||
$fieldset->addElement($field); | ||||
// Area/room create | // Settings when we are ignoring the location | |||
$field =new FieldInputCheckbox(); | $fieldset->addElement(get_fieldset_ignore_location_settings()); | |||
$field->setLabel(get_vocab('area_room_create')) | ||||
->setControlAttribute('name', 'area_room_create') | ||||
->setChecked($area_room_create); | ||||
$fieldset->addElement($field); | ||||
return $fieldset; | return $fieldset; | |||
} | } | |||
function get_fieldset_other_settings() | function get_fieldset_other_settings() : ElementFieldset | |||
{ | { | |||
global $booking_types; | global $booking_types; | |||
global $import_default_type, $skip; | global $import_default_type, $import_past, $skip; | |||
$fieldset = new ElementFieldset(); | $fieldset = new ElementFieldset(); | |||
$fieldset->addLegend(get_vocab('other_settings')); | $fieldset->addLegend(get_vocab('other_settings')); | |||
// Default type | // Default type | |||
$field = new FieldSelect(); | $field = new FieldSelect(); | |||
$options = array(); | $options = array(); | |||
foreach ($booking_types as $type) | foreach ($booking_types as $type) | |||
{ | { | |||
$options[$type] = get_type_vocab($type); | $options[$type] = get_type_vocab($type); | |||
} | } | |||
$field->setLabel(get_vocab('default_type')) | $field->setLabel(get_vocab('default_type')) | |||
->setControlAttribute('name', 'import_default_type') | ->setControlAttribute('name', 'import_default_type') | |||
->addSelectOptions($options, $import_default_type, true); | ->addSelectOptions($options, $import_default_type, true); | |||
$fieldset->addElement($field); | $fieldset->addElement($field); | |||
// Import past bookings | ||||
// Add a hidden element so that if the checkbox is not checked we | ||||
// get 0 instead of NULL passed to the server and so the default | ||||
// can be used. | ||||
// TODO: need a better way of doing this | ||||
$hidden = new ElementInputHidden(); | ||||
$hidden->setAttributes(array( | ||||
'name' => 'import_past', | ||||
'value' => 0 | ||||
)); | ||||
$fieldset->addElement($hidden); | ||||
$field = new FieldInputCheckbox(); | ||||
$field->setLabel(get_vocab('import_past')) | ||||
->setControlAttribute('name', 'import_past') | ||||
->setChecked($import_past); | ||||
$fieldset->addElement($field); | ||||
// Skip conflicts | // Skip conflicts | |||
$field =new FieldInputCheckbox(); | // Add a hidden element (see comment above) | |||
$hidden = new ElementInputHidden(); | ||||
$hidden->setAttributes(array( | ||||
'name' => 'skip', | ||||
'value' => 0 | ||||
)); | ||||
$fieldset->addElement($hidden); | ||||
$field = new FieldInputCheckbox(); | ||||
$field->setLabel(get_vocab('skip_conflicts')) | $field->setLabel(get_vocab('skip_conflicts')) | |||
->setControlAttribute('name', 'skip') | ->setControlAttribute('name', 'skip') | |||
->setChecked($skip); | ->setChecked($skip); | |||
$fieldset->addElement($field); | $fieldset->addElement($field); | |||
return $fieldset; | return $fieldset; | |||
} | } | |||
function get_fieldset_submit_button() | function get_fieldset_submit_button() : ElementFieldset | |||
{ | { | |||
$fieldset = new ElementFieldset(); | $fieldset = new ElementFieldset(); | |||
// The Submit button | // The Submit button | |||
$field = new FieldInputSubmit(); | $field = new FieldInputSubmit(); | |||
$field->setControlAttributes(array('name' => 'import', | $field->setControlAttributes(array('name' => 'import', | |||
'value' => get_vocab('import'))); | 'value' => get_vocab('import'))); | |||
$fieldset->addElement($field); | $fieldset->addElement($field); | |||
return $fieldset; | return $fieldset; | |||
} | } | |||
$import = get_form_var('import', 'string'); | $import = get_form_var('import', 'string'); | |||
$source_type = get_form_var('source_type', 'string', $default_import_source); | ||||
$url = get_form_var('url', 'string'); | ||||
$import_default_room = get_form_var('import_default_room', 'int'); | $import_default_room = get_form_var('import_default_room', 'int'); | |||
$ignore_location = get_form_var('ignore_location', 'string', '0'); | ||||
$add_location = get_form_var('add_location', 'array'); | ||||
$area_room_order = get_form_var('area_room_order', 'string', 'area_room'); | $area_room_order = get_form_var('area_room_order', 'string', 'area_room'); | |||
$area_room_delimiter = get_form_var('area_room_delimiter', 'string', $default_ar ea_room_delimiter); | $area_room_delimiter = get_form_var('area_room_delimiter', 'string', $default_ar ea_room_delimiter); | |||
$area_room_create = get_form_var('area_room_create', 'string', '0'); | $area_room_create = get_form_var('area_room_create', 'string', '0'); | |||
$import_default_type = get_form_var('import_default_type', 'string', $default_ty pe); | $import_default_type = get_form_var('import_default_type', 'string', $default_ty pe); | |||
$import_past = get_form_var('import_past', 'string', ((empty($default_import_pas t)) ? '0' : '1')); | ||||
$skip = get_form_var('skip', 'string', ((empty($skip_default)) ? '0' : '1')); | $skip = get_form_var('skip', 'string', ((empty($skip_default)) ? '0' : '1')); | |||
// Check the CSRF token if we're being asked to import data | // Check the CSRF token if we're being asked to import data | |||
if (!empty($import)) | if (!empty($import)) | |||
{ | { | |||
Form::checkToken(); | Form::checkToken(); | |||
} | } | |||
// Check the user is authorised for this page | // Check the user is authorised for this page | |||
checkAuthorised(this_page()); | checkAuthorised(this_page()); | |||
skipping to change at line 777 | skipping to change at line 980 | |||
'room' => isset($room) ? $room : null | 'room' => isset($room) ? $room : null | |||
); | ); | |||
print_header($context); | print_header($context); | |||
// PHASE 2 - Process the files | // PHASE 2 - Process the files | |||
// --------------------------- | // --------------------------- | |||
if (!empty($import)) | if (!empty($import)) | |||
{ | { | |||
if ($_FILES['upload_file']['error'] !== UPLOAD_ERR_OK) | if ($source_type == 'url') | |||
{ | { | |||
echo "<p>\n"; | if (!isset($url) || !filter_var($url, FILTER_VALIDATE_URL)) | |||
echo get_vocab("upload_failed"); | { | |||
switch($_FILES['upload_file']['error']) | echo "<p>\n"; | |||
{ | echo get_vocab("invalid_url"); | |||
case UPLOAD_ERR_INI_SIZE: | echo "</p>\n"; | |||
echo "<br>\n"; | } | |||
echo get_vocab("max_allowed_file_size") . " " . ini_get('upload_max_file | else | |||
size'); | { | |||
break; | $details = get_details($url); | |||
case UPLOAD_ERR_NO_FILE: | ||||
echo "<br>\n"; | ||||
echo get_vocab("no_file"); | ||||
break; | ||||
default: | ||||
// None of the other possible errors would make much sense to the user, | ||||
but should be reported | ||||
trigger_error($_FILES['upload_file']['error'], E_USER_NOTICE); | ||||
break; | ||||
} | } | |||
echo "</p>\n"; | ||||
} | ||||
elseif (!is_uploaded_file($_FILES['upload_file']['tmp_name'])) | ||||
{ | ||||
// This should not happen and if it does may mean that somebody is messing a | ||||
bout | ||||
echo "<p>\n"; | ||||
echo get_vocab("upload_failed"); | ||||
echo "</p>\n"; | ||||
trigger_error("Attempt to import a file that has not been uploaded", E_USER_ | ||||
WARNING); | ||||
} | } | |||
// We've got a file | ||||
else | else | |||
{ | { | |||
$archive = get_archive_details($_FILES['upload_file']); | if ($_FILES['upload_file']['error'] !== UPLOAD_ERR_OK) | |||
{ | ||||
echo "<p>\n"; | ||||
echo get_vocab("upload_failed"); | ||||
switch ($_FILES['upload_file']['error']) | ||||
{ | ||||
case UPLOAD_ERR_INI_SIZE: | ||||
echo "<br>\n"; | ||||
echo get_vocab("max_allowed_file_size") . " " . ini_get('upload_max_fi | ||||
lesize'); | ||||
break; | ||||
case UPLOAD_ERR_NO_FILE: | ||||
echo "<br>\n"; | ||||
echo get_vocab("no_file"); | ||||
break; | ||||
default: | ||||
// None of the other possible errors would make much sense to the user | ||||
, but should be reported | ||||
trigger_error($_FILES['upload_file']['error'], E_USER_NOTICE); | ||||
break; | ||||
} | ||||
echo "</p>\n"; | ||||
} | ||||
elseif (!is_uploaded_file($_FILES['upload_file']['tmp_name'])) | ||||
{ | ||||
// This should not happen and if it does may mean that somebody is messing | ||||
about | ||||
echo "<p>\n"; | ||||
echo get_vocab("upload_failed"); | ||||
echo "</p>\n"; | ||||
trigger_error("Attempt to import a file that has not been uploaded", E_USE | ||||
R_WARNING); | ||||
} | ||||
else | ||||
{ | ||||
// We've got a file | ||||
$details = get_details($_FILES['upload_file']); | ||||
} | ||||
} | ||||
if ($archive === FALSE) | if (isset($details)) | |||
{ | ||||
if ($details === false) | ||||
{ | { | |||
echo "<p>" . get_vocab("could_not_process") . "</p>\n"; | echo "<p>" . get_vocab("could_not_process") . "</p>\n"; | |||
} | } | |||
else | else | |||
{ | { | |||
foreach ($archive['files'] as $file) | foreach ($details['files'] as $file) | |||
{ | { | |||
echo "<h3>" . $file['name'] . "</h3>"; | echo "<h3>" . $file['name'] . "</h3>"; | |||
$n_success = 0; | $n_success = 0; | |||
$n_failure = 0; | $n_failure = 0; | |||
$handle = fopen($archive['wrapper'] . '://' . $file['tmp_name'], 'rb'); | $handle = fopen($details['wrapper'] . '://' . $file['tmp_name'], 'rb'); | |||
if ($handle === FALSE) | if ($handle === false) | |||
{ | { | |||
echo "<p>" . get_vocab("could_not_process") . "</p>\n"; | echo "<p>" . get_vocab("could_not_process") . "</p>\n"; | |||
} | } | |||
else | else | |||
{ | { | |||
while (FALSE !== ($vevent = get_event($handle))) | while (false !== ($vevent = get_event($handle))) | |||
{ | { | |||
(process_event($vevent)) ? $n_success++ : $n_failure++; | (process_event($vevent)) ? $n_success++ : $n_failure++; | |||
} | } | |||
fclose($handle); | fclose($handle); | |||
echo "<p>\n"; | echo "<p>\n"; | |||
echo "$n_success " . get_vocab("events_imported"); | echo "$n_success " . get_vocab("events_imported"); | |||
if ($n_failure > 0) | if ($n_failure > 0) | |||
{ | { | |||
skipping to change at line 878 | skipping to change at line 1100 | |||
$form = new Form(); | $form = new Form(); | |||
$form->setAttributes(array('class' => 'standard', | $form->setAttributes(array('class' => 'standard', | |||
'method' => 'post', | 'method' => 'post', | |||
'enctype' => 'multipart/form-data', | 'enctype' => 'multipart/form-data', | |||
'action' => multisite(this_page()))); | 'action' => multisite(this_page()))); | |||
$fieldset = new ElementFieldset(); | $fieldset = new ElementFieldset(); | |||
// The file | $fieldset->addElement(get_fieldset_source($compression_wrappers)) | |||
$field = new FieldInputFile(); | ||||
$accept_mime_types = array(); | ||||
foreach ($compression_wrappers as $compression_wrapper) | ||||
{ | ||||
$accept_mime_types[] = $wrapper_mime_types[$compression_wrapper]; | ||||
} | ||||
// 'file' will always be available. Put it at the beginning of the array. | ||||
array_unshift($accept_mime_types, $wrapper_mime_types['file']); | ||||
$field->setLabel(get_vocab('file_name')) | ||||
->setControlAttributes(array('accept' => implode(',', $accept_mime_types), | ||||
'name' => 'upload_file', | ||||
'id' => 'upload_file')); | ||||
$fieldset->addElement($field) | ||||
->addElement(get_fieldset_location_settings()) | ->addElement(get_fieldset_location_settings()) | |||
->addElement(get_fieldset_other_settings()) | ->addElement(get_fieldset_other_settings()) | |||
->addElement(get_fieldset_submit_button()); | ->addElement(get_fieldset_submit_button()); | |||
$form->addElement($fieldset); | $form->addElement($fieldset); | |||
$form->render(); | $form->render(); | |||
print_footer(); | print_footer(); | |||
End of changes. 69 change blocks. | ||||
151 lines changed or deleted | 362 lines changed or added |