Subversion Repositories eFlore/Applications.cel

Compare Revisions

No changes between revisions

Regard whitespace Rev 1913 → Rev 1914

/branches/v1.7-croissant/vendors/PHPExcel/issue-79.patch
New file
0,0 → 1,13
Index: Classes/PHPExcel/Worksheet.php
===================================================================
--- Classes/PHPExcel/Worksheet.php (révision 1547)
+++ Classes/PHPExcel/Worksheet.php (copie de travail)
@@ -431,7 +431,7 @@
}
// Maximum 31 characters allowed for sheet title
- if (PHPExcel_Shared_String::CountCharacters($pValue) > 31) {
+ if (PHPExcel_Shared_String::CountCharacters($pValue) > 131) {
throw new PHPExcel_Exception('Maximum 31 characters allowed in sheet title.');
}
/branches/v1.7-croissant/vendors/PHPExcel/f44b41242023265192efa5d4dd1dbf1dcb0d7cd1.diff
New file
0,0 → 1,48
diff --git a/Classes/PHPExcel/Reader/CSV.php b/Classes/PHPExcel/Reader/CSV.php
index d43b374..d45a0c6 100644
--- a/Classes/PHPExcel/Reader/CSV.php
+++ b/Classes/PHPExcel/Reader/CSV.php
@@ -144,28 +144,28 @@ public function getInputEncoding()
*/
protected function _skipBOM()
{
- rewind($fileHandle);
+ rewind($this->_fileHandle);
switch ($this->_inputEncoding) {
case 'UTF-8':
fgets($this->_fileHandle, 4) == "\xEF\xBB\xBF" ?
- fseek($this->_fileHandle, 3) : fseek($this->_fileHandle, 0);
+ fseek($this->_fileHandle, 3) : fseek($this->_fileHandle, 0);
break;
case 'UTF-16LE':
fgets($this->_fileHandle, 3) == "\xFF\xFE" ?
- fseek($this->_fileHandle, 2) : fseek($this->_fileHandle, 0);
+ fseek($this->_fileHandle, 2) : fseek($this->_fileHandle, 0);
break;
case 'UTF-16BE':
fgets($this->_fileHandle, 3) == "\xFE\xFF" ?
- fseek($this->_fileHandle, 2) : fseek($this->_fileHandle, 0);
+ fseek($this->_fileHandle, 2) : fseek($this->_fileHandle, 0);
break;
case 'UTF-32LE':
fgets($this->_fileHandle, 5) == "\xFF\xFE\x00\x00" ?
- fseek($this->_fileHandle, 4) : fseek($this->_fileHandle, 0);
+ fseek($this->_fileHandle, 4) : fseek($this->_fileHandle, 0);
break;
case 'UTF-32BE':
fgets($this->_fileHandle, 5) == "\x00\x00\xFE\xFF" ?
- fseek($this->_fileHandle, 4) : fseek($this->_fileHandle, 0);
+ fseek($this->_fileHandle, 4) : fseek($this->_fileHandle, 0);
break;
default:
break;
@@ -187,7 +187,7 @@ public function listWorksheetInfo($pFilename)
throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file.");
}
$fileHandle = $this->_fileHandle;
-
+
// Skip BOM, if any
$this->_skipBOM();
/branches/v1.7-croissant/vendors/gwt-ext-ux/UploadDialog/Ext.ux.UploadDialog.js
New file
0,0 → 1,1536
/**
* This namespace should be in another file but I dicided to put it here for consistancy.
*/
Ext.namespace('Ext.ux.Utils');
 
/**
* This class implements event queue behaviour.
*
* @class Ext.ux.Utils.EventQueue
* @param function handler Event handler.
* @param object scope Handler scope.
*/
Ext.ux.Utils.EventQueue = function(handler, scope)
{
if (!handler) {
throw 'Handler is required.';
}
this.handler = handler;
this.scope = scope || window;
this.queue = [];
this.is_processing = false;
/**
* Posts event into the queue.
*
* @access public
* @param mixed event Event identificator.
* @param mixed data Event data.
*/
this.postEvent = function(event, data)
{
data = data || null;
this.queue.push({event: event, data: data});
if (!this.is_processing) {
this.process();
}
}
this.flushEventQueue = function()
{
this.queue = [];
},
/**
* @access private
*/
this.process = function()
{
while (this.queue.length > 0) {
this.is_processing = true;
var event_data = this.queue.shift();
this.handler.call(this.scope, event_data.event, event_data.data);
}
this.is_processing = false;
}
}
 
/**
* This class implements Mili's finite state automata behaviour.
*
* Transition / output table format:
* {
* 'state_1' : {
* 'event_1' : [
* {
* p|predicate: function, // Transition predicate, optional, default to true.
* // If array then conjunction will be applyed to the operands.
* // Predicate signature is (data, event, this).
* a|action: function|array, // Transition action, optional, default to Ext.emptyFn.
* // If array then methods will be called sequentially.
* // Action signature is (data, event, this).
* s|state: 'state_x', // New state - transition destination, optional, default to
* // current state.
* scope: object // Predicate and action scope, optional, default to
* // trans_table_scope or window.
* }
* ]
* },
*
* 'state_2' : {
* ...
* }
* ...
* }
*
* @param mixed initial_state Initial state.
* @param object trans_table Transition / output table.
* @param trans_table_scope Transition / output table's methods scope.
*/
Ext.ux.Utils.FSA = function(initial_state, trans_table, trans_table_scope)
{
this.current_state = initial_state;
this.trans_table = trans_table || {};
this.trans_table_scope = trans_table_scope || window;
Ext.ux.Utils.FSA.superclass.constructor.call(this, this.processEvent, this);
}
 
Ext.extend(Ext.ux.Utils.FSA, Ext.ux.Utils.EventQueue, {
 
current_state : null,
trans_table : null,
trans_table_scope : null,
/**
* Returns current state
*
* @access public
* @return mixed Current state.
*/
state : function()
{
return this.current_state;
},
/**
* @access public
*/
processEvent : function(event, data)
{
var transitions = this.currentStateEventTransitions(event);
if (!transitions) {
throw "State '" + this.current_state + "' has no transition for event '" + event + "'.";
}
for (var i = 0, len = transitions.length; i < len; i++) {
var transition = transitions[i];
 
var predicate = transition.predicate || transition.p || true;
var action = transition.action || transition.a || Ext.emptyFn;
var new_state = transition.state || transition.s || this.current_state;
var scope = transition.scope || this.trans_table_scope;
if (this.computePredicate(predicate, scope, data, event)) {
this.callAction(action, scope, data, event);
this.current_state = new_state;
return;
}
}
throw "State '" + this.current_state + "' has no transition for event '" + event + "' in current context";
},
/**
* @access private
*/
currentStateEventTransitions : function(event)
{
return this.trans_table[this.current_state] ?
this.trans_table[this.current_state][event] || false
:
false;
},
/**
* @access private
*/
computePredicate : function(predicate, scope, data, event)
{
var result = false;
switch (Ext.type(predicate)) {
case 'function':
result = predicate.call(scope, data, event, this);
break;
case 'array':
result = true;
for (var i = 0, len = predicate.length; result && (i < len); i++) {
if (Ext.type(predicate[i]) == 'function') {
result = predicate[i].call(scope, data, event, this);
}
else {
throw [
'Predicate: ',
predicate[i],
' is not callable in "',
this.current_state,
'" state for event "',
event
].join('');
}
}
break;
case 'boolean':
result = predicate;
break;
default:
throw [
'Predicate: ',
predicate,
' is not callable in "',
this.current_state,
'" state for event "',
event
].join('');
}
return result;
},
/**
* @access private
*/
callAction : function(action, scope, data, event)
{
switch (Ext.type(action)) {
case 'array':
for (var i = 0, len = action.length; i < len; i++) {
if (Ext.type(action[i]) == 'function') {
action[i].call(scope, data, event, this);
}
else {
throw [
'Action: ',
action[i],
' is not callable in "',
this.current_state,
'" state for event "',
event
].join('');
}
}
break;
case 'function':
action.call(scope, data, event, this);
break;
default:
throw [
'Action: ',
action,
' is not callable in "',
this.current_state,
'" state for event "',
event
].join('');
}
}
});
 
// ---------------------------------------------------------------------------------------------- //
 
/**
* Ext.ux.UploadDialog namespace.
*/
Ext.namespace('Ext.ux.UploadDialog');
 
/**
* File upload browse button.
*
* @class Ext.ux.UploadDialog.BrowseButton
*/
Ext.ux.UploadDialog.BrowseButton = Ext.extend(Ext.Button,
{
input_name : 'file',
input_file : null,
original_handler : null,
original_scope : null,
/**
* @access private
*/
initComponent : function()
{
Ext.ux.UploadDialog.BrowseButton.superclass.initComponent.call(this);
this.original_handler = this.handler || null;
this.original_scope = this.scope || window;
this.handler = null;
this.scope = null;
},
/**
* @access private
*/
onRender : function(ct, position)
{
Ext.ux.UploadDialog.BrowseButton.superclass.onRender.call(this, ct, position);
this.createInputFile();
},
/**
* @access private
*/
createInputFile : function()
{
var button_container = this.el.child('.x-btn-center');
button_container.position('relative');
this.input_file = Ext.DomHelper.append(
button_container,
{
tag: 'input',
type: 'file',
size: 1,
name: this.input_name || Ext.id(this.el),
style: 'position: absolute; display: block; border: none; cursor: pointer'
},
true
);
var button_box = button_container.getBox();
this.input_file.setStyle('font-size', (button_box.width * 0.5) + 'px');
 
var input_box = this.input_file.getBox();
var adj = {x: 3, y: 3}
if (Ext.isIE) {
adj = {x: 0, y: 3}
}
this.input_file.setLeft(button_box.width - input_box.width + adj.x + 'px');
this.input_file.setTop(button_box.height - input_box.height + adj.y + 'px');
this.input_file.setOpacity(0.0);
if (this.handleMouseEvents) {
this.input_file.on('mouseover', this.onMouseOver, this);
this.input_file.on('mousedown', this.onMouseDown, this);
}
if(this.tooltip){
if(typeof this.tooltip == 'object'){
Ext.QuickTips.register(Ext.apply({target: this.input_file}, this.tooltip));
}
else {
this.input_file.dom[this.tooltipType] = this.tooltip;
}
}
this.input_file.on('change', this.onInputFileChange, this);
this.input_file.on('click', function(e) { e.stopPropagation(); });
},
/**
* @access public
*/
detachInputFile : function(no_create)
{
var result = this.input_file;
no_create = no_create || false;
if (typeof this.tooltip == 'object') {
Ext.QuickTips.unregister(this.input_file);
}
else {
this.input_file.dom[this.tooltipType] = null;
}
this.input_file.removeAllListeners();
this.input_file = null;
if (!no_create) {
this.createInputFile();
}
return result;
},
/**
* @access public
*/
getInputFile : function()
{
return this.input_file;
},
/**
* @access public
*/
disable : function()
{
Ext.ux.UploadDialog.BrowseButton.superclass.disable.call(this);
this.input_file.dom.disabled = true;
},
/**
* @access public
*/
enable : function()
{
Ext.ux.UploadDialog.BrowseButton.superclass.enable.call(this);
this.input_file.dom.disabled = false;
},
/**
* @access public
*/
destroy : function()
{
var input_file = this.detachInputFile(true);
input_file.remove();
input_file = null;
Ext.ux.UploadDialog.BrowseButton.superclass.destroy.call(this);
},
/**
* @access private
*/
onInputFileChange : function()
{
if (this.original_handler) {
this.original_handler.call(this.original_scope, this);
}
}
});
 
/**
* Toolbar file upload browse button.
*
* @class Ext.ux.UploadDialog.TBBrowseButton
*/
Ext.ux.UploadDialog.TBBrowseButton = Ext.extend(Ext.ux.UploadDialog.BrowseButton,
{
hideParent : true,
 
onDestroy : function()
{
Ext.ux.UploadDialog.TBBrowseButton.superclass.onDestroy.call(this);
if(this.container) {
this.container.remove();
}
}
});
 
/**
* Record type for dialogs grid.
*
* @class Ext.ux.UploadDialog.FileRecord
*/
Ext.ux.UploadDialog.FileRecord = Ext.data.Record.create([
{name: 'filename'},
{name: 'state', type: 'int'},
{name: 'note'},
{name: 'input_element'}
]);
 
Ext.ux.UploadDialog.FileRecord.STATE_QUEUE = 0;
Ext.ux.UploadDialog.FileRecord.STATE_FINISHED = 1;
Ext.ux.UploadDialog.FileRecord.STATE_FAILED = 2;
Ext.ux.UploadDialog.FileRecord.STATE_PROCESSING = 3;
 
/**
* Dialog class.
*
* @class Ext.ux.UploadDialog.Dialog
*/
Ext.ux.UploadDialog.Dialog = function(config)
{
var default_config = {
border: false,
width: 450,
height: 300,
minWidth: 450,
minHeight: 300,
plain: true,
constrainHeader: true,
draggable: true,
closable: true,
maximizable: false,
minimizable: false,
resizable: true,
autoDestroy: true,
closeAction: 'hide',
title: this.i18n.title,
cls: 'ext-ux-uploaddialog-dialog',
// --------
url: '',
base_params: {},
permitted_extensions: [],
reset_on_hide: true,
allow_close_on_upload: false,
upload_autostart: false,
post_var_name: 'file'
}
config = Ext.applyIf(config || {}, default_config);
config.layout = 'absolute';
Ext.ux.UploadDialog.Dialog.superclass.constructor.call(this, config);
}
 
Ext.extend(Ext.ux.UploadDialog.Dialog, Ext.Window, {
 
fsa : null,
state_tpl : null,
form : null,
grid_panel : null,
progress_bar : null,
is_uploading : false,
initial_queued_count : 0,
upload_frame : null,
/**
* @access private
*/
//--------------------------------------------------------------------------------------------- //
initComponent : function()
{
Ext.ux.UploadDialog.Dialog.superclass.initComponent.call(this);
// Setting automata protocol
var tt = {
// --------------
'created' : {
// --------------
'window-render' : [
{
action: [this.createForm, this.createProgressBar, this.createGrid],
state: 'rendering'
}
],
'destroy' : [
{
action: this.flushEventQueue,
state: 'destroyed'
}
]
},
// --------------
'rendering' : {
// --------------
'grid-render' : [
{
action: [this.fillToolbar, this.updateToolbar],
state: 'ready'
}
],
'destroy' : [
{
action: this.flushEventQueue,
state: 'destroyed'
}
]
},
// --------------
'ready' : {
// --------------
'file-selected' : [
{
predicate: [this.fireFileTestEvent, this.isPermittedFile],
action: this.addFileToUploadQueue,
state: 'adding-file'
},
{
// If file is not permitted then do nothing.
}
],
'grid-selection-change' : [
{
action: this.updateToolbar
}
],
'remove-files' : [
{
action: [this.removeFiles, this.fireFileRemoveEvent]
}
],
'reset-queue' : [
{
action: [this.resetQueue, this.fireResetQueueEvent]
}
],
'start-upload' : [
{
predicate: this.hasUnuploadedFiles,
action: [
this.setUploadingFlag, this.saveInitialQueuedCount, this.updateToolbar,
this.updateProgressBar, this.prepareNextUploadTask, this.fireUploadStartEvent
],
state: 'uploading'
},
{
// Has nothing to upload, do nothing.
}
],
'stop-upload' : [
{
// We are not uploading, do nothing. Can be posted by user only at this state.
}
],
'hide' : [
{
predicate: [this.isNotEmptyQueue, this.getResetOnHide],
action: [this.resetQueue, this.fireResetQueueEvent]
},
{
// Do nothing
}
],
'destroy' : [
{
action: this.flushEventQueue,
state: 'destroyed'
}
]
},
// --------------
'adding-file' : {
// --------------
'file-added' : [
{
predicate: this.isUploading,
action: [this.incInitialQueuedCount, this.updateProgressBar, this.fireFileAddEvent],
state: 'uploading'
},
{
predicate: this.getUploadAutostart,
action: [this.startUpload, this.fireFileAddEvent],
state: 'ready'
},
{
action: [this.updateToolbar, this.fireFileAddEvent],
state: 'ready'
}
]
},
// --------------
'uploading' : {
// --------------
'file-selected' : [
{
predicate: [this.fireFileTestEvent, this.isPermittedFile],
action: this.addFileToUploadQueue,
state: 'adding-file'
},
{
// If file is not permitted then do nothing.
}
],
'grid-selection-change' : [
{
// Do nothing.
}
],
'start-upload' : [
{
// Can be posted only by user in this state.
}
],
'stop-upload' : [
{
predicate: this.hasUnuploadedFiles,
action: [
this.resetUploadingFlag, this.abortUpload, this.updateToolbar,
this.updateProgressBar, this.fireUploadStopEvent
],
state: 'ready'
},
{
action: [
this.resetUploadingFlag, this.abortUpload, this.updateToolbar,
this.updateProgressBar, this.fireUploadStopEvent, this.fireUploadCompleteEvent
],
state: 'ready'
}
],
'file-upload-start' : [
{
action: [this.uploadFile, this.findUploadFrame, this.fireFileUploadStartEvent]
}
],
'file-upload-success' : [
{
predicate: this.hasUnuploadedFiles,
action: [
this.resetUploadFrame, this.updateRecordState, this.updateProgressBar,
this.prepareNextUploadTask, this.fireUploadSuccessEvent
]
},
{
action: [
this.resetUploadFrame, this.resetUploadingFlag, this.updateRecordState,
this.updateToolbar, this.updateProgressBar, this.fireUploadSuccessEvent,
this.fireUploadCompleteEvent
],
state: 'ready'
}
],
'file-upload-error' : [
{
predicate: this.hasUnuploadedFiles,
action: [
this.resetUploadFrame, this.updateRecordState, this.updateProgressBar,
this.prepareNextUploadTask, this.fireUploadErrorEvent
]
},
{
action: [
this.resetUploadFrame, this.resetUploadingFlag, this.updateRecordState,
this.updateToolbar, this.updateProgressBar, this.fireUploadErrorEvent,
this.fireUploadCompleteEvent
],
state: 'ready'
}
],
'file-upload-failed' : [
{
predicate: this.hasUnuploadedFiles,
action: [
this.resetUploadFrame, this.updateRecordState, this.updateProgressBar,
this.prepareNextUploadTask, this.fireUploadFailedEvent
]
},
{
action: [
this.resetUploadFrame, this.resetUploadingFlag, this.updateRecordState,
this.updateToolbar, this.updateProgressBar, this.fireUploadFailedEvent,
this.fireUploadCompleteEvent
],
state: 'ready'
}
],
'hide' : [
{
predicate: this.getResetOnHide,
action: [this.stopUpload, this.repostHide]
},
{
// Do nothing.
}
],
'destroy' : [
{
predicate: this.hasUnuploadedFiles,
action: [
this.resetUploadingFlag, this.abortUpload,
this.fireUploadStopEvent, this.flushEventQueue
],
state: 'destroyed'
},
{
action: [
this.resetUploadingFlag, this.abortUpload,
this.fireUploadStopEvent, this.fireUploadCompleteEvent, this.flushEventQueue
],
state: 'destroyed'
}
]
},
// --------------
'destroyed' : {
// --------------
}
}
this.fsa = new Ext.ux.Utils.FSA('created', tt, this);
// Registering dialog events.
this.addEvents({
'filetest': true,
'fileadd' : true,
'fileremove' : true,
'resetqueue' : true,
'uploadsuccess' : true,
'uploaderror' : true,
'uploadfailed' : true,
'uploadstart' : true,
'uploadstop' : true,
'uploadcomplete' : true,
'fileuploadstart' : true
});
// Attaching to window events.
this.on('render', this.onWindowRender, this);
this.on('beforehide', this.onWindowBeforeHide, this);
this.on('hide', this.onWindowHide, this);
this.on('destroy', this.onWindowDestroy, this);
// Compiling state template.
this.state_tpl = new Ext.Template(
"<div class='ext-ux-uploaddialog-state ext-ux-uploaddialog-state-{state}'>&#160;</div>"
).compile();
},
createForm : function()
{
this.form = Ext.DomHelper.append(this.body, {
tag: 'form',
method: 'post',
action: this.url,
style: 'position: absolute; left: -100px; top: -100px; width: 100px; height: 100px'
});
},
createProgressBar : function()
{
this.progress_bar = this.add(
new Ext.ProgressBar({
x: 0,
y: 0,
anchor: '0',
value: 0.0,
text: this.i18n.progress_waiting_text
})
);
},
createGrid : function()
{
var store = new Ext.data.Store({
proxy: new Ext.data.MemoryProxy([]),
reader: new Ext.data.JsonReader({}, Ext.ux.UploadDialog.FileRecord),
sortInfo: {field: 'state', direction: 'DESC'},
pruneModifiedRecords: true
});
var cm = new Ext.grid.ColumnModel([
{
header: this.i18n.state_col_title,
width: this.i18n.state_col_width,
resizable: false,
dataIndex: 'state',
sortable: true,
renderer: this.renderStateCell.createDelegate(this)
},
{
header: this.i18n.filename_col_title,
width: this.i18n.filename_col_width,
dataIndex: 'filename',
sortable: true,
renderer: this.renderFilenameCell.createDelegate(this)
},
{
header: this.i18n.note_col_title,
width: this.i18n.note_col_width,
dataIndex: 'note',
sortable: true,
renderer: this.renderNoteCell.createDelegate(this)
}
]);
this.grid_panel = new Ext.grid.GridPanel({
ds: store,
cm: cm,
x: 0,
y: 22,
anchor: '0 -22',
border: true,
viewConfig: {
autoFill: true,
forceFit: true
},
bbar : new Ext.Toolbar()
});
this.grid_panel.on('render', this.onGridRender, this);
this.add(this.grid_panel);
this.grid_panel.getSelectionModel().on('selectionchange', this.onGridSelectionChange, this);
},
fillToolbar : function()
{
var tb = this.grid_panel.getBottomToolbar();
tb.x_buttons = {}
tb.x_buttons.add = tb.addItem(new Ext.ux.UploadDialog.TBBrowseButton({
input_name: this.post_var_name,
text: this.i18n.add_btn_text,
tooltip: this.i18n.add_btn_tip,
iconCls: 'ext-ux-uploaddialog-addbtn',
handler: this.onAddButtonFileSelected,
scope: this
}));
tb.x_buttons.remove = tb.addButton({
text: this.i18n.remove_btn_text,
tooltip: this.i18n.remove_btn_tip,
iconCls: 'ext-ux-uploaddialog-removebtn',
handler: this.onRemoveButtonClick,
scope: this
});
tb.x_buttons.reset = tb.addButton({
text: this.i18n.reset_btn_text,
tooltip: this.i18n.reset_btn_tip,
iconCls: 'ext-ux-uploaddialog-resetbtn',
handler: this.onResetButtonClick,
scope: this
});
tb.add('-');
tb.x_buttons.upload = tb.addButton({
text: this.i18n.upload_btn_start_text,
tooltip: this.i18n.upload_btn_start_tip,
iconCls: 'ext-ux-uploaddialog-uploadstartbtn',
handler: this.onUploadButtonClick,
scope: this
});
tb.add('-');
tb.x_buttons.indicator = tb.addItem(
new Ext.Toolbar.Item(
Ext.DomHelper.append(tb.getEl(), {
tag: 'div',
cls: 'ext-ux-uploaddialog-indicator-stoped',
html: '&#160'
})
)
);
tb.add('->');
tb.x_buttons.close = tb.addButton({
text: this.i18n.close_btn_text,
tooltip: this.i18n.close_btn_tip,
handler: this.onCloseButtonClick,
scope: this
});
},
renderStateCell : function(data, cell, record, row_index, column_index, store)
{
return this.state_tpl.apply({state: data});
},
renderFilenameCell : function(data, cell, record, row_index, column_index, store)
{
var view = this.grid_panel.getView();
var f = function() {
try {
Ext.fly(
view.getCell(row_index, column_index)
).child('.x-grid3-cell-inner').dom['qtip'] = data;
}
catch (e)
{}
}
f.defer(1000);
return data;
},
renderNoteCell : function(data, cell, record, row_index, column_index, store)
{
var view = this.grid_panel.getView();
var f = function() {
try {
Ext.fly(
view.getCell(row_index, column_index)
).child('.x-grid3-cell-inner').dom['qtip'] = data;
}
catch (e)
{}
}
f.defer(1000);
return data;
},
getFileExtension : function(filename)
{
var result = null;
var parts = filename.split('.');
if (parts.length > 1) {
result = parts.pop();
}
return result;
},
isPermittedFileType : function(filename)
{
var result = true;
if (this.permitted_extensions.length > 0) {
result = this.permitted_extensions.indexOf(this.getFileExtension(filename)) != -1;
}
return result;
},
 
isPermittedFile : function(browse_btn)
{
var result = false;
var filename = browse_btn.getInputFile().dom.value;
if (this.isPermittedFileType(filename)) {
result = true;
}
else {
Ext.Msg.alert(
this.i18n.error_msgbox_title,
String.format(
this.i18n.err_file_type_not_permitted,
filename,
this.permitted_extensions.join(this.i18n.permitted_extensions_join_str)
)
);
result = false;
}
return result;
},
fireFileTestEvent : function(browse_btn)
{
return this.fireEvent('filetest', this, browse_btn.getInputFile().dom.value) !== false;
},
addFileToUploadQueue : function(browse_btn)
{
var input_file = browse_btn.detachInputFile();
input_file.appendTo(this.form);
input_file.setStyle('width', '100px');
input_file.dom.disabled = true;
var store = this.grid_panel.getStore();
store.add(
new Ext.ux.UploadDialog.FileRecord({
state: Ext.ux.UploadDialog.FileRecord.STATE_QUEUE,
filename: input_file.dom.value,
note: this.i18n.note_queued_to_upload,
input_element: input_file
})
);
this.fsa.postEvent('file-added', input_file.dom.value);
},
fireFileAddEvent : function(filename)
{
this.fireEvent('fileadd', this, filename);
},
updateProgressBar : function()
{
if (this.is_uploading) {
var queued = this.getQueuedCount(true);
var value = 1 - queued / this.initial_queued_count;
this.progress_bar.updateProgress(
value,
String.format(
this.i18n.progress_uploading_text,
this.initial_queued_count - queued,
this.initial_queued_count
)
);
}
else {
this.progress_bar.updateProgress(0, this.i18n.progress_waiting_text);
}
},
updateToolbar : function()
{
var tb = this.grid_panel.getBottomToolbar();
if (this.is_uploading) {
tb.x_buttons.remove.disable();
tb.x_buttons.reset.disable();
tb.x_buttons.upload.enable();
if (!this.getAllowCloseOnUpload()) {
tb.x_buttons.close.disable();
}
Ext.fly(tb.x_buttons.indicator.getEl()).replaceClass(
'ext-ux-uploaddialog-indicator-stoped',
'ext-ux-uploaddialog-indicator-processing'
);
tb.x_buttons.upload.setIconClass('ext-ux-uploaddialog-uploadstopbtn');
tb.x_buttons.upload.setText(this.i18n.upload_btn_stop_text);
tb.x_buttons.upload.getEl()
.child(tb.x_buttons.upload.buttonSelector)
.dom[tb.x_buttons.upload.tooltipType] = this.i18n.upload_btn_stop_tip;
}
else {
tb.x_buttons.remove.enable();
tb.x_buttons.reset.enable();
tb.x_buttons.close.enable();
Ext.fly(tb.x_buttons.indicator.getEl()).replaceClass(
'ext-ux-uploaddialog-indicator-processing',
'ext-ux-uploaddialog-indicator-stoped'
);
tb.x_buttons.upload.setIconClass('ext-ux-uploaddialog-uploadstartbtn');
tb.x_buttons.upload.setText(this.i18n.upload_btn_start_text);
tb.x_buttons.upload.getEl()
.child(tb.x_buttons.upload.buttonSelector)
.dom[tb.x_buttons.upload.tooltipType] = this.i18n.upload_btn_start_tip;
if (this.getQueuedCount() > 0) {
tb.x_buttons.upload.enable();
}
else {
tb.x_buttons.upload.disable();
}
if (this.grid_panel.getSelectionModel().hasSelection()) {
tb.x_buttons.remove.enable();
}
else {
tb.x_buttons.remove.disable();
}
if (this.grid_panel.getStore().getCount() > 0) {
tb.x_buttons.reset.enable();
}
else {
tb.x_buttons.reset.disable();
}
}
},
saveInitialQueuedCount : function()
{
this.initial_queued_count = this.getQueuedCount();
},
incInitialQueuedCount : function()
{
this.initial_queued_count++;
},
setUploadingFlag : function()
{
this.is_uploading = true;
},
resetUploadingFlag : function()
{
this.is_uploading = false;
},
 
prepareNextUploadTask : function()
{
// Searching for first unuploaded file.
var store = this.grid_panel.getStore();
var record = null;
store.each(function(r) {
if (!record && r.get('state') == Ext.ux.UploadDialog.FileRecord.STATE_QUEUE) {
record = r;
}
else {
r.get('input_element').dom.disabled = true;
}
});
record.get('input_element').dom.disabled = false;
record.set('state', Ext.ux.UploadDialog.FileRecord.STATE_PROCESSING);
record.set('note', this.i18n.note_processing);
record.commit();
this.fsa.postEvent('file-upload-start', record);
},
fireUploadStartEvent : function()
{
this.fireEvent('uploadstart', this);
},
removeFiles : function(file_records)
{
var store = this.grid_panel.getStore();
for (var i = 0, len = file_records.length; i < len; i++) {
var r = file_records[i];
r.get('input_element').remove();
store.remove(r);
}
},
fireFileRemoveEvent : function(file_records)
{
for (var i = 0, len = file_records.length; i < len; i++) {
this.fireEvent('fileremove', this, file_records[i].get('filename'));
}
},
resetQueue : function()
{
var store = this.grid_panel.getStore();
store.each(
function(r) {
r.get('input_element').remove();
}
);
store.removeAll();
},
fireResetQueueEvent : function()
{
this.fireEvent('resetqueue', this);
},
uploadFile : function(record)
{
Ext.Ajax.request({
url : this.url,
params : this.base_params || this.baseParams || this.params,
method : 'POST',
form : this.form,
isUpload : true,
success : this.onAjaxSuccess,
failure : this.onAjaxFailure,
scope : this,
record: record
});
},
fireFileUploadStartEvent : function(record)
{
this.fireEvent('fileuploadstart', this, record.get('filename'));
},
updateRecordState : function(data)
{
if ('success' in data.response && data.response.success) {
data.record.set('state', Ext.ux.UploadDialog.FileRecord.STATE_FINISHED);
data.record.set(
'note', data.response.message || data.response.error || this.i18n.note_upload_success
);
}
else {
data.record.set('state', Ext.ux.UploadDialog.FileRecord.STATE_FAILED);
data.record.set(
'note', data.response.message || data.response.error || this.i18n.note_upload_error
);
}
data.record.commit();
},
fireUploadSuccessEvent : function(data)
{
this.fireEvent('uploadsuccess', this, data.record.get('filename'), data.response);
},
fireUploadErrorEvent : function(data)
{
this.fireEvent('uploaderror', this, data.record.get('filename'), data.response);
},
fireUploadFailedEvent : function(data)
{
this.fireEvent('uploadfailed', this, data.record.get('filename'));
},
fireUploadCompleteEvent : function()
{
this.fireEvent('uploadcomplete', this);
},
findUploadFrame : function()
{
this.upload_frame = Ext.getBody().child('iframe.x-hidden:last');
},
resetUploadFrame : function()
{
this.upload_frame = null;
},
removeUploadFrame : function()
{
if (this.upload_frame) {
this.upload_frame.removeAllListeners();
this.upload_frame.dom.src = 'about:blank';
this.upload_frame.remove();
}
this.upload_frame = null;
},
abortUpload : function()
{
this.removeUploadFrame();
var store = this.grid_panel.getStore();
var record = null;
store.each(function(r) {
if (r.get('state') == Ext.ux.UploadDialog.FileRecord.STATE_PROCESSING) {
record = r;
return false;
}
});
record.set('state', Ext.ux.UploadDialog.FileRecord.STATE_FAILED);
record.set('note', this.i18n.note_aborted);
record.commit();
},
fireUploadStopEvent : function()
{
this.fireEvent('uploadstop', this);
},
repostHide : function()
{
this.fsa.postEvent('hide');
},
flushEventQueue : function()
{
this.fsa.flushEventQueue();
},
/**
* @access private
*/
// -------------------------------------------------------------------------------------------- //
onWindowRender : function()
{
this.fsa.postEvent('window-render');
},
onWindowBeforeHide : function()
{
return this.isUploading() ? this.getAllowCloseOnUpload() : true;
},
onWindowHide : function()
{
this.fsa.postEvent('hide');
},
onWindowDestroy : function()
{
this.fsa.postEvent('destroy');
},
onGridRender : function()
{
this.fsa.postEvent('grid-render');
},
onGridSelectionChange : function()
{
this.fsa.postEvent('grid-selection-change');
},
onAddButtonFileSelected : function(btn)
{
this.fsa.postEvent('file-selected', btn);
},
onUploadButtonClick : function()
{
if (this.is_uploading) {
this.fsa.postEvent('stop-upload');
}
else {
this.fsa.postEvent('start-upload');
}
},
onRemoveButtonClick : function()
{
var selections = this.grid_panel.getSelectionModel().getSelections();
this.fsa.postEvent('remove-files', selections);
},
onResetButtonClick : function()
{
this.fsa.postEvent('reset-queue');
},
onCloseButtonClick : function()
{
this[this.closeAction].call(this);
},
onAjaxSuccess : function(response, options)
{
var json_response = {
'success' : false,
'message' : this.response
}
if(this.response == 'OK' )
{
json_response.success = true ;
}
var data = {
record: options.record,
response: json_response
}
if ('success' in json_response && json_response.success) {
this.fsa.postEvent('file-upload-success', data);
}
else {
this.fsa.postEvent('file-upload-error', data);
}
},
onAjaxFailure : function(response, options)
{
var data = {
record : options.record,
response : {
'success' : false,
'error' : this.i18n.note_upload_error
}
}
 
this.fsa.postEvent('file-upload-failed', data);
},
/**
* @access public
*/
// -------------------------------------------------------------------------------------------- //
startUpload : function()
{
this.fsa.postEvent('start-upload');
},
stopUpload : function()
{
this.fsa.postEvent('stop-upload');
},
getUrl : function()
{
return this.url;
},
setUrl : function(url)
{
this.url = url;
},
getBaseParams : function()
{
return this.base_params;
},
setBaseParams : function(params)
{
this.base_params = params;
},
getUploadAutostart : function()
{
return this.upload_autostart;
},
setUploadAutostart : function(value)
{
this.upload_autostart = value;
},
getAllowCloseOnUpload : function()
{
return this.allow_close_on_upload;
},
setAllowCloseOnUpload : function(value)
{
this.allow_close_on_upload;
},
getResetOnHide : function()
{
return this.reset_on_hide;
},
setResetOnHide : function(value)
{
this.reset_on_hide = value;
},
getPermittedExtensions : function()
{
return this.permitted_extensions;
},
setPermittedExtensions : function(value)
{
this.permitted_extensions = value;
},
isUploading : function()
{
return this.is_uploading;
},
isNotEmptyQueue : function()
{
return this.grid_panel.getStore().getCount() > 0;
},
getQueuedCount : function(count_processing)
{
var count = 0;
var store = this.grid_panel.getStore();
store.each(function(r) {
if (r.get('state') == Ext.ux.UploadDialog.FileRecord.STATE_QUEUE) {
count++;
}
if (count_processing && r.get('state') == Ext.ux.UploadDialog.FileRecord.STATE_PROCESSING) {
count++;
}
});
return count;
},
hasUnuploadedFiles : function()
{
return this.getQueuedCount() > 0;
}
});
 
// ---------------------------------------------------------------------------------------------- //
 
var p = Ext.ux.UploadDialog.Dialog.prototype;
p.i18n = {
title: 'Ajout simple de fichiers',
state_col_title: 'Etat',
state_col_width: 70,
filename_col_title: 'Fichier',
filename_col_width: 230,
note_col_title: 'Note',
note_col_width: 150,
add_btn_text: 'Ajouter',
add_btn_tip: 'Ajoute un fichier à la liste.',
remove_btn_text: 'Supprimer',
remove_btn_tip: 'Supprime un fichier de la liste.',
reset_btn_text: 'Vider',
reset_btn_tip: 'Vider la liste.',
upload_btn_start_text: 'Envoyer',
upload_btn_stop_text: 'Annuler',
upload_btn_start_tip: 'Envoie les fichiers de la liste sur le serveur.',
upload_btn_stop_tip: 'Stopper l\'envoi.',
close_btn_text: 'Fermer',
close_btn_tip: 'Ferme la fenêtre.',
progress_waiting_text: 'En attente...',
progress_uploading_text: 'Envoi de: {0} sur {1} fichiers terminé.',
error_msgbox_title: 'Erreur',
permitted_extensions_join_str: ',',
err_file_type_not_permitted: 'Cette extension de fichier n\'est pas permise.<br/>Selectionnez un fichier portant une des extensions suivantes: {1}',
note_queued_to_upload: 'Prêt à être envoyé.',
note_processing: 'Envoi...',
note_upload_failed: 'Le serveur est inaccessible ou bien une erreur serveur s\'est produite.',
note_upload_success: 'OK.',
note_upload_error: 'Erreur d\'envoi.',
note_aborted: 'Annulé par l\'utilisateur.'
}
/branches/v1.7-croissant/vendors/gwt-ext-ux/UploadDialog/README.txt
New file
0,0 → 1,3
Ces fichiers doivent remplacer ceux contenus
dans gwt-ext-ux/main/src/com/gwtextux/public/js/UploadDialog/Ext.ux.UploadDialog.js
afin d'éviter un bug de retour d'upload et d'avoir une traduction française de son interface
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/branches/v1.7-croissant/vendors/gwt-ext-ux/UploadDialog/Ext.ux.UploadDialog.packed.js
New file
0,0 → 1,1534
/**
* This namespace should be in another file but I dicided to put it here for consistancy.
*/
Ext.namespace('Ext.ux.Utils');
 
/**
* This class implements event queue behaviour.
*
* @class Ext.ux.Utils.EventQueue
* @param function handler Event handler.
* @param object scope Handler scope.
*/
Ext.ux.Utils.EventQueue = function(handler, scope)
{
if (!handler) {
throw 'Handler is required.';
}
this.handler = handler;
this.scope = scope || window;
this.queue = [];
this.is_processing = false;
/**
* Posts event into the queue.
*
* @access public
* @param mixed event Event identificator.
* @param mixed data Event data.
*/
this.postEvent = function(event, data)
{
data = data || null;
this.queue.push({event: event, data: data});
if (!this.is_processing) {
this.process();
}
}
this.flushEventQueue = function()
{
this.queue = [];
},
/**
* @access private
*/
this.process = function()
{
while (this.queue.length > 0) {
this.is_processing = true;
var event_data = this.queue.shift();
this.handler.call(this.scope, event_data.event, event_data.data);
}
this.is_processing = false;
}
}
 
/**
* This class implements Mili's finite state automata behaviour.
*
* Transition / output table format:
* {
* 'state_1' : {
* 'event_1' : [
* {
* p|predicate: function, // Transition predicate, optional, default to true.
* // If array then conjunction will be applyed to the operands.
* // Predicate signature is (data, event, this).
* a|action: function|array, // Transition action, optional, default to Ext.emptyFn.
* // If array then methods will be called sequentially.
* // Action signature is (data, event, this).
* s|state: 'state_x', // New state - transition destination, optional, default to
* // current state.
* scope: object // Predicate and action scope, optional, default to
* // trans_table_scope or window.
* }
* ]
* },
*
* 'state_2' : {
* ...
* }
* ...
* }
*
* @param mixed initial_state Initial state.
* @param object trans_table Transition / output table.
* @param trans_table_scope Transition / output table's methods scope.
*/
Ext.ux.Utils.FSA = function(initial_state, trans_table, trans_table_scope)
{
this.current_state = initial_state;
this.trans_table = trans_table || {};
this.trans_table_scope = trans_table_scope || window;
Ext.ux.Utils.FSA.superclass.constructor.call(this, this.processEvent, this);
}
 
Ext.extend(Ext.ux.Utils.FSA, Ext.ux.Utils.EventQueue, {
 
current_state : null,
trans_table : null,
trans_table_scope : null,
/**
* Returns current state
*
* @access public
* @return mixed Current state.
*/
state : function()
{
return this.current_state;
},
/**
* @access public
*/
processEvent : function(event, data)
{
var transitions = this.currentStateEventTransitions(event);
if (!transitions) {
throw "State '" + this.current_state + "' has no transition for event '" + event + "'.";
}
for (var i = 0, len = transitions.length; i < len; i++) {
var transition = transitions[i];
 
var predicate = transition.predicate || transition.p || true;
var action = transition.action || transition.a || Ext.emptyFn;
var new_state = transition.state || transition.s || this.current_state;
var scope = transition.scope || this.trans_table_scope;
if (this.computePredicate(predicate, scope, data, event)) {
this.callAction(action, scope, data, event);
this.current_state = new_state;
return;
}
}
throw "State '" + this.current_state + "' has no transition for event '" + event + "' in current context";
},
/**
* @access private
*/
currentStateEventTransitions : function(event)
{
return this.trans_table[this.current_state] ?
this.trans_table[this.current_state][event] || false
:
false;
},
/**
* @access private
*/
computePredicate : function(predicate, scope, data, event)
{
var result = false;
switch (Ext.type(predicate)) {
case 'function':
result = predicate.call(scope, data, event, this);
break;
case 'array':
result = true;
for (var i = 0, len = predicate.length; result && (i < len); i++) {
if (Ext.type(predicate[i]) == 'function') {
result = predicate[i].call(scope, data, event, this);
}
else {
throw [
'Predicate: ',
predicate[i],
' is not callable in "',
this.current_state,
'" state for event "',
event
].join('');
}
}
break;
case 'boolean':
result = predicate;
break;
default:
throw [
'Predicate: ',
predicate,
' is not callable in "',
this.current_state,
'" state for event "',
event
].join('');
}
return result;
},
/**
* @access private
*/
callAction : function(action, scope, data, event)
{
switch (Ext.type(action)) {
case 'array':
for (var i = 0, len = action.length; i < len; i++) {
if (Ext.type(action[i]) == 'function') {
action[i].call(scope, data, event, this);
}
else {
throw [
'Action: ',
action[i],
' is not callable in "',
this.current_state,
'" state for event "',
event
].join('');
}
}
break;
case 'function':
action.call(scope, data, event, this);
break;
default:
throw [
'Action: ',
action,
' is not callable in "',
this.current_state,
'" state for event "',
event
].join('');
}
}
});
 
// ---------------------------------------------------------------------------------------------- //
 
/**
* Ext.ux.UploadDialog namespace.
*/
Ext.namespace('Ext.ux.UploadDialog');
 
/**
* File upload browse button.
*
* @class Ext.ux.UploadDialog.BrowseButton
*/
Ext.ux.UploadDialog.BrowseButton = Ext.extend(Ext.Button,
{
input_name : 'file',
input_file : null,
original_handler : null,
original_scope : null,
/**
* @access private
*/
initComponent : function()
{
Ext.ux.UploadDialog.BrowseButton.superclass.initComponent.call(this);
this.original_handler = this.handler || null;
this.original_scope = this.scope || window;
this.handler = null;
this.scope = null;
},
/**
* @access private
*/
onRender : function(ct, position)
{
Ext.ux.UploadDialog.BrowseButton.superclass.onRender.call(this, ct, position);
this.createInputFile();
},
/**
* @access private
*/
createInputFile : function()
{
var button_container = this.el.child('.x-btn-center');
button_container.position('relative');
this.input_file = Ext.DomHelper.append(
button_container,
{
tag: 'input',
type: 'file',
size: 1,
name: this.input_name || Ext.id(this.el),
style: 'position: absolute; display: block; border: none; cursor: pointer'
},
true
);
var button_box = button_container.getBox();
this.input_file.setStyle('font-size', (button_box.width * 0.5) + 'px');
 
var input_box = this.input_file.getBox();
var adj = {x: 3, y: 3}
if (Ext.isIE) {
adj = {x: 0, y: 3}
}
this.input_file.setLeft(button_box.width - input_box.width + adj.x + 'px');
this.input_file.setTop(button_box.height - input_box.height + adj.y + 'px');
this.input_file.setOpacity(0.0);
if (this.handleMouseEvents) {
this.input_file.on('mouseover', this.onMouseOver, this);
this.input_file.on('mousedown', this.onMouseDown, this);
}
if(this.tooltip){
if(typeof this.tooltip == 'object'){
Ext.QuickTips.register(Ext.apply({target: this.input_file}, this.tooltip));
}
else {
this.input_file.dom[this.tooltipType] = this.tooltip;
}
}
this.input_file.on('change', this.onInputFileChange, this);
this.input_file.on('click', function(e) { e.stopPropagation(); });
},
/**
* @access public
*/
detachInputFile : function(no_create)
{
var result = this.input_file;
no_create = no_create || false;
if (typeof this.tooltip == 'object') {
Ext.QuickTips.unregister(this.input_file);
}
else {
this.input_file.dom[this.tooltipType] = null;
}
this.input_file.removeAllListeners();
this.input_file = null;
if (!no_create) {
this.createInputFile();
}
return result;
},
/**
* @access public
*/
getInputFile : function()
{
return this.input_file;
},
/**
* @access public
*/
disable : function()
{
Ext.ux.UploadDialog.BrowseButton.superclass.disable.call(this);
this.input_file.dom.disabled = true;
},
/**
* @access public
*/
enable : function()
{
Ext.ux.UploadDialog.BrowseButton.superclass.enable.call(this);
this.input_file.dom.disabled = false;
},
/**
* @access public
*/
destroy : function()
{
var input_file = this.detachInputFile(true);
input_file.remove();
input_file = null;
Ext.ux.UploadDialog.BrowseButton.superclass.destroy.call(this);
},
/**
* @access private
*/
onInputFileChange : function()
{
if (this.original_handler) {
this.original_handler.call(this.original_scope, this);
}
}
});
 
/**
* Toolbar file upload browse button.
*
* @class Ext.ux.UploadDialog.TBBrowseButton
*/
Ext.ux.UploadDialog.TBBrowseButton = Ext.extend(Ext.ux.UploadDialog.BrowseButton,
{
hideParent : true,
 
onDestroy : function()
{
Ext.ux.UploadDialog.TBBrowseButton.superclass.onDestroy.call(this);
if(this.container) {
this.container.remove();
}
}
});
 
/**
* Record type for dialogs grid.
*
* @class Ext.ux.UploadDialog.FileRecord
*/
Ext.ux.UploadDialog.FileRecord = Ext.data.Record.create([
{name: 'filename'},
{name: 'state', type: 'int'},
{name: 'note'},
{name: 'input_element'}
]);
 
Ext.ux.UploadDialog.FileRecord.STATE_QUEUE = 0;
Ext.ux.UploadDialog.FileRecord.STATE_FINISHED = 1;
Ext.ux.UploadDialog.FileRecord.STATE_FAILED = 2;
Ext.ux.UploadDialog.FileRecord.STATE_PROCESSING = 3;
 
/**
* Dialog class.
*
* @class Ext.ux.UploadDialog.Dialog
*/
Ext.ux.UploadDialog.Dialog = function(config)
{
var default_config = {
border: false,
width: 450,
height: 300,
minWidth: 450,
minHeight: 300,
plain: true,
constrainHeader: true,
draggable: true,
closable: true,
maximizable: false,
minimizable: false,
resizable: true,
autoDestroy: true,
closeAction: 'hide',
title: this.i18n.title,
cls: 'ext-ux-uploaddialog-dialog',
// --------
url: '',
base_params: {},
permitted_extensions: [],
reset_on_hide: true,
allow_close_on_upload: false,
upload_autostart: false,
post_var_name: 'file'
}
config = Ext.applyIf(config || {}, default_config);
config.layout = 'absolute';
Ext.ux.UploadDialog.Dialog.superclass.constructor.call(this, config);
}
 
Ext.extend(Ext.ux.UploadDialog.Dialog, Ext.Window, {
 
fsa : null,
state_tpl : null,
form : null,
grid_panel : null,
progress_bar : null,
is_uploading : false,
initial_queued_count : 0,
upload_frame : null,
/**
* @access private
*/
//--------------------------------------------------------------------------------------------- //
initComponent : function()
{
Ext.ux.UploadDialog.Dialog.superclass.initComponent.call(this);
// Setting automata protocol
var tt = {
// --------------
'created' : {
// --------------
'window-render' : [
{
action: [this.createForm, this.createProgressBar, this.createGrid],
state: 'rendering'
}
],
'destroy' : [
{
action: this.flushEventQueue,
state: 'destroyed'
}
]
},
// --------------
'rendering' : {
// --------------
'grid-render' : [
{
action: [this.fillToolbar, this.updateToolbar],
state: 'ready'
}
],
'destroy' : [
{
action: this.flushEventQueue,
state: 'destroyed'
}
]
},
// --------------
'ready' : {
// --------------
'file-selected' : [
{
predicate: [this.fireFileTestEvent, this.isPermittedFile],
action: this.addFileToUploadQueue,
state: 'adding-file'
},
{
// If file is not permitted then do nothing.
}
],
'grid-selection-change' : [
{
action: this.updateToolbar
}
],
'remove-files' : [
{
action: [this.removeFiles, this.fireFileRemoveEvent]
}
],
'reset-queue' : [
{
action: [this.resetQueue, this.fireResetQueueEvent]
}
],
'start-upload' : [
{
predicate: this.hasUnuploadedFiles,
action: [
this.setUploadingFlag, this.saveInitialQueuedCount, this.updateToolbar,
this.updateProgressBar, this.prepareNextUploadTask, this.fireUploadStartEvent
],
state: 'uploading'
},
{
// Has nothing to upload, do nothing.
}
],
'stop-upload' : [
{
// We are not uploading, do nothing. Can be posted by user only at this state.
}
],
'hide' : [
{
predicate: [this.isNotEmptyQueue, this.getResetOnHide],
action: [this.resetQueue, this.fireResetQueueEvent]
},
{
// Do nothing
}
],
'destroy' : [
{
action: this.flushEventQueue,
state: 'destroyed'
}
]
},
// --------------
'adding-file' : {
// --------------
'file-added' : [
{
predicate: this.isUploading,
action: [this.incInitialQueuedCount, this.updateProgressBar, this.fireFileAddEvent],
state: 'uploading'
},
{
predicate: this.getUploadAutostart,
action: [this.startUpload, this.fireFileAddEvent],
state: 'ready'
},
{
action: [this.updateToolbar, this.fireFileAddEvent],
state: 'ready'
}
]
},
// --------------
'uploading' : {
// --------------
'file-selected' : [
{
predicate: [this.fireFileTestEvent, this.isPermittedFile],
action: this.addFileToUploadQueue,
state: 'adding-file'
},
{
// If file is not permitted then do nothing.
}
],
'grid-selection-change' : [
{
// Do nothing.
}
],
'start-upload' : [
{
// Can be posted only by user in this state.
}
],
'stop-upload' : [
{
predicate: this.hasUnuploadedFiles,
action: [
this.resetUploadingFlag, this.abortUpload, this.updateToolbar,
this.updateProgressBar, this.fireUploadStopEvent
],
state: 'ready'
},
{
action: [
this.resetUploadingFlag, this.abortUpload, this.updateToolbar,
this.updateProgressBar, this.fireUploadStopEvent, this.fireUploadCompleteEvent
],
state: 'ready'
}
],
'file-upload-start' : [
{
action: [this.uploadFile, this.findUploadFrame, this.fireFileUploadStartEvent]
}
],
'file-upload-success' : [
{
predicate: this.hasUnuploadedFiles,
action: [
this.resetUploadFrame, this.updateRecordState, this.updateProgressBar,
this.prepareNextUploadTask, this.fireUploadSuccessEvent
]
},
{
action: [
this.resetUploadFrame, this.resetUploadingFlag, this.updateRecordState,
this.updateToolbar, this.updateProgressBar, this.fireUploadSuccessEvent,
this.fireUploadCompleteEvent
],
state: 'ready'
}
],
'file-upload-error' : [
{
predicate: this.hasUnuploadedFiles,
action: [
this.resetUploadFrame, this.updateRecordState, this.updateProgressBar,
this.prepareNextUploadTask, this.fireUploadErrorEvent
]
},
{
action: [
this.resetUploadFrame, this.resetUploadingFlag, this.updateRecordState,
this.updateToolbar, this.updateProgressBar, this.fireUploadErrorEvent,
this.fireUploadCompleteEvent
],
state: 'ready'
}
],
'file-upload-failed' : [
{
predicate: this.hasUnuploadedFiles,
action: [
this.resetUploadFrame, this.updateRecordState, this.updateProgressBar,
this.prepareNextUploadTask, this.fireUploadFailedEvent
]
},
{
action: [
this.resetUploadFrame, this.resetUploadingFlag, this.updateRecordState,
this.updateToolbar, this.updateProgressBar, this.fireUploadFailedEvent,
this.fireUploadCompleteEvent
],
state: 'ready'
}
],
'hide' : [
{
predicate: this.getResetOnHide,
action: [this.stopUpload, this.repostHide]
},
{
// Do nothing.
}
],
'destroy' : [
{
predicate: this.hasUnuploadedFiles,
action: [
this.resetUploadingFlag, this.abortUpload,
this.fireUploadStopEvent, this.flushEventQueue
],
state: 'destroyed'
},
{
action: [
this.resetUploadingFlag, this.abortUpload,
this.fireUploadStopEvent, this.fireUploadCompleteEvent, this.flushEventQueue
],
state: 'destroyed'
}
]
},
// --------------
'destroyed' : {
// --------------
}
}
this.fsa = new Ext.ux.Utils.FSA('created', tt, this);
// Registering dialog events.
this.addEvents({
'filetest': true,
'fileadd' : true,
'fileremove' : true,
'resetqueue' : true,
'uploadsuccess' : true,
'uploaderror' : true,
'uploadfailed' : true,
'uploadstart' : true,
'uploadstop' : true,
'uploadcomplete' : true,
'fileuploadstart' : true
});
// Attaching to window events.
this.on('render', this.onWindowRender, this);
this.on('beforehide', this.onWindowBeforeHide, this);
this.on('hide', this.onWindowHide, this);
this.on('destroy', this.onWindowDestroy, this);
// Compiling state template.
this.state_tpl = new Ext.Template(
"<div class='ext-ux-uploaddialog-state ext-ux-uploaddialog-state-{state}'>&#160;</div>"
).compile();
},
createForm : function()
{
this.form = Ext.DomHelper.append(this.body, {
tag: 'form',
method: 'post',
action: this.url,
style: 'position: absolute; left: -100px; top: -100px; width: 100px; height: 100px'
});
},
createProgressBar : function()
{
this.progress_bar = this.add(
new Ext.ProgressBar({
x: 0,
y: 0,
anchor: '0',
value: 0.0,
text: this.i18n.progress_waiting_text
})
);
},
createGrid : function()
{
var store = new Ext.data.Store({
proxy: new Ext.data.MemoryProxy([]),
reader: new Ext.data.JsonReader({}, Ext.ux.UploadDialog.FileRecord),
sortInfo: {field: 'state', direction: 'DESC'},
pruneModifiedRecords: true
});
var cm = new Ext.grid.ColumnModel([
{
header: this.i18n.state_col_title,
width: this.i18n.state_col_width,
resizable: false,
dataIndex: 'state',
sortable: true,
renderer: this.renderStateCell.createDelegate(this)
},
{
header: this.i18n.filename_col_title,
width: this.i18n.filename_col_width,
dataIndex: 'filename',
sortable: true,
renderer: this.renderFilenameCell.createDelegate(this)
},
{
header: this.i18n.note_col_title,
width: this.i18n.note_col_width,
dataIndex: 'note',
sortable: true,
renderer: this.renderNoteCell.createDelegate(this)
}
]);
this.grid_panel = new Ext.grid.GridPanel({
ds: store,
cm: cm,
x: 0,
y: 22,
anchor: '0 -22',
border: true,
viewConfig: {
autoFill: true,
forceFit: true
},
bbar : new Ext.Toolbar()
});
this.grid_panel.on('render', this.onGridRender, this);
this.add(this.grid_panel);
this.grid_panel.getSelectionModel().on('selectionchange', this.onGridSelectionChange, this);
},
fillToolbar : function()
{
var tb = this.grid_panel.getBottomToolbar();
tb.x_buttons = {}
tb.x_buttons.add = tb.addItem(new Ext.ux.UploadDialog.TBBrowseButton({
input_name: this.post_var_name,
text: this.i18n.add_btn_text,
tooltip: this.i18n.add_btn_tip,
iconCls: 'ext-ux-uploaddialog-addbtn',
handler: this.onAddButtonFileSelected,
scope: this
}));
tb.x_buttons.remove = tb.addButton({
text: this.i18n.remove_btn_text,
tooltip: this.i18n.remove_btn_tip,
iconCls: 'ext-ux-uploaddialog-removebtn',
handler: this.onRemoveButtonClick,
scope: this
});
tb.x_buttons.reset = tb.addButton({
text: this.i18n.reset_btn_text,
tooltip: this.i18n.reset_btn_tip,
iconCls: 'ext-ux-uploaddialog-resetbtn',
handler: this.onResetButtonClick,
scope: this
});
tb.add('-');
tb.x_buttons.upload = tb.addButton({
text: this.i18n.upload_btn_start_text,
tooltip: this.i18n.upload_btn_start_tip,
iconCls: 'ext-ux-uploaddialog-uploadstartbtn',
handler: this.onUploadButtonClick,
scope: this
});
tb.add('-');
tb.x_buttons.indicator = tb.addItem(
new Ext.Toolbar.Item(
Ext.DomHelper.append(tb.getEl(), {
tag: 'div',
cls: 'ext-ux-uploaddialog-indicator-stoped',
html: '&#160'
})
)
);
tb.add('->');
tb.x_buttons.close = tb.addButton({
text: this.i18n.close_btn_text,
tooltip: this.i18n.close_btn_tip,
handler: this.onCloseButtonClick,
scope: this
});
},
renderStateCell : function(data, cell, record, row_index, column_index, store)
{
return this.state_tpl.apply({state: data});
},
renderFilenameCell : function(data, cell, record, row_index, column_index, store)
{
var view = this.grid_panel.getView();
var f = function() {
try {
Ext.fly(
view.getCell(row_index, column_index)
).child('.x-grid3-cell-inner').dom['qtip'] = data;
}
catch (e)
{}
}
f.defer(1000);
return data;
},
renderNoteCell : function(data, cell, record, row_index, column_index, store)
{
var view = this.grid_panel.getView();
var f = function() {
try {
Ext.fly(
view.getCell(row_index, column_index)
).child('.x-grid3-cell-inner').dom['qtip'] = data;
}
catch (e)
{}
}
f.defer(1000);
return data;
},
getFileExtension : function(filename)
{
var result = null;
var parts = filename.split('.');
if (parts.length > 1) {
result = parts.pop();
}
return result;
},
isPermittedFileType : function(filename)
{
var result = true;
if (this.permitted_extensions.length > 0) {
result = this.permitted_extensions.indexOf(this.getFileExtension(filename)) != -1;
}
return result;
},
 
isPermittedFile : function(browse_btn)
{
var result = false;
var filename = browse_btn.getInputFile().dom.value;
if (this.isPermittedFileType(filename)) {
result = true;
}
else {
Ext.Msg.alert(
this.i18n.error_msgbox_title,
String.format(
this.i18n.err_file_type_not_permitted,
filename,
this.permitted_extensions.join(this.i18n.permitted_extensions_join_str)
)
);
result = false;
}
return result;
},
fireFileTestEvent : function(browse_btn)
{
return this.fireEvent('filetest', this, browse_btn.getInputFile().dom.value) !== false;
},
addFileToUploadQueue : function(browse_btn)
{
var input_file = browse_btn.detachInputFile();
input_file.appendTo(this.form);
input_file.setStyle('width', '100px');
input_file.dom.disabled = true;
var store = this.grid_panel.getStore();
store.add(
new Ext.ux.UploadDialog.FileRecord({
state: Ext.ux.UploadDialog.FileRecord.STATE_QUEUE,
filename: input_file.dom.value,
note: this.i18n.note_queued_to_upload,
input_element: input_file
})
);
this.fsa.postEvent('file-added', input_file.dom.value);
},
fireFileAddEvent : function(filename)
{
this.fireEvent('fileadd', this, filename);
},
updateProgressBar : function()
{
if (this.is_uploading) {
var queued = this.getQueuedCount(true);
var value = 1 - queued / this.initial_queued_count;
this.progress_bar.updateProgress(
value,
String.format(
this.i18n.progress_uploading_text,
this.initial_queued_count - queued,
this.initial_queued_count
)
);
}
else {
this.progress_bar.updateProgress(0, this.i18n.progress_waiting_text);
}
},
updateToolbar : function()
{
var tb = this.grid_panel.getBottomToolbar();
if (this.is_uploading) {
tb.x_buttons.remove.disable();
tb.x_buttons.reset.disable();
tb.x_buttons.upload.enable();
if (!this.getAllowCloseOnUpload()) {
tb.x_buttons.close.disable();
}
Ext.fly(tb.x_buttons.indicator.getEl()).replaceClass(
'ext-ux-uploaddialog-indicator-stoped',
'ext-ux-uploaddialog-indicator-processing'
);
tb.x_buttons.upload.setIconClass('ext-ux-uploaddialog-uploadstopbtn');
tb.x_buttons.upload.setText(this.i18n.upload_btn_stop_text);
tb.x_buttons.upload.getEl()
.child(tb.x_buttons.upload.buttonSelector)
.dom[tb.x_buttons.upload.tooltipType] = this.i18n.upload_btn_stop_tip;
}
else {
tb.x_buttons.remove.enable();
tb.x_buttons.reset.enable();
tb.x_buttons.close.enable();
Ext.fly(tb.x_buttons.indicator.getEl()).replaceClass(
'ext-ux-uploaddialog-indicator-processing',
'ext-ux-uploaddialog-indicator-stoped'
);
tb.x_buttons.upload.setIconClass('ext-ux-uploaddialog-uploadstartbtn');
tb.x_buttons.upload.setText(this.i18n.upload_btn_start_text);
tb.x_buttons.upload.getEl()
.child(tb.x_buttons.upload.buttonSelector)
.dom[tb.x_buttons.upload.tooltipType] = this.i18n.upload_btn_start_tip;
if (this.getQueuedCount() > 0) {
tb.x_buttons.upload.enable();
}
else {
tb.x_buttons.upload.disable();
}
if (this.grid_panel.getSelectionModel().hasSelection()) {
tb.x_buttons.remove.enable();
}
else {
tb.x_buttons.remove.disable();
}
if (this.grid_panel.getStore().getCount() > 0) {
tb.x_buttons.reset.enable();
}
else {
tb.x_buttons.reset.disable();
}
}
},
saveInitialQueuedCount : function()
{
this.initial_queued_count = this.getQueuedCount();
},
incInitialQueuedCount : function()
{
this.initial_queued_count++;
},
setUploadingFlag : function()
{
this.is_uploading = true;
},
resetUploadingFlag : function()
{
this.is_uploading = false;
},
 
prepareNextUploadTask : function()
{
// Searching for first unuploaded file.
var store = this.grid_panel.getStore();
var record = null;
store.each(function(r) {
if (!record && r.get('state') == Ext.ux.UploadDialog.FileRecord.STATE_QUEUE) {
record = r;
}
else {
r.get('input_element').dom.disabled = true;
}
});
record.get('input_element').dom.disabled = false;
record.set('state', Ext.ux.UploadDialog.FileRecord.STATE_PROCESSING);
record.set('note', this.i18n.note_processing);
record.commit();
this.fsa.postEvent('file-upload-start', record);
},
fireUploadStartEvent : function()
{
this.fireEvent('uploadstart', this);
},
removeFiles : function(file_records)
{
var store = this.grid_panel.getStore();
for (var i = 0, len = file_records.length; i < len; i++) {
var r = file_records[i];
r.get('input_element').remove();
store.remove(r);
}
},
fireFileRemoveEvent : function(file_records)
{
for (var i = 0, len = file_records.length; i < len; i++) {
this.fireEvent('fileremove', this, file_records[i].get('filename'));
}
},
resetQueue : function()
{
var store = this.grid_panel.getStore();
store.each(
function(r) {
r.get('input_element').remove();
}
);
store.removeAll();
},
fireResetQueueEvent : function()
{
this.fireEvent('resetqueue', this);
},
uploadFile : function(record)
{
Ext.Ajax.request({
url : this.url,
params : this.base_params || this.baseParams || this.params,
method : 'POST',
form : this.form,
isUpload : true,
success : this.onAjaxSuccess,
failure : this.onAjaxFailure,
scope : this,
record: record
});
},
fireFileUploadStartEvent : function(record)
{
this.fireEvent('fileuploadstart', this, record.get('filename'));
},
updateRecordState : function(data)
{
if ('success' in data.response && data.response.success) {
data.record.set('state', Ext.ux.UploadDialog.FileRecord.STATE_FINISHED);
data.record.set(
'note', data.response.message || data.response.error || this.i18n.note_upload_success
);
}
else {
data.record.set('state', Ext.ux.UploadDialog.FileRecord.STATE_FAILED);
data.record.set(
'note', data.response.message || data.response.error || this.i18n.note_upload_error
);
}
data.record.commit();
},
fireUploadSuccessEvent : function(data)
{
this.fireEvent('uploadsuccess', this, data.record.get('filename'), data.response);
},
fireUploadErrorEvent : function(data)
{
this.fireEvent('uploaderror', this, data.record.get('filename'), data.response);
},
fireUploadFailedEvent : function(data)
{
this.fireEvent('uploadfailed', this, data.record.get('filename'));
},
fireUploadCompleteEvent : function()
{
this.fireEvent('uploadcomplete', this);
},
findUploadFrame : function()
{
this.upload_frame = Ext.getBody().child('iframe.x-hidden:last');
},
resetUploadFrame : function()
{
this.upload_frame = null;
},
removeUploadFrame : function()
{
if (this.upload_frame) {
this.upload_frame.removeAllListeners();
this.upload_frame.dom.src = 'about:blank';
this.upload_frame.remove();
}
this.upload_frame = null;
},
abortUpload : function()
{
this.removeUploadFrame();
var store = this.grid_panel.getStore();
var record = null;
store.each(function(r) {
if (r.get('state') == Ext.ux.UploadDialog.FileRecord.STATE_PROCESSING) {
record = r;
return false;
}
});
record.set('state', Ext.ux.UploadDialog.FileRecord.STATE_FAILED);
record.set('note', this.i18n.note_aborted);
record.commit();
},
fireUploadStopEvent : function()
{
this.fireEvent('uploadstop', this);
},
repostHide : function()
{
this.fsa.postEvent('hide');
},
flushEventQueue : function()
{
this.fsa.flushEventQueue();
},
/**
* @access private
*/
// -------------------------------------------------------------------------------------------- //
onWindowRender : function()
{
this.fsa.postEvent('window-render');
},
onWindowBeforeHide : function()
{
return this.isUploading() ? this.getAllowCloseOnUpload() : true;
},
onWindowHide : function()
{
this.fsa.postEvent('hide');
},
onWindowDestroy : function()
{
this.fsa.postEvent('destroy');
},
onGridRender : function()
{
this.fsa.postEvent('grid-render');
},
onGridSelectionChange : function()
{
this.fsa.postEvent('grid-selection-change');
},
onAddButtonFileSelected : function(btn)
{
this.fsa.postEvent('file-selected', btn);
},
onUploadButtonClick : function()
{
if (this.is_uploading) {
this.fsa.postEvent('stop-upload');
}
else {
this.fsa.postEvent('start-upload');
}
},
onRemoveButtonClick : function()
{
var selections = this.grid_panel.getSelectionModel().getSelections();
this.fsa.postEvent('remove-files', selections);
},
onResetButtonClick : function()
{
this.fsa.postEvent('reset-queue');
},
onCloseButtonClick : function()
{
this[this.closeAction].call(this);
},
onAjaxSuccess : function(response, options)
{
var json_response = {
'success' : false,
'message' : this.response
}
if(response.responseText == "OK" )
{
var data = {
record : options.record,
response : {
'success' : true,
'message' : this.response
}
}
this.fsa.postEvent('file-upload-success', data);
}
else {
this.fsa.postEvent('file-upload-error', data);
}
},
onAjaxFailure : function(response, options)
{
var data = {
record : options.record,
response : {
'success' : false,
'error' : this.i18n.note_upload_error
}
}
 
this.fsa.postEvent('file-upload-failed', data);
},
/**
* @access public
*/
// -------------------------------------------------------------------------------------------- //
startUpload : function()
{
this.fsa.postEvent('start-upload');
},
stopUpload : function()
{
this.fsa.postEvent('stop-upload');
},
getUrl : function()
{
return this.url;
},
setUrl : function(url)
{
this.url = url;
},
getBaseParams : function()
{
return this.base_params;
},
setBaseParams : function(params)
{
this.base_params = params;
},
getUploadAutostart : function()
{
return this.upload_autostart;
},
setUploadAutostart : function(value)
{
this.upload_autostart = value;
},
getAllowCloseOnUpload : function()
{
return this.allow_close_on_upload;
},
setAllowCloseOnUpload : function(value)
{
this.allow_close_on_upload;
},
getResetOnHide : function()
{
return this.reset_on_hide;
},
setResetOnHide : function(value)
{
this.reset_on_hide = value;
},
getPermittedExtensions : function()
{
return this.permitted_extensions;
},
setPermittedExtensions : function(value)
{
this.permitted_extensions = value;
},
isUploading : function()
{
return this.is_uploading;
},
isNotEmptyQueue : function()
{
return this.grid_panel.getStore().getCount() > 0;
},
getQueuedCount : function(count_processing)
{
var count = 0;
var store = this.grid_panel.getStore();
store.each(function(r) {
if (r.get('state') == Ext.ux.UploadDialog.FileRecord.STATE_QUEUE) {
count++;
}
if (count_processing && r.get('state') == Ext.ux.UploadDialog.FileRecord.STATE_PROCESSING) {
count++;
}
});
return count;
},
hasUnuploadedFiles : function()
{
return this.getQueuedCount() > 0;
}
});
 
// ---------------------------------------------------------------------------------------------- //
 
var p = Ext.ux.UploadDialog.Dialog.prototype;
p.i18n = {
title: 'Ajout simple de fichiers',
state_col_title: 'Etat',
state_col_width: 70,
filename_col_title: 'Fichier',
filename_col_width: 230,
note_col_title: 'Note',
note_col_width: 150,
add_btn_text: 'Ajouter',
add_btn_tip: 'Ajoute un fichier à la liste.',
remove_btn_text: 'Supprimer',
remove_btn_tip: 'Supprime un fichier de la liste.',
reset_btn_text: 'Vider',
reset_btn_tip: 'Vider la liste.',
upload_btn_start_text: 'Envoyer',
upload_btn_stop_text: 'Annuler',
upload_btn_start_tip: 'Envoie les fichiers de la liste sur le serveur.',
upload_btn_stop_tip: 'Stopper l\'envoi.',
close_btn_text: 'Fermer',
close_btn_tip: 'Ferme la fenêtre.',
progress_waiting_text: 'En attente...',
progress_uploading_text: 'Envoi de: {0} sur {1} fichiers terminé.',
error_msgbox_title: 'Erreur',
permitted_extensions_join_str: ',',
err_file_type_not_permitted: 'Cette extension de fichier n\'est pas permise.<br/>Selectionnez un fichier portant une des extensions suivantes: {1}',
note_queued_to_upload: 'Prêt à être envoyé.',
note_processing: 'Envoi...',
note_upload_failed: 'Le serveur est inaccessible ou bien une erreur serveur s\'est produite.',
note_upload_success: 'OK.',
note_upload_error: 'Erreur d\'envoi.',
note_aborted: 'Annulé par l\'utilisateur.'
}
/branches/v1.7-croissant/widget/widget.ini.defaut.php
34,7 → 34,7
baseURLServicesEfloreTpl = "http://www.tela-botanica.org/service:eflore:%s/%s/%s"
; Dossier de stockage temporaire des images (ATTENTION : mettre le slash à la fin)
imagesTempDossier = "/home/telabotap/www/eflore/cel/cache/images/"
; Squelette d'URL pour les images temporaires sotckées sur le serveur
; Squelette d'URL pour les images temporaires sotckées sur le serveur - OBSOLETE
imagesTempUrlTpl = "http://www.tela-botanica.org/eflore/cel/cache/images/%s"
; Url du service fournissant des infos sur les noms à partir d'un num tax
infosTaxonUrl = "http://www.tela-botanica.org/service:eflore:0.1/bdtfx/noms/%s"
/branches/v1.7-croissant/widget/modules/saisie/squelettes/defaut/defaut.tpl.html
412,7 → 412,7
</div>
</div>
</form>
<form id="form-upload" class="form-horizontal" action="<?=$url_base?>saisie?projet=sauvages&amp;service=upload-image"
<form id="form-upload" class="form-horizontal" action="<?= $url_ws_upload ?>?projet=sauvages"
method="post" enctype="multipart/form-data">
<h2>Image(s) de cette plante</h2>
<strong>Ajouter une image</strong>
/branches/v1.7-croissant/widget/modules/saisie/squelettes/defaut/js/defaut.js
784,9 → 784,9
$("#dialogue-obs-transaction-ko .alert-txt").append('<pre class="msg-erreur">'+erreurMsg+'</pre>');
$("#dialogue-obs-transaction-ko .alert-txt").append('<pre class="msg-debug">Débogage : '+debugMsg+'</pre>');
}
var hrefCourriel = "mailto:cel@tela-botanica.org?"+
"subject=Disfonctionnement du widget de saisie "+TAG_PROJET+
"&body="+erreurMsg+"\nDébogage :\n"+debugMsg;
var hrefCourriel = "mailto:cel_remarques@tela-botanica.org?"+
"subject=Dysfonctionnement du widget de saisie "+TAG_PROJET+
"&body="+erreurMsg+"%0D%0ADébogage :%0D%0A"+debugMsg;
$('#dialogue-obs-transaction-ko .alert-txt').append($("#tpl-transmission-ko").clone()
.find('.courriel-erreur')
/branches/v1.7-croissant/widget/modules/saisie/squelettes/florileges/florileges.tpl.html
904,7 → 904,7
</div>
</form>
<form id="form-upload" class="form-horizontal" action="<?=$url_base?>saisie?projet=sauvages&amp;service=upload-image"
<form id="form-upload" class="form-horizontal" action="<?= $url_ws_upload ?>?projet=sauvages"
method="post" enctype="multipart/form-data">
<div class="row-fluid">
<div class="span12 well">
/branches/v1.7-croissant/widget/modules/saisie/squelettes/sauvages/js/sauvages.js
555,6 → 555,7
'num_nom_ret' : taxons[numNomSel]['num_nom_ret'],
'num_taxon' : taxons[numNomSel]['num_taxon'],
'famille' : taxons[numNomSel]['famille'],
'nom_referentiel' : 'bdtfx',
'nom_fr' : taxons[numNomSel]['nom_fr'],
'milieu' : milieux.join(','),
'latitude' : $("#latitude").val(),
/branches/v1.7-croissant/widget/modules/saisie/squelettes/sauvages/sauvages.tpl.html
232,7 → 232,7
</form>
<div id="zone-fiche-terrain-photo">
<form id="form-upload" action="<?=$url_base?>saisie?projet=sauvages&amp;service=upload-image"
<form id="form-upload" action="<?= $url_ws_upload ?>?projet=sauvages"
method="post" enctype="multipart/form-data">
<fieldset id="partie-photo">
<legend>Ajouter une photo</legend>
/branches/v1.7-croissant/widget/modules/saisie/squelettes/biodiversite34/js/biodiversite34.js
114,6 → 114,7
'num_nom_ret' : taxons[numNomSel]['num_nom_ret'],
'num_taxon' : taxons[numNomSel]['num_taxon'],
'famille' : taxons[numNomSel]['famille'],
'nom_referentiel' : 'bdtfx',
'nom_fr' : taxons[numNomSel]['nom_fr'],
'milieu' : $("#milieu option:selected").val(),
'latitude' : $("#latitude").val(),
/branches/v1.7-croissant/widget/modules/saisie/Saisie.php
23,6 → 23,7
const DS = DIRECTORY_SEPARATOR;
const PROJET_DEFAUT = 'defaut';
const WS_SAISIE = 'CelWidgetSaisie';
const WS_UPLOAD = 'CelWidgetUploadImageTemp';
const WS_OBS = 'CelObs';
const WS_NOM = 'noms';
private $NS_PROJET_VERSION = '1.01';
107,6 → 108,7
$widget['donnees']['url_base'] = sprintf($this->config['chemins']['baseURLAbsoluDyn'], '');
$widget['donnees']['url_ws_saisie'] = sprintf($this->config['chemins']['baseURLServicesCelTpl'], self::WS_SAISIE);
$widget['donnees']['url_ws_obs'] = sprintf($this->config['chemins']['baseURLServicesCelTpl'], self::WS_OBS);
$widget['donnees']['url_ws_upload'] = sprintf($this->config['chemins']['baseURLServicesCelTpl'], self::WS_UPLOAD);
$widget['donnees']['url_ws_annuaire'] = sprintf($this->config['chemins']['baseURLServicesAnnuaireTpl'], 'utilisateur/identite-par-courriel/');
 
 
/branches/v1.7-croissant/widget/modules/saisie
Property changes:
Modified: svn:mergeinfo
Merged /trunk/widget/modules/saisie:r1840-1913
/branches/v1.7-croissant/widget/modules/cartopoint/squelettes/carte_defaut.tpl.html
248,7 → 248,7
<td>
<span class="nom-sci">&nbsp;
{{if nn != null && nn != 0 && nn != ''}}
<a href="{urlEflore}"
<a href="${urlEflore}"
onclick="ouvrirNouvelleFenetre(this, event)">
${nomSci}
</a>
/branches/v1.7-croissant/widget/modules/photo/config.defaut.ini
1,8 → 1,10
[photo]
; Chemin pour l'autoload à ajouter
autoload = "bibliotheque/;bibliotheque/xml_feed_parser/1.0.4/;bibliotheque/xml_feed_parser/1.0.4/parsers/"
; URL ou chemin du flux RSS contenant les liens vers les photos
; URL ou chemin du flux RSS contenant les liens vers les photos - ne pas oublier de changer motif_guid en même temps!
fluxRssUrl = "http://www.tela-botanica.org/service:cel:CelSyndicationImage/multicriteres/atom/M"
; Expression régulière pour récupérer le numéro de l'image à partir de l'URL renvoyée par le flux Atom
motif_guid = "/appli:cel-img:([0-9]+)[^.]+\.jpg$/"
; Squelette d'url pour accéder à la fiche eFlore
efloreUrlTpl = "http://www.tela-botanica.org/bdtfx-nn-%s"
; Nombre de vignette à afficher : nombre de vignettes par ligne et nombre de lignes séparés par une vigule (ex. : 4,3).
/branches/v1.7-croissant/widget/modules/photo/Photo.php
176,8 → 176,8
$item['eflore_url'] = $item['lien'] ;
}
// Récupération du GUID
if (preg_match('/appli:cel-img:([0-9]+)[^.]+\.jpg$/', $entree->guid, $match)) {
// Récupération du GUID - aaaaah c'est cracra si on change la config yatoukipett !! Satan is in this code !!!
if (preg_match($this->config['photo']['motif_guid'], $entree->guid, $match)) {
$item['guid'] = (int) $match[1];
} else {
$item['guid'] = $entree->guid;
/branches/v1.7-croissant/Changelog
1,3 → 1,8
Changements <next>:
config jrest: ajout de api_host, dédié à la simplification des appels aux webservices
config jrest: ajout de images_temp_url, dédié à la lecture des images temporaires du widget de saisie
config widget: imagesTempUrlTpl est désormais obsolète
config widget/photo: ajout de motif_guid
war/config.default.js: bdtfx 2.00 et bdtxa 1.01
 
Changements 20130917 [création de la branche "v1.7-Croissant"]:
/branches/v1.7-croissant/jrest/lib/ImageRecreation.php
1,8 → 1,8
<?php
Class ImageRecreation {
 
private $droits = 0705;
private $formats = array('CRX2S','CXS','CS','CRS','XS','S','M','L','XL','X2L','X3L');
private $droits = 0755;
private $formats = array('CRX2S','CRXS','CXS','CS','CRS','XS','S','M','L','XL','X2L','X3L');
const MODE_GD = 'gd';
const MODE_IMAGEMAGICK = 'imagemagick';
private $mode;
/branches/v1.7-croissant/jrest/lib/GestionObservation.php
1,27 → 1,30
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
 
/**
* PHP Version 5
* PHP Version 5.2
*
* @category PHP
* @package jrest
* @author Raphaël Droz <raphael@tela-botanica.org>
* @author Aurelien Peronnet <aurelien@tela-botanica.org>
* @copyright 2010 Tela-Botanica
* @copyright 2010, 2013 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @link /doc/jrest/
*/
 
/**
*
* Classe de gestion de l'ajout, modification et suppression des observations
*
* in=utf8
* out=utf8
* TODO: $sous_requete .= ' date_modification = now() '
* devrait être une clause ON UPDATE ou un TRIGGER
* afin de mettre à jour la date de modification uniquement lorsqu'une modification a effectivement eu lieu
*
*/
class GestionObservation extends Cel {
static $cel_obs = array(
"id_observation", "ordre", "ce_utilisateur", "prenom_utilisateur", "nom_utilisateur", "courriel_utilisateur", "nom_sel", "nom_sel_nn", "nom_ret", "nom_ret_nn", "nt", "famille", "nom_referentiel",
"ce_zone_geo", "zone_geo", "lieudit", "station", "milieu", "latitude", "longitude", "altitude", "geodatum", "date_observation", "mots_cles_texte", "commentaire", "transmission",
"date_creation", "date_modification", "date_transmission", "abondance", "certitude", "phenologie", "code_insee_calcul");
 
/**
* Ajoute une observation grâce aux paramètres fournis
*
31,13 → 34,28
* @return true ou false suivant le succès de l'opération
*/
public function ajouterObservation($utilisateur, $parametres) {
$origin_params = $parametres;
$base_param = array('nom_sel_nn' => NULL,
'nom_sel' => NULL,
'nom_ret_nn' => NULL,
'nom_referentiel' => NULL);
$parametres = array_merge($base_param, $parametres);
$retour = true;
$parametres['ordre'] = $this->renvoyerDernierOrdreUtilisePlusUn($utilisateur);
$this->traiterEspece($parametres);
$this->formaterParametresObservation($parametres);
 
// si la détermination à échoué, alors:
// soit le référentiel d'origine était "valide", soit non
if(!$parametres['nom_sel_nn']) {
// quoiqu'il en soit, on le met à "autre"
$parametres['nom_referentiel'] = Cel::$fallback_referentiel;
}
 
$this->ajoutInfoUtilisateurARequete($parametres);
self::formaterParametresObservation($parametres);
 
$requete_insertion_observation = 'INSERT INTO cel_obs ';
$sous_requete_colonnes = $this->traiterParametresObservationEtConstruireSousRequeteAjout($parametres);
110,13 → 128,12
'nom_sel' => NULL,
'nom_ret_nn' => NULL,
'nom_referentiel' => NULL);
$parametres = array_merge($base_param, $parametres);
// $parametres = array_merge($base_param, $parametres);
$retour = true;
$requete_modification = "UPDATE cel_obs SET " ;
 
// si pas de nom_sel : on supprime les champs automatiques. et le référentiel.
if(!isset($parametres['nom_sel']) || !@$parametres['nom_sel']) {
if(false && (!isset($parametres['nom_sel']) || !@$parametres['nom_sel'])) {
$parametres['nom_referentiel'] = NULL; // pas d'update de traiterParametresObservationEtConstruireSousRequeteMaj()
$requete_modification .= "nom_referentiel = NULL, nom_sel_nn = NULL, nom_ret_nn = NULL, nom_ret = NULL, nt = NULL, famille = NULL,";
}
135,20 → 152,25
famille = IF(SUBSTR(nom_referentiel, 1, 5) != "$r", NULL, famille),
EOF;
}
else {
elseif(isset($parametres['nom_sel'])) {
// uniquement en cas de nom_sel présent
$this->traiterEspece($parametres);
}
$this->formaterParametresObservation($parametres);
 
$requete_modification .= $this->traiterParametresObservationEtConstruireSousRequeteMaj($parametres) .
" WHERE ordre IN (".$ordre.") AND ce_utilisateur = ".Cel::db()->proteger($utilisateur);
self::formaterParametresObservation($parametres);
 
$champ_maj = self::traiterParametresObservationEtConstruireSousRequeteMaj($parametres);
$champ_maj[] = "date_modification = now()";
 
$requete_modification .=
implode(', ', $champ_maj)
. " WHERE ordre IN (".$ordre.") AND ce_utilisateur = ".Cel::db()->proteger($utilisateur);
 
 
// important ! ne pas utiliser la fonction executerRequete qui renvoie une erreur si la requete contient des | (pipes)
// ce qui peut arriver dans les commentaires
// TODO: corriger la fonction ou bien continuer à utiliser executerRequeteSimple
$resultat_modification = Cel::db()->executerRequeteSimple($requete_modification);
$resultat_modification = Cel::db()->executerRequeteSimple($requete_modification . ' -- ' . __FILE__ . ':' . __LINE__);
if ($resultat_modification === false) {
$retour = false;
159,6 → 181,39
}
/**
* @return nombre d'observations mises à jour, ou FALSE en cas de problème
*/
static function modifierMultiplesObservation($utilisateur, Array $ordre, $parametres) {
// nous pouvons aussi retirer 'ce_utilisateur' (== $utilisateur) qui sera dans la clause WHERE
$exclusions = array('nom_sel_nn', 'nom_sel', 'nom_ret_nn', 'nom_referentiel', 'ce_utilisateur');
$parametres = array_diff_key($parametres, array_flip($exclusions));
$parametres = array_intersect_key($parametres, array_flip(self::$cel_obs));
 
$parametres = array_filter(
$parametres,
create_function('$e','return strpos($e, "(Valeurs multiples)") === false;'));
 
// modifie $parametres par référence
self::formaterParametresObservation($parametres);
 
$champ_maj = self::traiterParametresObservationEtConstruireSousRequeteMaj($parametres);
if(!$champ_maj) return 0; // rien à mettre à jour finalement
 
$champ_maj[] = "date_modification = now()";
$nb_upd = Cel::db()->executer(sprintf(
"UPDATE cel_obs SET %s WHERE ordre IN (%s) AND ce_utilisateur = %s -- %s:%d",
implode(', ', $champ_maj),
implode(', ', $ordre),
Cel::db()->proteger($utilisateur),
__FILE__, __LINE__));
 
if($nb_upd === FALSE) return FALSE;
return $nb_upd;
// TODO: return json_encode(updated_rows());
}
 
/**
* Modifie une observation publique dont l'id et l'utilisateur sont passé en paramètre
*
* @param int $utilisateur id utilisateur du proprietaire de l'observation
175,11 → 230,15
$parametres = array_merge($base_param, $parametres);
 
$this->traiterEspece($parametres);
$this->formaterParametresObservation($parametres);
self::formaterParametresObservation($parametres);
 
$retour = true;
 
$champ_maj = self::traiterParametresObservationEtConstruireSousRequeteMaj($parametres);
$champ_maj[] = "date_modification = now()";
 
$requete_modification = "UPDATE cel_obs SET " .
$this->traiterParametresObservationEtConstruireSousRequeteMaj($parametres) .
implode(', ', $champ_maj) .
" WHERE id_observation = ".Cel::db()->proteger($id).
" AND ce_utilisateur = ".Cel::db()->proteger($utilisateur)." ".
" AND transmission = 1";
187,14 → 246,13
// important ! ne pas utiliser la fonction executerRequete qui renvoie une erreur si la requete contient des | (pipes)
// ce qui peut arriver dans les commentaires
// TODO: corriger la fonction ou bien continuer à utiliser executerRequeteSimple
$resultat_modification = Cel::db()->executerRequeteSimple($requete_modification);
$resultat_modification = Cel::db()->executerRequeteSimple($requete_modification . ' -- ' . __FILE__ . ':' . __LINE__);
if ($resultat_modification === false) {
$retour = false;
$this->logger("CEL_bugs","Erreur de mise à jour de l\'observation : ".$id);
}
return $retour;
return $resultat_modification;
}
/**
374,7 → 432,7
 
// XXX: ne devrait plus être nécessaire maintenant que rechercherInformationsComplementairesSurNom() [plus précisément effectuerRequeteUrlRecherche()]
// a été modifiée pour retourner tous les champs nécessaire.
if ($deuxieme_passe && (!$parametres['nom_ret_nn'] || !$parametres['nt'])) {
if ($deuxieme_passe && (! array_key_exists('nom_ret_nn', $parametres) || ! array_key_exists('nt', $parametres))) {
// Utilisation d'un nom faisant parti du referentiel : recherche du nom valide correspondant
$chercheur_infos_complementaires = new RechercheInfosTaxonBeta($this->config , $code_referentiel);
$complement = $chercheur_infos_complementaires->effectuerRequeteInfosComplementairesSurNumNom($parametres['nom_sel_nn']);
400,6 → 458,16
$parametres['nom_referentiel'] = $code_referentiel;
}
 
// uniquement nécessaire lors de l'ajout
private function ajoutInfoUtilisateurARequete(&$parametres) {
if(! isset($parametres['ce_utilisateur'])) return;
$infos_utilisateur = $this->getInfosComplementairesUtilisateur($parametres['ce_utilisateur']);
$parametres['courriel_utilisateur'] = $infos_utilisateur['courriel'];
$parametres['nom_utilisateur'] = $infos_utilisateur['nom'];
$parametres['prenom_utilisateur'] = $infos_utilisateur['prenom'];
}
 
/**
* Formate les paramètres fournis en ajoutant des infos complementaires
*
407,16 → 475,7
*
* @return $parametres le tableau modifié selon ce qu'il contenait
*/
private function formaterParametresObservation(&$parametres) {
if(isset($parametres['ce_utilisateur'])) {
$infos_utilisateur = $this->getInfosComplementairesUtilisateur($parametres['ce_utilisateur']);
$parametres['courriel_utilisateur'] = $infos_utilisateur['courriel'];
$parametres['nom_utilisateur'] = $infos_utilisateur['nom'];
$parametres['prenom_utilisateur'] = $infos_utilisateur['prenom'];
}
static function formaterParametresObservation(&$parametres) {
// Pour empecher que des numéros de département de 1 à 9 soient saisis sans 0
// TODO: décider quoi faire pour les zones géo plus générales
if (isset($parametres['ce_zone_geo'])) {
429,9 → 488,9
}
if (strlen($parametres['ce_zone_geo']) > 0 && strlen($parametres['ce_zone_geo']) <= 2) {
$parametres['ce_zone_geo'] = $this->obtenirCodeInseeCommunePourNomEtDepartement($parametres['zone_geo'], $parametres['ce_zone_geo']);
$parametres['ce_zone_geo'] = Cel::obtenirCodeInseeCommunePourNomEtDepartement($parametres['zone_geo'], $parametres['ce_zone_geo']);
} else {
$parametres['ce_zone_geo'] = $this->convertirCodeInseeVersCodeZoneGeo($parametres['ce_zone_geo']);
$parametres['ce_zone_geo'] = 'INSEE-C:'. $parametres['ce_zone_geo'];
}
}
}
493,13 → 552,12
* @return string une sous requete utilisable pour la modification d'une observation
* selon la syntaxe UPDATE table SET colonne1 = valeur1, colonne2 = valeur2 WHERE condition
*/
private function traiterParametresObservationEtConstruireSousRequeteMaj($parametres) {
$sous_requete = '';
static function traiterParametresObservationEtConstruireSousRequeteMaj($parametres) {
$champs = array();
// Nullifiage ...
// TODO: code dupliqué, en faire une fonction à mettre à la place appropriée
foreach($parametres as $cle => $valeur) {
// Pour apparaitre le premier dans les tris ...
if (trim($valeur) == "" || trim($valeur) == "null" || trim($valeur) == "000null") {
$valeur = "NULL";
506,13 → 564,8
} else {
$valeur = Cel::db()->proteger($valeur);
}
$sous_requete .= $cle." = ".$valeur.", ";
$champs[] = $cle." = ".$valeur;
}
$sous_requete .= ' date_modification = now() ';
return $sous_requete;
return $champs;
}
}
?>
/branches/v1.7-croissant/jrest/lib/RechercheInfosTaxonBeta.php
40,6 → 40,7
$this->url_service_nom = str_replace('{referentiel}', $this->code_referentiel ,$config['eflore']['url_service_nom']);
$this->url_service_taxon = str_replace('{referentiel}', $this->code_referentiel ,$config['eflore']['url_service_taxon']);
$this->url_service_chorologie_obs = $config['eflore']['url_service_chorologie_obs'];
$this->config = $config;
}
public function rechercherGenreEspeceSurPrefixe($genre = null, $espece = null) {
84,26 → 85,30
public function rechercherInformationsComplementairesSurNom($nom_saisi) {
$nom_saisi = trim($nom_saisi);
// Essai de recherche sur le nom saisi tel quel
$liste_genre_espece = $this->effectuerRequeteUrlRecherche($nom_saisi, true);
if(empty($liste_genre_espece)) {
$liste_genre_espece = $this->effectuerRequeteUrlRecherche($nom_saisi, 'stricte');
if($liste_genre_espece) return $liste_genre_espece;
 
// Essai de recherche stricte en tentant de supprimer le nom d'auteur
$nom_saisi_sans_auteur = self::supprimerAuteur($nom_saisi);
if($nom_saisi_sans_auteur) { // ne pas faire la requête sur un mot vide
$liste_genre_espece = $this->effectuerRequeteUrlRecherche($nom_saisi_sans_auteur, true);
if( ($nom_saisi_sans_auteur = self::supprimerAuteur($nom_saisi)) ) { // ne pas faire la requête sur un mot vide
$liste_genre_espece = $this->effectuerRequeteUrlRecherche($nom_saisi_sans_auteur, 'stricte');
}
if(empty($liste_genre_espece)) {
// Dernière tentative : essai de recherche étendue
$liste_genre_espece = $this->effectuerRequeteUrlRecherche($nom_saisi, false);
}
}
if($liste_genre_espece) return $liste_genre_espece;
 
// avant-dernière tentative : essai de recherche étendue
$liste_genre_espece = $this->effectuerRequeteUrlRecherche($nom_saisi, 'etendue');
if($liste_genre_espece) return $liste_genre_espece;
 
// dernière tentative: concaténation (nom_sci,auteur) (= nom-retenu généré utilisé comme nom_sci)
$liste_genre_espece = $this->effectuerRequeteUrlRecherche($nom_saisi, 'concat');
return $liste_genre_espece;
}
private function effectuerRequeteUrlRecherche($nom_saisi, $stricte = true) {
private function effectuerRequeteUrlRecherche($nom_saisi, $mode = 'stricte') {
$res = @json_decode(file_get_contents(sprintf('%1$s?masque=%2$s&recherche=%3$s&ns.format=txt&retour.champs=%4$s&navigation.limite=1',
$this->url_service_nom,
urlencode($nom_saisi),
($stricte ? 'stricte' : 'etendue'),
$mode,
implode(',', array("id","nom_sci","auteur","nom_retenu.id","famille","num_taxonomique","nom_retenu_complet")))));
if(!$res) return NULL;
$resultat = (array)$res->resultat;
136,7 → 141,20
return strpos($nom_saisi,'x ') === 0;
}
public function effectuerRequeteInfosComplementairesSurNumNom($num_nom) {
public function effectuerRequeteInfosComplementairesSurNumNom($num_nom, $ref = NULL) {
if($ref && isset($this->config['eflore']['api_host'])) {
return @json_decode(file_get_contents($this->config['eflore']['api_host'] . '/' .
$ref . '/' .
'noms' . '/' .
$num_nom .
'?retour.champs=' . implode(',', array('nom_sci,auteur',
'id',
'nom_retenu_complet',
'nom_retenu.id',
'num_taxonomique',
'famille'))));
}
// XXX: compat
return @json_decode(file_get_contents($this->url_service_nom.'/'.$num_nom.'?retour.champs=nom_sci,auteur,id,nom_retenu_complet,nom_retenu.id,num_taxonomique,famille'));
}
 
183,10 → 201,12
// TODO: ignorer la colonne référentiel, et utiliser le référentiel donné
// mais il faut alors avertir le service (d'import/modif) d'utiliser le référentiel
// passé au nom d'espèce
// Seul le effectuerRequeteInfosComplementairesSurNumNom() le supporte, car c'est encore
// un peu complexe à implémenter proprement pour cause d'attributs de classes.
}
// Numero nomenclatural
if ($type == 'nn') {
$obj = $this->effectuerRequeteInfosComplementairesSurNumNom($num);
$obj = $this->effectuerRequeteInfosComplementairesSurNumNom($num, $ref);
}
// Numero taxonomique
else {
/branches/v1.7-croissant/jrest/lib/Cel.php
121,10 → 121,7
 
protected function verifierSecuriteParametreUrl($param) {
//$verifier = array('NULL', "\n", "\r", "\\", "'", '"', "\x00", "\x1a", ';');
if (!is_string($param)) return $param;
 
$param = strip_tags($param);
return $param;
return is_string($param) ? strip_tags($param) : $param;
}
 
private function definirParametresUrlParDefaut() {
219,12 → 216,12
print $contenu;
}
 
private function envoyerAuth($message_accueil, $message_echec) {
static function envoyerAuth($message_accueil, $message_echec) {
header('HTTP/1.0 401 Unauthorized');
header('WWW-Authenticate: Basic realm="'.mb_convert_encoding($message_accueil, 'ISO-8859-1', 'UTF-8').'"');
header('Content-type: text/plain; charset=UTF-8');
print $message_echec;
exit(0);
exit;
}
 
//+----------------------------------------------------------------------------------------------------------------+
240,14 → 237,12
//+----------------------------------------------------------------------------------------------------------------+
// GESTION DE L'IDENTIFICATION
protected function getAuthIdentifiant() {
$id = (isset($_SERVER['PHP_AUTH_USER'])) ? $_SERVER['PHP_AUTH_USER'] : null;
return $id;
static function getAuthIdentifiant() {
return isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : null;
}
 
protected function getAuthMotDePasse() {
$mdp = (isset($_SERVER['PHP_AUTH_PW'])) ? $_SERVER['PHP_AUTH_PW'] : null;
return $mdp;
static function getAuthMotDePasse() {
return isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : null;
}
 
public function authentifierAdmin() {
268,19 → 263,11
}
 
public function isAdmin($id) {
$admins = $this->config['jrest_admin']['admin'];
$admin_tab = explode(',',$admins);
 
if (in_array($id,$admin_tab)) {
return true;
} else {
return false;
return in_array($id, explode(',', $this->config['jrest_admin']['admin']));
}
}
 
public function controleUtilisateur($id) {
 
if (isset($_SESSION['user']) && isset($_SESSION['user']['name']) && $_SESSION['user']['name'] == '') {
if (@array_key_exists('name', $_SESSION['user']) && empty($_SESSION['user']['name'])) {
//cas de la session temporaire, on ne fait rien de particulier
} else {
if (isset($_SESSION['user']) && isset($_SESSION['user']['name']) && !$this->isAdmin($_SESSION['user']['name']) && $_SESSION['user']['name'] != $id) {
292,12 → 279,10
}
public function controleAppelIpAutorisee() {
$ips_autorisees = explode(',', $this->config['jrest_admin']['ip_autorisees']);
$ip_appelante = $_SERVER['REMOTE_ADDR'];
if(!in_array($ip_appelante, $ips_autorisees) && $ip_appelante != $_SERVER['SERVER_ADDR']) {
$ips_autorisees = explode(',', @$this->config['jrest_admin']['ip_autorisees']);
if(!in_array($_SERVER['REMOTE_ADDR'], $ips_autorisees) && $_SERVER['REMOTE_ADDR'] != $_SERVER['SERVER_ADDR']) {
header('HTTP/1.0 401 Unauthorized');
echo 'Accès interdit';
exit(0);
exit('Accès interdit');
}
return true;
}
315,11 → 300,11
}
 
private function authentifier($message_accueil, $message_echec, $type) {
$id = $this->getAuthIdentifiant();
if (!isset($id)) {
$this->envoyerAuth($message_accueil, $message_echec);
} else {
if ($type == 'Utilisateur' && $this->getAuthMotDePasse() == 'debug') {
if (!isset($_SERVER['PHP_AUTH_USER'])) {
self::envoyerAuth($message_accueil, $message_echec); // exit
}
 
if ($type == 'Utilisateur' && self::getAuthMotDePasse() == 'debug') {
$autorisation = true;
} else {
$methodeAutorisation = "etre{$type}Autorise";
326,15 → 311,15
$autorisation = $this->$methodeAutorisation();
}
if ($autorisation == false) {
$this->envoyerAuth($message_accueil, $message_echec);
self::envoyerAuth($message_accueil, $message_echec);
}
}
 
return true;
}
 
public function etreUtilisateurAutorise() {
$identifiant = $this->getAuthIdentifiant();
$mdp = md5($this->getAuthMotDePasse());
$identifiant = self::getAuthIdentifiant();
$mdp = md5(self::getAuthMotDePasse());
$service = "TestLoginMdp/$identifiant/$mdp";
$url = sprintf($this->config['settings']['baseURLServicesAnnuaireTpl'], $service);
$json = $this->getRestClient()->consulter($url);
345,38 → 330,28
}
 
public function etreAdminAutorise() {
$identifiant = $this->getAuthIdentifiant();
$identifiant = self::getAuthIdentifiant();
$autorisation = ($this->etreUtilisateurAutorise() && $this->etreAdminCel($identifiant)) ? true : false;
return $autorisation;
}
 
public function etreAdminCel($courriel) {
$admins = $this->config['jrest_admin']['admin'];
$courriels_autorises = explode(',', $admins);
 
$autorisation = (in_array($courriel, $courriels_autorises)) ? true : false ;
return $autorisation;
// parmi les admins ?
return in_array($courriel, explode(',', $this->config['jrest_admin']['admin']));
}
 
public function getInfosComplementairesUtilisateur($id_utilisateur) {
$defaut_infos = array('prenom' => $id_utilisateur, 'nom' => $id_utilisateur, 'courriel' => $id_utilisateur);
if(! is_numeric($id_utilisateur)) return $defaut_infos;
 
$infos_utilisateur = array('prenom' => $id_utilisateur, 'nom' => $id_utilisateur, 'courriel' => $id_utilisateur);
$resultat_infos_utilisateur = Cel::db()->requeter(
'SELECT prenom, nom, courriel FROM cel_utilisateurs'
. ' WHERE id_utilisateur = '.Cel::db()->proteger($id_utilisateur));
 
if(is_numeric($id_utilisateur)) {
 
$requete_infos_utilisateur = 'SELECT prenom, nom, courriel FROM cel_utilisateurs '.
'WHERE id_utilisateur = '.Cel::db()->proteger($id_utilisateur);
 
$resultat_infos_utilisateur = Cel::db()->requeter($requete_infos_utilisateur);
 
if($resultat_infos_utilisateur && is_array($resultat_infos_utilisateur) && count($resultat_infos_utilisateur) > 0) {
$infos_utilisateur = $resultat_infos_utilisateur[0];
if($resultat_infos_utilisateur && count($resultat_infos_utilisateur)) return $resultat_infos_utilisateur[0];
return $defaut_infos; // autrement, info par défaut
}
}
 
return $infos_utilisateur;
}
 
public function getInfosComplementairesUtilisateurPourMail($mail_utilisateur) {
 
$infos_utilisateur = array('prenom' => $mail_utilisateur, 'nom' => $mail_utilisateur, 'courriel' => $mail_utilisateur);
456,8 → 431,7
}
 
protected function tronquerCourriel($courriel) {
$courriel = preg_replace('/[^@]+$/i', '...', $courriel);
return $courriel;
return preg_replace('/[^@]+$/i', '...', $courriel);
}
 
protected function nettoyerTableau(Array $tableau) {
546,28 → 520,16
return $code_departement;
}
 
protected function convertirCodeInseeVersCodeZoneGeo($code_insee) {
return 'INSEE-C:'.$code_insee;
}
static function obtenirCodeInseeCommunePourNomEtDepartement($nom_commune, $code_insee) {
$resultat = Cel::db()->requeter(sprintf(
'SELECT id_zone_geo FROM cel_zones_geo WHERE nom LIKE %s AND id_zone_geo LIKE %s',
Cel::db()->proteger($nom_commune),
Cel::db()->proteger("INSEE-C:" . $code_insee . '%')));
 
protected function obtenirCodeInseeCommunePourNomEtDepartement($nom_commune, $dpt) {
 
$code_insee = $dpt;
 
$requete = 'SELECT id_zone_geo FROM cel_zones_geo '.
'WHERE nom LIKE '.Cel::db()->proteger($nom_commune).' '.
'AND id_zone_geo LIKE "INSEE-C:'.$dpt.'%"';
 
$resultat = Cel::db()->requeter($requete);
 
if(is_array($resultat) && count($resultat) > 0) {
$code_insee = $resultat[0]['id_zone_geo'];
if($resultat && count($resultat)) return $resultat[0]['id_zone_geo'];
return $code_insee; // autrement retourne l'original
}
 
return $code_insee;
 
}
 
protected function encoderMotCle($mot_cle) {
return md5(mb_strtolower(trim($mot_cle)));
}
718,5 → 680,3
return $contenu;
}
}
 
?>
/branches/v1.7-croissant/jrest/lib/LiaisonMotsCles.php
1,24 → 1,14
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
/**
* PHP Version 5
*
* @category PHP
* @package jrest
* @author Aurélien Peronnet <aurelien@tela-botania.org>
* @copyright 2010 Tela-Botanica
* @author Raphaël Droz <raphael@tela-botania.org>
* @copyright 2010, 2013 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/jrest/
*/
/**
* in : utf8
* out : utf8
*
* Librairie de liaison d'images et d'observation à des mots clés
*
*/
 
class LiaisonMotsCles extends Cel {
const SEPARATEUR_MOT_CLE_TEXTE = ',';
30,35 → 20,46
}
public function ajouterLiaisonMotsCles($id_utilisateur, $ids_images_ou_obs, $mots_cles) {
$mode = $this->mode;
$champ_objet_lie = ($this->mode == 'obs') ? 'id_observation' : 'id_image';
$champ_mot_cle = ($this->mode == 'obs') ? 'id_mot_cle_obs' : 'id_mot_cle_image';
// le mot clé ignore est spécifique mysql, mais il est utilisé ici pour des raisons
// de performance, à remplacer par un test sur les mots clés déjà existant si ça gène
$requete_liaison_mots_cles = 'INSERT IGNORE INTO cel_'.$this->mode.'_mots_cles '.
'('.$champ_objet_lie.', '.$champ_mot_cle.') '.
'VALUES ';
$requete_liaison_mots_cles = sprintf('INSERT IGNORE INTO cel_%s_mots_cles '.
'(%s, %s) VALUES ',
$mode,
$mode == 'obs' ? 'id_observation' : 'id_image',
$mode == 'obs' ? 'id_mot_cle_obs' : 'id_mot_cle_image');
$insert = array();
foreach($ids_images_ou_obs as $id_image_ou_obs) {
foreach($mots_cles as $mot) {
$requete_liaison_mots_cles .= '('.$id_image_ou_obs.','.Cel::db()->proteger($mot).'),';
// TODO!! ce_utilisateur
$insert[] = '('.$id_image_ou_obs.','.Cel::db()->proteger($mot).')';
}
}
$requete_liaison_mots_cles = rtrim($requete_liaison_mots_cles,',');
$resultat_liaison_mots_cles = Cel::db()->executer($requete_liaison_mots_cles);
foreach($ids_images_ou_obs as $id_image_ou_obs) {
$this->regenererIndexTexteMotCle($id_image_ou_obs, $id_utilisateur);
if(!$insert) {
// peut arriver, par exemple lorsqu'on décoche tous les mots-clef associés à une image
$this->logger('CEL_bugs', 'Pas de mot-clef à ajouter à des '.$mode.' : '. implode(',', $ids_images_ou_obs));
}
 
else {
$resultat_liaison_mots_cles = Cel::db()->executer($requete_liaison_mots_cles . implode(',',$insert));
if(!$resultat_liaison_mots_cles) {
$this->logger('CEL_bugs', 'Erreur d\'ajout de mots clés à des '.$this->mode.' : '.$requete_liaison_mots_cles);
$this->logger('CEL_bugs', 'Erreur d\'ajout de mots clés à des '.$mode.' : '.$requete_liaison_mots_cles);
// ne pas retourner car si nous sommes passés par InventoryKeyWordImageLink updateElement(),
// alors celui-ci à *purgé* les mots-clefs en amont et compte sur nous pour faire une réinitialisation
/// correcte ...
// return FALSE;
}
}
return $resultat_liaison_mots_cles;
// ... donc dans tous les cas nous devons conserver une cohérence entre les deux modes de stockage des mots-clefs
$ret = TRUE;
foreach($ids_images_ou_obs as $id_image_ou_obs) {
$bool = self::regenererIndexTexteMotCle($id_image_ou_obs, $id_utilisateur, $mode);
$ret = $ret & ($bool !== FALSE); // peut légitimement retourner 0
}
return $ret;
}
public function supprimerLiaisonMotsClesEtRegenererIndexTexte($id_utilisateur, $ids_images_ou_obs, $mots_cles) {
65,7 → 66,7
$retour = $this->supprimerLiaisonMotsCles($id_utilisateur, $ids_images_ou_obs, $mots_cles);
foreach($ids_images_ou_obs as $image_ou_obs) {
$this->regenererIndexTexteMotCle($image_ou_obs, $id_utilisateur);
self::regenererIndexTexteMotCle($image_ou_obs, $id_utilisateur, $this->mode);
}
return $retour;
82,18 → 83,12
$resultat_suppression_mot_cle = Cel::db()->executer($requete_suppression_liaison_mot_cle);
 
if ($requete_suppression_liaison_mot_cle !== false) {
$retour = true;
} else {
$message = "Erreur de suppression des mots clés de plusieurs ".$this->mode." : $requete";
$this->logger($message);
if ($requete_suppression_liaison_mot_cle !== false) return TRUE;
$retour = false;
$this->logger("Erreur de suppression des mots clés de plusieurs ".$this->mode." : $requete");
return FALSE;
}
return $retour;
}
public function supprimerToutesLiaisonsPourIdImageOuObs($id_utilisateur, $ids_images_ou_obs) {
$champ_objet_lie = ($this->mode == 'obs') ? 'id_observation' : 'id_image';
105,15 → 100,11
$resultat_suppression_mot_cle = Cel::db()->executer($requete_suppression_liaison_mot_cle);
 
if ($requete_suppression_liaison_mot_cle !== false) {
$retour = true;
} else {
$message = "Erreur de suppression des mots clés de plusieurs ".$this->mode." : $requete";
$this->logger($message);
$retour = false;
return TRUE;
}
return $retour;
$this->logger("Erreur de suppression des mots clés de plusieurs ".$this->mode." : $requete");
return FALSE;
}
public function supprimerToutesLiaisonsPourIdMotCle($id_utilisateur, $tableau_ids_mots_cles) {
133,7 → 124,7
$resultat_requete_objets_lies_mot_cle = Cel::db()->requeter($requete_objets_lies_mot_cle);
foreach($resultat_requete_objets_lies_mot_cle as $objet_lie) {
$this->regenererIndexTexteMotCle($objet_lie['id'], $id_utilisateur);
self::regenererIndexTexteMotCle($objet_lie['id'], $id_utilisateur, $this->mode);
}
if ($requete_suppression_liaison_mot_cle !== false) {
148,42 → 139,37
return $retour;
}
private function regenererIndexTexteMotCle($image_ou_obs, $identifiant_utilisateur) {
$mots_cles = $this->obtenirMotsClesTexte($image_ou_obs, $identifiant_utilisateur);
static private function regenererIndexTexteMotCle($id_image_ou_obs, $identifiant_utilisateur, $mode) {
$mots_cles = self::obtenirMotsClesTexte($id_image_ou_obs, $identifiant_utilisateur, $mode);
$mots_cles_texte_chaine = "";
if (count($mots_cles) > 0) {
$mots_cles_texte_chaine = $this->formaterTableauMotCleTextePourInsertion($mots_cles);
$mots_cles_texte_chaine = self::formaterTableauMotCleTextePourInsertion($mots_cles);
}
 
$this->executerRequeteMiseAJourMotCleTexte($mots_cles_texte_chaine, $image_ou_obs, $identifiant_utilisateur);
}
// self::executerRequeteMiseAJourMotCleTexte($mots_cles_texte_chaine, $id_image_ou_obs, $identifiant_utilisateur, $mode);
return Cel::db()->executer(sprintf('UPDATE %s SET mots_cles_texte = %s WHERE %s = %s AND ce_utilisateur = %s -- %s:%d',
$mode == 'obs' ? 'cel_obs' : 'cel_images',
Cel::db()->proteger($mots_cles_texte_chaine),
$mode == 'obs' ? 'id_observation' : 'id_image',
Cel::db()->proteger($id_image_ou_obs),
Cel::db()->proteger($identifiant_utilisateur),
__FILE__ , __LINE__));
private function executerRequeteMiseAJourMotCleTexte($mots_cles_texte_chaine, $id_image_ou_obs, $identifiant_utilisateur) {
$requete = 'UPDATE '.(($this->mode == 'obs') ? 'cel_obs' : 'cel_images').' '.
'SET mots_cles_texte = '.Cel::db()->proteger($mots_cles_texte_chaine).' '.
'WHERE '.(($this->mode == 'obs') ? 'id_observation' : 'id_image').' = '.Cel::db()->proteger($id_image_ou_obs).
' AND ce_utilisateur = '.Cel::db()->proteger($identifiant_utilisateur);
 
return Cel::db()->executer($requete);
}
private function obtenirMotsClesTexte($id_image_ou_obs, $identifiant_utilisateur) {
$requete = 'SELECT mot_cle '.
'FROM '.'cel_mots_cles_'.$this->mode.' '.
'WHERE id_mot_cle_'.(($this->mode == 'obs') ? 'obs' : 'image').' IN '.
'('.
'SELECT id_mot_cle_'.(($this->mode == 'obs') ? 'obs' : 'image').' '.
'FROM cel_'.$this->mode.'_mots_cles '.
'WHERE '.(($this->mode == 'obs') ? 'id_observation' : 'id_image').' = '.Cel::db()->proteger($id_image_ou_obs).
')'.
' AND id_utilisateur = '.Cel::db()->proteger($identifiant_utilisateur);
 
$resultats = Cel::db()->requeter($requete);
return $resultats;
private static function obtenirMotsClesTexte($id_image_ou_obs, $identifiant_utilisateur, $mode) {
return Cel::db()->requeter(sprintf('SELECT mot_cle FROM cel_mots_cles_%1$s WHERE id_mot_cle_%2$s IN '.
' (SELECT id_mot_cle_%2$s FROM cel_%1$s_mots_cles WHERE %3$s = %4$s)'.
' AND id_utilisateur = %5$s -- %6$s:%7$d',
$mode,
$mode == 'obs' ? 'obs' : 'image',
$mode == 'obs' ? 'id_observation' : 'id_image',
Cel::db()->proteger($id_image_ou_obs),
Cel::db()->proteger($identifiant_utilisateur),
__FILE__ , __LINE__));
}
private function formaterTableauMotCleTextePourInsertion($tableau_mots_cles_texte) {
private static function formaterTableauMotCleTextePourInsertion($tableau_mots_cles_texte) {
$mot_cles_texte_chaine = '';
if (is_array($tableau_mots_cles_texte)) {
197,7 → 183,7
return $mot_cles_texte_chaine;
}
public function nettoyerMotsCles($chaine) {
static function nettoyerMotsCles($chaine) {
$valeur = str_replace('null', '', $chaine);
$valeur = trim($valeur, ';;');
/branches/v1.7-croissant/jrest/jrest.ini.php.defaut
45,7 → 45,8
hostspec =
database = tela_prod_eflore_v1_1_principale
 
url_service_nom = "http://localhost/service:eflore:0.1/bdtfx/noms"
api_host = "http://localhost/service:eflore:0.1"
url_service_nom = "http://localhost/service:eflore:0.1/{referentiel}/noms"
url_service_taxon = "http://localhost/service:eflore:0.1/bdtfx/taxons"
url_service_chorologie_obs = "http://localhost/service:eflore:0.1/chorodep/observations"
url_service_chorologie_carte = "http://localhost/service:eflore:0.1/{referentiel_choro}/cartes"
58,6 → 59,7
chemin_images = /opt/lampp/htdocs/Documents/images_serveur
chemin_export = /opt/lampp/htdocs/Documents/export_images
chemin_stockage_temp = /home/tmp
images_temp_url = "http://localhost/tmp/images/%s"
 
url_images = http://localhost/Documents/images_serveur
url_export = http://localhost/Documents/export_images
/branches/v1.7-croissant/jrest/tests/phptests/ref-nonom-nonum.test.php
New file
0,0 → 1,9
<?php
/* test détermination setting du référentiel:
Théorie, valable pour insert et update:
- pas de nom_sel = pas de num_nom
MAIS:
- pas de nom_sel = pas de référentiel (NULL)
- nom_sel mais pas de num_nom = référentiel = "autre"
*/
return array('data' => array('nom_referentiel' => 'bdtfx'));
/branches/v1.7-croissant/jrest/tests/phptests/ref-nom-nonum.result.php
New file
0,0 → 1,0
<?php return array ('nom_sel' => 'blah','nom_referentiel' => 'autre');
/branches/v1.7-croissant/jrest/tests/phptests/determ-espece-from-nom-ret.test.php
New file
0,0 → 1,3
<?php
// test détermination espèce avec un nom retenu (contenant déjà le nom_sci concaténé)
return array('data' => array('Espèce' => 'Hieracium lysanum Arv.-Touv. & Gaut.', 'nom_referentiel' => 'bdtfx'));
/branches/v1.7-croissant/jrest/tests/phptests/determ-espece-badref-bdnffnn.result.php
1,3 → 1,3
<?php return array (
'nom_sel' => 'bdtfx:nn:72475',
'nom_referentiel' => 'bdtxa');
'nom_sel' => 'Viola riviniana subsp. bavarica',
'nom_referentiel' => 'bdtfx');
/branches/v1.7-croissant/jrest/tests/phptests/ref-nonom-nonum.result.php
New file
0,0 → 1,0
<?php return array ( 'nom_referentiel' => 'autre' );
/branches/v1.7-croissant/jrest/tests/phptests/ref-nom-nonum.test.php
New file
0,0 → 1,9
<?php
/* test détermination setting du référentiel:
Théorie, valable pour insert et update:
- pas de nom_sel = pas de num_nom
MAIS:
- pas de nom_sel = pas de référentiel (NULL)
- nom_sel mais pas de num_nom = référentiel = "autre"
*/
return array('data' => array('nom_referentiel' => 'bdtfx', 'nom_sel' => 'blah'));
/branches/v1.7-croissant/jrest/tests/phptests/determ-espece-bdnffnt.result.php
1,7 → 1,7
<?php return array (
'nom_sel' => 'Viola riviniana subsp. riviniana',
'nom_sel' => 'Viola riviniana f. riviniana',
'nom_sel_nn' => '72478',
'nom_ret' => 'Viola riviniana subsp. riviniana',
'nom_ret' => 'Viola riviniana f. riviniana',
'nom_ret_nn' => '72478',
'nt' => '5757',
'famille' => 'Violaceae',
/branches/v1.7-croissant/jrest/tests/phptests/determ-espece-from-nom-ret.result.php
New file
0,0 → 1,9
<?php return array (
'nom_sel' => 'Hieracium lysanum Arv.-Touv. & Gaut.',
'nom_sel_nn' => '33392',
'nom_ret' => 'Hieracium lysanum Arv.-Touv. & Gaut.',
'nom_ret_nn' => '33392',
'nt' => '11235',
'famille' => 'Asteraceae',
'nom_referentiel' => 'bdtfx'
);
/branches/v1.7-croissant/jrest/tests/phptests/determ-espece-ref-badbdnffnn.test.php
New file
0,0 → 1,3
<?php
// test détermination espèce avec mauvais bdnffnn mais bon référentiel
return array('data' => array('Espèce' => 'bdtfx:nn:72475000', 'nom_referentiel' => 'bdtfx'));
/branches/v1.7-croissant/jrest/tests/phptests/transmission.result.php
1,4 → 1,6
<?php return array (
<?php
date_default_timezone_set("Europe/Paris");
return array (
'transmission' => 'oui',
//'date_transmission' => '2013-07-26 18:20:08',
'date_transmission' => date("Y-m-d H:i:s") // attention au décallage (1sec par exemple)
);
/branches/v1.7-croissant/jrest/tests/phptests/ref-nonom-num.result.php
New file
0,0 → 1,0
<?php return array ('nom_referentiel' => 'autre');
/branches/v1.7-croissant/jrest/tests/phptests/ref-nom-num.test.php
New file
0,0 → 1,9
<?php
/* test détermination setting du référentiel:
Théorie, valable pour insert et update:
- pas de nom_sel = pas de num_nom
MAIS:
- pas de nom_sel = pas de référentiel (NULL)
- nom_sel mais pas de num_nom = référentiel = "autre"
*/
return array('data' => array('nom_referentiel' => 'bdtfx', 'nom_sel' => 'blah', 'nom_sel_nn' => -42));
/branches/v1.7-croissant/jrest/tests/phptests/determ-espece-ref-badbdnffnn.result.php
New file
0,0 → 1,4
<?php return array (
'nom_sel' => 'bdtfx:nn:72475000',
'nom_referentiel' => 'autre',
);
/branches/v1.7-croissant/jrest/tests/phptests/ref-nonom-num.test.php
New file
0,0 → 1,9
<?php
/* test détermination setting du référentiel:
Théorie, valable pour insert et update:
- pas de nom_sel = pas de num_nom
MAIS:
- pas de nom_sel = pas de référentiel (NULL)
- nom_sel mais pas de num_nom = référentiel = "autre"
*/
return array('data' => array('nom_referentiel' => 'bdtfx', 'nom_sel_nn' => 182));
/branches/v1.7-croissant/jrest/tests/phptests/ref-nom-num.result.php
New file
0,0 → 1,0
<?php return array ('nom_sel' => 'blah','nom_referentiel' => 'autre');
/branches/v1.7-croissant/jrest/tests/phptests/determ-espece-noref-bdnffnn.result.php
1,3 → 1,3
<?php return array (
'nom_sel' => 'bdtfx:nn:72475',
'nom_referentiel' => 'autre');
'nom_sel' => 'Viola riviniana subsp. bavarica',
'nom_referentiel' => 'bdtfx');
/branches/v1.7-croissant/jrest/tests/api.php
36,6 → 36,8
'phenologie' => 'Phénologie',
'images' => 'Image(s)',
'nom_commun' => 'Nom Commun',
 
'observateur' => 'Observateur',
);
 
 
104,8 → 106,10
'ce_utilisateur' => USER
));
 
curl_setopt($ch,CURLOPT_RETURNTRANSFER, TRUE);
//curl_setopt($ch,CURLOPT_RETURNTRANSFER, TRUE);
//execute post
if(DEBUG) @fwrite(STDERR, sprintf("curl -F file=@%s '%s'\n", $file, $URL));
 
$result = curl_exec($ch);
curl_close($ch);
return $result;
/branches/v1.7-croissant/jrest/tests/cmd-test.php
1,9 → 1,10
#!/usr/bin/env php
<?php
 
define('DEFAULT_DOMAIN', 'http://cel');
define('DEFAULT_USER', 22506);
 
$options = getopt("hiou:d:e:p:FU:P:",array("help", "images", "obs", "user:", "domain:", "email:", "pass:", "flush", "upload:", "phpsessid"));
$options = getopt("hiou:d:e:p:FU:P:D",array("help", "images", "obs", "user:", "domain:", "email:", "pass:", "flush", "upload:", "phpsessid", "debug"));
if(isset($options['h']) || isset($options['help'])) die(__help());
 
 
11,8 → 12,11
define('DOMAIN', isset($options['d']) ? $options['d'] : (isset($options['domain']) ? $options['domain'] : DEFAULT_DOMAIN));
define('EMAIL', isset($options['e']) ? $options['e'] : (isset($options['email']) ? $options['email'] : NULL));
define('PASS', isset($options['p']) ? $options['p'] : (isset($options['pass']) ? $options['pass'] : NULL));
define('COOKIE', isset($options['P']) ? $options['P'] : (isset($options['phpsessid']) ? $options['phpsessid'] : NULL));
define('DEBUG', isset($options['D']) ? 1 : (isset($options['debug']) ? 1 : 0));
 
if (isset($options['P'])) define('COOKIE', $options['P']);
elseif (isset($options['phpsessid'])) define('COOKIE', $options['phpsessid']);
 
// API::auth() define()'s COOKIE
require_once('api.php');
 
27,7 → 31,7
$upload = isset($options['U']) ? $options['U'] : (isset($options['upload']) ? $options['upload'] : NULL);
if($upload) cel_upload_image($upload);
 
if(! COOKIE) { if(!auth()) die('no auth'); }
if(! defined('COOKIE')) { if(!auth()) die('no auth'); }
 
 
// $csv = genCSV(array('ordre' => 1, 'Date' => '23/06/1991', 'rien' => 'rien'));
58,8 → 62,9
La priorité est donnée à -P sur le couple (-e , -p) pour l'authentification, eg:
$ sqlite3 .mozilla/firefox/*.default/cookies.sqlite<<<"SELECT * FROM moz_cookies WHERE baseDomain = 'cel' AND name = 'PHPSESSID';"
 
%1\$s -u|--upload <file>
%1\$s -U|--upload <file>
Upload le fichier "file".
 
EOF
, // */
basename(__FILE__),
/branches/v1.7-croissant/jrest/services/CelWidgetMapPoint.php
249,7 → 249,7
if (isset($this->parametres['ne']) && $this->parametres['sw'] && ! $this->etreNull($this->parametres['ne']) && ! $this->etreNull($this->parametres['ne']) && ! $this->etreNull($this->parametres['sw'])) {
$ne = $this->decomposerLatLng($this->parametres['ne']);
$sw = $this->decomposerLatLng($this->parametres['sw']);
$marqueurs['points'] = CartoGroupage::creerGroupesQuadtree(&$points, $ne['lat'], $ne['lng'], $sw['lat'], $sw['lng'], $zoom);
$marqueurs['points'] = CartoGroupage::creerGroupesQuadtree($points, $ne['lat'], $ne['lng'], $sw['lat'], $sw['lng'], $zoom);
} else {
$marqueurs['points'] = $points;
}
/branches/v1.7-croissant/jrest/services/InventoryKeyWordImageLink.php
1,26 → 1,19
<?php
// declare(encoding='UTF-8');
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
/**
* PHP Version 5
*
* @category PHP
* @package jrest
* @author Aurélien Peronnet <aurelien@tela-botania.org>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/jrest/
*/
/**
* in : utf8
* out : utf8
* @author Raphaël Droz <raphael@tela-botania.org>
* @copyright 2010, 2013 Tela-Botanica
* @license Licence CECILL <http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
*
* Service de liaisons de mots clés à des images.
* Le service lie une ou plusieurs mots clés à une ou plusieurs images
*
*/
 
require_once('InventoryKeyWordObsLink.php');
 
class InventoryKeyWordImageLink extends Cel {
public function getElement($uid) {
36,46 → 29,24
return;
}
$pairs['images'] = rtrim($pairs['images'],',');
$id_images = explode(',',$pairs['images']);
$id_images = array_filter(explode(',', $pairs['images']));
$mots_cles = array_filter(explode(',', $pairs['mots_cles']));
$pairs['mots_cles'] = rtrim($pairs['mots_cles'],',');
$mots_cles = explode(',',$pairs['mots_cles']);
// Pour le moment on ne peut que supprimer les mots clés et ajouter les nouveaux à cause du fonctionnement
// de l'arbre de mots clés des images
$gestionnaire_mots_cles = new LiaisonMotsCles($this->config,'images');
$suppression_liaison_mot_cle = $gestionnaire_mots_cles->supprimerToutesLiaisonsPourIdImageOuObs($pairs['ce_utilisateur'], $id_images);
$liaison_mot_cle = $gestionnaire_mots_cles->ajouterLiaisonMotsCles($pairs['ce_utilisateur'],$id_images, $mots_cles);
return $liaison_mot_cle;
return $gestionnaire_mots_cles->ajouterLiaisonMotsCles($pairs['ce_utilisateur'],$id_images, $mots_cles);
}
 
public function deleteElement($uid){
$retour = false;
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
if (!isset($uid[0]) || !isset($uid[1]) || !isset($uid[2]) || !$this->estUnIdentifiantMotCle($uid[2])) {
return;
if (!isset($uid[0]) || !isset($uid[1]) || !isset($uid[2]) || ! InventoryKeyWordObsLink::estUnIdentifiantMotCle($uid[2])) {
return FALSE;
}
$id_images = explode(',',$uid[1]);
$id_utilisateur = $uid[0];
$gestionnaire_mots_cles = new LiaisonMotsCles($this->config,'images');
$mots_cles = $gestionnaire_mots_cles->nettoyerMotsCles($uid[2]);
$mots_cles = explode(',',$mots_cles);
$suppression_liaison_mot_cle = $gestionnaire_mots_cles->supprimerLiaisonMotsClesEtRegenererIndexTexte($id_utilisateur, $id_images, $mots_cles);
 
return $suppression_liaison_mot_cle;
return InventoryKeyWordObsLink::unlinkKeyword($this->config, 'images', explode(',',$uid[1]), $uid[0], $uid[2]);
}
 
private function estUnIdentifiantMotCle($chaine) {
return trim($chaine) != '' && preg_match('/[0-9A-Z]+\.[0-9A-Z]+/i', $chaine);
}
}
?>
/branches/v1.7-croissant/jrest/services/InventoryKeyWordObsLink.php
1,31 → 1,18
<?php
// declare(encoding='UTF-8');
/**
* PHP Version 5
*
* @category PHP
* @package jrest
* @author Aurélien Peronnet <aurelien@tela-botania.org>
* @copyright 2010 Tela-Botanica
* @copyright 2010, 2013 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/jrest/
*/
/**
* in : utf8
* out : utf8
*
* Service de liaisons de mots clés à des observations.
* Le service lie une ou plusieurs mots clés à une ou plusieurs observations
*
*/
 
class InventoryKeyWordObsLink extends Cel {
public function getElement($uid) {
public function getElement($uid) { }
}
public function createElement($pairs) {
// Controle detournement utilisateur
45,30 → 32,25
}
 
public function deleteElement($uid){
$retour = false;
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
if (!isset($uid[0]) || !isset($uid[1]) || !isset($uid[2]) || !$this->estUnIdentifiantMotCle($uid[2])) {
return;
if (!isset($uid[0]) || !isset($uid[1]) || !isset($uid[2]) || ! self::estUnIdentifiantMotCle($uid[2])) {
return FALSE;
}
return self::unlinkKeyword($this->config, 'obs', explode(',',$uid[1]), $uid[0], $uid[2]);
}
$ids_obs = explode(',',$uid[1]);
$id_utilisateur = $uid[0];
static function unlinkKeyword($config, $type /* = obs|images */, Array $obsIds, $uid, $keywordIds /* comma-separated string */) {
if($type != 'obs' && $type != 'images') return FALSE;
$gestionnaire_mots_cles = new LiaisonMotsCles($this->config,'obs');
$mots_cles = $gestionnaire_mots_cles->nettoyerMotsCles($uid[2]);
$mots_cles = explode(',',$mots_cles);
$suppression_liaison_mot_cle = $gestionnaire_mots_cles->supprimerLiaisonMotsClesEtRegenererIndexTexte($id_utilisateur, $ids_obs, $mots_cles);
 
return $suppression_liaison_mot_cle;
$gestionnaire_mots_cles = new LiaisonMotsCles($config, $type);
$mots_cles = explode(',', LiaisonMotsCles::nettoyerMotsCles($keywordIds));
return $gestionnaire_mots_cles->supprimerLiaisonMotsClesEtRegenererIndexTexte($uid, $obsIds, $mots_cles);
}
 
private function estUnIdentifiantMotCle($chaine) {
static function estUnIdentifiantMotCle($chaine) {
return trim($chaine) != '' && preg_match('/[0-9A-Z]+\.[0-9A-Z]+/i', $chaine);
}
 
}
?>
/branches/v1.7-croissant/jrest/services/CelImageDoublon.php
69,7 → 69,7
private function getDoublonHtml($parametres) {
$widget = null;
$utilisateur_mail = $this->getAuthIdentifiant();
$utilisateur_mail = Cel::getAuthIdentifiant();
$utilisateur_infos = new User($this->config);
$utilisateur = $utilisateur_infos->obtenirUtilisateurSiExiste($utilisateur_mail);
$utilisateur = $utilisateur['id_utilisateur'];
/branches/v1.7-croissant/jrest/services/CelValidationObservation.php
1,59 → 1,137
<?php
/**
* @category PHP
* @package jrest
* @author Aurélien Peronnet <aurelien@tela-botania.org>
* @author Raphaël Droz <raphael@tela-botania.org>
* @copyright 2013 Tela-Botanica
* @license Licence CECILL <http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
*
*/
class CelValidationObservation extends Cel {
/**
* Méthode appelée avec une requête de type POST avec un identifiant d'obs.
* Modifie le taxon associé à une observation avec les informations envoyées
* Utilisé par:
* - del/services/modules/0.1/determinations/ValiderDetermination.php::modifierObservationParDetermination()
*
* @param int $uid[0] identifiant observation
* @param pairs array tableau contenant les valeurs à modifier
* @param pairs['obsKeywordDelete'] optional string: mot-clef à délier à cette observation
*/
public function updateElement($uid,$pairs)
{
public function updateElement($uid, $pairs) {
// ce service est uniquement destiné à être appelé en local,
// depuis le serveur lui même
// en particulier par l'application identiplante
$this->controleAppelIpAutorisee();
$this->verifierParametresObligatoires($uid, $pairs);
self::verifierParametresObligatoires($uid, $pairs);
$id = $uid[0];
 
$gestion_observation = new GestionObservation($this->config);
$pairs = array_map('trim', $pairs);
$utilisateur = $pairs['ce_utilisateur'];
unset($pairs['ce_utilisateur']);
unset($pairs['ce_utilisateur'], $pairs['id_observation']);
 
// mise à jour des mots-clefs suite à une validation:
// typiquement, DEL modifierObservationParDetermination()
// nous enverra obsKeywordDelete=aDeterminer en plus de certitude=Certaine
$obsKeywordDelete = @trim($pairs['obsKeywordDelete']);
// $imgKeywordDelete = @trim($pairs['imgKeywordDelete']);
unset($pairs['obsKeywordDelete']); // , $pairs['imgKeywordDelete']);
 
// complete les données de la proposition validée car:
// 1) la table tb_del.del_commentaire ne contient pas toutes les informations nécessaires
// 2) la table tb_del.del_commentaire ne *devrait* pas contenir beaucoup plus que nom_sel et nom_sel_nn
// 3) la génération de ces données ici, au moment de l'UPDATE, est le meilleur garant de leur fiabilité
$more_data = CelTaxonNomFrom::NN2($this->bdd, @$pairs['nom_sel_nn'], @$pairs['nom_referentiel']);
if($more_data) $pairs = array_merge($pairs, $more_data);
 
$modification = $gestion_observation->modifierObservationPublique($utilisateur, $id, $pairs);
if($modification !== false) {
$resultat = 'ok';
$this->envoyer($resultat);
exit;
} else {
$info = array();
$info = 'Impossible de modifier l\'observation associée à cet identifiant ';
$this->envoyer($info, 'text/html', 'utf-8', false);
exit;
if($modification) {
// quel impact de ces valeurs de retour ?
if($kid = InventoryKeyWordList::getMotsClefId($utilisateur, 'obs', $obsKeywordDelete))
InventoryKeyWordObsLink::unlinkKeyword($this->config, 'obs', explode(',', $id), $utilisateur, $kid);
/* if($kid = InventoryKeyWordList::getMotsClefId($utilisateur, 'images', $imgKeywordDelete))
InventoryKeyWordObsLink::unlinkKeyword($this->config, 'obs', explode(',', $id), $utilisateur, $kid); */
header("Content-Type: text/plain; charset=utf-8");
die("OK"); // attention, compatibilité avec ValiderDetermination.php de DEL !
}
// cf TODO: n'arrivera pas tant que l'UPDATE ajoutera systématiquement date_modification = now()
elseif($modification === 0) {
header("HTTP/1.0 304 Not Modified"); // XXX: PHP 5.4 // http_response_code(304); // Not Modified
header("Content-Type: text/plain; charset=utf-8");
die("Not Modified");
}
else {
header("HTTP/1.0 500 Internal Server Error"); // XXX: PHP: 5.4 // http_response_code(500); // Internal Server Error
header("Content-Type: text/plain; charset=utf-8");
die("Impossible de modifier l'observation associée à cet identifiant " . mysql_error());
}
}
private function verifierParametresObligatoires($uid ,$params) {
$params_obligatoires = array('id_observation',
'ce_utilisateur',
'nom_sel');
$info = array();
if(!isset($uid[0]) || !is_numeric($uid[0])) {
$info .= 'l\' identifiant doit être un entier ';
static function verifierParametresObligatoires($uid, $params) {
if(!@intval($uid[0]) || !@intval($params['id_observation'])) {
header("Content-Type: text/plain; charset=utf-8");
die("L'identifiant d'observation doit être un entier");
}
// TODO: check sur 'id_observation' en tant que param est superflu ?
// TODO: avec l'apparition de CelTaxonNomFrom, "nom_sel" devrait être optionnel
// puisque nous regénérons des données valides avant l'update et puisque
// seul un nom_sel_nn *valide* a pu nous provenir depuis une validation de proposition de la part de DEL.
$params_obligatoires = array('id_observation', 'ce_utilisateur', 'nom_sel');
foreach($params_obligatoires as $param) {
if(!isset($params[$param]) || trim($params[$param]) == "") {
$info = 'le paramètre '.$param.' doit exister et ne peut pas être vide ';
if(@trim($params[$param])) continue;
header("HTTP/1.0 412 Precondition Failed"); // XXX: PHP: 5.4 // http_response_code(412); // Precondition Failed
header("Content-Type: text/plain; charset=utf-8");
die(sprintf("Paramètre %s manquant (parmi %s)", $param, implode(', ', $params_obligatoires)));
}
}
}
if(!empty($info)) {
$this->envoyer($info, 'text/html', 'utf-8', false);
exit;
// pour les modifications touchants aux nom_sel(nn)/nom_ret(nn)/...
// les clefs du tableau (= les aliases de champs) correspondent aux champs attendus
// par tb_cel.cel_obs afin de pouvoir array_merger() et passer le résultat à modifierObservationPublique()
class CelTaxonNomFrom {
const db = 'tb_eflore';
const bdtfx = 'bdtfx_v2_00';
const bdtxa = 'bdtxa_v1_01';
const isfan = 'isfan_v2013';
 
// get from num_nom(_sel)
static function NN($db, $id, $ref) {
if(!$db || !$id || !$ref) return FALSE;
return $db->query(sprintf("SELECT num_nom_retenu AS nom_ret_nn, num_taxon AS nt, CONCAT(nom_sci, ' ', auteur) AS nom_sel".
" FROM cel_references".
" WHERE referentiel = %s AND num_nom = %d", $db->quote($ref), intval($id)))->fetch(PDO::FETCH_ASSOC);
}
 
// get from num_nom(_sel) directement via la DB
// ce qui nous permet l'initialisation des champs non-présents dans cel_references
// cf TODO
static function NN2($db, $id, $ref) {
if(!$db || !$id || !$ref) return FALSE;
switch($ref) {
case "bdtfx":
return $db->query(sprintf("SELECT o.num_nom_retenu AS nom_ret_nn, o.num_taxonomique AS nt, CONCAT(o.nom_sci, ' ', o.auteur) AS nom_sel".
" , o.famille, CONCAT(ret.nom_sci, ' ', ret.auteur) AS nom_ret".
" FROM %s.%s o".
" LEFT JOIN %s.%s ret ON o.num_nom_retenu != 0 AND o.num_nom_retenu = ret.num_nom".
" WHERE o.num_nom = %d -- %s:%d", self::db, self::bdtfx, self::db, self::bdtfx, intval($id), __FILE__, __LINE__))->fetch(PDO::FETCH_ASSOC);
case "bdtxa":
return $db->query(sprintf("SELECT o.num_nom_retenu AS nom_ret_nn, o.num_tax AS nt, CONCAT(o.nom_sci, ' ', o.auteur) AS nom_sel". // subtilité: "num_tax"
" , o.famille, CONCAT(ret.nom_sci, ' ', ret.auteur) AS nom_ret".
" FROM %s.%s o".
" LEFT JOIN %s.%s ret ON o.num_nom_retenu != 0 AND o.num_nom_retenu = ret.num_nom".
" WHERE o.num_nom = %d -- %s:%d", self::db, self::bdtxa, self::db, self::bdtxa, intval($id), __FILE__, __LINE__))->fetch(PDO::FETCH_ASSOC);
case "isfan":
return $db->query(sprintf("SELECT o.num_nom_retenu AS nom_ret_nn, o.num_taxonomique AS nt, CONCAT(o.nom_sci, ' ', o.auteur) AS nom_sel".
" , o.famille, CONCAT(ret.nom_sci, ' ', ret.auteur) AS nom_ret".
" FROM %s.%s o".
" LEFT JOIN %s.%s ret ON o.num_nom_retenu != 0 AND o.num_nom_retenu = ret.num_nom".
" WHERE o.num_nom = %d -- %s:%d", self::db, self::isfan, self::db, self::isfan, intval($id), __FILE__, __LINE__))->fetch(PDO::FETCH_ASSOC);
}
return FALSE;
}
?>
}
/branches/v1.7-croissant/jrest/services/InventoryTransmit.php
1,67 → 1,42
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
 
/**
* PHP Version 5
*
* @category PHP
* @package jrest
/*
* @author Raphaël Droz <raphael@tela-botanica.org>
* @author David Delon <david.delon@clapas.net>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @link /doc/jrest/
* @copyright 2010, 2013 Tela-Botanica
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
*/
 
/**
*
* in : utf8
* out : utf8
*
*
* Transmission observation vers Tela
*/
class InventoryTransmit extends Cel {
 
function updateElement($uid,$pairs) {
// Controle detournement utilisateur
$this->controleUtilisateur($uid[0]);
if (!isset($uid[1])) return false;
 
//TODO: modification pour passer ceci dans la classe gestion observation
if (isset($uid[1]) && $this->estUneSuiteIdentifiantsObservation($uid[1])) {
$requete_transmission = 'UPDATE cel_obs '.
'SET transmission = '.$pairs['transmission'].','.
'date_modification = now(), date_transmission = now() '.
'WHERE ce_utilisateur = '.Cel::db()->proteger($uid[0]).' AND ordre in ('.$uid[1].')';
}
$transmission = intval($pairs['transmission']);
if($transmission != 0 && $transmission != 1) return false;
 
$resultat_transmission = Cel::db()->executer($requete_transmission);
$ids = array_filter(array_map(create_function('$v','return intval($v);'),
explode(',', $uid[1])));
if(!$ids) return FALSE;
if ($resultat_transmission === false) {
return false;
}
$resultat_transmission = Cel::db()->executer(
sprintf('UPDATE cel_obs SET'.
// mise à jour de la valeur de transmission (peut-être ?)
' transmission = %1$d,'.
return true;
}
// date_transmission n'est réactualisé que si nécessaire, c'est à dire si le statut de "transmission" actuel n'est
// pas à 1 et que le nouveau statut est à 1. Autrement il est mis (ou reste) à NULL
' date_transmission = IF(transmission != 1 AND %1$s = 1, now(), NULL),'.
private function estUneSuiteIdentifiantsObservation($chaine) {
// idem pour date_modification qui n'est mise à now() que si l'on passe une observation
// de non-transmise à tranmise ou de transmise à non-transmise
' date_modification = IF(transmission != %1$d, now(), date_modification)'.
// un ensemble d'identifiants est une suite d'identifiants séparés par des virgules
// sans virgule terminale
$reg_exp = "/^(([0-9])+,)*([0-9])+$/";
return preg_match($reg_exp, $chaine);
' WHERE ce_utilisateur = %2$s AND ordre in (%3$s)',
$transmission,
Cel::db()->proteger($uid[0]),
implode(',', $ids)));
return ($resultat_transmission != 0);
}
}
/* +--Fin du code ---------------------------------------------------------------------------------------+
* $Log$
* Revision 1.3 2008-01-30 08:57:28 ddelon
* fin mise en place mygwt
*
* Revision 1.2 2007-05-22 12:54:09 ddelon
* Securisation acces utilisateur
*
*/
?>
/branches/v1.7-croissant/jrest/services/InventoryKeyWordList.php
42,27 → 42,69
// Controle detournement utilisateur
$id_utilisateur = $uid[1] ;
$this->controleUtilisateur($uid[1]);
$this->setChampsEtTablePourSuffixe($uid[0]);
$requete = 'SELECT mot_cle, id_mot_cle'.$this->suffixe_champ.', ce_mot_cle'.$this->suffixe_champ.'_parent '.
'FROM cel_mots_cles'.$this->suffixe_table.' '.
'WHERE id_utilisateur = '.Cel::db()->proteger($id_utilisateur).' '.
'ORDER BY niveau ';
$this->envoyerJson(self::getMotsClefs($uid[1], $uid[0]));
return TRUE; // compat: pourquoi renvoyer true si vide ?
}
$resultats_mots_cles = Cel::db()->requeter($requete);
if (is_array($resultats_mots_cles)) {
$mots_cles = array();
foreach($resultats_mots_cles as $mot_cle) {
$mots_cles[] = $mot_cle;
static function getMotsClefs($uid, $type) {
if($type == 'obs') {
return Cel::db()->requeter(sprintf(
'SELECT mot_cle, id_mot_cle_obs, ce_mot_cle_obs_parent'.
' FROM cel_mots_cles_obs'.
' WHERE id_utilisateur = %s'.
' ORDER BY niveau',
Cel::db()->proteger($uid)));
}
$this->envoyerJson($mots_cles);
return true;
if($type == 'images') {
return Cel::db()->requeter(sprintf(
'SELECT mot_cle, id_mot_cle_image, ce_mot_cle_image_parent'.
' FROM cel_mots_cles_images'.
' WHERE id_utilisateur = %s'.
' ORDER BY niveau',
Cel::db()->proteger($uid)));
}
/* pour extraire un mot-clef en particulier (bien que getMotsClefId() soit plus adapté:
array_walk($ret,
create_function('&$val, $k, $keyword',
'if($val["mot_cle"] != $keyword) $val = NULL;' .
'else $val = $val["id_mot_cle_obs"];'),
'XXX');
$obsKeywordIdToDetach = array_filter($ret);
$obsKeywordIdToDetach = array_pop($obsKeywordIdToDetach); */
 
return array();
}
 
 
static function getMotsClefId($uid, $type, $keyword) {
if($type == 'obs') {
$ret = Cel::db()->requeter(sprintf(
'SELECT mot_cle, id_mot_cle_obs, ce_mot_cle_obs_parent'.
' FROM cel_mots_cles_obs'.
' WHERE id_utilisateur = %s'.
' AND mot_cle = %s'.
' ORDER BY niveau',
Cel::db()->proteger($uid),
Cel::db()->proteger($keyword) ));
}
 
if($type == 'images') {
$ret = Cel::db()->requeter(sprintf(
'SELECT mot_cle, id_mot_cle_image, ce_mot_cle_image_parent'.
' FROM cel_mots_cles_images'.
' WHERE id_utilisateur = %s'.
' AND mot_cle = %s'.
' ORDER BY niveau',
Cel::db()->proteger($uid),
Cel::db()->proteger($keyword) ));
}
return @$ret[0]['id_mot_cle_obs'];
}
 
public function updateElement($uid, $pairs) {
$id_utilisateur = $uid[1];
$this->controleUtilisateur($uid[1]);
90,7 → 132,7
}
} else if ($action == 'deplacement') {
$this->commencerTransaction();
self::commencerTransaction();
$transaction_reussie_1 = true;
$id_pere = $pairs['parent'];
129,10 → 171,10
if ($transaction_reussie_1 !== false && $transaction_reussie_2 !== false &&
$transaction_reussie_3 !== false && $transaction_reussie_4 !== false &&
$transaction_reussie_5 !== false && $transaction_reussie_6 !== false) {
$this->completerTransaction();
self::completerTransaction();
return true;
} else {
$this->annulerTransaction();
self::annulerTransaction();
return false;
}
}
154,8 → 196,6
 
$this->ajouterMotCleRacine($id_utilisateur);
 
$this->commencerTransaction();
 
$bornes = $this->calculerBornesEtNiveau($id_parent, $id_utilisateur);
$borne_pere = $bornes['bd'];
$niveau = $bornes['niveau'] + 1;
162,6 → 202,9
$bg = $bornes['bd'];
$bd = $bg + 1;
 
if(!$borne_pere) return false;
 
self::commencerTransaction();
$transaction_reussie_1 = $this->decalerBornesPlusDeux($borne_pere,$id_utilisateur) ? true : false;
$requete = 'INSERT INTO cel_mots_cles'.$this->suffixe_table.' '.
178,11 → 221,18
$transaction_reussie_2 = Cel::db()->executer($requete);
 
if ($transaction_reussie_1 && $transaction_reussie_2) {
$this->completerTransaction();
return true;
// on sort de self::createElement ==> JRest::(get|post) ==> JRest->created() qui fait header().
// or si nous dépassons ini_get(output_buffering) nous ne pouvons plus réécrire le code de retour
// HTTP, de plus, si ini_get(output_buffering) == off, nous enverrions un warning.
// d'où ce clone de JRest::created();
header('HTTP/1.0 201 Created');
self::completerTransaction();
exit;
} else {
$this->annulerTransaction();
return false;
// cf ci-dessus: JRest::badRequest
header('HTTP/1.0 400 Bad Request');
self::annulerTransaction();
exit;
}
return true;
}
197,7 → 247,7
$tableau_ids_mots_cles[] = $id_mot_cle;
 
$this->controleUtilisateur($id_utilisateur);
$this->commencerTransaction();
self::commencerTransaction();
 
$bornes = $this->calculerBornesEtNiveau($id_mot_cle, $id_utilisateur);
if($bornes) {
223,9 → 273,9
$transaction_reussie_2 = $this->decalerBornesMoinsIntervalle($bg, $bd, $id_utilisateur) ? true : false;
if ($transaction_reussie_1 !== false && $transaction_reussie_2 !== false) {
$this->completerTransaction();
self::completerTransaction();
} else {
$this->annulerTransaction();
self::annulerTransaction();
}
}
// Suppression des liaisons associées à ce mot clé
276,27 → 326,21
/**
* Désactive l'auto-commit puis débute la transaction
*/
private function commencerTransaction() {
static function commencerTransaction() {
// Désactive l'autocommit le temps de la manipulation de l'arbre
$requete = 'SET AUTOCOMMIT = 0 ';
$reussite_autocommit = Cel::db()->executer($requete);
 
$reussite_autocommit = Cel::db()->executer("SET AUTOCOMMIT = 0");
// Débute une nouvelle transaction
$requete = 'BEGIN ';
$reussite_begin = Cel::db()->executer($requete);
$reussite_begin = Cel::db()->executer("BEGIN");
}
 
/**
* Termine la transaction puis réactive l'auto-commit
*/
private function completerTransaction() {
static function completerTransaction() {
// Complète la transaction
$requete = 'COMMIT ';
$reussite_commit = Cel::db()->executer($requete);
 
$reussite_commit = Cel::db()->executer("COMMIT");
// Réactive l'autocommit le temps de la manipulation de l'arbre
$requete = 'SET AUTOCOMMIT = 1 ';
$reussite_autocommit = Cel::db()->executer($requete);
$reussite_autocommit = Cel::db()->executer("SET AUTOCOMMIT = 1");
 
echo 'OK';
}
304,14 → 348,11
/**
* Annule la transaction et réactive l'auto-commit
*/
private function annulerTransaction() {
static function annulerTransaction() {
// Annule la transaction
$requete = 'ROLLBACK ';
$reussite_rollback = Cel::db()->executer($requete);
 
$reussite_rollback = Cel::db()->executer("ROLLBACK");
// Réactive l'autocommit le temps de la manipulation de l'arbre
$requete = 'SET AUTOCOMMIT = 1 ';
$reussite_autocommit = Cel::db()->executer($requete);
$reussite_autocommit = Cel::db()->executer("SET AUTOCOMMIT = 1");
 
echo 'ERROR';
}
/branches/v1.7-croissant/jrest/services/ImportXLS.php
482,6 → 482,9
C_NOM_RET_NN => NULL, C_NT => NULL, C_FAMILLE => NULL);
self::traiterEspece($ligne, $espece, $referentiel, $cel);
 
if(!$espece[C_NOM_SEL]) $referentiel = Cel::$fallback_referentiel;
if($espece[C_NOM_SEL] && !$espece[C_NOM_SEL_NN]) $referentiel = Cel::$fallback_referentiel;
 
// $localisation est rempli à partir de plusieurs champs: C_ZONE_GEO et C_CE_ZONE_GEO
$localisation = Array(C_ZONE_GEO => NULL, C_CE_ZONE_GEO => NULL);
self::traiterLocalisation($ligne, $localisation);
636,7 → 639,7
if(strpos($referentiel, 'autre') !== FALSE) return 'autre';
 
if($referentiel && isset($ligne[C_NOM_SEL]) && $ligne[C_NOM_SEL]) {
trigger_error("ligne \"{$ref_ligne}\": Attention: référentiel inconnu", E_USER_NOTICE);
trigger_error("ligne \"{$ref_ligne}\": Attention: référentiel \"{$referentiel}\" inconnu", E_USER_NOTICE);
return 'autre';
}
 
688,7 → 691,14
pour des questions de performances
*/
static function traiterEspece($ligne, Array &$espece, &$referentiel, $cel) {
if(empty($ligne[C_NOM_SEL])) return;
if(empty($ligne[C_NOM_SEL])) {
// TODO: nous ne déclarons pas "Numéro nomenclatural" comme colonne importable
// Nous ne pouvons donc pas tenter d'être sympa sur la détermination par num_nom
/* if(!empty($ligne[C_NOM_SEL_NN]) && $referentiel != Cel::$fallback_referentiel)
$ligne[C_NOM_SEL] = $referentiel . ':nn:' . $ligne[C_NOM_SEL_NN];
else */
return;
}
 
// nom_sel reste toujours celui de l'utilisateur
$espece[C_NOM_SEL] = trim($ligne[C_NOM_SEL]);
/branches/v1.7-croissant/jrest/services/InventoryObservationList.php
1,23 → 1,17
<?php
// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel //
/**
* PHP Version 5
* PHP Version 5.2
*
* @category PHP
* @package jrest
* @author Raphaël Droz <raphael@tela-botanica.org>
* @author Aurelien Peronnet <aurelien@tela-botanica.org>
* @copyright 2010 Tela-Botanica
* @copyright 2010, 2013 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @version SVN: <svn_id>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @link /doc/jrest/
*/
 
/**
*
* InventoryObservationList.php
*
* in=utf8
* out=utf8
*
* Cas d'utilisation :
* 1: Service recherche d'observations a partir de divers critères
* a: Le service recherche les observations correspondant aux critères demandés
84,14 → 78,33
return;
}
$uid[1] = rtrim($uid[1],',');
$obs = array_filter(array_map('intval', explode(',', $uid[1])));
if(count($obs) == 0) {
return;
}
$gestionnaire_observation = new GestionObservation($this->config);
$modification_observation = $gestionnaire_observation->modifierObservation($uid[0],$uid[1],$pairs);
if(count($obs) == 1) {
return $gestionnaire_observation->modifierObservation($uid[0], $obs[0], $pairs);
}
return true;
// cas de mise à jour de multiples observations:
$ret = GestionObservation::modifierMultiplesObservation($uid[0], $obs, $pairs);
if($ret === FALSE) return FALSE; // JRest::badRequest();
if($ret === 0) {
header('HTTP/1.0 304 Not Modified');
die;
}
 
header('HTTP/1.0 200 OK'); // et non pas une 201 !
// die(); // non, car incompatible avec PHPUnit
// throw(new Exception()); // non, lance une 400 (cf JRest::updateElement())
// return TRUE; // non, lance une 201
// return FALSE; // non, lance une 400
 
die; // tant pis
}
 
/**
* Supprime une liste d'observations
*
/branches/v1.7-croissant/jrest/services/CelWidgetUploadImageTemp.php
New file
0,0 → 1,130
<?php
// declare(encoding='UTF-8');
/**
* Service permettant d'enregistrer dans le répertoire temporaire les images envoyées depuis le widget Saisie
*
* Cas d'utilisation :
* POST /CelWidgetUploadImageTemp : écriture d'une image dans le répertoire temporaire
*
* @author Mathias Chouet <mathias@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $Id$
* @copyright © 2013, Tela-Botanica
*/
class CelWidgetUploadImageTemp extends Cel {
 
protected $projet = '';
 
public function createElement($donnees) {
$image = array_shift($donnees); // dangereux!
if (isset($_GET['projet'])) {
$this->projet = $_GET['projet'];
}
$retour = $this->enregistrerImageTemporaire($image);
return $this->formaterRetourAvecSquelette($retour);
}
 
private function formaterRetourAvecSquelette($retour) {
$codeRetour = 'tralala pouet pouet'; // tant que non vide, considère que c'est un succès !
if (is_array($retour)) {
$squelette = 'services/squelettes/image_temp.tpl.xml';
$contenu = $this->traiterSquelettePhp($squelette, $retour);
$mime = 'text/xml';
} else {
$contenu = 'Un problème est survenu : '.print_r($retour['message'], true);
$codeRetour = false;
}
$this->envoyer($contenu, $mime);
return $codeRetour;
}
 
// enregistre l'image envoyée dans le chemin de stockage temporaire, puis
// renvoie le XML attendu par le widget de saisie du CEL
public function enregistrerImageTemporaire($image) {
$retour = array(
'urlMiniature' => '',
'imageNom' => '',
'message' => '',
'debogage' => '');
$message = '';
$debogage = '';
if ($image['error'] == UPLOAD_ERR_OK) {
if (is_uploaded_file($image['tmp_name'])) {
if ($this->verifierFormatJpeg($image['tmp_name'])) {
$dossierStockage = $this->config['cel']['chemin_stockage_temp'];
 
$nomFichierOriginal = preg_replace('/[.](jpeg|jpg)$/i', '.jpg', strtolower($image['name']));
$originalChemin = $dossierStockage.'/'.$nomFichierOriginal;
$deplacementOk = move_uploaded_file($image['tmp_name'], $originalChemin);
 
if ($deplacementOk === true) {
$miniatureFichier = str_replace('.jpg', '_min.jpg', $nomFichierOriginal);
$miniatureChemin = $dossierStockage.'/'.$miniatureFichier;
 
// Parametres
$largeurIdeale = 100;
$hauteurIdeale = 100;
$qualite = 85;
 
// Calcul de la hauteur et de la largeur optimale de la miniature
$taillesImgOriginale = getimagesize($originalChemin);
$largeurOrigine = $taillesImgOriginale[0];
$hauteurOrigine = $taillesImgOriginale[1];
 
$largeurMin = $largeurIdeale;
$hauteurMin = (int) ($hauteurOrigine * ($largeurIdeale / $largeurOrigine));
if ($hauteurMin > $hauteurIdeale) {
$hauteurMin = $hauteurIdeale;
$largeurMin = (int)($largeurOrigine * ($hauteurMin / $hauteurOrigine));
}
 
// Création de la miniature
$imageOriginale = imagecreatefromjpeg($originalChemin);
$imageMiniature = imagecreatetruecolor($largeurMin, $hauteurMin);
$couleurFond = imagecolorallocate($imageMiniature, 255, 255, 255);
imagefill($imageMiniature, 0, 0, $couleurFond);
imagecopyresized($imageMiniature, $imageOriginale, 0, 0, 0, 0, $largeurMin, $hauteurMin, $largeurOrigine, $hauteurOrigine);
imagejpeg($imageMiniature, $miniatureChemin, $qualite);
imagedestroy($imageMiniature);
imagedestroy($imageOriginale);
 
// Retour des infos
$retour['urlMiniature'] = sprintf($this->config['cel']['images_temp_url'], $miniatureFichier);
$retour['imageNom'] = $nomFichierOriginal;
} else {
$message = "L'image n'a pu être déplacé sur le serveur.";
}
} else {
$message = "L'image n'est pas au format JPEG.";
}
} else {
$message = "L'image n'a pu être téléversée.";
$debogage = $message.print_r($image, true);
}
} else {
if ($image['error'] == UPLOAD_ERR_FORM_SIZE) {
$message = "L'image téléversée excède la taille maximum autorisée.".
"Veuillez modifier votre image avant de la téléverser à nouveau.";
} else {
$message = "Une erreur de transfert a eu lieu (téléversement interrompu).";
}
$debogage = "Code erreur : {$image['error']}. ".
"Voir : http://php.net/manual/fr/features.file-upload.errors.php";
}
// Retour des infos
$retour['message'] = $message;
$retour['debogage'] = $debogage;
return $retour;
}
 
// Il ne faut pas utiliser l'index type du tableau files pour tester
// si une image est en jpeg car le type renvoyé par les navigateurs
// peut varier (ex. sous ie qui renvoie image/pjpeg
private function verifierFormatJpeg($chemin) {
// get imagesize renvoie un résultat consistant par contre
$infos = getimagesize($chemin, $infos);
return (isset($infos['mime']) && $infos['mime'] == 'image/jpeg');
}
}
?>
/branches/v1.7-croissant/jrest/services/squelettes/image_temp.tpl.xml
New file
0,0 → 1,7
<?='<?xml version="1.0" encoding="UTF-8"?>'."\n";?>
<root>
<miniature-url><?=$urlMiniature?></miniature-url>
<image-nom><?=$imageNom?></image-nom>
<message><?=$message?></message>
<debogage><?=$debogage?></debogage>
</root>
/branches/v1.7-croissant/src/org/tela_botanica/client/vues/observation/FormulaireSaisieObservationVue.java
1437,7 → 1437,7
String champs = modeleMessageModif;
if(communeModifiee) {
if(communeModifiee && ! commune.getRawValue().equals(VALEURS_MULTIPLES)) {
communeM = commune.getText();
if(departement.equals("000null") || departement.equals("")) {
1449,38 → 1449,36
dep = dep.replace('\\',' ');
dep = dep.trim();
try
{
try {
int nDep = Integer.parseInt(dep);
if(nDep > 0 && nDep < 110) {
departement = dep ;
}
}
catch(NumberFormatException e)
{
catch(NumberFormatException e) {
departement = "" ;
}
}
}
departementM = departement;
} else {
}
else {
champs = champs.replaceAll("commune", "");
}
if(lieuDitModifie) {
if(lieuDitModifie && ! lieudit.getRawValue().equals(VALEURS_MULTIPLES)) {
lieuDitM = lieudit.getText();
}else {
champs = champs.replaceAll(":lieu-dit", "");
}
if(stationModifiee) {
if(stationModifiee && ! station.getRawValue().equals(VALEURS_MULTIPLES)) {
stationM = station.getText();
}else {
champs = champs.replaceAll(":station", "");
}
 
if(milieuModifie) {
if(milieuModifie && ! milieu.getRawValue().equals(VALEURS_MULTIPLES)) {
milieuM = milieu.getText();
}else {
champs = champs.replaceAll(":milieu", "");
1493,7 → 1491,7
champs = champs.replaceAll(":date", "");
}
 
if(especeModifiee) {
if(especeModifiee && ! espece.getRawValue().equals(VALEURS_MULTIPLES)) {
especeM = espece.getText();
numNomSelM = numeroNom;
}else {
1500,25 → 1498,25
champs = champs.replaceAll(":espece", "");
}
 
if(commModifie) {
if(commModifie && ! comment.getRawValue().equals(VALEURS_MULTIPLES)) {
commM = comment.getText();
}else {
champs = champs.replaceAll(":commentaire", "");
}
if(latModifiee) {
if(latModifiee && ! latitude.getRawValue().equals(VALEURS_MULTIPLES)) {
latM = latitude.getText();
}else {
champs = champs.replaceAll(":latitude", "");
}
if(altModifiee) {
if(altModifiee && ! altitude.getRawValue().equals(VALEURS_MULTIPLES)) {
altM = altitude.getText();
}else {
champs = champs.replaceAll(":altitude", "");
}
if(longModifiee) {
if(longModifiee && ! longitude.getRawValue().equals(VALEURS_MULTIPLES)) {
longM = longitude.getText();
}else {
champs = champs.replaceAll(":longitude", "");
Property changes:
Modified: svn:mergeinfo
Merged /trunk/src/org/tela_botanica/client/vues/observation/FormulaireSaisieObservationVue.java:r1840-1908
/branches/v1.7-croissant/src/org/tela_botanica/public
New file
Property changes:
Added: svn:ignore
+*
/branches/v1.7-croissant/src/org/tela_botanica/cel-test.gwt.xml
New file
0,0 → 1,10
<module rename-to="org.tela_botanica.cel2">
<!--
http://stackoverflow.com/questions/1011863/how-do-i-speed-up-the-gwt-compiler
http://code.google.com/p/google-web-toolkit/source/browse/trunk/user/src/com/google/gwt/useragent/UserAgent.gwt.xml
http://www.gwtproject.org/doc/latest/DevGuideOrganizingProjects.html#DevGuideModuleXml
-->
<inherits name="org.tela_botanica.cel2" />
<set-property name="user.agent" value="gecko1_8" />
<set-property name="locale" value="default" />
</module>
/branches/v1.7-croissant/src/org/tela_botanica/cel2.gwt.xml
14,9 → 14,9
<!-- Parsing JSON -->
<inherits name='com.google.gwt.json.JSON' />
<!-- Encore des trucs pour les cartes -->
<!-- cartes -->
<inherits name="com.google.gwt.maps.GoogleMaps" />
<!-- Encore des trucs pour les user extensions -->
<inherits name='com.gwtext.GwtExt'/>
<inherits name='com.gwtextux.GwtExtUx' />
<!-- Specify the app entry point class. -->
/branches/v1.7-croissant/war/config.defaut.js
9,7 → 9,7
utiliseRedirectionImage:"1",
referentielGeo:"WGS84",
cleGoogleMaps:"ABQIAAAADBUAHF9l14gI02QVAbUYJBRqPsByHDhzHLE0yoC9hASLZaFmoRT4_9Zkiscf-BaH_gEy7DVHX5BxwQ",
referentielsDispos:"bdtfx:v1.01,Métropole (BDTFX);bdtxa:v1.00,Antilles Françaises (BDTXA);isfan:v1.00,Afrique du Nord (ISFAN);autre,Autre/Inconnu",
referentielsDispos:"bdtfx:v2.00,Métropole (BDTFX);bdtxa:v1.01,Antilles Françaises (BDTXA);isfan:v1.00,Afrique du Nord (ISFAN);autre,Autre/Inconnu",
refTaxVersion:"1",
lienEfloreBaseUrl:"www.tela-botanica.org/eflore",
licence:"",
/branches/v1.7-croissant/build.properties
New file
0,0 → 1,19
projectName = org.tela_botanica.cel2
# pour la compilation "rapide" (ant quick)
projectTestName = org.tela_botanica.cel-test
celhost = cel # ou localhost
 
# note: les répertoires de gwt, gwt-google-api, gwtext et gwtextux sont fixé relatif à ${gwt-path} dans build.xml
gwt-path = ${user.home}/src/gwt
 
# doit contenir ext-all.js, resources et adapter/ext/ext-base.js
# Ces ressources sont nécessaire pour les widgets de gwt-ext-ux
# et ce dernier attend des images dans resources/images du répertoire
# de extjs.
# Or, en extjs 4.2.1 par exemple, les ressources se trouvent désormais
# dans resources/themes/images. Ainsi 2.0.2 est supportée, mais 4.2.1 ne l'est pas.
extjsdir = ${gwt-path}/gwt-xxxx/ext-serv # obtenu raw depuis le serveur
# extjsdir = ${gwt-path}/ext-4.2.1.883
 
# À noter la CSS personnalisée n'est (encore) versionnée dans ce dépôt et se trouve
# dans la version de extjs 2.0.2 sur le serveur
/branches/v1.7-croissant/build.xml
1,5 → 1,8
<project name="cel_GWT2" xmlns:artifact="urn:maven-artifact-ant" basedir=".">
 
<property file="build.properties"/>
<property name="extjsdestdir" value="src/org/tela_botanica/public/js/ext"/>
 
<target name="init">
<property file="local.properties" />
<property name="server-url" value="${server-url}" />
9,8 → 12,8
<property name="gwt-path" value="${gwt-path}" />
</target>
<target name="generate-vocabulary" depends="init">
 
<java classname="com.google.gwt.i18n.tools.I18NSync" fork="true">
<arg value="org.tela_botanica.client.i18n.VocabulaireMetadonnees" />
<classpath>
22,4 → 25,63
</classpath>
</java>
</target>
</project>
 
 
<path id="gwt">
<fileset includes="*.jar" dir="${gwt-path}/gwt/build/lib"/>
<fileset includes="*.jar" dir="${gwt-path}/gwt-google-apis/maps/build/lib"/>
<fileset includes="gwtext.jar" dir="${gwt-path}/gwt-ext/build/lib"/>
<!-- alternativement, en cas de passage (très hypothétique) a gwt 3:
<fileset includes="gxt-legacy-3.0.1.jar" dir="${gwt-path}/gxt"/>
<fileset includes="gxt-3.0.1.jar" dir="${gwt-path}/gxt"/> -->
<fileset includes="*.jar" dir="${gwt-path}/gwt-ext-ux/build/lib"/>
<pathelement location="src" />
</path>
 
<!-- todo: must be inside cel2.gwt.xml in some way -->
<target name="link-resources">
<mkdir dir="${extjsdestdir}"/>
<mkdir dir="${extjsdestdir}/adapter/ext"/> <!-- normalement optionnel en extjs 4.2.1 -->
<symlink overwrite="true" link="${extjsdestdir}/adapter/ext/" resource="${extjsdir}/adapter/ext/ext-base.js"/>
<symlink overwrite="true" link="${extjsdestdir}" resource="${extjsdir}/ext-all.js"/>
<symlink overwrite="true" link="${extjsdestdir}" resource="${extjsdir}/resources"/>
</target>
 
 
<target name="test"><echoproperties/></target> <!-- sometimes useful -->
 
<target name="compile" depends="link-resources">
<!-- <java classname="com.google.gwt.dev.GWTCompiler" fork="true"> -->
<java classname="com.google.gwt.dev.Compiler" fork="true">
<arg line="-localWorkers 2 -style DETAILED ${projectName}"/>
<!-- <arg line="-out build/gwtOutput"/> -->
<classpath refid="gwt"/>
</java>
</target>
 
<target name="quick" depends="link-resources">
<java classname="com.google.gwt.dev.Compiler" fork="true">
<arg line="-style DETAILED -draftCompile ${projectTestName}" />
<classpath refid="gwt"/>
</java>
</target>
 
 
<target name="debug" depends="link-resources">
<java classname="com.google.gwt.dev.Compiler" fork="true">
<arg line="-style DETAILED -logLevel DEBUG"/> <!-- TRACE -->
<arg value="${projectName}" />
<classpath refid="gwt"/>
</java>
</target>
 
 
<target name="live">
<java classname="com.google.gwt.dev.DevMode" spawn="true" fork="true">
<arg line="-startupUrl http://${celhost}/war/cel2.html -noserver -codeServerPort auto ${projectName}" />
<classpath refid="gwt"/>
</java>
</target>
 
 
</project>
/branches/v1.7-croissant/TODO
New file
0,0 → 1,7
GestionObservation.php: amélioration du query-builder
GestionObservation.php/cel_obs schéma: TRIGGER pour date_modification
plutôt que gestion en PHP
CelValidationObservation.php: pose la question de la validation des
données par rapport à l'indépendance vis-à-vis des référentiels
nomenclaturaux et taxonomiques (tables bdtfx/bdtxa/isfan...)
 
/branches/v1.7-croissant/doc/bdd/schema_bdd_cel_v2.mwb
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/branches/v1.7-croissant/doc/bdd/cel_v2.sql
258,14 → 258,14
`phenologie` VARCHAR(255) NULL DEFAULT NULL ,
`code_insee_calcule` VARCHAR(5) NULL DEFAULT NULL COMMENT 'Code INSEE calculé par un scrip CRON.' ,
PRIMARY KEY (`id_observation`) ,
INDEX `id_obs` (`ordre` ASC, `ce_utilisateur` ASC) ,
INDEX `date_creation` (`ce_utilisateur` ASC, `date_creation` ASC) ,
UNIQUE INDEX `id_obs` (`ce_utilisateur` ASC, `ordre` ASC),
INDEX `date_creation` (`ce_utilisateur`(10) ASC, `date_creation` ASC),
INDEX `coordonnees` (`latitude` ASC, `longitude` ASC) ,
INDEX `nom_retenu` (`nom_ret` ASC) ,
INDEX `date_observation` (`date_observation` ASC) COMMENT 'Date_transmission : nécessaire à l'ORDER BY utilisé dans la liste d'observation de DEL' ,
INDEX `nom_referentiel` (`nom_referentiel`(5) ASC) COMMENT 'Index sur (bdtfx,bdtfx,isfan)' ,
INDEX `date_transmission` (`date_transmission` DESC) COMMENT 'Nécessaire à CEL/DEL qui officie avec transmission = 1' ,
INDEX `transmission` (`transmission` ASC) )
INDEX `date_observation` (`date_observation` ASC),
INDEX `nom_referentiel` (`nom_referentiel`(5) ASC) COMMENT ' /* comment truncated */ /*Index sur (bdtfx,bdtfx,isfan)*/',
INDEX `date_transmission` (`date_transmission` DESC) COMMENT ' /* comment truncated */ /*Date_transmission : nécessaire à l'ORDER BY utilisé dans la liste d'observation de DEL*/',
INDEX `transmission` (`transmission` ASC) COMMENT ' /* comment truncated */ /*Nécessaire à CEL/DEL qui officie avec transmission = 1*/')
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;
375,7 → 375,6
where `o`.`transmission` = 1
AND (`o`.`mots_cles_texte` NOT LIKE '%sensible%' OR `o`.`mots_cles_texte` IS NULL);
 
 
SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
/branches/v1.7-croissant/doc
Property changes:
Deleted: svn:mergeinfo
Reverse-merged /trunk/doc:r1841,1881
Reverse-merged /branches/topic-dbsingleton/doc:r1720-1764
/branches/v1.7-croissant/.
Property changes:
Modified: svn:mergeinfo
Merged /trunk:r1840,1842-1902,1904-1913