// Validation
if ( isset($_POST[array_shift($real_requireds)]) ) {
- $adherent['dyn'] = $dyn_fields->extractPosted($_POST, $disabled);
+ $adherent['dyn'] = $dyn_fields->extractPosted($_POST, $_FILES, $disabled, $member->id);
+ $dyn_fields_errors = $dyn_fields->getErrors();
+ if ( count($dyn_fields_errors) > 0 ) {
+ $error_detected = array_merge($error_detected, $dyn_fields_errors);
+ }
+ // regular fields
$valid = $member->check($_POST, $required, $disabled);
- if ( $valid === true ) {
+ if ( $valid !== true ) {
+ $error_detected = array_merge($error_detected, $valid);
+ }
+
+ if ( count($error_detected ) == 0) {
//all goes well, we can proceed
$new = false;
//something went wrong :'(
$error_detected[] = _T("An error occured while storing the member.");
}
- } else {
- //hum... there are errors :'(
- $error_detected = $valid;
}
if ( count($error_detected) == 0 ) {
// Validation
$contribution['dyn'] = array();
if ( isset($_POST['valid']) ) {
- $contribution['dyn'] = $dyn_fields->extractPosted($_POST, array());
-
+ // dynamic fields
+ $contribution['dyn'] = $dyn_fields->extractPosted($_POST, $_FILES, array(), $id_adh);
+ $dyn_fields_errors = $dyn_fields->get_errors();
+ if ( $count($dyn_fields_errors) > 0 ) {
+ $error_detected = array_merge($error_detected, $dyn_fields_errors);
+ }
+ // regular fields
$valid = $contrib->check($_POST, $required, $disabled);
- if ( $valid === true ) {
+ if ( $valid !== true ) {
+ $error_detected = array_merge($error_detected, $valid);
+ }
+
+ if ( count($error_detected ) == 0) {
//all goes well, we can proceed
if ( $contrib->isCotis() ) {
// Check that membership fees does not overlap
$error_detected[] = _T("An error occured while storing the contribution.");
}
}
- } else {
- //hum... there are errors :'(
- $error_detected = $valid;
}
if ( count($error_detected) == 0 ) {
$transaction['dyn'] = array();
if ( isset($_POST['valid']) ) {
- $transaction['dyn'] = $dyn_fields->extractPosted($_POST, array());
-
+ // dynamic fields
+ $transaction['dyn'] = $dyn_fields->extractPosted($_POST, $_FILES, array(), $id_adh);
+ $dyn_fields_errors = $dyn_fields->get_errors();
+ if ( $count($dyn_fields_errors) > 0 ) {
+ $error_detected = array_merge($error_detected, $dyn_fields_errors);
+ }
+ // regular fields
$valid = $trans->check($_POST, $required, $disabled);
- if ( $valid === true ) {
+ if ( $valid !== true ) {
+ $error_detected = array_merge($error_detected, $valid);
+ }
+
+ if ( count($error_detected ) == 0) {
//all goes well, we can proceed
$new = false;
if ( $trans->id == '' ) {
if ( !defined('GALETTE_ATTACHMENTS_PATH') ) {
define('GALETTE_ATTACHMENTS_PATH', GALETTE_ROOT . 'attachments/');
}
+if ( !defined('GALETTE_FILES_PATH') ) {
+ define('GALETTE_FILES_PATH', GALETTE_ROOT . 'files/');
+}
if ( !defined('GALETTE_TEMPIMAGES_PATH') ) {
define('GALETTE_TEMPIMAGES_PATH', GALETTE_ROOT . 'tempimages/');
}
--- /dev/null
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Get an exported file
+ *
+ * PHP version 5
+ *
+ * Copyright © 2013-2014 The Galette Team
+ *
+ * This file is part of Galette (http://galette.tuxfamily.org).
+ *
+ * Galette is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Galette is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Galette. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Main
+ * @package Galette
+ *
+ * @author Guillaume Rousse <guillomovitch@gmail.com>
+ * @copyright 2013-2014 The Galette Team
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
+ * @version SVN: $Id$
+ * @link http://galette.tuxfamily.org
+ * @since Available since 0.7dev - 2013-07-27
+ */
+
+use Analog\Analog as Analog;
+
+/** @ignore */
+require_once 'includes/galette.inc.php';
+
+if ( !isset($_GET['file']) ) {
+ Analog::log(
+ 'No requested file',
+ Analog::INFO
+ );
+ header("HTTP/1.1 500 Internal Server Error");
+ die();
+}
+
+$file = $_GET['file'];
+$name = $_GET['name'];
+
+//Exports main contain user confidential data, they're accessible only for
+//admins or staff members
+if ( $login->isAdmin() || $login->isStaff() ) {
+
+ if (file_exists(GALETTE_FILES_PATH . $file) ) {
+ // try to identify MIME type
+ if (function_exists("finfo_open")) {
+ // require PECL fileinfo
+ $finfo = finfo_open(FILEINFO_MIME_TYPE);
+ $type = finfo_file($finfo, $file);
+ } else {
+ // deprecated
+ $type = mime_content_type($file);
+ }
+ header('Content-Type: ' . $type);
+ header('Content-Disposition: attachment; filename="' . $name . '";');
+ header('Pragma: no-cache');
+ readfile(GALETTE_FILES_PATH . $file);
+ } else {
+ Analog::log(
+ 'A request has been made to get an exported file named `' .
+ $file .'` that does not exists.',
+ Analog::WARNING
+ );
+ header('HTTP/1.0 404 Not Found');
+ }
+} else {
+ Analog::log(
+ 'A non authorized person asked to retrieve exported file named `' .
+ $file . '`. Access has not been granted.',
+ Analog::WARNING
+ );
+ header('HTTP/1.0 403 Forbidden');
+}
_T("Exports") => GALETTE_EXPORTS_PATH,
_T("Imports") => GALETTE_IMPORTS_PATH,
_T("Logs") => GALETTE_LOGS_PATH,
- _T("Attachments") => GALETTE_ATTACHMENTS_PATH
+ _T("Attachments") => GALETTE_ATTACHMENTS_PATH,
+ _T("Files") => GALETTE_FILES_PATH
);
$files_perms_class = $class . 'ok';
--- /dev/null
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * File field type
+ *
+ * PHP version 5
+ *
+ * Copyright © 2013-2014 The Galette Team
+ *
+ * This file is part of Galette (http://galette.tuxfamily.org).
+ *
+ * Galette is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Galette is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Galette. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category DynamicFields
+ * @package Galette
+ *
+ * @author Guillaume Rousse <guillomovitch@gmail.com>
+ * @copyright 2013-2014 The Galette Team
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
+ * @version SVN: $Id$
+ * @link http://galette.tuxfamily.org
+ * @since Available since 0.8 - 2013-07-27
+ */
+
+namespace Galette\DynamicFieldsTypes;
+
+use Analog\Analog as Analog;
+
+/**
+ * File field type
+ *
+ * @name File
+ * @category DynamicFields
+ * @package Galette
+ *
+ * @author Guillaume Rousse <guillomovitch@gmail.com>
+ * @copyright 2013-2014 The Galette Team
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
+ * @link http://galette.tuxfamily.org
+ */
+
+class File extends DynamicFieldType
+{
+ /**
+ * Default constructor
+ *
+ * @param int $id Optionnal field id to load data
+ */
+ public function __construct($id = null)
+ {
+ parent::__construct($id);
+ $this->has_data = true;
+ $this->has_size = true;
+ }
+
+ /**
+ * Get field type name
+ *
+ * @return String
+ */
+ public function getTypeName()
+ {
+ return _T("file");
+ }
+
+ /**
+ * Load field
+ *
+ * @return void
+ */
+ public function load()
+ {
+ parent::load();
+ $this->repeat = 1;
+ }
+}
use Galette\DynamicFieldsTypes\Choice as Choice;
use Galette\DynamicFieldsTypes\Date as Date;
use Galette\DynamicFieldsTypes\Boolean as Boolean;
+use Galette\DynamicFieldsTypes\File as File;
use Galette\DynamicFieldsTypes\DynamicFieldType as DynamicFieldType;
/**
const DATE = 4;
/** Boolean field (checkbox) */
const BOOLEAN = 5;
+ /** File field (upload) */
+ const FILE = 6;
const PERM_ALL = 0;
const PERM_STAFF = 2;
const PERM_ADM = 1;
+ const DEFAULT_MAX_FILE_SIZE = 1024;
+
private $_id;
private $_index;
private $_name;
private $_perms_names;
private $_forms_names;
+ private $_errors = array();
+
/**
* Default constructor
*
self::LINE => _T("single line"),
self::CHOICE => _T("choice"),
self::DATE => _T("date"),
- self::BOOLEAN => _T("boolean")
+ self::BOOLEAN => _T("boolean"),
+ self::FILE => _T("file")
);
//Permissions names
|| (int)$r['field_type'] === self::TEXT
|| (int)$r['field_type'] === self::DATE
|| (int)$r['field_type'] === self::BOOLEAN
+ || (int)$r['field_type'] === self::FILE
) {
$r['field_repeat'] = 1;
}
* Extract posted values for dynamic fields
*
* @param array $post Array containing the posted values
+ * @param array $files Array containing the posted files
* @param array $disabled Array with fields that are discarded as key
*
* @return array
*/
- public function extractPosted($post, $disabled)
+ public function extractPosted($post, $files, $disabled, $member_id)
{
if ( $post != null ) {
$dfields = array();
if ( is_numeric($field_id)
&& is_numeric($val_index)
) {
- $dfields[$field_id][$val_index] = $value;
+ if ((int) $descriptions[$field_id]['field_type'] == self::FILE) {
+ # delete checkbox
+ $filename = sprintf(
+ 'member_%d_field_%d_value_%d',
+ $member_id,
+ $field_id,
+ $val_index
+ );
+ unlink(GALETTE_FILES_PATH . $filename);
+ $dfields[$field_id][$val_index] = '';
+ } else {
+ # actual field value
+ $dfields[$field_id][$val_index] = $value;
+ }
}
}
}
}
+
+ while ( list($key, $value) = each($files) ) {
+ // if the field is disabled, skip it
+ if (isset($disabled[$key]) ) {
+ continue;
+ }
+
+ if (substr($key, 0, 11) != 'info_field_') {
+ continue;
+ }
+
+ list($field_id, $val_index) = explode('_', substr($key, 11));
+ if (! is_numeric($field_id) || ! is_numeric($val_index)) {
+ continue;
+ }
+
+ if ($files[$key]['error'] !== UPLOAD_ERR_OK ) {
+ Analog::log("file upload error", Analog::ERROR);
+ continue;
+ }
+
+ $tmp_filename = $files[$key]['tmp_name'];
+ if ( $tmp_filename == '' ) {
+ Analog::log("empty temporary filename", Analog::ERROR);
+ continue;
+ }
+
+ if (! is_uploaded_file($tmp_filename) ) {
+ Analog::log("not an uploaded file", Analog::ERROR);
+ continue;
+ }
+
+ $max_size =
+ $descriptions[$field_id]['field_size'] === 'NULL' ?
+ self::DEFAULT_MAX_FILE_SIZE * 1024:
+ $descriptions[$field_id]['field_size'] * 1024;
+ if ($files[$key]['size'] > $max_size ) {
+ Analog::log(
+ "file too large: " . $files[$key]['size'] . " Ko, vs $max_size Ko allowed",
+ Analog::ERROR
+ );
+ $this->_errors[] = preg_replace(
+ '|%d|',
+ $max_size,
+ _T("File is too big. Maximum allowed size is %dKo")
+ );
+ continue;
+ }
+
+ $new_filename = sprintf(
+ 'member_%d_field_%d_value_%d',
+ $member_id,
+ $field_id,
+ $val_index
+ );
+ Analog::log("new file: $new_filename", Analog::DEBUG);
+
+ move_uploaded_file(
+ $tmp_filename,
+ GALETTE_FILES_PATH . $new_filename
+ );
+ $dfields[$field_id][$val_index] = $files[$key]['name'];
+ }
+
return $dfields;
}
}
case self::BOOLEAN:
$df = new \Galette\DynamicFieldsTypes\Boolean($id);
break;
+ case self::FILE:
+ $df = new \Galette\DynamicFieldsTypes\File($id);
+ break;
default:
throw new \Exception('Unknow field type ' . $t . '!');
break;
}
return $duplicated;
}
+
+ /**
+ * Get errors
+ *
+ * @return array
+ */
+ public function getErrors()
+ {
+ return $this->_errors;
+ }
}
$fields = Adherent::getDbFields();
-// checking posted values for 'regular' fields
if ( isset($_POST["nom_adh"]) ) {
- $adherent['dyn'] = $dyn_fields->extractPosted($_POST, $disabled);
+ // dynamic fields
+ $adherent['dyn'] = $dyn_fields->extractPosted($_POST, $_FILES, $disabled, $member->id);
+ $dyn_fields_errors = $dyn_fields->get_errors();
+ if ( $count($dyn_fields_errors) > 0 ) {
+ $error_detected = array_merge($error_detected, $dyn_fields_errors);
+ }
+ // regular fields
$valid = $member->check($_POST, $required, $disabled);
- if ( $valid === true ) {
+ if ( $valid !== true ) {
+ $error_detected = array_merge($error_detected, $valid);
+ }
+
+ if ( count($error_detected ) == 0) {
//all goes well, we can proceed
$store = $member->store();
if ( $store === true ) {
//something went wrong :'(
$error_detected[] = _T("An error occured while storing the member.");
}
- } else {
- //hum... there are errors :'(
- $error_detected = $valid;
}
} elseif ( isset($_POST["update_lang"]) && $_POST["update_lang"] == 1 ) {
while ( list($key, $properties) = each($fields) ) {
{if $smarty.section.fieldLoop.index_prev > 0}<br />{/if}
<a href="{$data.dyn[$field.field_id][$smarty.section.fieldLoop.index]}" target="_blank" title="{_T string="Open '%s' in a new window" replace=$data.dyn[$field.field_id][$smarty.section.fieldLoop.index] pattern="/%s/"}">{$data.dyn[$field.field_id][$smarty.section.fieldLoop.index]}</a>
{else if isset($data.dyn[$field.field_id][$smarty.section.fieldLoop.index]) and $field.field_type eq 5}
- {if $data.dyn[$field.field_id][$smarty.section.fieldLoop.index]}
- {_T string="Yes"}
- {else}
- {_T string="No"}
- {/if}
- <br/>
+ {if $data.dyn[$field.field_id][$smarty.section.fieldLoop.index]}
+ {_T string="Yes"}
+ {else}
+ {_T string="No"}
+ {/if}
+ <br/>
+ {else if isset($data.dyn[$field.field_id][$smarty.section.fieldLoop.index]) and $field.field_type eq 6}
+ <a href="get_file.php?file=member_{$member->id}_field_{$field.field_id}_value_{$smarty.section.fieldLoop.index}&name={$data.dyn[$field.field_id][$smarty.section.fieldLoop.index]}">{$data.dyn[$field.field_id][$smarty.section.fieldLoop.index]}</a><br/>
{else}
{$data.dyn[$field.field_id][$smarty.section.fieldLoop.index]|nl2br|default:" "}<br/>
{/if}
{if isset($disabled.dyn[$field.field_id])} {$disabled.dyn[$field.field_id]}{/if}
{if $field.field_required eq 1} required{/if}
/>
+ {elseif $field.field_type eq 6}
+ {_T string="new"}: <input type="file" name="info_field_{$field.field_id}_{$smarty.section.fieldLoop.index}" id="info_field_{$field.field_id}_{$smarty.section.fieldLoop.index}_{$count}_new"
+ {if isset($disabled.dyn[$field.field_id])} {$disabled.dyn[$field.field_id]}{/if}
+ {if $field.field_required eq 1} required{/if}
+ />
+ {_T string="current"}: <input type="text" name="info_field_{$field.field_id}_{$smarty.section.fieldLoop.index}" id="info_field_{$field.field_id}_{$smarty.section.fieldLoop.index}_{$count}_current" disabled
+ value="{if isset($data.dyn[$field.field_id][$smarty.section.fieldLoop.index])}{$data.dyn[$field.field_id][$smarty.section.fieldLoop.index]|escape}{/if}"
+ />
+ {_T string="delete"}: <input type="checkbox" name="info_field_{$field.field_id}_{$smarty.section.fieldLoop.index}" id="info_field_{$field.field_id}_{$smarty.section.fieldLoop.index}_{$count}_delete"
+ {if !$data.dyn[$field.field_id][$smarty.section.fieldLoop.index]}disabled{/if}
+ onclick="this.form.info_field_{$field.field_id}_{$smarty.section.fieldLoop.index}_{$count}_new.disabled = this.checked;"
+ />
{/if}
{/section}
</p>
<p>
<label for="field_size" class="bline">{_T string="Size:"}</label>
<input type="text" name="field_size" id="field_size" value="{$df->getSize()}" size="3"/>
+ {if $df instanceof 'Galette\DynamicFieldsTypes\File'}
+ <span class="exemple">{_T string="Maximum file size, in Ko."}</span>
+ {else}
<span class="exemple">{_T string="Maximum number of characters."}</span>
+ {/if}
</p>
{/if}
{if $df->isMultiValued()}